Browse Source

[3008] Addressed review comments.

Thomas Markwalder 11 years ago
parent
commit
07c566bffc
6 changed files with 226 additions and 168 deletions
  1. 19 11
      src/bin/d2/d2_messages.mes
  2. 72 39
      src/bin/d2/ncr_io.cc
  3. 72 50
      src/bin/d2/ncr_io.h
  4. 15 18
      src/bin/d2/ncr_udp.cc
  5. 7 4
      src/bin/d2/ncr_udp.h
  6. 41 46
      src/bin/d2/tests/ncr_udp_unittests.cc

+ 19 - 11
src/bin/d2/d2_messages.mes

@@ -134,24 +134,32 @@ This is a debug message issued when the DHCP-DDNS application encountered an
 error while decoding a response to DNS Update message. Typically, this error
 error while decoding a response to DNS Update message. Typically, this error
 will be encountered when a response message is malformed.
 will be encountered when a response message is malformed.
 
 
-% DHCP_DDNS_NCR_UDP_LISTEN_CLOSE application encountered an error while closing the UDP socket used to receive NameChangeRequests : %1
+% DHCP_DDNS_NCR_LISTEN_CLOSE_ERROR application encountered an error while closing the the listener used to receive NameChangeRequests : %1
 This is an error message that indicates the application was unable to close the
 This is an error message that indicates the application was unable to close the
-UDP socket being used to receive NameChangeRequests.  Socket closure may occur
+listener connection used to receive NameChangeRequests.  Closure may occur
 during the course of error recovery or duing normal shutdown procedure.  In
 during the course of error recovery or duing normal shutdown procedure.  In
 either case the error is unlikely to impair the application's ability to
 either case the error is unlikely to impair the application's ability to
 process requests but it should be reported for analysis.
 process requests but it should be reported for analysis.
 
 
-% DHCP_DDNS_NCR_UDP_RECV_ERROR UDP socket receive error while listening for DNS Update requests: %1
-This is an error message indicating that an IO error occured while listening
-over a UDP socket for DNS update requests. in the request. This could indicate
-a network connectivity or system resource issue.
+% DHCP_DDNS_NCR_RECV_NEXT application could not initiate the next read following
+a request receive.
+This is a error message indicating that NameChangeRequest listener could not start another read after receiving a request.  While possible, this is highly unlikely and is probably a programmatic error.  The application should recover on its
+own.
 
 
-% DHCP_DDNS_NCR_UDP_SEND_CLOSE application encountered an error while closing the UDP socket used to send NameChangeRequests : %1
+% DHCP_DDNS_NCR_SEND_CLOSE_ERROR DHCP-DDNS client encountered an error while closing ththe sender connection used to send NameChangeRequests : %1
 This is an error message that indicates the DHCP-DDNS client was unable to close
 This is an error message that indicates the DHCP-DDNS client was unable to close
-the UDP socket being used to send NameChangeRequests.  Socket closure may occur
-during the course of error recovery or duing normal shutdown procedure.  In
-either case the error is unlikely to impair the client's ability to send
-requests but it should be reported for analysis.
+the connection used to send NameChangeRequests.  Closure may occur during the
+course of error recovery or duing normal shutdown procedure.  In either case
+the error is unlikely to impair the client's ability to send requests but it
+should be reported for analysis.
+
+% DHCP_DDNS_NCR_SEND_NEXT DHCP-DDNS client could not initiate the next request send following send completion.
+This is a error message indicating that NameChangeRequest sender could not start another send after completing the send of the previous request.  While possible, this is highly unlikely and is probably a programmatic error.  The application should recover on its own.
+
+% DHCP_DDNS_NCR_UDP_RECV_ERROR UDP socket receive error while listening for DNS Update requests: %1
+This is an error message indicating that an IO error occured while listening
+over a UDP socket for DNS update requests. This could indicate a network
+connectivity or system resource issue.
 
 
 % DHCP_DDNS_NO_MATCH No DNS servers match FQDN: %1
 % DHCP_DDNS_NO_MATCH No DNS servers match FQDN: %1
 This is warning message issued when there are no domains in the configuration
 This is warning message issued when there are no domains in the configuration

+ 72 - 39
src/bin/d2/ncr_io.cc

@@ -20,13 +20,9 @@ namespace d2 {
 
 
 //************************** NameChangeListener ***************************
 //************************** NameChangeListener ***************************
 
 
-NameChangeListener::NameChangeListener(const RequestReceiveHandler*
+NameChangeListener::NameChangeListener(RequestReceiveHandler&
                                        recv_handler)
                                        recv_handler)
     : listening_(false), recv_handler_(recv_handler) {
     : listening_(false), recv_handler_(recv_handler) {
-    if (!recv_handler) {
-        isc_throw(NcrListenerError,
-                      "NameChangeListener ctor - recv_handler cannot be null");
-    }
 };
 };
 
 
 void
 void
@@ -64,41 +60,64 @@ NameChangeListener::stopListening() {
     } catch (const isc::Exception &ex) {
     } catch (const isc::Exception &ex) {
         // Swallow exceptions. If we have some sort of error we'll log
         // Swallow exceptions. If we have some sort of error we'll log
         // it but we won't propagate the throw.
         // it but we won't propagate the throw.
-        LOG_ERROR(dctl_logger, DHCP_DDNS_NCR_UDP_LISTEN_CLOSE).arg(ex.what());
+        LOG_ERROR(dctl_logger, DHCP_DDNS_NCR_LISTEN_CLOSE_ERROR).arg(ex.what());
     }
     }
 
 
+    // Set it false, no matter what.  This allows us to at least try to
+    // re-open via startListening().
     setListening(false);
     setListening(false);
 }
 }
 
 
 void
 void
