You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by cl...@apache.org on 2016/04/23 20:45:39 UTC

qpid-proton git commit: PROTON-1182: c++: hide proton::link, replace with sender/receiver

Repository: qpid-proton
Updated Branches:
  refs/heads/master 6fabb14ce -> 337b4364c


PROTON-1182: c++: hide proton::link, replace with sender/receiver


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/337b4364
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/337b4364
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/337b4364

Branch: refs/heads/master
Commit: 337b4364ce9717ed7940830df226fbd5bb6599d6
Parents: 6fabb14
Author: Clifford Jansen <cl...@apache.org>
Authored: Sat Apr 23 11:42:27 2016 -0700
Committer: Clifford Jansen <cl...@apache.org>
Committed: Sat Apr 23 11:42:27 2016 -0700

----------------------------------------------------------------------
 examples/cpp/broker.hpp                         |  11 +-
 examples/cpp/client.cpp                         |   3 +-
 examples/cpp/engine/client.cpp                  |   3 +-
 examples/cpp/engine/direct_recv.cpp             |   2 +-
 examples/cpp/engine/simple_recv.cpp             |   2 +-
 examples/cpp/queue_browser.cpp                  |   5 +-
 examples/cpp/selected_recv.cpp                  |   5 +-
 proton-c/bindings/cpp/CMakeLists.txt            |   3 +-
 .../bindings/cpp/include/proton/connection.hpp  |  16 +-
 .../bindings/cpp/include/proton/container.hpp   |  40 ++--
 .../bindings/cpp/include/proton/delivery.hpp    |   4 +-
 .../cpp/include/proton/delivery_mode.hpp        |  44 +++++
 .../cpp/include/proton/error_condition.hpp      |   6 +-
 .../bindings/cpp/include/proton/handler.hpp     |   3 +-
 proton-c/bindings/cpp/include/proton/link.hpp   |  89 ++++-----
 .../cpp/include/proton/link_options.hpp         | 192 -------------------
 .../bindings/cpp/include/proton/message.hpp     |   1 -
 .../bindings/cpp/include/proton/receiver.hpp    |  30 ++-
 .../cpp/include/proton/receiver_options.hpp     | 133 +++++++++++++
 proton-c/bindings/cpp/include/proton/sender.hpp |  30 ++-
 .../cpp/include/proton/sender_options.hpp       | 108 +++++++++++
 .../bindings/cpp/include/proton/session.hpp     |  19 +-
 .../bindings/cpp/include/proton/terminus.hpp    |  12 +-
 proton-c/bindings/cpp/src/connection.cpp        |   8 +-
 proton-c/bindings/cpp/src/container.cpp         |  11 +-
 proton-c/bindings/cpp/src/container_impl.cpp    |  16 +-
 proton-c/bindings/cpp/src/container_impl.hpp    |  16 +-
 proton-c/bindings/cpp/src/endpoint.cpp          |   4 +
 proton-c/bindings/cpp/src/engine_test.cpp       |   6 +-
 proton-c/bindings/cpp/src/link.cpp              |  33 ++--
 proton-c/bindings/cpp/src/link_options.cpp      | 189 ------------------
 proton-c/bindings/cpp/src/message.cpp           |   4 +-
 proton-c/bindings/cpp/src/messaging_adapter.cpp |  18 +-
 proton-c/bindings/cpp/src/receiver.cpp          |  20 ++
 proton-c/bindings/cpp/src/receiver_options.cpp  | 122 ++++++++++++
 proton-c/bindings/cpp/src/sender.cpp            |  18 ++
 proton-c/bindings/cpp/src/sender_options.cpp    | 102 ++++++++++
 proton-c/bindings/cpp/src/session.cpp           |  32 +++-
 tests/tools/apps/cpp/reactor_send.cpp           |   3 +-
 39 files changed, 807 insertions(+), 556 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/examples/cpp/broker.hpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.hpp b/examples/cpp/broker.hpp
