PROTON-1269: [C++ binding] Add missing handlers
- on_receiver_detach & on_sender_detach
- on_container_stop
- Made underlying pn_link_detach() idempotent.
diff --git a/proton-c/bindings/cpp/include/proton/messaging_handler.hpp b/proton-c/bindings/cpp/include/proton/messaging_handler.hpp
index cef7328..8520846 100644
--- a/proton-c/bindings/cpp/include/proton/messaging_handler.hpp
+++ b/proton-c/bindings/cpp/include/proton/messaging_handler.hpp
@@ -79,8 +79,13 @@
     PN_CPP_EXTERN virtual ~messaging_handler();
 
     /// The container event loop is starting.
+    /// This is the first event received after calling container::run
     PN_CPP_EXTERN virtual void on_container_start(container &c);
 
+    /// The container event loop is stopping.
+    /// This is the last event received before the container event loop stops.
+    PN_CPP_EXTERN virtual void on_container_stop(container &c);
+
     /// A message is received.
     PN_CPP_EXTERN virtual void on_message(delivery &d, message &m);
 
@@ -118,6 +123,9 @@
     /// The remote peer opened the link.
     PN_CPP_EXTERN virtual void on_receiver_open(receiver& l);
 
+    /// The remote peer detached the link.
+    PN_CPP_EXTERN virtual void on_receiver_detach(receiver& l);
+
     /// The remote peer closed the link.
     PN_CPP_EXTERN virtual void on_receiver_close(receiver& l);
 
@@ -127,6 +135,9 @@
     /// The remote peer opened the link.
     PN_CPP_EXTERN virtual void on_sender_open(sender& l);
 
+    /// The remote peer detached the link.
+    PN_CPP_EXTERN virtual void on_sender_detach(sender& l);
+
     /// The remote peer closed the link.
     PN_CPP_EXTERN virtual void on_sender_close(sender& l);
 
diff --git a/proton-c/bindings/cpp/src/handler.cpp b/proton-c/bindings/cpp/src/handler.cpp
index bacedd0..cda8acb 100644
--- a/proton-c/bindings/cpp/src/handler.cpp
+++ b/proton-c/bindings/cpp/src/handler.cpp
@@ -40,6 +40,7 @@
 messaging_handler::~messaging_handler(){}
 
 void messaging_handler::on_container_start(container &) {}
+void messaging_handler::on_container_stop(container &) {}
 void messaging_handler::on_message(delivery &, message &) {}
 void messaging_handler::on_sendable(sender &) {}
 void messaging_handler::on_transport_close(transport &) {}
@@ -54,9 +55,11 @@
 void messaging_handler::on_receiver_close(receiver &) {}
 void messaging_handler::on_receiver_error(receiver &l) { on_error(l.error()); }
 void messaging_handler::on_receiver_open(receiver &) {}
+void messaging_handler::on_receiver_detach(receiver &) {}
 void messaging_handler::on_sender_close(sender &) {}
 void messaging_handler::on_sender_error(sender &l) { on_error(l.error()); }
 void messaging_handler::on_sender_open(sender &) {}
+void messaging_handler::on_sender_detach(sender &) {}
 void messaging_handler::on_tracker_accept(tracker &) {}
 void messaging_handler::on_tracker_reject(tracker &) {}
 void messaging_handler::on_tracker_release(tracker &) {}
diff --git a/proton-c/bindings/cpp/src/messaging_adapter.cpp b/proton-c/bindings/cpp/src/messaging_adapter.cpp
index 4328ca2..37fc4e0 100644
--- a/proton-c/bindings/cpp/src/messaging_adapter.cpp
+++ b/proton-c/bindings/cpp/src/messaging_adapter.cpp
@@ -62,6 +62,10 @@
     delegate_.on_container_start(pe.container());
 }
 
+void messaging_adapter::on_reactor_final(proton_event &pe) {
+    delegate_.on_container_stop(pe.container());
+}
+
 void messaging_adapter::on_link_flow(proton_event &pe) {
     pn_event_t *pne = pe.pn_event();
     pn_link_t *lnk = pn_event_link(pne);
@@ -183,6 +187,19 @@
 
 } // namespace
 
+void messaging_adapter::on_link_remote_detach(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(make_wrapper<receiver>(lnk));
+        delegate_.on_receiver_detach(r);
+    } else {
+        sender s(make_wrapper<sender>(lnk));
+        delegate_.on_sender_detach(s);
+    }
+    pn_link_detach(lnk);
+}
+
 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);
diff --git a/proton-c/bindings/cpp/src/messaging_adapter.hpp b/proton-c/bindings/cpp/src/messaging_adapter.hpp
index 5d7b37a..846b466 100644
--- a/proton-c/bindings/cpp/src/messaging_adapter.hpp
+++ b/proton-c/bindings/cpp/src/messaging_adapter.hpp
@@ -41,6 +41,7 @@
     virtual ~messaging_adapter();
 
     void on_reactor_init(proton_event &e);
+    void on_reactor_final(proton_event & e);
     void on_link_flow(proton_event &e);
     void on_delivery(proton_event &e);
     void on_connection_remote_open(proton_event &e);
@@ -49,6 +50,7 @@
     void on_session_remote_close(proton_event &e);
     void on_link_local_open(proton_event &e);
     void on_link_remote_open(proton_event &e);
+    void on_link_remote_detach(proton_event & e);
     void on_link_remote_close(proton_event &e);
     void on_transport_closed(proton_event &e);
 
diff --git a/proton-c/src/engine/engine.c b/proton-c/src/engine/engine.c
index c620101..b076a5f 100644
--- a/proton-c/src/engine/engine.c
+++ b/proton-c/src/engine/engine.c
@@ -315,6 +315,8 @@
 void pn_link_detach(pn_link_t *link)
 {
   assert(link);
+  if (link->detached) return;
+
   link->detached = true;
   pn_collector_put(link->session->connection->collector, PN_OBJECT, link, PN_LINK_LOCAL_DETACH);
   pn_modified(link->session->connection, &link->endpoint, true);