+#if 0
 NameChangeListener::invokeRecvHandler(Result result, NameChangeRequestPtr ncr) {
 NameChangeListener::invokeRecvHandler(Result result, NameChangeRequestPtr ncr) {
+#else
+NameChangeListener::invokeRecvHandler(const Result result, 
+                                      NameChangeRequestPtr& ncr) {
+#endif
     // Call the registered application layer handler.
     // Call the registered application layer handler.
-    (*(const_cast<RequestReceiveHandler*>(recv_handler_)))(result, ncr);
+    recv_handler_(result, ncr);
 
 
     // Start the next IO layer asynchronous receive.
     // Start the next IO layer asynchronous receive.
-    doReceive();
-};
+    // In the event the handler above intervened and decided to stop listening
+    // we need to check that first.
+    if (amListening()) {
+        try {
+            doReceive();
+        } catch (const isc::Exception& ex) {
+            // It is possible though unlikely, for doReceive to fail without
+            // scheduling the read. While, unlikely, it does mean the callback
+            // will not get called with a failure. A throw here would surface
+            // at the IOService::run (or run variant) invocation.  So we will
+            // close the window by invoking the application handler with
+            // a failed result, and let the application layer sort it out.
+            LOG_ERROR(dctl_logger, DHCP_DDNS_NCR_RECV_NEXT).arg(ex.what());
+#if 0
+            recv_handler_(ERROR, NameChangeRequestPtr());
+#else
+            NameChangeRequestPtr empty;
+            recv_handler_(ERROR, empty);
+#endif
+        }
+    }
+}
 
 
 //************************* NameChangeSender ******************************
 //************************* NameChangeSender ******************************
 
 
-NameChangeSender::NameChangeSender(const RequestSendHandler* send_handler,
-                                   size_t send_que_max)
+NameChangeSender::NameChangeSender(RequestSendHandler& send_handler,
+                                   size_t send_queue_max)
     : sending_(false), send_handler_(send_handler),
     : sending_(false), send_handler_(send_handler),
-      send_que_max_(send_que_max) {
-    if (!send_handler) {
-        isc_throw(NcrSenderError,
-                  "NameChangeSender ctor - send_handler cannot be null");
-    }
+      send_queue_max_(send_queue_max) {
 
 
     // Queue size must be big enough to hold at least 1 entry.
     // Queue size must be big enough to hold at least 1 entry.
-    if (send_que_max == 0) {
-        isc_throw(NcrSenderError, "NameChangeSender ctor -"
+    if (send_queue_max == 0) {
+        isc_throw(NcrSenderError, "NameChangeSender constructor"
                   " queue size must be greater than zero");
                   " queue size must be greater than zero");
     }
     }
-};
+}
 
 
 void
 void
-NameChangeSender::startSending(isc::asiolink::IOService & io_service) {
+NameChangeSender::startSending(isc::asiolink::IOService& io_service) {
     if (amSending()) {
     if (amSending()) {
         // This amounts to a programmatic error.
         // This amounts to a programmatic error.
         isc_throw(NcrSenderError, "NameChangeSender is already sending");
         isc_throw(NcrSenderError, "NameChangeSender is already sending");
@@ -112,7 +131,7 @@ NameChangeSender::startSending(isc::asiolink::IOService & io_service) {
         open(io_service);
         open(io_service);
     } catch (const isc::Exception& ex) {
     } catch (const isc::Exception& ex) {
         stopSending();
         stopSending();
-        isc_throw(NcrSenderOpenError, "Open failed:" << ex.what());
+        isc_throw(NcrSenderOpenError, "Open failed: " << ex.what());
     }
     }
 
 
     // Set our status to sending.
     // Set our status to sending.
@@ -127,13 +146,16 @@ NameChangeSender::stopSending() {
     } catch (const isc::Exception &ex) {
     } catch (const isc::Exception &ex) {
         // Swallow exceptions. If we have some sort of error we'll log
         // Swallow exceptions. If we have some sort of error we'll log
         // it but we won't propagate the throw.
         // it but we won't propagate the throw.
-        LOG_ERROR(dctl_logger, DHCP_DDNS_NCR_UDP_SEND_CLOSE).arg(ex.what());
+        LOG_ERROR(dctl_logger, DHCP_DDNS_NCR_SEND_CLOSE_ERROR).arg(ex.what());
     }
     }
+
+    // Set it false, no matter what.  This allows us to at least try to
+    // re-open via startSending().
     setSending(false);
     setSending(false);
 }
 }
 
 
 void
 void
-NameChangeSender::sendRequest(NameChangeRequestPtr ncr) {
+NameChangeSender::sendRequest(NameChangeRequestPtr& ncr) {
     if (!amSending()) {
     if (!amSending()) {
         isc_throw(NcrSenderError, "sender is not ready to send");
         isc_throw(NcrSenderError, "sender is not ready to send");
     }
     }
@@ -142,13 +164,13 @@ NameChangeSender::sendRequest(NameChangeRequestPtr ncr) {
         isc_throw(NcrSenderError, "request to send is empty");
         isc_throw(NcrSenderError, "request to send is empty");
     }
     }
 
 
-    if (send_que_.size() >= send_que_max_) {
-        isc_throw(NcrSenderQueFull, "send queue has reached maximum capacity:"
-                  << send_que_max_ );
+    if (send_queue_.size() >= send_queue_max_) {
+        isc_throw(NcrSenderQueueFull, "send queue has reached maximum capacity:"
+                  << send_queue_max_ );
     }
     }
 
 
     // Put it on the queue.
     // Put it on the queue.
-    send_que_.push_back(ncr);
+    send_queue_.push_back(ncr);
 
 
     // Call sendNext to schedule the next one to go.
     // Call sendNext to schedule the next one to go.
     sendNext();
     sendNext();
@@ -165,8 +187,8 @@ NameChangeSender::sendNext() {
 
 
     // If queue isn't empty, then get one from the front. Note we leave
     // If queue isn't empty, then get one from the front. Note we leave
     // it on the front of the queue until we successfully send it.
     // it on the front of the queue until we successfully send it.
-    if (send_que_.size()) {
-        ncr_to_send_ = send_que_.front();
+    if (send_queue_.size()) {
+        ncr_to_send_ = send_queue_.front();
 
 
        // @todo start defense timer
        // @todo start defense timer
        // If a send were to hang and we timed it out, then timeout
        // If a send were to hang and we timed it out, then timeout
@@ -178,39 +200,50 @@ NameChangeSender::sendNext() {
 }
 }
 
 
 void
 void
-NameChangeSender::invokeSendHandler(NameChangeSender::Result result) {
+NameChangeSender::invokeSendHandler(const NameChangeSender::Result result) {
     // @todo reset defense timer
     // @todo reset defense timer
     if (result == SUCCESS) {
     if (result == SUCCESS) {
         // It shipped so pull it off the queue.
         // It shipped so pull it off the queue.
-        send_que_.pop_front();
+        send_queue_.pop_front();
     }
     }
 
 
     // Invoke the completion handler passing in the result and a pointer
     // Invoke the completion handler passing in the result and a pointer
     // the request involved.
     // the request involved.
-    (*(const_cast<RequestSendHandler*>(send_handler_))) (result, ncr_to_send_);
+    send_handler_(result, ncr_to_send_);
 
 
     // Clear the pending ncr pointer.
     // Clear the pending ncr pointer.
     ncr_to_send_.reset();
     ncr_to_send_.reset();
 
 
     // Set up the next send
     // Set up the next send
-    sendNext();
-};
+    try {
+        sendNext();
+    } catch (const isc::Exception& ex) {
+        // It is possible though unlikely, for sendNext to fail without
+        // scheduling the send. While, unlikely, it does mean the callback
+        // will not get called with a failure. A throw here would surface
+        // at the IOService::run (or run variant) invocation.  So we will
+        // close the window by invoking the application handler with
+        // a failed result, and let the application layer sort it out.
+        LOG_ERROR(dctl_logger, DHCP_DDNS_NCR_SEND_NEXT).arg(ex.what());
+        send_handler_(ERROR, ncr_to_send_);
+    }
+}
 
 
 void
 void
 NameChangeSender::skipNext() {
 NameChangeSender::skipNext() {
-    if (send_que_.size()) {
+    if (send_queue_.size()) {
         // Discards the request at the front of the queue.
         // Discards the request at the front of the queue.
-        send_que_.pop_front();
+        send_queue_.pop_front();
     }
     }
 }
 }
 
 
 void
 void
-NameChangeSender::flushSendQue() {
+NameChangeSender::clearSendQueue() {
     if (amSending()) {
     if (amSending()) {
-        isc_throw(NcrSenderError, "Cannot flush queue while sending");
+        isc_throw(NcrSenderError, "Cannot clear queue while sending");
     }
     }
 
 
-    send_que_.clear();
+    send_queue_.clear();
 }
 }
 
 
 } // namespace isc::d2
 } // namespace isc::d2

+ 72 - 50
src/bin/d2/ncr_io.h

@@ -19,28 +19,29 @@
 /// @brief This file defines abstract classes for exchanging NameChangeRequests.
 /// @brief This file defines abstract classes for exchanging NameChangeRequests.
 ///
 ///
 /// These classes are used for sending and receiving requests to update DNS
 /// These classes are used for sending and receiving requests to update DNS
-/// information for FQDNs embodied as NameChangeRequests (aka NCRs). Ultimately,/// NCRs must move through the following three layers in order to implement
+/// information for FQDNs embodied as NameChangeRequests (aka NCRs). Ultimately,
+/// NCRs must move through the following three layers in order to implement
 /// DHCP-DDNS:
 /// DHCP-DDNS:
 ///
 ///
 ///    * Application layer - the business layer which needs to
 ///    * Application layer - the business layer which needs to
 ///    transport NameChangeRequests, and is unaware of the means by which
 ///    transport NameChangeRequests, and is unaware of the means by which
 ///    they are transported.
 ///    they are transported.
 ///
 ///
-///    * IO layer - the low-level layer that is directly responsible for
-///    sending and receiving data asynchronously and is supplied through
-///    other libraries.  This layer is largely unaware of the nature of the
-///    data being transmitted.  In other words, it doesn't know beans about
-///    NCRs.
-///
 ///    * NameChangeRequest layer - This is the layer which acts as the
 ///    * NameChangeRequest layer - This is the layer which acts as the
 ///    intermediary between the Application layer and the IO layer.  It must
 ///    intermediary between the Application layer and the IO layer.  It must
 ///    be able to move NameChangeRequests to the IO layer as raw data and move
 ///    be able to move NameChangeRequests to the IO layer as raw data and move
 ///    raw data from the IO layer in the Application layer as
 ///    raw data from the IO layer in the Application layer as
 ///    NameChangeRequests.
 ///    NameChangeRequests.
 ///
 ///
-/// The abstract classes defined here implement implement the latter, middle
-/// layer, the NameChangeRequest layer.  There are two types of participants
-/// in this middle ground:
+///    * IO layer - the low-level layer that is directly responsible for
+///    sending and receiving data asynchronously and is supplied through
+///    other libraries.  This layer is largely unaware of the nature of the
+///    data being transmitted.  In other words, it doesn't know beans about
+///    NCRs.
+///
+/// The abstract classes defined here implement the latter, middle layer, 
+/// the NameChangeRequest layer.  There are two types of participants in this
+/// middle ground:
 ///
 ///
 ///    * listeners - Receive NCRs from one or more sources. The DHCP-DDNS
 ///    * listeners - Receive NCRs from one or more sources. The DHCP-DDNS
 ///   application, (aka D2), is a listener. Listeners are embodied by the
 ///   application, (aka D2), is a listener. Listeners are embodied by the
@@ -65,7 +66,7 @@
 namespace isc {
 namespace isc {
 namespace d2 {
 namespace d2 {
 
 
-/// @brief Exception thrown if an NcrListenerError occurs.
+/// @brief Exception thrown if an NcrListenerError encounters a general error.
 class NcrListenerError : public isc::Exception {
 class NcrListenerError : public isc::Exception {
 public:
 public:
     NcrListenerError(const char* file, size_t line, const char* what) :
     NcrListenerError(const char* file, size_t line, const char* what) :
@@ -168,16 +169,15 @@ public:
         /// result is NameChangeListener::SUCCESS.  It is indeterminate other
         /// result is NameChangeListener::SUCCESS.  It is indeterminate other
         /// wise.
         /// wise.
         /// @throw This method MUST NOT throw.
         /// @throw This method MUST NOT throw.
-        virtual void operator ()(Result result, NameChangeRequestPtr ncr) = 0;
+        virtual void operator ()(const Result result, 
+                                 NameChangeRequestPtr& ncr) = 0;
     };
     };
 
 
     /// @brief Constructor
     /// @brief Constructor
     ///
     ///
     /// @param recv_handler is a pointer the application layer handler to be
     /// @param recv_handler is a pointer the application layer handler to be
     /// invoked each time a NCR is received or a receive error occurs.
     /// invoked each time a NCR is received or a receive error occurs.
-    ///
-    /// @throw throws NcrListenerError if recv_handler is NULL.
-    NameChangeListener(const RequestReceiveHandler* recv_handler);
+    NameChangeListener(RequestReceiveHandler& recv_handler);
 
 
     /// @brief Destructor
     /// @brief Destructor
     virtual ~NameChangeListener() {
     virtual ~NameChangeListener() {
@@ -207,11 +207,27 @@ public:
     /// is called.  This method MUST be invoked by the derivation's
     /// is called.  This method MUST be invoked by the derivation's
     /// implementation of doReceive.
     /// implementation of doReceive.
     ///
     ///
+    /// NOTE:
+    /// The handler invoked by this method MUST NOT THROW. The handler is
+    /// at application level and should trap and handle any errors at
+    /// that level, rather than throw exceptions.  If an error has occurred
+    /// prior to invoking the handler, it will be expressed in terms a failed
+    /// result being passed to the handler, not a throw.  Therefore any 
+    /// exceptions at the handler level are application issues and should be 
+    /// dealt with at that level.
+    ///
+    /// If the handler were to throw, the exception will surface at 
+    /// IOService::run (or run variant) method invocation as this occurs as 
+    /// part of the callback chain.  This will cause the invocation of  
+    /// doReceive to be skipped which will break the listen-receive-listen 
+    /// cycle. To restart the cycle it would be necessary to call  
+    /// stopListener() and then startListener().
+    ///
     /// @param result contains that receive outcome status.
     /// @param result contains that receive outcome status.
     /// @param ncr is a pointer to the newly received NameChangeRequest if
     /// @param ncr is a pointer to the newly received NameChangeRequest if
     /// result is NameChangeListener::SUCCESS.  It is indeterminate other
     /// result is NameChangeListener::SUCCESS.  It is indeterminate other
     /// wise.
     /// wise.
-    void invokeRecvHandler(Result result, NameChangeRequestPtr ncr);
+    void invokeRecvHandler(const Result result, NameChangeRequestPtr& ncr);
 
 
     /// @brief Abstract method which opens the IO source for reception.
     /// @brief Abstract method which opens the IO source for reception.
     ///
     ///
@@ -266,7 +282,7 @@ private:
     bool listening_;
     bool listening_;
 
 
     /// @brief Application level NCR receive completion handler.
     /// @brief Application level NCR receive completion handler.
-    const RequestReceiveHandler* recv_handler_;
+    RequestReceiveHandler& recv_handler_;
 };
 };
 
 
 /// @brief Defines a smart pointer to an instance of a listener.
 /// @brief Defines a smart pointer to an instance of a listener.
@@ -288,9 +304,9 @@ public:
 };
 };
 
 
 /// @brief Exception thrown if an error occurs initiating an IO send.
 /// @brief Exception thrown if an error occurs initiating an IO send.
-class NcrSenderQueFull : public isc::Exception {
+class NcrSenderQueueFull : public isc::Exception {
 public:
 public:
-    NcrSenderQueFull(const char* file, size_t line, const char* what) :
+    NcrSenderQueueFull(const char* file, size_t line, const char* what) :
         isc::Exception(file, line, what) { };
         isc::Exception(file, line, what) { };
 };
 };
 
 
@@ -324,7 +340,7 @@ public:
 /// will remain there until one of three things occur:
 /// will remain there until one of three things occur:
 ///     * It is successfully delivered
 ///     * It is successfully delivered
 ///     * @c NameChangeSender::skipNext() is called
 ///     * @c NameChangeSender::skipNext() is called
-///     * @c NameChangeSender::flushSendQue() is called
+///     * @c NameChangeSender::clearSendQueue() is called
 ///
 ///
 /// The queue contents are preserved across start and stop listening
 /// The queue contents are preserved across start and stop listening
 /// transitions. This is to provide for error recovery without losing
 /// transitions. This is to provide for error recovery without losing
@@ -387,10 +403,10 @@ class NameChangeSender {
 public:
 public:
 
 
     /// @brief Defines the type used for the request send queue.
     /// @brief Defines the type used for the request send queue.
-    typedef std::deque<NameChangeRequestPtr> SendQue;
+    typedef std::deque<NameChangeRequestPtr> SendQueue;
 
 
     /// @brief Defines a default maximum number of entries in the send queue.
     /// @brief Defines a default maximum number of entries in the send queue.
-    static const size_t MAX_QUE_DEFAULT = 1024;
+    static const size_t MAX_QUEUE_DEFAULT = 1024;
 
 
     /// @brief Defines the outcome of an asynchronous NCR send.
     /// @brief Defines the outcome of an asynchronous NCR send.
     enum Result {
     enum Result {
@@ -418,20 +434,18 @@ public:
         /// delivered (or attempted).
         /// delivered (or attempted).
         ///
         ///
         /// @throw This method MUST NOT throw.
         /// @throw This method MUST NOT throw.
-        virtual void operator ()(Result result, NameChangeRequestPtr ncr) = 0;
+        virtual void operator ()(const Result result, NameChangeRequestPtr& ncr) = 0;
     };
     };
 
 
     /// @brief Constructor
     /// @brief Constructor
     ///
     ///
     /// @param send_handler is a pointer the application layer handler to be
     /// @param send_handler is a pointer the application layer handler to be
     /// invoked each time a NCR send attempt completes.
     /// invoked each time a NCR send attempt completes.
-    /// @param send_que_max is the maximum number of entries allowed in the
+    /// @param send_queue_max is the maximum number of entries allowed in the
     /// send queue.  Once the maximum number is reached, all calls to
     /// send queue.  Once the maximum number is reached, all calls to
     /// sendRequest will fail with an exception.
     /// sendRequest will fail with an exception.
-    ///
-    /// @throw throws NcrSenderError if send_handler is NULL.
-    NameChangeSender(const RequestSendHandler* send_handler,
-            size_t send_que_max = MAX_QUE_DEFAULT);
+    NameChangeSender(RequestSendHandler& send_handler,
+            size_t send_queue_max = MAX_QUEUE_DEFAULT);
 
 
     /// @brief Destructor
     /// @brief Destructor
     virtual ~NameChangeSender() {
     virtual ~NameChangeSender() {
@@ -458,13 +472,14 @@ public:
     ///
     ///
     /// The given request is placed at the back of the send queue and then
     /// The given request is placed at the back of the send queue and then
     /// sendNext is invoked.
     /// sendNext is invoked.
+
     ///
     ///
     /// @param ncr is the NameChangeRequest to send.
     /// @param ncr is the NameChangeRequest to send.
     ///
     ///
     /// @throw throws NcrSenderError if the sender is not in sending state or
     /// @throw throws NcrSenderError if the sender is not in sending state or
-    /// the request is empty; NcrSenderQueFull if the send queue has reached
+    /// the request is empty; NcrSenderQueueFull if the send queue has reached
     /// capacity.
     /// capacity.
-    void sendRequest(NameChangeRequestPtr ncr);
+    void sendRequest(NameChangeRequestPtr& ncr);
 
 
     /// @brief Dequeues and sends the next request on the send queue.
     /// @brief Dequeues and sends the next request on the send queue.
     ///
     ///
@@ -484,8 +499,24 @@ public:
     /// If not we leave it there so we can retry it.  After we invoke the
     /// If not we leave it there so we can retry it.  After we invoke the
     /// handler we clear the pending ncr value and queue up the next send.
     /// handler we clear the pending ncr value and queue up the next send.
     ///
     ///
+    /// NOTE:
+    /// The handler invoked by this method MUST NOT THROW. The handler is
+    /// application level logic and should trap and handle any errors at
+    /// that level, rather than throw exceptions.  If IO errors have occurred
+    /// prior to invoking the handler, they are expressed in terms a failed
+    /// result being passed to the handler.  Therefore any exceptions at the
+    /// handler level are application issues and should be dealt with at that
+    /// level.
+    ///
+    /// If the handler were to throw, the exception will surface at 
+    /// IOService::run (or run variant) method invocation as this occurs as 
+    /// part of the callback chain.  This will cause the invocation of  
+    /// sendNext to be skipped which will interrupt automatic buffer drain 
+    /// cycle.  Assuming there is not a connectivity issue, the cycle will
+    /// resume with the next sendRequest call, or an explicit call to sendNext.
+    ///
     /// @param result contains that send outcome status.
     /// @param result contains that send outcome status.
-    void invokeSendHandler(NameChangeSender::Result result);
+    void invokeSendHandler(const NameChangeSender::Result result);
 
 
     /// @brief Removes the request at the front of the send queue
     /// @brief Removes the request at the front of the send queue
     ///
     ///
@@ -502,11 +533,11 @@ public:
 
 
     /// @brief Flushes all entries in the send queue
     /// @brief Flushes all entries in the send queue
     ///
     ///
-    /// This method can be used to flush all of the NCRs currently in the
+    /// This method can be used to discard all of the NCRs currently in the
     /// the send queue.  Note it may not be called while the sender is in
     /// the send queue.  Note it may not be called while the sender is in
-    /// the sending state.
+    /// the sending state. 
     /// @throw throws NcrSenderError if called and sender is in sending state.
     /// @throw throws NcrSenderError if called and sender is in sending state.
-    void flushSendQue();
+    void clearSendQueue();
 
 
     /// @brief Abstract method which opens the IO sink for transmission.
     /// @brief Abstract method which opens the IO sink for transmission.
     ///
     ///
@@ -556,23 +587,14 @@ public:
         return ((ncr_to_send_) ? true : false);
         return ((ncr_to_send_) ? true : false);
     }
     }
 
 
-    /// @brief Returns the request that is in the process of being sent.
-    ///
-    /// The pointer returned by this method will be populated with the
-    /// request that has been passed into doSend() and for which the
-    /// completion callback has not yet been invoked.
-    const NameChangeRequestPtr& getNcrToSend() {
-        return (ncr_to_send_);
-    }
-
     /// @brief Returns the maximum number of entries allowed in the send queue.
     /// @brief Returns the maximum number of entries allowed in the send queue.
-    size_t getQueMaxSize() const  {
-        return (send_que_max_);
+    size_t getQueueMaxSize() const  {
+        return (send_queue_max_);
     }
     }
 
 
     /// @brief Returns the number of entries currently in the send queue.
     /// @brief Returns the number of entries currently in the send queue.
-    size_t getQueSize() const {
-        return (send_que_.size());
+    size_t getQueueSize() const {
+        return (send_queue_.size());
     }
     }
 
 
 private:
 private:
@@ -590,13 +612,13 @@ private:
     bool sending_;
     bool sending_;
 
 
     /// @brief A pointer to regisetered send completion handler.
     /// @brief A pointer to regisetered send completion handler.
-    const RequestSendHandler* send_handler_;
+    RequestSendHandler& send_handler_;
 
 
     /// @brief Maximum number of entries permitted in the send queue.
     /// @brief Maximum number of entries permitted in the send queue.
-    size_t send_que_max_;
+    size_t send_queue_max_;
 
 
     /// @brief Queue of the requests waiting to be sent.
     /// @brief Queue of the requests waiting to be sent.
-    SendQue send_que_;
+    SendQueue send_queue_;
 
 
     /// @brief Pointer to the request which is in the process of being sent.
     /// @brief Pointer to the request which is in the process of being sent.
     NameChangeRequestPtr ncr_to_send_;
     NameChangeRequestPtr ncr_to_send_;

+ 15 - 18
src/bin/d2/ncr_udp.cc

@@ -22,7 +22,6 @@
 namespace isc {
 namespace isc {
 namespace d2 {
 namespace d2 {
 
 
-
 //*************************** UDPCallback ***********************
 //*************************** UDPCallback ***********************
 
 
 UDPCallback::UDPCallback (RawBufferPtr buffer, size_t buf_size,
 UDPCallback::UDPCallback (RawBufferPtr buffer, size_t buf_size,
@@ -40,7 +39,7 @@ UDPCallback::UDPCallback (RawBufferPtr buffer, size_t buf_size,
 
 
 void
 void
 UDPCallback::operator ()(const asio::error_code error_code,
 UDPCallback::operator ()(const asio::error_code error_code,
-                             const size_t bytes_transferred) {
+                         const size_t bytes_transferred) {
 
 
     // Save the result state and number of bytes transferred.
     // Save the result state and number of bytes transferred.
     setErrorCode(error_code);
     setErrorCode(error_code);
@@ -70,25 +69,23 @@ UDPCallback::putData(const uint8_t* src, size_t len) {
 
 
 
 
 //*************************** NameChangeUDPListener ***********************
 //*************************** NameChangeUDPListener ***********************
-
-NameChangeUDPListener::NameChangeUDPListener(
-            const isc::asiolink::IOAddress& ip_address, const uint32_t port,
-            NameChangeFormat format,
-            const RequestReceiveHandler* ncr_recv_handler,
-            const bool reuse_address)
+NameChangeUDPListener::
+NameChangeUDPListener(const isc::asiolink::IOAddress& ip_address, 
+                      const uint32_t port, NameChangeFormat format, 
+                      RequestReceiveHandler& ncr_recv_handler,
+                      const bool reuse_address)
     : NameChangeListener(ncr_recv_handler), ip_address_(ip_address),
     : NameChangeListener(ncr_recv_handler), ip_address_(ip_address),
       port_(port), format_(format), reuse_address_(reuse_address) {
       port_(port), format_(format), reuse_address_(reuse_address) {
     // Instantiate the receive callback.  This gets passed into each receive.
     // Instantiate the receive callback.  This gets passed into each receive.
     // Note that the callback constructor is passed an instance method
     // Note that the callback constructor is passed an instance method
     // pointer to our recv_completion_handler.
     // pointer to our recv_completion_handler.
-    recv_callback_.reset(new UDPCallback(
-                                       RawBufferPtr(new uint8_t[RECV_BUF_MAX]),
-                                       RECV_BUF_MAX,
-                                       UDPEndpointPtr(new asiolink::
-                                                      UDPEndpoint()),
-                                       boost::bind(&NameChangeUDPListener::
-                                       recv_completion_handler, this,
-                                       _1, _2)));
+    recv_callback_.reset(new 
+                         UDPCallback(RawBufferPtr(new uint8_t[RECV_BUF_MAX]),
+                                     RECV_BUF_MAX,
+                                     UDPEndpointPtr(new 
+                                                    asiolink::UDPEndpoint()),
+                                     boost::bind(&NameChangeUDPListener::
+                                     recv_completion_handler, this, _1, _2)));
 }
 }
 
 
 NameChangeUDPListener::~NameChangeUDPListener() {
 NameChangeUDPListener::~NameChangeUDPListener() {
@@ -113,7 +110,7 @@ NameChangeUDPListener::open(isc::asiolink::IOService& io_service) {
             asio_socket_->set_option(asio::socket_base::reuse_address(true));
             asio_socket_->set_option(asio::socket_base::reuse_address(true));
         }
         }
 
 
-        // Bind the low leve socket to our endpoint.
+        // Bind the low level socket to our endpoint.
         asio_socket_->bind(endpoint.getASIOEndpoint());
         asio_socket_->bind(endpoint.getASIOEndpoint());
     } catch (asio::system_error& ex) {
     } catch (asio::system_error& ex) {
         isc_throw (NcrUDPError, ex.code().message());
         isc_throw (NcrUDPError, ex.code().message());
@@ -190,7 +187,7 @@ NameChangeUDPSender::NameChangeUDPSender(
             const isc::asiolink::IOAddress& ip_address, const uint32_t port,
             const isc::asiolink::IOAddress& ip_address, const uint32_t port,
             const isc::asiolink::IOAddress& server_address,
             const isc::asiolink::IOAddress& server_address,
             const uint32_t server_port, const NameChangeFormat format,
             const uint32_t server_port, const NameChangeFormat format,
-            RequestSendHandler* ncr_send_handler, const size_t send_que_max,
+            RequestSendHandler& ncr_send_handler, const size_t send_que_max,
             const bool reuse_address)
             const bool reuse_address)
     : NameChangeSender(ncr_send_handler, send_que_max),
     : NameChangeSender(ncr_send_handler, send_que_max),
       ip_address_(ip_address), port_(port), server_address_(server_address),
       ip_address_(ip_address), port_(port), server_address_(server_address),

+ 7 - 4
src/bin/d2/ncr_udp.h

@@ -341,7 +341,11 @@ public:
     NameChangeUDPListener(const isc::asiolink::IOAddress& ip_address,
     NameChangeUDPListener(const isc::asiolink::IOAddress& ip_address,
                           const uint32_t port,
                           const uint32_t port,
                           const NameChangeFormat format,
                           const NameChangeFormat format,
+#if 0
                           const RequestReceiveHandler* ncr_recv_handler,
                           const RequestReceiveHandler* ncr_recv_handler,
+#else
+                          RequestReceiveHandler& ncr_recv_handler,
+#endif
                           const bool reuse_address = false);
                           const bool reuse_address = false);
 
 
     /// @brief Destructor.
     /// @brief Destructor.
@@ -460,16 +464,15 @@ public:
     /// when a send completes.
     /// when a send completes.
     /// @param send_que_max sets the maximum number of entries allowed in
     /// @param send_que_max sets the maximum number of entries allowed in
     /// the send queue.
     /// the send queue.
-    /// It defaults to NameChangeSender::MAX_QUE_DEFAULT
+    /// It defaults to NameChangeSender::MAX_QUEUE_DEFAULT
     /// @param reuse_address enables IP address sharing when true
     /// @param reuse_address enables IP address sharing when true
     /// It defaults to false.
     /// It defaults to false.
     ///
     ///
-    /// @throw base class throws NcrSenderError if handler is invalid.
     NameChangeUDPSender(const isc::asiolink::IOAddress& ip_address,
     NameChangeUDPSender(const isc::asiolink::IOAddress& ip_address,
         const uint32_t port, const isc::asiolink::IOAddress& server_address,
         const uint32_t port, const isc::asiolink::IOAddress& server_address,
         const uint32_t server_port, const NameChangeFormat format,
         const uint32_t server_port, const NameChangeFormat format,
-        RequestSendHandler * ncr_send_handler,
-        const size_t send_que_max = NameChangeSender::MAX_QUE_DEFAULT,
+        RequestSendHandler& ncr_send_handler,
+        const size_t send_que_max = NameChangeSender::MAX_QUEUE_DEFAULT,
         const bool reuse_address = false);
         const bool reuse_address = false);
 
 
     /// @brief Destructor
     /// @brief Destructor

+ 41 - 46
src/bin/d2/tests/ncr_udp_unittests.cc

@@ -75,29 +75,23 @@ const long TEST_TIMEOUT = 5 * 1000;
 /// @brief A NOP derivation for constructor test purposes.
 /// @brief A NOP derivation for constructor test purposes.
 class SimpleListenHandler : public NameChangeListener::RequestReceiveHandler {
 class SimpleListenHandler : public NameChangeListener::RequestReceiveHandler {
 public:
 public:
-    virtual void operator ()(NameChangeListener::Result, NameChangeRequestPtr) {
+    virtual void operator ()(const NameChangeListener::Result, 
+                             NameChangeRequestPtr&) {
     }
     }
 };
 };
 
 
 /// @brief Tests the NameChangeUDPListener constructors.
 /// @brief Tests the NameChangeUDPListener constructors.
 /// This test verifies that:
 /// This test verifies that:
-/// 1. Listener constructor requires valid completion handler
-/// 2. Given valid parameters, the listener constructor works
+/// 1. Given valid parameters, the listener constructor works
 TEST(NameChangeUDPListenerBasicTest, constructionTests) {
 TEST(NameChangeUDPListenerBasicTest, constructionTests) {
     // Verify the default constructor works.
     // Verify the default constructor works.
     isc::asiolink::IOAddress ip_address(TEST_ADDRESS);
     isc::asiolink::IOAddress ip_address(TEST_ADDRESS);
     uint32_t port = LISTENER_PORT;
     uint32_t port = LISTENER_PORT;
     isc::asiolink::IOService io_service;
     isc::asiolink::IOService io_service;
     SimpleListenHandler ncr_handler;
     SimpleListenHandler ncr_handler;
-
-    // Verify that constructing with an empty receive handler is not allowed.
-    EXPECT_THROW(NameChangeUDPListener(ip_address, port, FMT_JSON, NULL),
-                                       NcrListenerError);
-
     // Verify that valid constructor works.
     // Verify that valid constructor works.
     EXPECT_NO_THROW(NameChangeUDPListener(ip_address, port, FMT_JSON,
     EXPECT_NO_THROW(NameChangeUDPListener(ip_address, port, FMT_JSON,
-                                          &ncr_handler));
-
+                                          ncr_handler));
 }
 }
 
 
 /// @brief Tests NameChangeUDPListener starting and stopping listening .
 /// @brief Tests NameChangeUDPListener starting and stopping listening .
@@ -115,7 +109,7 @@ TEST(NameChangeUDPListenerBasicTest, basicListenTests) {
 
 
     NameChangeListenerPtr listener;
     NameChangeListenerPtr listener;
     ASSERT_NO_THROW(listener.reset(
     ASSERT_NO_THROW(listener.reset(
-        new NameChangeUDPListener(ip_address, port, FMT_JSON, &ncr_handler)));
+        new NameChangeUDPListener(ip_address, port, FMT_JSON, ncr_handler)));
 
 
     // Verify that we can start listening.
     // Verify that we can start listening.
     EXPECT_NO_THROW(listener->startListening(io_service));
     EXPECT_NO_THROW(listener->startListening(io_service));
@@ -165,7 +159,7 @@ public:
           test_timer_(io_service_) {
           test_timer_(io_service_) {
         isc::asiolink::IOAddress addr(TEST_ADDRESS);
         isc::asiolink::IOAddress addr(TEST_ADDRESS);
         listener_ = new NameChangeUDPListener(addr, LISTENER_PORT,
         listener_ = new NameChangeUDPListener(addr, LISTENER_PORT,
-                                              FMT_JSON, this, true);
+                                              FMT_JSON, *this, true);
 
 
         // Set the test timeout to break any running tasks if they hang.
         // Set the test timeout to break any running tasks if they hang.
         test_timer_.setup(boost::bind(&NameChangeUDPListenerTest::
         test_timer_.setup(boost::bind(&NameChangeUDPListenerTest::
@@ -206,8 +200,8 @@ public:
     /// The fixture acts as the "application" layer.  It derives from
     /// The fixture acts as the "application" layer.  It derives from
     /// RequestReceiveHandler and as such implements operator() in order to
     /// RequestReceiveHandler and as such implements operator() in order to
     /// receive NCRs.
     /// receive NCRs.
-    virtual void operator ()(NameChangeListener::Result result,
-                             NameChangeRequestPtr ncr) {
+    virtual void operator ()(const NameChangeListener::Result result,
+                             NameChangeRequestPtr& ncr) {
         // save the result and the NCR we received
         // save the result and the NCR we received
         result_ = result;
         result_ = result;
         received_ncr_ = ncr;
         received_ncr_ = ncr;
@@ -256,42 +250,43 @@ TEST_F(NameChangeUDPListenerTest, basicReceivetest) {
 /// @brief A NOP derivation for constructor test purposes.
 /// @brief A NOP derivation for constructor test purposes.
 class SimpleSendHandler : public NameChangeSender::RequestSendHandler {
 class SimpleSendHandler : public NameChangeSender::RequestSendHandler {
 public:
 public:
-    virtual void operator ()(NameChangeSender::Result, NameChangeRequestPtr) {
+    virtual void operator ()(const NameChangeSender::Result, 
+                             NameChangeRequestPtr&) {
     }
     }
 };
 };
 
 
 /// @brief Tests the NameChangeUDPSender constructors.
 /// @brief Tests the NameChangeUDPSender constructors.
 /// This test verifies that:
 /// This test verifies that:
-/// 1. Sender constructor requires valid completion handler
+/// 1. Constructing with a max queue size of 0 is not allowed
 /// 2. Given valid parameters, the sender constructor works
 /// 2. Given valid parameters, the sender constructor works
+/// 3. Default construction provides default max queue size 
+/// 4. Construction with a custom max queue size works
 TEST(NameChangeUDPSenderBasicTest, constructionTests) {
 TEST(NameChangeUDPSenderBasicTest, constructionTests) {
     isc::asiolink::IOAddress ip_address(TEST_ADDRESS);
     isc::asiolink::IOAddress ip_address(TEST_ADDRESS);
     uint32_t port = SENDER_PORT;
     uint32_t port = SENDER_PORT;
     isc::asiolink::IOService io_service;
     isc::asiolink::IOService io_service;
     SimpleSendHandler ncr_handler;
     SimpleSendHandler ncr_handler;
 
 
-    // Verify that constructing with an empty send handler is not allowed.
-    EXPECT_THROW(NameChangeUDPSender(ip_address, port,
-        ip_address, port, FMT_JSON, NULL), NcrSenderError);
-
     // Verify that constructing with an queue size of zero is not allowed.
     // Verify that constructing with an queue size of zero is not allowed.
     EXPECT_THROW(NameChangeUDPSender(ip_address, port,
     EXPECT_THROW(NameChangeUDPSender(ip_address, port,
-        ip_address, port, FMT_JSON, &ncr_handler, 0), NcrSenderError);
+        ip_address, port, FMT_JSON, ncr_handler, 0), NcrSenderError);
 
 
     NameChangeSenderPtr sender;
     NameChangeSenderPtr sender;
     // Verify that valid constructor works.
     // Verify that valid constructor works.
     EXPECT_NO_THROW(sender.reset(
     EXPECT_NO_THROW(sender.reset(
                     new NameChangeUDPSender(ip_address, port, ip_address, port,
                     new NameChangeUDPSender(ip_address, port, ip_address, port,
-                                            FMT_JSON, &ncr_handler)));
+                                            FMT_JSON, ncr_handler)));
 
 
     // Verify that send queue default max is correct.
     // Verify that send queue default max is correct.
-    size_t expected = NameChangeSender::MAX_QUE_DEFAULT;
-    EXPECT_EQ(expected, sender->getQueMaxSize());
+    size_t expected = NameChangeSender::MAX_QUEUE_DEFAULT;
+    EXPECT_EQ(expected, sender->getQueueMaxSize());
 
 
     // Verify that constructor with a valid custom queue size works.
     // Verify that constructor with a valid custom queue size works.
     EXPECT_NO_THROW(sender.reset(
     EXPECT_NO_THROW(sender.reset(
                     new NameChangeUDPSender(ip_address, port, ip_address, port,
                     new NameChangeUDPSender(ip_address, port, ip_address, port,
-                                            FMT_JSON, &ncr_handler, 100)));
+                                            FMT_JSON, ncr_handler, 100)));
+
+    EXPECT_EQ(100, sender->getQueueMaxSize());
 }
 }
 
 
 /// @brief Tests NameChangeUDPSender basic send functionality
 /// @brief Tests NameChangeUDPSender basic send functionality
@@ -308,7 +303,7 @@ TEST(NameChangeUDPSenderBasicTest, basicSendTests) {
     // Create the sender, setting the queue max equal to the number of
     // Create the sender, setting the queue max equal to the number of
     // messages we will have in the list.
     // messages we will have in the list.
     NameChangeUDPSender sender(ip_address, port, ip_address, port,
     NameChangeUDPSender sender(ip_address, port, ip_address, port,
-                               FMT_JSON, &ncr_handler, num_msgs);
+                               FMT_JSON, ncr_handler, num_msgs);
 
 
     // Verify that we can start sending.
     // Verify that we can start sending.
     EXPECT_NO_THROW(sender.startSending(io_service));
     EXPECT_NO_THROW(sender.startSending(io_service));
@@ -336,12 +331,12 @@ TEST(NameChangeUDPSenderBasicTest, basicSendTests) {
         ASSERT_NO_THROW(ncr = NameChangeRequest::fromJSON(valid_msgs[i]));
         ASSERT_NO_THROW(ncr = NameChangeRequest::fromJSON(valid_msgs[i]));
         EXPECT_NO_THROW(sender.sendRequest(ncr));
         EXPECT_NO_THROW(sender.sendRequest(ncr));
         // Verify that the queue count increments in step with each send.
         // Verify that the queue count increments in step with each send.
-        EXPECT_EQ(i+1, sender.getQueSize());
+        EXPECT_EQ(i+1, sender.getQueueSize());
     }
     }
 
 
     // Verify that attempting to send an additional message results in a
     // Verify that attempting to send an additional message results in a
     // queue full exception.
     // queue full exception.
-    EXPECT_THROW(sender.sendRequest(ncr), NcrSenderQueFull);
+    EXPECT_THROW(sender.sendRequest(ncr), NcrSenderQueueFull);
 
 
     // Loop for the number of valid messages and invoke IOService::run_one.
     // Loop for the number of valid messages and invoke IOService::run_one.
     // This should send exactly one message and the queue count should
     // This should send exactly one message and the queue count should
@@ -349,37 +344,37 @@ TEST(NameChangeUDPSenderBasicTest, basicSendTests) {
     for (int i = num_msgs; i > 0; i--) {
     for (int i = num_msgs; i > 0; i--) {
         io_service.run_one();
         io_service.run_one();
         // Verify that the queue count decrements in step with each run.
         // Verify that the queue count decrements in step with each run.
-        EXPECT_EQ(i-1, sender.getQueSize());
+        EXPECT_EQ(i-1, sender.getQueueSize());
     }
     }
 
 
     // Verify that the queue is empty.
     // Verify that the queue is empty.
-    EXPECT_EQ(0, sender.getQueSize());
+    EXPECT_EQ(0, sender.getQueueSize());
 
 
     // Verify that we can add back to the queue
     // Verify that we can add back to the queue
     EXPECT_NO_THROW(sender.sendRequest(ncr));
     EXPECT_NO_THROW(sender.sendRequest(ncr));
-    EXPECT_EQ(1, sender.getQueSize());
+    EXPECT_EQ(1, sender.getQueueSize());
 
 
     // Verify that we can remove the current entry at the front of the queue.
     // Verify that we can remove the current entry at the front of the queue.
     EXPECT_NO_THROW(sender.skipNext());
     EXPECT_NO_THROW(sender.skipNext());
-    EXPECT_EQ(0, sender.getQueSize());
+    EXPECT_EQ(0, sender.getQueueSize());
 
 
     // Verify that flushing the queue is not allowed in sending state.
     // Verify that flushing the queue is not allowed in sending state.
-    EXPECT_THROW(sender.flushSendQue(), NcrSenderError);
+    EXPECT_THROW(sender.clearSendQueue(), NcrSenderError);
 
 
     // Put a message on the queue.
     // Put a message on the queue.
     EXPECT_NO_THROW(sender.sendRequest(ncr));
     EXPECT_NO_THROW(sender.sendRequest(ncr));
-    EXPECT_EQ(1, sender.getQueSize());
+    EXPECT_EQ(1, sender.getQueueSize());
 
 
     // Verify that we can gracefully stop sending.
     // Verify that we can gracefully stop sending.
     EXPECT_NO_THROW(sender.stopSending());
     EXPECT_NO_THROW(sender.stopSending());
     EXPECT_FALSE(sender.amSending());
     EXPECT_FALSE(sender.amSending());
 
 
     // Verify that the queue is preserved after leaving sending state.
     // Verify that the queue is preserved after leaving sending state.
-    EXPECT_EQ(1, sender.getQueSize());
+    EXPECT_EQ(1, sender.getQueueSize());
 
 
     // Verify that flushing the queue works when not sending.
     // Verify that flushing the queue works when not sending.
-    EXPECT_NO_THROW(sender.flushSendQue());
-    EXPECT_EQ(0, sender.getQueSize());
+    EXPECT_NO_THROW(sender.clearSendQueue());
+    EXPECT_EQ(0, sender.getQueueSize());
 }
 }
 
 
 /// @brief Text fixture that allows testing a listener and sender together
 /// @brief Text fixture that allows testing a listener and sender together
@@ -406,12 +401,12 @@ public:
         // Create our listener instance. Note that reuse_address is true.
         // Create our listener instance. Note that reuse_address is true.
         listener_.reset(
         listener_.reset(
             new NameChangeUDPListener(addr, LISTENER_PORT, FMT_JSON,
             new NameChangeUDPListener(addr, LISTENER_PORT, FMT_JSON,
-                                      this, true));
+                                      *this, true));
 
 
         // Create our sender instance. Note that reuse_address is true.
         // Create our sender instance. Note that reuse_address is true.
         sender_.reset(
         sender_.reset(
             new NameChangeUDPSender(addr, SENDER_PORT, addr, LISTENER_PORT,
             new NameChangeUDPSender(addr, SENDER_PORT, addr, LISTENER_PORT,
-                                    FMT_JSON, this, 100, true));
+                                    FMT_JSON, *this, 100, true));
 
 
         // Set the test timeout to break any running tasks if they hang.
         // Set the test timeout to break any running tasks if they hang.
         test_timer_.setup(boost::bind(&NameChangeUDPTest::testTimeoutHandler,
         test_timer_.setup(boost::bind(&NameChangeUDPTest::testTimeoutHandler,
@@ -425,16 +420,16 @@ public:
     }
     }
 
 
     /// @brief Implements the receive completion handler.
     /// @brief Implements the receive completion handler.
-    virtual void operator ()(NameChangeListener::Result result,
-                             NameChangeRequestPtr ncr) {
+    virtual void operator ()(const NameChangeListener::Result result,
+                             NameChangeRequestPtr& ncr) {
         // save the result and the NCR received.
         // save the result and the NCR received.
         recv_result_ = result;
         recv_result_ = result;
         received_ncrs_.push_back(ncr);
         received_ncrs_.push_back(ncr);
     }
     }
 
 
     /// @brief Implements the send completion handler.
     /// @brief Implements the send completion handler.
-    virtual void operator ()(NameChangeSender::Result result,
-                             NameChangeRequestPtr ncr) {
+    virtual void operator ()(const NameChangeSender::Result result,
+                             NameChangeRequestPtr& ncr) {
         // save the result and the NCR sent.
         // save the result and the NCR sent.
         send_result_ = result;
         send_result_ = result;
         sent_ncrs_.push_back(ncr);
         sent_ncrs_.push_back(ncr);
@@ -469,16 +464,16 @@ TEST_F (NameChangeUDPTest, roundTripTest) {
         NameChangeRequestPtr ncr;
         NameChangeRequestPtr ncr;
         ASSERT_NO_THROW(ncr = NameChangeRequest::fromJSON(valid_msgs[i]));
         ASSERT_NO_THROW(ncr = NameChangeRequest::fromJSON(valid_msgs[i]));
         sender_->sendRequest(ncr);
         sender_->sendRequest(ncr);
-        EXPECT_EQ(i+1, sender_->getQueSize());
+        EXPECT_EQ(i+1, sender_->getQueueSize());
     }
     }
 
 
     // Execute callbacks until we have sent and received all of messages.
     // Execute callbacks until we have sent and received all of messages.
-    while (sender_->getQueSize() > 0 || (received_ncrs_.size() < num_msgs)) {
+    while (sender_->getQueueSize() > 0 || (received_ncrs_.size() < num_msgs)) {
         EXPECT_NO_THROW(io_service_.run_one());
         EXPECT_NO_THROW(io_service_.run_one());
     }
     }
 
 
     // Send queue should be empty.
     // Send queue should be empty.
-    EXPECT_EQ(0, sender_->getQueSize());
+    EXPECT_EQ(0, sender_->getQueueSize());
 
 
     // We should have the same number of sends and receives as we do messages.
     // We should have the same number of sends and receives as we do messages.
     ASSERT_EQ(num_msgs, sent_ncrs_.size());
     ASSERT_EQ(num_msgs, sent_ncrs_.size());