index 8d08f2a..a89c948 100644
--- a/examples/cpp/broker.hpp
+++ b/examples/cpp/broker.hpp
@@ -203,10 +203,13 @@ class broker_handler : public proton::handler {
     }
 
     void remove_stale_consumers(proton::connection connection) {
-        proton::link_range r = connection.links();
-        for (proton::link_iterator l = r.begin(); l != r.end(); ++l) {
-            if (!!l->sender() && l->active())
-                unsubscribe(l->sender());
+        proton::session_range r1 = connection.sessions();
+        for (proton::session_iterator i1 = r1.begin(); i1 != r1.end(); ++i1) {
+            proton::sender_range r2 = i1->senders();
+            for (proton::sender_iterator i2 = r2.begin(); i2 != r2.end(); ++i2) {
+                if (i2->active())
+                    unsubscribe(*i2);
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/examples/cpp/client.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/client.cpp b/examples/cpp/client.cpp
index 5e4d529..6617a03 100644
--- a/examples/cpp/client.cpp
+++ b/examples/cpp/client.cpp
@@ -44,7 +44,8 @@ class client : public proton::handler {
     void on_container_start(proton::container &c) override {
         sender = c.open_sender(url);
         // Create a receiver with a dynamically chosen unique address.
-        receiver = sender.connection().open_receiver("", proton::link_options().dynamic_address(true));
+        // Note: the following signature is changing in Proton 0.13
+        receiver = sender.connection().open_receiver("", proton::receiver_options().dynamic_address(true));
     }
 
     void send_request() {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/examples/cpp/engine/client.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/engine/client.cpp b/examples/cpp/engine/client.cpp
index 2ef99b0..070133b 100644
--- a/examples/cpp/engine/client.cpp
+++ b/examples/cpp/engine/client.cpp
@@ -44,7 +44,8 @@ class client : public proton::handler {
 
     void on_connection_open(proton::connection &c) override {
         sender = c.open_sender(url.path());
-        receiver = c.open_receiver("", proton::link_options().dynamic_address(true));
+        // Note: the following signature is changing in Proton 0.13
+        receiver = c.open_receiver("", proton::receiver_options().dynamic_address(true));
     }
 
     void send_request() {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/examples/cpp/engine/direct_recv.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/engine/direct_recv.cpp b/examples/cpp/engine/direct_recv.cpp
index 6f220cd..48f4478 100644
--- a/examples/cpp/engine/direct_recv.cpp
+++ b/examples/cpp/engine/direct_recv.cpp
@@ -24,7 +24,7 @@
 #include "proton/delivery.hpp"
 #include "proton/io/socket.hpp"
 #include "proton/handler.hpp"
-#include "proton/link.hpp"
+#include "proton/receiver.hpp"
 #include "proton/url.hpp"
 #include "proton/value.hpp"
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/examples/cpp/engine/simple_recv.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/engine/simple_recv.cpp b/examples/cpp/engine/simple_recv.cpp
index a7df1d3..ffd80f9 100644
--- a/examples/cpp/engine/simple_recv.cpp
+++ b/examples/cpp/engine/simple_recv.cpp
@@ -24,7 +24,7 @@
 #include "proton/io/socket.hpp"
 #include "proton/url.hpp"
 #include "proton/handler.hpp"
-#include "proton/link.hpp"
+#include "proton/receiver.hpp"
 #include "proton/value.hpp"
 #include "proton/message_id.hpp"
 #include "proton/delivery.hpp"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/examples/cpp/queue_browser.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/queue_browser.cpp b/examples/cpp/queue_browser.cpp
index eef933b..d71a65c 100644
--- a/examples/cpp/queue_browser.cpp
+++ b/examples/cpp/queue_browser.cpp
@@ -24,7 +24,7 @@
 #include "proton/delivery.hpp"
 #include "proton/handler.hpp"
 #include "proton/url.hpp"
-#include "proton/link_options.hpp"
+#include "proton/receiver_options.hpp"
 
 #include <iostream>
 
@@ -39,7 +39,8 @@ class browser : public proton::handler {
 
     void on_container_start(proton::container &c) override {
         proton::connection conn = c.connect(url);
-        conn.open_receiver(url.path(), proton::link_options().browsing(true));
+        // Note: the following signature is changing in Proton 0.13
+        conn.open_receiver(url.path(), proton::receiver_options().browsing(true));
     }
 
     void on_message(proton::delivery &d, proton::message &m) override {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/examples/cpp/selected_recv.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/selected_recv.cpp b/examples/cpp/selected_recv.cpp
index 3ddb8c2..f02760f 100644
--- a/examples/cpp/selected_recv.cpp
+++ b/examples/cpp/selected_recv.cpp
@@ -23,7 +23,7 @@
 #include "proton/container.hpp"
 #include "proton/handler.hpp"
 #include "proton/url.hpp"
-#include "proton/link_options.hpp"
+#include "proton/receiver_options.hpp"
 
 #include <iostream>
 
@@ -38,7 +38,8 @@ class selected_recv : public proton::handler {
 
     void on_container_start(proton::container &c) override {
         proton::connection conn = c.connect(url);
-        conn.open_receiver(url.path(), proton::link_options().selector("colour = 'green'"));
+        // Note: the following signature is changing in Proton 0.13
+        conn.open_receiver(url.path(), proton::receiver_options().selector("colour = 'green'"));
     }
 
     void on_message(proton::delivery &d, proton::message &m) override {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt
index 070728f..f53c292 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -47,7 +47,6 @@ set(qpid-proton-cpp-source
   src/id_generator.cpp
   src/io/connection_engine.cpp
   src/link.cpp
-  src/link_options.cpp
   src/message.cpp
   src/messaging_adapter.cpp
   src/object.cpp
@@ -56,10 +55,12 @@ set(qpid-proton-cpp-source
   src/proton_handler.cpp
   src/reactor.cpp
   src/receiver.cpp
+  src/receiver_options.cpp
   src/reconnect_timer.cpp
   src/sasl.cpp
   src/scalar_base.cpp
   src/sender.cpp
+  src/sender_options.cpp
   src/session.cpp
   src/ssl.cpp
   src/ssl_domain.cpp

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/connection.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/connection.hpp b/proton-c/bindings/cpp/include/proton/connection.hpp
index 9a1feab..e562df7 100644
--- a/proton-c/bindings/cpp/include/proton/connection.hpp
+++ b/proton-c/bindings/cpp/include/proton/connection.hpp
@@ -24,7 +24,8 @@
 
 #include "proton/export.hpp"
 #include "proton/endpoint.hpp"
-#include "proton/link.hpp"
+#include "proton/sender.hpp"
+#include "proton/receiver.hpp"
 #include "proton/object.hpp"
 #include "proton/session.hpp"
 #include "proton/connection_options.hpp"
@@ -41,6 +42,10 @@ namespace io {
 class connection_engine;
 }
 
+namespace internal {
+class link;
+}
+
 /// A connection to a remote AMQP peer.
 class
 PN_CPP_CLASS_EXTERN connection : public internal::object<pn_connection_t>, public endpoint {
@@ -103,14 +108,11 @@ PN_CPP_CLASS_EXTERN connection : public internal::object<pn_connection_t>, publi
 
     /// Open a sender for `addr` on default_session().
     PN_CPP_EXTERN sender open_sender(const std::string &addr,
-                                     const link_options &opts = link_options());
+                                     const sender_options &opts = sender_options());
 
     /// Open a receiver for `addr` on default_session().
     PN_CPP_EXTERN receiver open_receiver(const std::string &addr,
-                                         const link_options &opts = link_options());
-
-    /// Return links on this connection matching the state mask.
-    PN_CPP_EXTERN link_range links() const;
+                                         const receiver_options &opts = receiver_options());
 
     /// Return sessions on this connection matching the state mask.
     PN_CPP_EXTERN session_range sessions() const;
@@ -128,7 +130,7 @@ PN_CPP_CLASS_EXTERN connection : public internal::object<pn_connection_t>, publi
     friend class container_impl;
     friend class transport;
     friend class session;
-    friend class link;
+    friend class internal::link;
     friend class transfer;
     friend class reactor;
     friend class proton_event;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/container.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/container.hpp b/proton-c/bindings/cpp/include/proton/container.hpp
index 7e0f0ee..22f4c08 100644
--- a/proton-c/bindings/cpp/include/proton/container.hpp
+++ b/proton-c/bindings/cpp/include/proton/container.hpp
@@ -27,7 +27,8 @@
 #include "proton/pn_unique_ptr.hpp"
 #include "proton/url.hpp"
 #include "proton/connection_options.hpp"
-#include "proton/link_options.hpp"
+#include "proton/sender_options.hpp"
+#include "proton/receiver_options.hpp"
 
 #include <string>
 
@@ -36,22 +37,23 @@ namespace proton {
 class connection;
 class acceptor;
 class handler;
-class sender;
-class receiver;
-class link;
 class handler;
 class task;
 class container_impl;
 
-/// A top-level container of connections, sessions, and links.
+namespace internal {
+class link;
+}
+
+/// A top-level container of connections, sessions, senders and receivers.
 ///
 /// A container gives a unique identity to each communicating peer. It
 /// is often a process-level object.
 
-/// It serves as an entry point to the API, allowing connections and
-/// links to be established. It can be supplied with an event handler
+/// It serves as an entry point to the API, allowing connections, senders
+/// and receivers to be established. It can be supplied with an event handler
 /// in order to intercept important messaging events, such as newly
-/// received messages or newly issued link credit for sending
+/// received messages or newly issued credit for sending
 /// messages.
 class container {
   public:
@@ -85,17 +87,17 @@ class container {
     PN_CPP_EXTERN void run();
 
     /// Open a connection to `url` and open a sender for `url.path()`.
-    /// Any supplied link or connection options will override the
+    /// Any supplied sender or connection options will override the
     /// container's template options.
     PN_CPP_EXTERN sender open_sender(const proton::url &,
-                                     const proton::link_options &l = proton::link_options(),
+                                     const proton::sender_options &o = proton::sender_options(),
                                      const connection_options &c = connection_options());
 
     /// Open a connection to `url` and open a receiver for
-    /// `url.path()`.  Any supplied link or connection options will
+    /// `url.path()`.  Any supplied receiver or connection options will
     /// override the container's template options.
     PN_CPP_EXTERN receiver open_receiver(const url &,
-                                         const proton::link_options &l = proton::link_options(),
+                                         const proton::receiver_options &o = proton::receiver_options(),
                                          const connection_options &c = connection_options());
 
     /// A unique identifier for the container.
@@ -119,11 +121,17 @@ class container {
     /// first open event on the connection.
     PN_CPP_EXTERN void server_connection_options(const connection_options &);
 
-    /// Copy the link options to a template applied to new links
+    /// Copy the sender options to a template applied to new senders
+    /// created and opened by this container.  They are applied before
+    /// the open event on the sender and may be overriden by sender
+    /// options in other methods.
+    PN_CPP_EXTERN void sender_options(const sender_options &);
+
+    /// Copy the receiver options to a template applied to new receivers
     /// created and opened by this container.  They are applied before
-    /// the open event on the link and may be overriden by link
+    /// the open event on the receiver and may be overriden by receiver
     /// options in other methods.
-    PN_CPP_EXTERN void link_options(const link_options &);
+    PN_CPP_EXTERN void receiver_options(const receiver_options &);
 
     /// @cond INTERNAL
   private:
@@ -133,8 +141,8 @@ class container {
     internal::pn_unique_ptr<container_impl> impl_;
 
     friend class connector;
-    friend class link;
     friend class messaging_adapter;
+    friend class internal::link;
     /// @endcond
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/delivery.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/delivery.hpp b/proton-c/bindings/cpp/include/proton/delivery.hpp
index 0fe6c90..49f68af 100644
--- a/proton-c/bindings/cpp/include/proton/delivery.hpp
+++ b/proton-c/bindings/cpp/include/proton/delivery.hpp
@@ -34,7 +34,7 @@ namespace proton {
 class receiver;
 
 /// A message transfer.  Every delivery exists within the context of a
-/// proton::link.  A delivery attempt can fail. As a result, a
+/// proton::receiver.  A delivery attempt can fail. As a result, a
 /// particular message may correspond to multiple deliveries.
 class delivery : public transfer {
     /// @cond INTERNAL
@@ -68,7 +68,7 @@ class delivery : public transfer {
     /// Check if a delivery is readable.
     ///
     /// A delivery is considered readable if it is the current
-    /// delivery on an incoming link.
+    /// delivery on a receiver.
     bool readable() const;
 
   friend class message;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/delivery_mode.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/delivery_mode.hpp b/proton-c/bindings/cpp/include/proton/delivery_mode.hpp
new file mode 100644
index 0000000..677ce7e
--- /dev/null
+++ b/proton-c/bindings/cpp/include/proton/delivery_mode.hpp
@@ -0,0 +1,44 @@
+#ifndef PROTON_CPP_DELIVERY_MODE_H
+#define PROTON_CPP_DELIVERY_MODE_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+namespace proton {
+
+/// The message delivery policy to establish when opening a link.
+enum delivery_mode {
+    // No set policy.  The application must settle messages itself
+    // according to its own policy.
+    DELIVERY_MODE_NONE = 0,
+    // Outgoing messages are settled immediately by the link.
+    // There are no duplicates.
+    AT_MOST_ONCE,
+    // The receiver settles the delivery first with an
+    // accept/reject/release disposition.  The sender waits to
+    // settle until after the disposition notification is
+    // received.
+    AT_LEAST_ONCE
+};
+
+}
+
+#endif // PROTON_CPP_DELIVERY_MODE_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/error_condition.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/error_condition.hpp b/proton-c/bindings/cpp/include/proton/error_condition.hpp
index 0da428d..0b9fa9f 100644
--- a/proton-c/bindings/cpp/include/proton/error_condition.hpp
+++ b/proton-c/bindings/cpp/include/proton/error_condition.hpp
@@ -34,6 +34,10 @@ struct pn_condition_t;
 
 namespace proton {
 
+namespace internal {
+class link;
+}
+
 /// Describes an endpoint error state.
 class error_condition {
     /// @cond INTERNAL
@@ -83,7 +87,7 @@ class error_condition {
     friend class transport;
     friend class connection;
     friend class session;
-    friend class link;
+    friend class internal::link;
     /// @endcond
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/handler.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/handler.hpp b/proton-c/bindings/cpp/include/proton/handler.hpp
index ff50b37..ef87ff3 100644
--- a/proton-c/bindings/cpp/include/proton/handler.hpp
+++ b/proton-c/bindings/cpp/include/proton/handler.hpp
@@ -149,7 +149,8 @@ PN_CPP_CLASS_EXTERN handler
     friend class container;
     friend class io::connection_engine;
     friend class connection_options;
-    friend class link_options;
+    friend class receiver_options;
+    friend class sender_options;
     /// @endcond
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/link.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/link.hpp b/proton-c/bindings/cpp/include/proton/link.hpp
index a9c5edc..d7386c4 100644
--- a/proton-c/bindings/cpp/include/proton/link.hpp
+++ b/proton-c/bindings/cpp/include/proton/link.hpp
@@ -26,9 +26,9 @@
 #include <proton/export.hpp>
 #include <proton/message.hpp>
 #include <proton/terminus.hpp>
-
 #include <proton/object.hpp>
-#include <proton/link_options.hpp>
+#include <proton/sender_options.hpp>
+#include <proton/receiver_options.hpp>
 
 #include <proton/types.h>
 
@@ -40,17 +40,29 @@ class sender;
 class receiver;
 class error_condition;
 class link_context;
+class proton_event;
+class messaging_adapter;
+class proton_handler;
+class delivery;
+class connection;
+class container;
+class session;
+class sender_iterator;
+class receiver_iterator;
+
+namespace internal {
 
 /// A named channel for sending or receiving messages.  It is the base
 /// class for sender and receiver.
 class
-PN_CPP_CLASS_EXTERN link : public internal::object<pn_link_t> , public endpoint {
+PN_CPP_CLASS_EXTERN link : public object<pn_link_t> , public endpoint {
+  private:
     /// @cond INTERNAL
-    link(pn_link_t* l) : internal::object<pn_link_t>(l) {}
+    link(pn_link_t* l) : object<pn_link_t>(l) {}
     /// @endcond
 
   public:
-    link() : internal::object<pn_link_t>(0) {}
+    link() : object<pn_link_t>(0) {}
 
     // Endpoint behaviours
     PN_CPP_EXTERN bool uninitialized() const;
@@ -59,10 +71,6 @@ PN_CPP_CLASS_EXTERN link : public internal::object<pn_link_t> , public endpoint
 
     PN_CPP_EXTERN class error_condition error() const;
 
-    /// Locally open the link.  The operation is not complete till
-    /// handler::on_link_open.
-    PN_CPP_EXTERN void open(const link_options &opts = link_options());
-
     /// Locally close the link.  The operation is not complete till
     /// handler::on_link_close.
     PN_CPP_EXTERN void close();
@@ -131,57 +139,42 @@ PN_CPP_CLASS_EXTERN link : public internal::object<pn_link_t> , public endpoint
     /// Session that owns this link.
     PN_CPP_EXTERN class session session() const;
 
-    ///@cond INTERNAL
-    /// XXX local versus remote, mutability
-    /// XXX - local_sender_settle_mode and local_receiver_settle_mode
-    PN_CPP_EXTERN link_options::sender_settle_mode sender_settle_mode();
-    PN_CPP_EXTERN link_options::receiver_settle_mode receiver_settle_mode();
-    PN_CPP_EXTERN link_options::sender_settle_mode remote_sender_settle_mode();
-    PN_CPP_EXTERN link_options::receiver_settle_mode remote_receiver_settle_mode();
-    ///@endcond
-
   private:
-    // Used by link_options
+    /// Initiate the AMQP attach frame.  The operation is not complete till
+    /// handler::on_link_open.
+    void attach();
+
+    // Used by sender/receiver options
     void handler(proton_handler &);
     void detach_handler();
-    void sender_settle_mode(link_options::sender_settle_mode);
-    void receiver_settle_mode(link_options::receiver_settle_mode);
+    void sender_settle_mode(sender_options::sender_settle_mode);
+    void receiver_settle_mode(receiver_options::receiver_settle_mode);
     // Used by message to decode message from a delivery
     ssize_t recv(char* buffer, size_t size);
     bool advance();
     link_context &context();
 
-  friend class connection;
-  friend class transfer;
-  friend class receiver;
-  friend class sender;
-  friend class message;
-  friend class proton_event;
-  friend class link_iterator;
-  friend class link_options;
-  friend class messaging_adapter;
-};
-
-/// An iterator for links.
-class link_iterator : public internal::iter_base<link, link_iterator> {
-  public:
     ///@cond INTERNAL
-    explicit link_iterator(link l = 0, pn_session_t* s = 0) :
-        internal::iter_base<link, link_iterator>(l), session_(s) {}
+    /// XXX local versus remote, mutability
+    /// XXX - local_sender_settle_mode and local_receiver_settle_mode
+    PN_CPP_EXTERN sender_options::sender_settle_mode sender_settle_mode();
+    PN_CPP_EXTERN receiver_options::receiver_settle_mode receiver_settle_mode();
+    PN_CPP_EXTERN sender_options::sender_settle_mode remote_sender_settle_mode();
+    PN_CPP_EXTERN receiver_options::receiver_settle_mode remote_receiver_settle_mode();
     ///@endcond
-    /// Advance
-    PN_CPP_EXTERN link_iterator operator++();
 
-  private:
-    pn_session_t* session_;
+  friend class proton::delivery;
+  friend class proton::sender;
+  friend class proton::receiver;
+  friend class proton::sender_options;
+  friend class proton::receiver_options;
+  friend class proton::sender_iterator;
+  friend class proton::receiver_iterator;
+  friend class proton::message;
+  friend class proton::proton_event;
+  friend class proton::messaging_adapter;
 };
 
-/// A range of links.
-typedef internal::iter_range<link_iterator> link_range;
-
-}
-
-#include <proton/sender.hpp>
-#include <proton/receiver.hpp>
+}}
 
 #endif // PROTON_CPP_LINK_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/link_options.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/link_options.hpp b/proton-c/bindings/cpp/include/proton/link_options.hpp
deleted file mode 100644
index 7f70c4a..0000000
--- a/proton-c/bindings/cpp/include/proton/link_options.hpp
+++ /dev/null
@@ -1,192 +0,0 @@
-#ifndef PROTON_CPP_LINK_OPTIONS_H
-#define PROTON_CPP_LINK_OPTIONS_H
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "proton/config.hpp"
-#include "proton/export.hpp"
-#include "proton/pn_unique_ptr.hpp"
-#include "proton/types.hpp"
-#include "proton/terminus.hpp"
-
-#include <vector>
-#include <string>
-
-namespace proton {
-
-class proton_handler;
-class link;
-
-/// Options for creating a link.
-///
-/// Options can be "chained" like this:
-///
-/// @code
-/// l = container.create_sender(url, link_options().handler(h).browsing(true));
-/// @endcode
-///
-/// You can also create an options object with common settings and use
-/// it as a base for different connections that have mostly the same
-/// settings:
-///
-/// @code
-/// link_options opts;
-/// opts.browsing(true);
-/// l1 = container.open_sender(url1, opts.handler(h1));
-/// c2 = container.open_receiver(url2, opts.handler(h2));
-/// @endcode
-///
-/// Normal value semantics: copy or assign creates a separate copy of
-/// the options.
-class link_options {
-  public:
-    /// The message delivery policy to establish when opening a link.
-    enum delivery_mode {
-        // No set policy.  The application must settle messages itself
-        // according to its own policy.
-        DELIVERY_MODE_NONE = 0,
-        // Outgoing messages are settled immediately by the link.
-        // There are no duplicates.
-        AT_MOST_ONCE,
-        // The receiver settles the delivery first with an
-        // accept/reject/release disposition.  The sender waits to
-        // settle until after the disposition notification is
-        // received.
-        AT_LEAST_ONCE
-    };
-
-    /// Sender settlement behaviour for a link.
-    enum sender_settle_mode {
-        UNSETTLED = PN_SND_UNSETTLED,
-        SETTLED = PN_SND_SETTLED,
-        MIXED = PN_SND_MIXED
-    };
-
-    /// @cond INTERNAL
-    /// XXX discuss the names
-    /// Receiver settlement behaviour for a link.
-    enum receiver_settle_mode {
-        SETTLE_ALWAYS = PN_RCV_FIRST,
-        SETTLE_SECOND = PN_RCV_SECOND
-    };
-    /// @endcond
-
-    /// The lifetime of dynamically created nodes.
-    enum lifetime_policy {
-        // The policy is unspecified.
-        LIFETIME_UNSPECIFIED = 0,
-        // The lifetime of the dynamic node is scoped to lifetime of
-        // the creating link.
-        DELETE_ON_CLOSE = 0x2B,
-        // The node will be deleted when it is neither the source nor
-        // the target of any link.
-        DELETE_ON_NO_LINKS = 0x2C,
-        // The node will be deleted when the creating link no longer
-        // exists and no messages remain at the node.
-        DELETE_ON_NO_MESSAGES = 0x2D,
-        // The node will be deleted when there are no links which have
-        // this node as their source or target, and there remain no
-        // messages at the node.
-        DELETE_ON_NO_LINKS_OR_MESSAGES = 0x2E
-    };
-
-    /// Create an empty set of options.
-    PN_CPP_EXTERN link_options();
-
-    /// Copy options.
-    PN_CPP_EXTERN link_options(const link_options&);
-
-    PN_CPP_EXTERN ~link_options();
-
-    /// Copy options.
-    PN_CPP_EXTERN link_options& operator=(const link_options&);
-
-    /// Set a handler for events scoped to the link.  If NULL,
-    /// link-scoped events on the link are discarded.
-    PN_CPP_EXTERN link_options& handler(class handler *);
-
-    /// Receiver-only option to specify whether messages are browsed
-    /// or consumed.  Setting browsing to true is equivalent to
-    /// setting distribution_mode(COPY).  Setting browsing to false is
-    /// equivalent to setting distribution_mode(MOVE).
-    PN_CPP_EXTERN link_options& browsing(bool);
-
-    /// Set the distribution mode for message transfer.
-    PN_CPP_EXTERN link_options& distribution_mode(enum terminus::distribution_mode);
-
-    /// Receiver-only option to create a durable subsription on the
-    /// receiver.  Equivalent to setting the terminus durability to
-    /// terminus::DELIVERIES and the expiry policy to
-    /// terminus::EXPIRE_NEVER.
-    PN_CPP_EXTERN link_options& durable_subscription(bool);
-
-    /// Set the delivery mode on the link.
-    PN_CPP_EXTERN link_options& delivery_mode(delivery_mode);
-
-    /// Request a dynamically generated node at the peer.
-    PN_CPP_EXTERN link_options& dynamic_address(bool);
-
-    /// Set the lifetime policy for a receiver to a dynamically
-    /// created node.
-    PN_CPP_EXTERN link_options& lifetime_policy(lifetime_policy);
-
-    /// Set the local address for the link.
-    PN_CPP_EXTERN link_options& local_address(const std::string &addr);
-
-    /// Automatically accept inbound messages that aren't otherwise
-    /// released, rejected or modified (default value:true).
-    PN_CPP_EXTERN link_options& auto_accept(bool);
-
-    /// Automatically settle messages (default value: true).
-    PN_CPP_EXTERN link_options& auto_settle(bool);
-
-    /// Set automated flow control to pre-fetch this many messages
-    /// (default value:10).  Set to zero to disable automatic credit
-    /// replenishing.
-    PN_CPP_EXTERN link_options& credit_window(int);
-
-    /// @cond INTERNAL
-    /// XXX need to discuss spec issues, jms versus amqp filters
-    ///
-    /// Set a selector on the receiver to str.  This sets a single
-    /// registered filter on the link of type
-    /// apache.org:selector-filter with value str.
-    PN_CPP_EXTERN link_options& selector(const std::string &str);
-    /// @endcond
-
-    /// @cond INTERNAL
-  private:
-    void apply(link&) const;
-    proton_handler* handler() const;
-    PN_CPP_EXTERN void update(const link_options& other);
-
-    class impl;
-    internal::pn_unique_ptr<impl> impl_;
-
-    friend class link;
-    friend class container_impl;
-    /// @endcond
-};
-
-}
-
-#endif // PROTON_CPP_LINK_OPTIONS_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/message.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/message.hpp b/proton-c/bindings/cpp/include/proton/message.hpp
index 3bf345a..b0ea95c 100644
--- a/proton-c/bindings/cpp/include/proton/message.hpp
+++ b/proton-c/bindings/cpp/include/proton/message.hpp
@@ -38,7 +38,6 @@ struct pn_message_t;
 
 namespace proton {
 
-class link;
 class delivery;
 class message_id;
 class annotation_key;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/receiver.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/receiver.hpp b/proton-c/bindings/cpp/include/proton/receiver.hpp
index ade17a2..8123687 100644
--- a/proton-c/bindings/cpp/include/proton/receiver.hpp
+++ b/proton-c/bindings/cpp/include/proton/receiver.hpp
@@ -34,22 +34,44 @@ namespace proton {
 
 /// A link for receiving messages.
 class
-PN_CPP_CLASS_EXTERN receiver : public link {
+PN_CPP_CLASS_EXTERN receiver : public internal::link {
     /// @cond INTERNAL
-    receiver(pn_link_t* r) : link(r) {}
+    receiver(pn_link_t* r) : internal::link(r) {}
     /// @endcond
 
   public:
-    receiver() : link(0) {}
+    receiver() : internal::link(0) {}
+
+    /// Locally open the receiver.  The operation is not complete till
+    /// handler::on_receiver_open.
+    PN_CPP_EXTERN void open(const receiver_options &opts = receiver_options());
 
   /// @cond INTERNAL
-  friend class link;
+  friend class internal::link;
   friend class delivery;
   friend class session;
   friend class messaging_adapter;
+  friend class receiver_iterator;
   /// @endcond
 };
 
+class receiver_iterator : public internal::iter_base<receiver, receiver_iterator> {
+  public:
+    ///@cond INTERNAL
+    explicit receiver_iterator(receiver r = 0, pn_session_t* s = 0) :
+        iter_base<receiver, receiver_iterator>(r), session_(s) {}
+    ///@endcond
+    /// Advance
+    PN_CPP_EXTERN receiver_iterator operator++();
+
+  private:
+    pn_session_t* session_;
+};
+
+/// A range of receivers.
+typedef internal::iter_range<receiver_iterator> receiver_range;
+
+
 }
 
 #endif // PROTON_CPP_RECEIVER_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/receiver_options.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/receiver_options.hpp b/proton-c/bindings/cpp/include/proton/receiver_options.hpp
new file mode 100644
index 0000000..e95147d
--- /dev/null
+++ b/proton-c/bindings/cpp/include/proton/receiver_options.hpp
@@ -0,0 +1,133 @@
+#ifndef PROTON_CPP_RECEIVER_OPTIONS_H
+#define PROTON_CPP_RECEIVER_OPTIONS_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "proton/config.hpp"
+#include "proton/export.hpp"
+#include "proton/pn_unique_ptr.hpp"
+#include "proton/types.hpp"
+#include "proton/delivery_mode.hpp"
+#include "proton/terminus.hpp"
+
+#include <vector>
+#include <string>
+
+namespace proton {
+
+class proton_handler;
+class receiver;
+
+/// Options for creating a receiver.
+///
+/// Options can be "chained" like this:
+///
+/// @code
+/// l = container.create_receiver(url, receiver_options().handler(h).auto_settle(true));
+/// @endcode
+///
+/// You can also create an options object with common settings and use
+/// it as a base for different connections that have mostly the same
+/// settings:
+///
+/// @code
+/// receiver_options opts;
+/// opts.auto_settle(true);
+/// c2 = container.open_receiver(url2, opts.handler(h2));
+/// @endcode
+///
+/// Normal value semantics: copy or assign creates a separate copy of
+/// the options.
+class receiver_options {
+  public:
+    /// @cond INTERNAL
+    /// XXX discuss the names
+    /// Receiver settlement behaviour.
+    enum receiver_settle_mode {
+        SETTLE_ALWAYS = PN_RCV_FIRST,
+        SETTLE_SECOND = PN_RCV_SECOND
+    };
+    /// @endcond
+
+    /// Create an empty set of options.
+    PN_CPP_EXTERN receiver_options();
+
+    /// Copy options.
+    PN_CPP_EXTERN receiver_options(const receiver_options&);
+
+    PN_CPP_EXTERN ~receiver_options();
+
+    /// Copy options.
+    PN_CPP_EXTERN receiver_options& operator=(const receiver_options&);
+
+    /// Set a handler for events scoped to the receiver.  If NULL,
+    /// receiver-scoped events are discarded.
+    PN_CPP_EXTERN receiver_options& handler(class handler *);
+
+    /// Set the delivery mode on the receiver.
+    PN_CPP_EXTERN receiver_options& delivery_mode(delivery_mode);
+
+    /// @cond INTERNAL
+    /// XXX dynamic_address, browsing, selector, all to be moved to a new options mechanism
+    /// Request a dynamically generated node at the peer.
+    PN_CPP_EXTERN receiver_options& dynamic_address(bool);
+    PN_CPP_EXTERN receiver_options& browsing(bool);
+    /// XXX need to discuss spec issues, jms versus amqp filters
+    ///
+    /// Set a selector on the receiver to str.  This sets a single
+    /// registered filter on the link of type
+    /// apache.org:selector-filter with value str.
+    PN_CPP_EXTERN receiver_options& selector(const std::string&){return *this;};
+    /// @endcond
+
+    /// Automatically accept inbound messages that aren't otherwise
+    /// released, rejected or modified (default value:true).
+    PN_CPP_EXTERN receiver_options& auto_accept(bool);
+
+    /// Automatically settle messages (default value: true).
+    PN_CPP_EXTERN receiver_options& auto_settle(bool);
+
+    /// @cond INTERNAL
+    /// XXX moving to ???
+    /// Set automated flow control to pre-fetch this many messages
+    /// (default value:10).  Set to zero to disable automatic credit
+    /// replenishing.
+    PN_CPP_EXTERN receiver_options& credit_window(int);
+    /// @endcond
+
+    /// @cond INTERNAL
+  private:
+    void apply(receiver &) const;
+    proton_handler* handler() const;
+    PN_CPP_EXTERN void update(const receiver_options& other);
+
+    class impl;
+    internal::pn_unique_ptr<impl> impl_;
+
+    friend class receiver;
+    friend class container_impl;
+    /// @endcond
+};
+
+}
+
+#endif // PROTON_CPP_RECEIVER_OPTIONS_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/sender.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/sender.hpp b/proton-c/bindings/cpp/include/proton/sender.hpp
index 74b1303..0c7666a 100644
--- a/proton-c/bindings/cpp/include/proton/sender.hpp
+++ b/proton-c/bindings/cpp/include/proton/sender.hpp
@@ -37,26 +37,48 @@ class tracker;
 
 /// A link for sending messages.
 class
-PN_CPP_CLASS_EXTERN sender : public link
+PN_CPP_CLASS_EXTERN sender : public internal::link
 {
     /// @cond INTERNAL
-    sender(pn_link_t* s) : link(s) {}
+    sender(pn_link_t* s) : internal::link(s) {}
     /// @endcond
 
   public:
-    sender() : link(0) {}
+    sender() : internal::link(0) {}
+
+    /// Locally open the sender.  The operation is not complete till
+    /// handler::on_sender_open.
+    PN_CPP_EXTERN void open(const sender_options &opts = sender_options());
 
     /// Send a message on the link.
     PN_CPP_EXTERN tracker send(const message &m);
 
   /// @cond INTERNAL
-  friend class link;
+  friend class internal::link;
   friend class tracker;
   friend class session;
   friend class messaging_adapter;
+  friend class sender_iterator;
   /// @endcond
 };
 
+class sender_iterator : public internal::iter_base<sender, sender_iterator> {
+  public:
+    ///@cond INTERNAL
+    explicit sender_iterator(sender snd = 0, pn_session_t* s = 0) :
+        iter_base<sender, sender_iterator>(snd), session_(s) {}
+    ///@endcond
+    /// Advance
+    PN_CPP_EXTERN sender_iterator operator++();
+
+  private:
+    pn_session_t* session_;
+};
+
+/// A range of senders.
+typedef internal::iter_range<sender_iterator> sender_range;
+
+
 }
 
 #endif // PROTON_CPP_SENDER_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/sender_options.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/sender_options.hpp b/proton-c/bindings/cpp/include/proton/sender_options.hpp
new file mode 100644
index 0000000..84084a4
--- /dev/null
+++ b/proton-c/bindings/cpp/include/proton/sender_options.hpp
@@ -0,0 +1,108 @@
+#ifndef PROTON_CPP_SENDER_OPTIONS_H
+#define PROTON_CPP_SENDER_OPTIONS_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "proton/config.hpp"
+#include "proton/export.hpp"
+#include "proton/pn_unique_ptr.hpp"
+#include "proton/types.hpp"
+#include "proton/delivery_mode.hpp"
+#include "proton/terminus.hpp"
+
+#include <vector>
+#include <string>
+
+namespace proton {
+
+class proton_handler;
+class sender;
+
+/// Options for creating a sender.
+///
+/// Options can be "chained" like this:
+///
+/// @code
+/// l = container.create_sender(url, sender_options().handler(h).auto_settle(false));
+/// @endcode
+///
+/// You can also create an options object with common settings and use
+/// it as a base for different connections that have mostly the same
+/// settings:
+///
+/// @code
+/// sender_options opts;
+/// opts.browsing(true);
+/// l1 = container.open_sender(url1, opts.handler(h1));
+/// c2 = container.open_receiver(url2, opts.handler(h2));
+/// @endcode
+///
+/// Normal value semantics: copy or assign creates a separate copy of
+/// the options.
+class sender_options {
+  public:
+    /// Sender settlement behaviour.
+    enum sender_settle_mode {
+        UNSETTLED = PN_SND_UNSETTLED,
+        SETTLED = PN_SND_SETTLED,
+        MIXED = PN_SND_MIXED
+    };
+
+    /// Create an empty set of options.
+    PN_CPP_EXTERN sender_options();
+
+    /// Copy options.
+    PN_CPP_EXTERN sender_options(const sender_options&);
+
+    PN_CPP_EXTERN ~sender_options();
+
+    /// Copy options.
+    PN_CPP_EXTERN sender_options& operator=(const sender_options&);
+
+    /// Set a handler for events scoped to the sender.  If NULL,
+    /// sender-scoped events are discarded.
+    PN_CPP_EXTERN sender_options& handler(class handler *);
+
+    /// Set the delivery mode on the sender.
+    PN_CPP_EXTERN sender_options& delivery_mode(delivery_mode);
+
+    /// Automatically settle messages (default value: true).
+    PN_CPP_EXTERN sender_options& auto_settle(bool);
+
+
+    /// @cond INTERNAL
+  private:
+    void apply(sender&) const;
+    proton_handler* handler() const;
+    PN_CPP_EXTERN void update(const sender_options& other);
+
+    class impl;
+    internal::pn_unique_ptr<impl> impl_;
+
+    friend class sender;
+    friend class container_impl;
+    /// @endcond
+};
+
+}
+
+#endif // PROTON_CPP_SENDER_OPTIONS_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/session.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/session.hpp b/proton-c/bindings/cpp/include/proton/session.hpp
index 5321221..df4d153 100644
--- a/proton-c/bindings/cpp/include/proton/session.hpp
+++ b/proton-c/bindings/cpp/include/proton/session.hpp
@@ -24,7 +24,8 @@
 
 #include "proton/export.hpp"
 #include "proton/endpoint.hpp"
-#include "proton/link.hpp"
+#include "proton/receiver.hpp"
+#include "proton/sender.hpp"
 
 #include "proton/types.h"
 #include "proton/link.h"
@@ -38,7 +39,7 @@ namespace proton {
 class container;
 class handler;
 
-/// A container of links.
+/// A container of senders and receivers.
 class
 PN_CPP_CLASS_EXTERN session : public internal::object<pn_session_t>, public endpoint
 {
@@ -79,15 +80,19 @@ PN_CPP_CLASS_EXTERN session : public internal::object<pn_session_t>, public endp
     PN_CPP_EXTERN class connection connection() const;
 
     /// Open a sender for `addr`.
-    PN_CPP_EXTERN sender open_sender(const std::string &addr, const link_options &opts = link_options());
+    PN_CPP_EXTERN sender open_sender(const std::string &addr, const sender_options &opts = sender_options());
 
     /// Open a receiver for `addr`.
-    PN_CPP_EXTERN receiver open_receiver(const std::string &addr, const link_options &opts = link_options());
+    PN_CPP_EXTERN receiver open_receiver(const std::string &addr, const receiver_options &opts = receiver_options());
 
-    /// Return the links on this session matching the state mask.
-    PN_CPP_EXTERN link_range links() const;
+    /// Return the senders on this session.
+    PN_CPP_EXTERN sender_range senders() const;
 
-  friend class link_iterator;
+    /// Return the receivers on this session.
+    PN_CPP_EXTERN receiver_range receivers() const;
+
+  friend class sender_iterator;
+  friend class receiver_iterator;
   friend class session_iterator;
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/include/proton/terminus.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/terminus.hpp b/proton-c/bindings/cpp/include/proton/terminus.hpp
index 84ad27c..b0135a2 100644
--- a/proton-c/bindings/cpp/include/proton/terminus.hpp
+++ b/proton-c/bindings/cpp/include/proton/terminus.hpp
@@ -31,7 +31,9 @@
 
 namespace proton {
 
+namespace internal {
 class link;
+}
 
 /// One end of a link, either a source or a target.
 ///
@@ -120,19 +122,19 @@ class terminus {
     PN_CPP_EXTERN void dynamic(bool);
 
     /// Obtain a reference to the AMQP dynamic node properties for the
-    /// terminus.  See also link_options::lifetime_policy.
+    /// terminus.  See also lifetime_policy.
     PN_CPP_EXTERN value& node_properties();
 
     /// Obtain a reference to the AMQP dynamic node properties for the
-    /// terminus.  See also link_options::lifetime_policy.
+    /// terminus.  See also lifetime_policy.
     PN_CPP_EXTERN const value& node_properties() const;
 
     /// Obtain a reference to the AMQP filter set for the terminus.
-    /// See also link_options::selector.
+    /// See also selector.
     PN_CPP_EXTERN value& filter();
 
     /// Obtain a reference to the AMQP filter set for the terminus.
-    /// See also link_options::selector.
+    /// See also selector.
     PN_CPP_EXTERN const value& filter() const;
 
     /// @cond INTERNAL
@@ -140,7 +142,7 @@ class terminus {
     pn_terminus_t* object_;
     value properties_, filter_;
 
-    friend class link;
+    friend class internal::link;
     /// @endcond
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/connection.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection.cpp b/proton-c/bindings/cpp/src/connection.cpp
index b1d296f..4100843 100644
--- a/proton-c/bindings/cpp/src/connection.cpp
+++ b/proton-c/bindings/cpp/src/connection.cpp
@@ -75,10 +75,6 @@ container& connection::container() const {
     return container_context::get(r);
 }
 
-link_range connection::links() const {
-    return link_range(link_iterator(pn_link_head(pn_object(), 0)));
-}
-
 session_range connection::sessions() const {
     return session_range(session_iterator(pn_session_head(pn_object(), 0)));
 }
@@ -97,11 +93,11 @@ session connection::default_session() {
     return ctx.default_session;
 }
 
-sender connection::open_sender(const std::string &addr, const link_options &opts) {
+sender connection::open_sender(const std::string &addr, const sender_options &opts) {
     return default_session().open_sender(addr, opts);
 }
 
-receiver connection::open_receiver(const std::string &addr, const link_options &opts)
+receiver connection::open_receiver(const std::string &addr, const receiver_options &opts)
 {
     return default_session().open_receiver(addr, opts);
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/container.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container.cpp b/proton-c/bindings/cpp/src/container.cpp
index fb09017..de55655 100644
--- a/proton-c/bindings/cpp/src/container.cpp
+++ b/proton-c/bindings/cpp/src/container.cpp
@@ -21,7 +21,8 @@
 #include "proton/container.hpp"
 
 #include "proton/connection.hpp"
-#include "proton/link_options.hpp"
+#include "proton/sender_options.hpp"
+#include "proton/receiver_options.hpp"
 #include "proton/session.hpp"
 #include "proton/acceptor.hpp"
 #include "proton/error.hpp"
@@ -62,11 +63,11 @@ std::string container::id() const { return impl_->id_; }
 
 void container::run() { impl_->reactor_.run(); }
 
-sender container::open_sender(const proton::url &url, const proton::link_options &lo, const connection_options &co) {
+sender container::open_sender(const proton::url &url, const proton::sender_options &lo, const connection_options &co) {
     return impl_->open_sender(url, lo, co);
 }
 
-receiver container::open_receiver(const proton::url &url, const proton::link_options &lo, const connection_options &co) {
+receiver container::open_receiver(const proton::url &url, const proton::receiver_options &lo, const connection_options &co) {
     return impl_->open_receiver(url, lo, co);
 }
 
@@ -80,6 +81,8 @@ void container::client_connection_options(const connection_options &o) { impl_->
 
 void container::server_connection_options(const connection_options &o) { impl_->server_connection_options(o); }
 
-void container::link_options(const class link_options &o) { impl_->link_options(o); }
+void container::sender_options(const class sender_options &o) { impl_->sender_options(o); }
+
+void container::receiver_options(const class receiver_options &o) { impl_->receiver_options(o); }
 
 } // namespace proton

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container_impl.cpp b/proton-c/bindings/cpp/src/container_impl.cpp
index 1848734..89cfd89 100644
--- a/proton-c/bindings/cpp/src/container_impl.cpp
+++ b/proton-c/bindings/cpp/src/container_impl.cpp
@@ -158,8 +158,8 @@ connection container_impl::connect(const proton::url &url, const connection_opti
     return conn;
 }
 
-sender container_impl::open_sender(const proton::url &url, const proton::link_options &o1, const connection_options &o2) {
-    proton::link_options lopts(link_options_);
+sender container_impl::open_sender(const proton::url &url, const proton::sender_options &o1, const connection_options &o2) {
+    proton::sender_options lopts(sender_options_);
     lopts.update(o1);
     connection_options copts(client_connection_options_);
     copts.update(o2);
@@ -168,8 +168,8 @@ sender container_impl::open_sender(const proton::url &url, const proton::link_op
     return conn.default_session().open_sender(path, lopts);
 }
 
-receiver container_impl::open_receiver(const proton::url &url, const proton::link_options &o1, const connection_options &o2) {
-    proton::link_options lopts(link_options_);
+receiver container_impl::open_receiver(const proton::url &url, const proton::receiver_options &o1, const connection_options &o2) {
+    proton::receiver_options lopts(receiver_options_);
     lopts.update(o1);
     connection_options copts(client_connection_options_);
     copts.update(o2);
@@ -211,8 +211,12 @@ void container_impl::server_connection_options(const connection_options &opts) {
     server_connection_options_ = opts;
 }
 
-void container_impl::link_options(const proton::link_options &opts) {
-    link_options_ = opts;
+void container_impl::sender_options(const proton::sender_options &opts) {
+    sender_options_ = opts;
+}
+
+void container_impl::receiver_options(const proton::receiver_options &opts) {
+    receiver_options_ = opts;
 }
 
 void container_impl::configure_server_connection(connection &c) {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/container_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container_impl.hpp b/proton-c/bindings/cpp/src/container_impl.hpp
index 05e2058..8d68c35 100644
--- a/proton-c/bindings/cpp/src/container_impl.hpp
+++ b/proton-c/bindings/cpp/src/container_impl.hpp
@@ -28,7 +28,8 @@
 #include "proton/duration.hpp"
 #include "proton/export.hpp"
 #include "proton/handler.hpp"
-#include "proton/link.hpp"
+#include "proton/sender.hpp"
+#include "proton/receiver.hpp"
 #include "proton/reactor.h"
 #include "reactor.hpp"
 #include "proton_handler.hpp"
@@ -51,8 +52,8 @@ class container_impl
     container_impl(container&, messaging_adapter*, const std::string& id);
     ~container_impl();
     connection connect(const url&, const connection_options&);
-    sender open_sender(const url&, const proton::link_options &, const connection_options &);
-    receiver open_receiver(const url&, const proton::link_options &, const connection_options &);
+    sender open_sender(const url&, const proton::sender_options &, const connection_options &);
+    receiver open_receiver(const url&, const proton::receiver_options &, const connection_options &);
     class acceptor listen(const url&, const connection_options &);
     duration timeout();
     void timeout(duration timeout);
@@ -60,8 +61,10 @@ class container_impl
     const connection_options& client_connection_options() { return client_connection_options_; }
     void server_connection_options(const connection_options &);
     const connection_options& server_connection_options() { return server_connection_options_; }
-    void link_options(const proton::link_options&);
-    const proton::link_options& link_options() { return link_options_; }
+    void sender_options(const proton::sender_options&);
+    const proton::sender_options& sender_options() { return sender_options_; }
+    void receiver_options(const proton::receiver_options&);
+    const proton::receiver_options& receiver_options() { return receiver_options_; }
 
     void configure_server_connection(connection &c);
     task schedule(int delay, proton_handler *h);
@@ -80,7 +83,8 @@ class container_impl
     id_generator id_gen_;
     connection_options client_connection_options_;
     connection_options server_connection_options_;
-    proton::link_options link_options_;
+    proton::sender_options sender_options_;
+    proton::receiver_options receiver_options_;
 
   friend class container;
   friend class messaging_adapter;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/endpoint.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/endpoint.cpp b/proton-c/bindings/cpp/src/endpoint.cpp
index 60d9355..1834201 100644
--- a/proton-c/bindings/cpp/src/endpoint.cpp
+++ b/proton-c/bindings/cpp/src/endpoint.cpp
@@ -57,6 +57,8 @@ void session::close(const error_condition& condition) {
     close();
 }
 
+namespace internal {
+
 bool link::uninitialized() const { return ::uninitialized(pn_link_state(pn_object())); }
 bool link::active() const { return ::active(pn_link_state(pn_object())); }
 bool link::closed() const { return ::closed(pn_link_state(pn_object())); }
@@ -66,6 +68,8 @@ void link::close(const error_condition& condition) {
     close();
 }
 
+}
+
 endpoint::~endpoint() {}
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/engine_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/engine_test.cpp b/proton-c/bindings/cpp/src/engine_test.cpp
index 8c2385d..058f6b5 100644
--- a/proton-c/bindings/cpp/src/engine_test.cpp
+++ b/proton-c/bindings/cpp/src/engine_test.cpp
@@ -95,7 +95,7 @@ template <class S> typename S::value_type quick_pop(S& s) {
 
 /// A handler that records incoming endpoints, errors etc.
 struct record_handler : public handler {
-    std::deque<proton::link> links;
+    std::deque<proton::internal::link> links;
     std::deque<proton::session> sessions;
     std::deque<std::string> errors, transport_errors, connection_errors;
 
@@ -200,8 +200,8 @@ void test_endpoint_close() {
     e.a.connection().open_sender("x");
     e.a.connection().open_receiver("y");
     while (ha.links.size() < 2 || hb.links.size() < 2) e.process();
-    proton::link ax = quick_pop(ha.links), ay = quick_pop(ha.links);
-    proton::link bx = quick_pop(hb.links), by = quick_pop(hb.links);
+    proton::internal::link ax = quick_pop(ha.links), ay = quick_pop(ha.links);
+    proton::internal::link bx = quick_pop(hb.links), by = quick_pop(hb.links);
 
     // Close a link
     ax.close(proton::error_condition("err", "foo bar"));

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/link.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/link.cpp b/proton-c/bindings/cpp/src/link.cpp
index 8798694..a81a8ed 100644
--- a/proton-c/bindings/cpp/src/link.cpp
+++ b/proton-c/bindings/cpp/src/link.cpp
@@ -31,9 +31,9 @@
 #include "proton/link.h"
 
 namespace proton {
+namespace internal {
 
-void link::open(const link_options &lo) {
-    lo.apply(*this);
+void link::attach() {
     pn_link_open(pn_object());
 }
 
@@ -111,39 +111,32 @@ bool link::advance() {
     return pn_link_advance(pn_object());
 }
 
-link_options::sender_settle_mode link::sender_settle_mode() {
-    return (link_options::sender_settle_mode) pn_link_snd_settle_mode(pn_object());
+sender_options::sender_settle_mode link::sender_settle_mode() {
+    return (sender_options::sender_settle_mode) pn_link_snd_settle_mode(pn_object());
 }
 
-void link::sender_settle_mode(link_options::sender_settle_mode mode) {
+void link::sender_settle_mode(sender_options::sender_settle_mode mode) {
     pn_link_set_snd_settle_mode(pn_object(), (pn_snd_settle_mode_t) mode);
 }
 
-link_options::receiver_settle_mode link::receiver_settle_mode() {
-    return (link_options::receiver_settle_mode) pn_link_rcv_settle_mode(pn_object());
+receiver_options::receiver_settle_mode link::receiver_settle_mode() {
+    return (receiver_options::receiver_settle_mode) pn_link_rcv_settle_mode(pn_object());
 }
 
-void link::receiver_settle_mode(link_options::receiver_settle_mode mode) {
+void link::receiver_settle_mode(receiver_options::receiver_settle_mode mode) {
     pn_link_set_rcv_settle_mode(pn_object(), (pn_rcv_settle_mode_t) mode);
 }
 
-link_options::sender_settle_mode link::remote_sender_settle_mode() {
-    return (link_options::sender_settle_mode) pn_link_remote_snd_settle_mode(pn_object());
+sender_options::sender_settle_mode link::remote_sender_settle_mode() {
+    return (sender_options::sender_settle_mode) pn_link_remote_snd_settle_mode(pn_object());
 }
 
-link_options::receiver_settle_mode link::remote_receiver_settle_mode() {
-    return (link_options::receiver_settle_mode) pn_link_remote_rcv_settle_mode(pn_object());
-}
-
-link_iterator link_iterator::operator++() {
-    do {
-        obj_ = pn_link_next(obj_.pn_object(), 0);
-    } while (!!obj_ && obj_.session().pn_object() != session_);
-    return *this;
+receiver_options::receiver_settle_mode link::remote_receiver_settle_mode() {
+    return (receiver_options::receiver_settle_mode) pn_link_remote_rcv_settle_mode(pn_object());
 }
 
 link_context &link::context() {
     return link_context::get(pn_object());
 }
 
-}
+}}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/link_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/link_options.cpp b/proton-c/bindings/cpp/src/link_options.cpp
deleted file mode 100644
index 136d6a8..0000000
--- a/proton-c/bindings/cpp/src/link_options.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "proton/binary.hpp"
-#include "proton/link.hpp"
-#include "proton/link_options.hpp"
-#include "proton/handler.hpp"
-
-#include "msg.hpp"
-#include "messaging_adapter.hpp"
-#include "contexts.hpp"
-
-
-namespace proton {
-
-namespace {
-std::string lifetime_policy_symbol(enum link_options::lifetime_policy lp) {
-    switch (lp) {
-    case link_options::DELETE_ON_CLOSE: return "amqp:delete-on-close:list";
-    case link_options::DELETE_ON_NO_LINKS: return "amqp:delete-on-no-links:list";
-    case link_options::DELETE_ON_NO_MESSAGES: return "amqp:delete-on-no-messages:list";
-    case link_options::DELETE_ON_NO_LINKS_OR_MESSAGES: return "amqp:delete-on-no-links-or-messages:list";
-    default: break;
-    }
-    return "";
-}
-
-std::string distribution_mode_symbol(enum terminus::distribution_mode dm) {
-    switch (dm) {
-    case terminus::COPY: return "copy";
-    case terminus::MOVE: return "move";
-    default: break;
-    }
-    return "";
-}
-}
-
-template <class T> struct option {
-    T value;
-    bool set;
-
-    option() : value(), set(false) {}
-    option& operator=(const T& x) { value = x;  set = true; return *this; }
-    void update(const option<T>& x) { if (x.set) *this = x.value; }
-};
-
-class link_options::impl {
-  public:
-    option<proton_handler*> handler;
-    option<enum terminus::distribution_mode> distribution_mode;
-    option<bool> durable_subscription;
-    option<enum delivery_mode> delivery_mode;
-    option<bool> dynamic_address;
-    option<std::string> local_address;
-    option<enum lifetime_policy> lifetime_policy;
-    option<std::string> selector;
-    option<bool> auto_accept;
-    option<bool> auto_settle;
-    option<int> credit_window;
-
-    void apply(link& l) {
-        if (l.uninitialized()) {
-            bool sender = !l.receiver();
-            if (local_address.set) {
-                if (sender)
-                    l.local_target().address(local_address.value);
-                else
-                    l.local_source().address(local_address.value);
-            }
-            if (delivery_mode.set) {
-                switch (delivery_mode.value) {
-                case AT_MOST_ONCE:
-                    l.sender_settle_mode(link_options::SETTLED);
-                    break;
-                case AT_LEAST_ONCE:
-                        l.sender_settle_mode(link_options::UNSETTLED);
-                        l.receiver_settle_mode(link_options::SETTLE_ALWAYS);
-                    break;
-                default:
-                    break;
-                }
-            }
-            if (handler.set) {
-                if (handler.value)
-                    l.handler(*handler.value);
-                else
-                    l.detach_handler();
-            }
-            if (dynamic_address.set) {
-                terminus t = sender ? l.local_target() : l.local_source();
-                t.dynamic(dynamic_address.value);
-                if (dynamic_address.value) {
-                    std::string lp, dm;
-                    if (lifetime_policy.set) lp = lifetime_policy_symbol(lifetime_policy.value);
-                    if (!sender && distribution_mode.set) dm = distribution_mode_symbol(distribution_mode.value);
-                    if (lp.size() || dm.size()) {
-                        codec::encoder enc(t.node_properties());
-                        enc << codec::start::map();
-                        if (dm.size())
-                            enc << symbol("supported-dist-modes") << std::string(dm);
-                        if (lp.size())
-                            enc << symbol("lifetime-policy") << codec::start::described()
-                                << symbol(lp) << codec::start::list() << codec::finish();
-                    }
-                }
-            }
-            if (auto_settle.set) l.context().auto_settle = auto_settle.value;
-            if (!sender) {
-                // receiver only options
-                if (distribution_mode.set) l.local_source().distribution_mode(distribution_mode.value);
-                if (durable_subscription.set && durable_subscription.value) {
-                    l.local_source().durability(terminus::DELIVERIES);
-                    l.local_source().expiry_policy(terminus::EXPIRE_NEVER);
-                }
-                if (selector.set && selector.value.size()) {
-                    codec::encoder enc(l.local_source().filter());
-                    enc << codec::start::map() << symbol("selector") << codec::start::described()
-                        << symbol("apache.org:selector-filter:string") << binary(selector.value) << codec::finish();
-                }
-                if (auto_accept.set) l.context().auto_accept = auto_accept.value;
-                if (credit_window.set) l.context().credit_window = credit_window.value;
-            }
-        }
-    }
-
-    void update(const impl& x) {
-        handler.update(x.handler);
-        distribution_mode.update(x.distribution_mode);
-        durable_subscription.update(x.durable_subscription);
-        delivery_mode.update(x.delivery_mode);
-        dynamic_address.update(x.dynamic_address);
-        local_address.update(x.local_address);
-        lifetime_policy.update(x.lifetime_policy);
-        selector.update(x.selector);
-        auto_accept.update(x.auto_accept);
-        auto_settle.update(x.auto_settle);
-        credit_window.update(x.credit_window);
-    }
-
-};
-
-link_options::link_options() : impl_(new impl()) {}
-link_options::link_options(const link_options& x) : impl_(new impl()) {
-    *this = x;
-}
-link_options::~link_options() {}
-
-link_options& link_options::operator=(const link_options& x) {
-    *impl_ = *x.impl_;
-    return *this;
-}
-
-void link_options::update(const link_options& x) { impl_->update(*x.impl_); }
-
-link_options& link_options::handler(class handler *h) { impl_->handler = h->messaging_adapter_.get(); return *this; }
-link_options& link_options::browsing(bool b) { distribution_mode(b ? terminus::COPY : terminus::MOVE); return *this; }
-link_options& link_options::distribution_mode(enum terminus::distribution_mode m) { impl_->distribution_mode = m; return *this; }
-link_options& link_options::durable_subscription(bool b) {impl_->durable_subscription = b; return *this; }
-link_options& link_options::delivery_mode(enum delivery_mode m) {impl_->delivery_mode = m; return *this; }
-link_options& link_options::dynamic_address(bool b) {impl_->dynamic_address = b; return *this; }
-link_options& link_options::local_address(const std::string &addr) {impl_->local_address = addr; return *this; }
-link_options& link_options::lifetime_policy(enum lifetime_policy lp) {impl_->lifetime_policy = lp; return *this; }
-link_options& link_options::selector(const std::string &str) {impl_->selector = str; return *this; }
-link_options& link_options::auto_accept(bool b) {impl_->auto_accept = b; return *this; }
-link_options& link_options::auto_settle(bool b) {impl_->auto_settle = b; return *this; }
-link_options& link_options::credit_window(int w) {impl_->credit_window = w; return *this; }
-
-void link_options::apply(link& l) const { impl_->apply(l); }
-proton_handler* link_options::handler() const { return impl_->handler.value; }
-
-} // namespace proton

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/message.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/message.cpp b/proton-c/bindings/cpp/src/message.cpp
index d53ea56..416701d 100644
--- a/proton-c/bindings/cpp/src/message.cpp
+++ b/proton-c/bindings/cpp/src/message.cpp
@@ -292,9 +292,9 @@ void message::decode(const std::vector<char> &s) {
 void message::decode(proton::delivery delivery) {
     std::vector<char> buf;
     buf.resize(delivery.pending());
-    proton::link link = delivery.receiver();
+    proton::receiver link = delivery.receiver();
     ssize_t n = link.recv(const_cast<char *>(&buf[0]), buf.size());
-    if (n != ssize_t(buf.size())) throw error(MSG("link read failure"));
+    if (n != ssize_t(buf.size())) throw error(MSG("receiver read failure"));
     clear();
     decode(buf);
     link.advance();

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/messaging_adapter.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/messaging_adapter.cpp b/proton-c/bindings/cpp/src/messaging_adapter.cpp
index cf022b9..83f737b 100644
--- a/proton-c/bindings/cpp/src/messaging_adapter.cpp
+++ b/proton-c/bindings/cpp/src/messaging_adapter.cpp
@@ -145,13 +145,13 @@ void messaging_adapter::on_link_remote_close(proton_event &pe) {
     pn_event_t *cevent = pe.pn_event();
     pn_link_t *lnk = pn_event_link(cevent);
     if (pn_link_is_receiver(lnk)) {
-        receiver r(lnk);
+        receiver r = internal::link(lnk).receiver();
         if (pn_condition_is_set(pn_link_remote_condition(lnk))) {
             delegate_.on_receiver_error(r);
         }
         delegate_.on_receiver_close(r);
     } else {
-        sender s(lnk);
+        sender s = internal::link(lnk).sender();
         if (pn_condition_is_set(pn_link_remote_condition(lnk))) {
             delegate_.on_sender_error(s);
         }
@@ -205,20 +205,24 @@ void messaging_adapter::on_link_local_open(proton_event &pe) {
 }
 
 void messaging_adapter::on_link_remote_open(proton_event &pe) {
+    receiver r;
+    sender s;
     pn_link_t *lnk = pn_event_link(pe.pn_event());
     if (pn_link_is_receiver(lnk)) {
-      receiver r(lnk);
+      r = internal::link(lnk).receiver();
       delegate_.on_receiver_open(r);
     } else {
-      sender s(lnk);
+      s = internal::link(lnk).sender();
       delegate_.on_sender_open(s);
     }
     if (!is_local_open(pn_link_state(lnk)) && is_local_unititialised(pn_link_state(lnk))) {
-        link l(lnk);
         if (pe.container())
-            l.open(pe.container()->impl_->link_options_);
+            if (!!s)
+                s.open(pe.container()->impl_->sender_options_);
+            else
+                r.open(pe.container()->impl_->receiver_options_);
         else
-            l.open();    // No default for engine
+            pn_link_open(lnk);    // No default for engine
     }
     credit_topup(lnk);
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/receiver.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/receiver.cpp b/proton-c/bindings/cpp/src/receiver.cpp
index 2331bdb..2ebb9e5 100644
--- a/proton-c/bindings/cpp/src/receiver.cpp
+++ b/proton-c/bindings/cpp/src/receiver.cpp
@@ -29,4 +29,24 @@
 
 namespace proton {
 
+void receiver::open(const receiver_options &opts) {
+    opts.apply(*this);
+    attach();
+}
+
+
+receiver_iterator receiver_iterator::operator++() {
+    if (!!obj_) {
+        pn_link_t *lnk = pn_link_next(obj_.pn_object(), 0);
+        while (lnk) {
+            if (pn_link_is_receiver(lnk) && pn_link_session(lnk) == session_)
+                break;
+            lnk = pn_link_next(lnk, 0);
+        }
+        obj_ = lnk;
+    }
+    return *this;
+}
+
+
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/receiver_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/receiver_options.cpp b/proton-c/bindings/cpp/src/receiver_options.cpp
new file mode 100644
index 0000000..6b06dc9
--- /dev/null
+++ b/proton-c/bindings/cpp/src/receiver_options.cpp
@@ -0,0 +1,122 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "proton/binary.hpp"
+#include "proton/receiver.hpp"
+#include "proton/receiver_options.hpp"
+#include "proton/handler.hpp"
+
+#include "msg.hpp"
+#include "messaging_adapter.hpp"
+#include "contexts.hpp"
+
+
+namespace proton {
+
+template <class T> struct option {
+    T value;
+    bool set;
+
+    option() : value(), set(false) {}
+    option& operator=(const T& x) { value = x;  set = true; return *this; }
+    void update(const option<T>& x) { if (x.set) *this = x.value; }
+};
+
+class receiver_options::impl {
+  public:
+    option<proton_handler*> handler;
+    option<enum delivery_mode> delivery_mode;
+    option<bool> auto_accept;
+    option<bool> auto_settle;
+    option<int> credit_window;
+    option<bool> dynamic_address;
+    option<enum terminus::distribution_mode> distribution_mode;
+
+    void apply(receiver& r) {
+        if (r.uninitialized()) {
+            if (delivery_mode.set) {
+                switch (delivery_mode.value) {
+                case AT_MOST_ONCE:
+                    r.sender_settle_mode(sender_options::SETTLED);
+                    break;
+                case AT_LEAST_ONCE:
+                    r.sender_settle_mode(sender_options::UNSETTLED);
+                    r.receiver_settle_mode(receiver_options::SETTLE_ALWAYS);
+                    break;
+                default:
+                    break;
+                }
+            }
+            if (handler.set) {
+                if (handler.value)
+                    r.handler(*handler.value);
+                else
+                    r.detach_handler();
+            }
+            if (dynamic_address.set) {
+                terminus t = r.local_source();
+                t.dynamic(dynamic_address.value);
+            }
+
+            if (auto_settle.set) r.context().auto_settle = auto_settle.value;
+            if (auto_accept.set) r.context().auto_accept = auto_accept.value;
+            if (credit_window.set) r.context().credit_window = credit_window.value;
+            if (distribution_mode.set) r.local_source().distribution_mode(distribution_mode.value);
+        }
+    }
+
+    void update(const impl& x) {
+        handler.update(x.handler);
+        delivery_mode.update(x.delivery_mode);
+        auto_accept.update(x.auto_accept);
+        auto_settle.update(x.auto_settle);
+        credit_window.update(x.credit_window);
+        dynamic_address.update(x.dynamic_address);
+        distribution_mode.update(x.distribution_mode);
+    }
+
+};
+
+receiver_options::receiver_options() : impl_(new impl()) {}
+receiver_options::receiver_options(const receiver_options& x) : impl_(new impl()) {
+    *this = x;
+}
+receiver_options::~receiver_options() {}
+
+receiver_options& receiver_options::operator=(const receiver_options& x) {
+    *impl_ = *x.impl_;
+    return *this;
+}
+
+void receiver_options::update(const receiver_options& x) { impl_->update(*x.impl_); }
+
+receiver_options& receiver_options::handler(class handler *h) { impl_->handler = h->messaging_adapter_.get(); return *this; }
+receiver_options& receiver_options::delivery_mode(enum delivery_mode m) {impl_->delivery_mode = m; return *this; }
+receiver_options& receiver_options::auto_accept(bool b) {impl_->auto_accept = b; return *this; }
+receiver_options& receiver_options::auto_settle(bool b) {impl_->auto_settle = b; return *this; }
+receiver_options& receiver_options::credit_window(int w) {impl_->credit_window = w; return *this; }
+receiver_options& receiver_options::dynamic_address(bool b) {impl_->dynamic_address = b; return *this; }
+receiver_options& receiver_options::browsing(bool b) { impl_->distribution_mode = (b ? terminus::COPY : terminus::MOVE); return *this; }
+
+void receiver_options::apply(receiver& r) const { impl_->apply(r); }
+proton_handler* receiver_options::handler() const { return impl_->handler.value; }
+
+} // namespace proton

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/sender.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/sender.cpp b/proton-c/bindings/cpp/src/sender.cpp
index a564567..6e55f8f 100644
--- a/proton-c/bindings/cpp/src/sender.cpp
+++ b/proton-c/bindings/cpp/src/sender.cpp
@@ -29,6 +29,11 @@
 
 namespace proton {
 
+void sender::open(const sender_options &opts) {
+    opts.apply(*this);
+    attach();
+}
+
 namespace {
 // TODO: revisit if thread safety required
 uint64_t tag_counter = 0;
@@ -47,4 +52,17 @@ tracker sender::send(const message &message) {
     return dlv;
 }
 
+sender_iterator sender_iterator::operator++() {
+    if (!!obj_) {
+        pn_link_t *lnk = pn_link_next(obj_.pn_object(), 0);
+        while (lnk) {
+            if (pn_link_is_sender(lnk) && pn_link_session(lnk) == session_)
+                break;
+            lnk = pn_link_next(lnk, 0);
+        }
+        obj_ = lnk;
+    }
+    return *this;
+}
+
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/sender_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/sender_options.cpp b/proton-c/bindings/cpp/src/sender_options.cpp
new file mode 100644
index 0000000..59b5947
--- /dev/null
+++ b/proton-c/bindings/cpp/src/sender_options.cpp
@@ -0,0 +1,102 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "proton/binary.hpp"
+#include "proton/sender.hpp"
+#include "proton/sender_options.hpp"
+#include "proton/handler.hpp"
+
+#include "msg.hpp"
+#include "messaging_adapter.hpp"
+#include "contexts.hpp"
+
+
+namespace proton {
+
+template <class T> struct option {
+    T value;
+    bool set;
+
+    option() : value(), set(false) {}
+    option& operator=(const T& x) { value = x;  set = true; return *this; }
+    void update(const option<T>& x) { if (x.set) *this = x.value; }
+};
+
+class sender_options::impl {
+  public:
+    option<proton_handler*> handler;
+    option<enum delivery_mode> delivery_mode;
+    option<bool> auto_settle;
+
+    void apply(sender& s) {
+        if (s.uninitialized()) {
+            if (delivery_mode.set) {
+                switch (delivery_mode.value) {
+                case AT_MOST_ONCE:
+                    s.sender_settle_mode(sender_options::SETTLED);
+                    break;
+                case AT_LEAST_ONCE:
+                        s.sender_settle_mode(sender_options::UNSETTLED);
+                        s.receiver_settle_mode(receiver_options::SETTLE_ALWAYS);
+                    break;
+                default:
+                    break;
+                }
+            }
+            if (handler.set) {
+                if (handler.value)
+                    s.handler(*handler.value);
+                else
+                    s.detach_handler();
+            }
+            if (auto_settle.set) s.context().auto_settle = auto_settle.value;
+        }
+    }
+
+    void update(const impl& x) {
+        handler.update(x.handler);
+        delivery_mode.update(x.delivery_mode);
+        auto_settle.update(x.auto_settle);
+    }
+
+};
+
+sender_options::sender_options() : impl_(new impl()) {}
+sender_options::sender_options(const sender_options& x) : impl_(new impl()) {
+    *this = x;
+}
+sender_options::~sender_options() {}
+
+sender_options& sender_options::operator=(const sender_options& x) {
+    *impl_ = *x.impl_;
+    return *this;
+}
+
+void sender_options::update(const sender_options& x) { impl_->update(*x.impl_); }
+
+sender_options& sender_options::handler(class handler *h) { impl_->handler = h->messaging_adapter_.get(); return *this; }
+sender_options& sender_options::delivery_mode(enum delivery_mode m) {impl_->delivery_mode = m; return *this; }
+sender_options& sender_options::auto_settle(bool b) {impl_->auto_settle = b; return *this; }
+
+void sender_options::apply(sender& s) const { impl_->apply(s); }
+proton_handler* sender_options::handler() const { return impl_->handler.value; }
+
+} // namespace proton

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/proton-c/bindings/cpp/src/session.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/session.cpp b/proton-c/bindings/cpp/src/session.cpp
index 24bbb72..d78d60c 100644
--- a/proton-c/bindings/cpp/src/session.cpp
+++ b/proton-c/bindings/cpp/src/session.cpp
@@ -55,18 +55,18 @@ std::string next_link_name(const connection& c) {
 }
 }
 
-sender session::open_sender(const std::string &addr, const link_options &lo) {
+sender session::open_sender(const std::string &addr, const sender_options &so) {
     sender snd = pn_sender(pn_object(), next_link_name(connection()).c_str());
     snd.local_target().address(addr);
-    snd.open(lo);
+    snd.open(so);
     return snd;
 }
 
-receiver session::open_receiver(const std::string &addr, const link_options &lo)
+receiver session::open_receiver(const std::string &addr, const receiver_options &ro)
 {
     receiver rcv = pn_receiver(pn_object(), next_link_name(connection()).c_str());
     rcv.local_source().address(addr);
-    rcv.open(lo);
+    rcv.open(ro);
     return rcv;
 }
 
@@ -74,14 +74,26 @@ error_condition session::error() const {
     return pn_session_remote_condition(pn_object());
 }
 
-link_range session::links()  const {
-    link_range r(connection().links());
-    if (r.empty()) return r;
-    link_iterator i(*r.begin(), pn_object());
-    if (*this != (*i).session()) ++i;
-    return link_range(i);
+sender_range session::senders() const {
+    pn_link_t *lnk = pn_link_head(pn_session_connection(pn_object()), 0);
+    while (lnk) {
+        if (pn_link_is_sender(lnk) && pn_link_session(lnk) == pn_object())
+            break;
+        lnk = pn_link_next(lnk, 0);
+    }
+    return sender_range(sender_iterator(lnk));
 }
 
+receiver_range session::receivers() const {
+    pn_link_t *lnk = pn_link_head(pn_session_connection(pn_object()), 0);
+    while (lnk) {
+        if (pn_link_is_receiver(lnk) && pn_link_session(lnk) == pn_object())
+            break;
+    }
+    return receiver_range(receiver_iterator(lnk));
+}
+
+
 session_iterator session_iterator::operator++() {
     obj_ = pn_session_next(obj_.pn_object(), 0);
     return *this;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/337b4364/tests/tools/apps/cpp/reactor_send.cpp
----------------------------------------------------------------------
diff --git a/tests/tools/apps/cpp/reactor_send.cpp b/tests/tools/apps/cpp/reactor_send.cpp
index f6d3e7b..a3dc003 100644
--- a/tests/tools/apps/cpp/reactor_send.cpp
+++ b/tests/tools/apps/cpp/reactor_send.cpp
@@ -27,7 +27,6 @@
 #include "proton/decoder.hpp"
 #include "proton/delivery.hpp"
 #include "proton/handler.hpp"
-#include "proton/link_options.hpp"
 #include "proton/tracker.hpp"
 #include "proton/value.hpp"
 
@@ -67,7 +66,7 @@ class reactor_send : public proton::handler {
     }
 
     void on_container_start(proton::container &c) override {
-        c.link_options(proton::link_options().credit_window(1024));
+        c.receiver_options(proton::receiver_options().credit_window(1024));
         c.open_sender(url_);
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org