]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3281] use shared_from_this
authorRazvan Becheriu <razvan@isc.org>
Fri, 15 Mar 2024 23:44:37 +0000 (01:44 +0200)
committerRazvan Becheriu <razvan@isc.org>
Thu, 4 Apr 2024 05:26:51 +0000 (08:26 +0300)
20 files changed:
src/bin/d2/d2_process.cc
src/bin/d2/d2_process.h
src/bin/d2/tests/d2_process_unittests.cc
src/bin/d2/tests/d2_queue_mgr_unittests.cc
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/tests/d2_unittest.cc
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/tests/d2_unittest.cc
src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.h
src/lib/dhcp_ddns/ncr_io.cc
src/lib/dhcp_ddns/ncr_io.h
src/lib/dhcp_ddns/ncr_udp.cc
src/lib/dhcp_ddns/tests/ncr_udp_unittests.cc
src/lib/dhcpsrv/d2_client_mgr.cc
src/lib/dhcpsrv/d2_client_mgr.h
src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc
src/lib/dhcpsrv/tests/d2_client_unittest.cc
src/lib/dhcpsrv/tests/d2_udp_unittest.cc
src/lib/dhcpsrv/tests/ncr_generator_unittest.cc
src/lib/http/client.cc

index 8ebc5400440eed9b6adbb5b350b195784d39d34a..40c436d59f7f6671d2c929688a10a901537373a0 100644 (file)
@@ -440,6 +440,12 @@ D2Process::reconfigureQueueMgr() {
 
 D2Process::~D2Process() {
     queue_mgr_->stopListening();
+    getIOService()->restart();
+    try {
+        getIOService()->poll();
+    } catch (...) {
+    }
+    queue_mgr_->removeListener();
 }
 
 D2CfgMgrPtr
index 5ca34222d3616a0166532c5acf6c6f80b510f268..11f5f9f9311409485cdb32da0b341a9e43256d68 100644 (file)
@@ -129,8 +129,7 @@ public:
     /// @return an Element that contains the results of argument processing,
     /// consisting of an integer status value (0 means successful,
     /// non-zero means failure), and a string explanation of the outcome.
-    virtual isc::data::ConstElementPtr
-        shutdown(isc::data::ConstElementPtr args);
+    virtual isc::data::ConstElementPtr shutdown(isc::data::ConstElementPtr args);
 
     /// @brief Processes the given configuration.
     ///
@@ -155,9 +154,8 @@ public:
     /// @return an Element that contains the results of configuration composed
     /// of an integer status value (0 means successful, non-zero means failure),
     /// and a string explanation of the outcome.
-    virtual isc::data::ConstElementPtr
-    configure(isc::data::ConstElementPtr config_set,
-              bool check_only = false);
+    virtual isc::data::ConstElementPtr configure(isc::data::ConstElementPtr config_set,
+                                                 bool check_only = false);
 
     /// @brief Destructor
     virtual ~D2Process();
@@ -318,7 +316,7 @@ private:
 /// @brief Defines a shared pointer to D2Process.
 typedef boost::shared_ptr<D2Process> D2ProcessPtr;
 
-}; // namespace isc::d2
-}; // namespace isc
+} // namespace isc::d2
+} // namespace isc
 
 #endif
index d4e1709421603eddb35456c520cdf6cba8ec9533..35727b814a501dee0550051c252875166398c4bb 100644 (file)
@@ -9,9 +9,11 @@
 #include <asiolink/io_service.h>
 #include <cc/command_interpreter.h>
 #include <d2srv/testutils/nc_test_utils.h>
+#include <d2/d2_controller.h>
 #include <d2/d2_process.h>
 #include <d2/tests/test_configured_libraries.h>
 #include <dhcp_ddns/ncr_io.h>
+#include <hooks/hooks_manager.h>
 #include <process/testutils/d_test_stubs.h>
 
 #include <boost/date_time/posix_time/posix_time.hpp>
@@ -25,6 +27,7 @@ using namespace isc;
 using namespace isc::config;
 using namespace isc::d2;
 using namespace isc::data;
+using namespace isc::hooks;
 using namespace isc::process;
 using namespace boost::posix_time;
 
@@ -64,6 +67,8 @@ public:
     D2ProcessTest() :
         D2Process("d2test",
                   asiolink::IOServicePtr(new isc::asiolink::IOService())) {
+        HooksManager::setTestMode(false);
+        D2Controller::instance();
     }
 
     /// @brief Destructor
index 153df5b97d8d77dbdaa53c6bb5342702844517ca..93f4166f3c65edcea0617f2d210165a3ed20b94f 100644 (file)
@@ -247,12 +247,15 @@ public:
     }
 
     virtual ~QueueMgrUDPTest() {
+        sender_->stopSending();
+        queue_mgr_->stopListening();
         test_timer_.cancel();
         io_service_->restart();
         try {
             io_service_->poll();
         } catch (...) {
         }
+        queue_mgr_->removeListener();
     }
 
     void reset_results() {
index cead6efbfbb100327f54644fdd99c939e4d48025..51a9e4735264bf9a2ac88314d9150e4c2e3ef43c 100644 (file)
@@ -4812,6 +4812,7 @@ Dhcpv4Srv::stopD2() {
     D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
     if (d2_mgr.ddnsEnabled()) {
         // Updates are enabled, so lets stop the sender
+        d2_mgr.stop();
         d2_mgr.stopSender();
     }
 }
index ebb2c4733b03104e67afa0252510c49681c674ec..68c9801da37d380723df9380a43be654286deed3 100644 (file)
@@ -370,6 +370,7 @@ TEST_F(Dhcp4SrvD2Test, DISABLED_forceUDPSendFailure) {
 
     // First message is off the queue.
     EXPECT_EQ(2, mgr.getQueueSize());
+    mgr.stop();
 }
 
 // Tests error handling of D2ClientMgr::sendRequest() failure
index 1f21a2f7e01d11b28b05b8760033e1fd64f786e0..86396258603d745a2890b184a57267ed2efe3602 100644 (file)
@@ -4626,6 +4626,7 @@ Dhcpv6Srv::stopD2() {
     D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
     if (d2_mgr.ddnsEnabled()) {
         // Updates are enabled, so lets stop the sender
+        d2_mgr.stop();
         d2_mgr.stopSender();
     }
 }
index 7b6ebdb11f04633769a669e46417d2ec11f05029..0246835cba34bd52c3cb6f656886afeaf0b1079b 100644 (file)
@@ -374,6 +374,7 @@ TEST_F(Dhcp6SrvD2Test, DISABLED_forceUDPSendFailure) {
 
     // First message is off the queue.
     EXPECT_EQ(2, mgr.getQueueSize());
+    mgr.stop();
 }
 
 // Tests error handling of D2ClientMgr::sendRequest() failure
index 2a6fb2e2b8d4de6f8ba0f515923189e926ac00b9..0052c229c1feee5749e2f4b28f98f9b97ba6b49d 100644 (file)
@@ -536,6 +536,7 @@ public:
 
     /// @brief Disables DHCP-DDNS updates.
     void disableD2() {
+        d2_mgr_.stop();
         d2_mgr_.stopSender();
         // Default constructor creates a config with DHCP-DDNS updates
         // disabled.
index 8028091efc37d698e61ef0005b0da670719051f0..70ded4bb8c44849507460fe06470a75aecdd729c 100644 (file)
@@ -48,14 +48,12 @@ std::string ncrProtocolToString(NameChangeProtocol protocol) {
     return (stream.str());
 }
 
-
 //************************** NameChangeListener ***************************
 
 NameChangeListener::NameChangeListener(RequestReceiveHandlerPtr recv_handler)
     : listening_(false), io_pending_(false), recv_handler_(recv_handler) {
 };
 
-
 void
 NameChangeListener::startListening(const isc::asiolink::IOServicePtr& io_service) {
     if (amListening()) {
@@ -231,6 +229,18 @@ NameChangeSender::stopSending() {
                   DHCP_DDNS_NCR_SEND_CLOSE_ERROR).arg(ex.what());
     }
 
+    if (io_service_) {
+        try {
+            io_service_->restart();
+            io_service_->poll();
+        } catch (const std::exception& ex) {
+            // Swallow exceptions. If we have some sort of error we'll log
+            // it but we won't propagate the throw.
+            LOG_ERROR(dhcp_ddns_logger,
+                      DHCP_DDNS_NCR_FLUSH_IO_ERROR).arg(ex.what());
+        }
+    }
+
     io_service_.reset();
 }
 
index d90ea926a993b286bf11b94403480cee1b81778c..b2b3287e02fbbbd4e0efb4b6aaf2363b21a06c60 100644 (file)
@@ -593,7 +593,7 @@ private:
     /// @brief Prepares the IO for transmission in a thread safe context.
     ///
     /// @param io_service is the IOService that will handle IO event processing.
-    void startSendingInternal(const isc::asiolink::IOServicePtr & io_service);
+    void startSendingInternal(const isc::asiolink::IOServicePtr& io_service);
 
     /// @brief Queues the given request to be sent in a thread safe context.
     ///
index 26579742f777fb2ef7ec1324e99f2aa07fae0790..bfbd8abb3330d64d9c688869f0da282c864083e2 100644 (file)
@@ -86,6 +86,7 @@ NameChangeUDPListener::~NameChangeUDPListener() {
 
 void
 NameChangeUDPListener::open(const isc::asiolink::IOServicePtr& io_service) {
+
     // create our endpoint and bind the low level socket to it.
     isc::asiolink::UDPEndpoint endpoint(ip_address_, port_);
 
@@ -299,7 +300,6 @@ NameChangeUDPSender::close() {
 
     closeWatchSocket();
     watch_socket_.reset();
-    io_service_.reset();
 }
 
 void
@@ -327,6 +327,9 @@ NameChangeUDPSender::doSend(NameChangeRequestPtr& ncr) {
 void
 NameChangeUDPSender::sendCompletionHandler(const bool successful,
                                            const UDPCallback *send_callback) {
+    if (!watch_socket_) {
+        return;
+    }
     // Clear the IO ready marker.
     try {
         watch_socket_->clearReady();
@@ -369,7 +372,7 @@ NameChangeUDPSender::getSelectFd() {
                                   " not in send mode");
     }
 
-    return(watch_socket_->getSelectFd());
+    return (watch_socket_->getSelectFd());
 }
 
 bool
index fb9c7204d3e851706f11e79d5979ea7654722c1e..b7063ebb814aa2c7399c8275661449fb4b7e9173 100644 (file)
@@ -1046,10 +1046,6 @@ public:
         MultiThreadingMgr::instance().setMode(false);
     }
 
-    void SetUp() {
-
-    }
-
     void reset_results() {
         s_handle_->sent_ncrs_.clear();
         r_handle_->received_ncrs_.clear();
index 575b6f395ecf21ed497bb9810f881a8fbd1eca46..022e01212c62044bd5ecf10e30498cf851ae80c5 100644 (file)
@@ -25,7 +25,8 @@ D2ClientMgr::D2ClientMgr() : d2_client_config_(new D2ClientConfig()),
     // Default constructor initializes with a disabled configuration.
 }
 
-D2ClientMgr::~D2ClientMgr(){
+D2ClientMgr::~D2ClientMgr() {
+    stop();
     stopSender();
 }
 
@@ -177,7 +178,6 @@ D2ClientMgr::generateFqdn(const asiolink::IOAddress& address,
     return (qualifyName(gen_name.str(), ddns_params, trailing_dot));
 }
 
-
 std::string
 D2ClientMgr::qualifyName(const std::string& partial_name,
                          const DdnsParams& ddns_params,
@@ -312,6 +312,14 @@ D2ClientMgr::stopSender() {
         name_change_sender_->stopSending();
         LOG_INFO(dhcpsrv_logger, DHCPSRV_DHCP_DDNS_SENDER_STOPPED);
     }
+
+    if (private_io_service_) {
+        private_io_service_->restart();
+        try {
+            private_io_service_->poll();
+        } catch (...) {
+        }
+    }
 }
 
 void
@@ -354,7 +362,7 @@ D2ClientMgr::getQueueSize() const {
         isc_throw(D2ClientError, "D2ClientMgr::getQueueSize sender is null");
     }
 
-    return(name_change_sender_->getQueueSize());
+    return (name_change_sender_->getQueueSize());
 }
 
 size_t
@@ -363,11 +371,9 @@ D2ClientMgr::getQueueMaxSize() const {
         isc_throw(D2ClientError, "D2ClientMgr::getQueueMaxSize sender is null");
     }
 
-    return(name_change_sender_->getQueueMaxSize());
+    return (name_change_sender_->getQueueMaxSize());
 }
 
-
-
 const dhcp_ddns::NameChangeRequestPtr&
 D2ClientMgr::peekAt(const size_t index) const {
     if (!name_change_sender_) {
@@ -397,6 +403,11 @@ D2ClientMgr::operator()(const dhcp_ddns::NameChangeSender::Result result,
     }
 }
 
+void
+D2ClientMgr::stop() {
+    name_change_sender_.reset();
+}
+
 int
 D2ClientMgr::getSelectFd() {
     if (!amSending()) {
@@ -418,6 +429,5 @@ D2ClientMgr::runReadyIO() {
     name_change_sender_->runReadyIO();
 }
 
-};  // namespace dhcp
-
-};  // namespace isc
+}  // namespace dhcp
+}  // namespace isc
index 5356b61efa85b915be19abe10ec3452f12e2bad1..ecd755fcbd8371325403814a91ba35da045f3a3a 100644 (file)
@@ -394,6 +394,9 @@ public:
     /// it will not accept additional messages.
     void suspendUpdates();
 
+    /// @brief Stop the sender
+    void stop();
+
 protected:
     /// @brief Function operator implementing the NCR sender callback.
     ///
@@ -429,6 +432,7 @@ protected:
     int getRegisteredSelectFd();
 
 private:
+
     /// @brief Container class for DHCP-DDNS configuration parameters.
     D2ClientConfigPtr d2_client_config_;
 
index 6e3a7cb010ea7b45f6584c61c798ef672bfc3b81..4ecac66900ca97168f4f53ed80bb9fbab26d5c98 100644 (file)
@@ -202,6 +202,7 @@ public:
         if (mgr.amSending()) {
             mgr.stopSender();
             mgr.clearQueue();
+            mgr.stop();
         }
 
         // Clear configuration.
index 6bab3abeed522e58d1aab9a47403272c4a256c69..0908950281355d0fb70552c43bd008ce4f357c02 100644 (file)
@@ -300,6 +300,7 @@ TEST(D2ClientMgr, validConfig) {
     // and not the original configuration.
     EXPECT_EQ(*new_cfg, *updated_config);
     EXPECT_NE(*original_config, *updated_config);
+    d2_client_mgr->stop();
 }
 
 /// @brief Checks passing the D2ClientMgr a valid D2 client configuration
@@ -335,6 +336,7 @@ TEST(D2ClientMgr, ipv6Config) {
     // and not the original configuration.
     EXPECT_EQ(*new_cfg, *updated_config);
     EXPECT_NE(*original_config, *updated_config);
+    d2_client_mgr->stop();
 }
 
 /// @brief Test class for execerising manager functions that are
index e1d66c087c27c4e1baa4b4f85bbb51c1e56f2b44..c387fb57a544e60c49e050711242f7e9351ee872 100644 (file)
@@ -28,30 +28,68 @@ namespace ph = std::placeholders;
 
 namespace {
 
+class D2ClientMgrTestSendHandler : public D2ClientMgr {
+public:
+    /// @brief Constructor
+    D2ClientMgrTestSendHandler() : simulate_send_failure_(false), callback_count_(0) {
+    }
+
+    /// @brief Overrides base class completion callback.
+    ///
+    /// This method will be invoked each time a send completes. It allows
+    /// intervention prior to calling the production implementation in the
+    /// base.  If simulate_send_failure_ is true, the base call impl will
+    /// be called with an error status, otherwise it will be called with
+    /// the result parameter given.
+    ///
+    /// @param result Result code of the send operation.
+    /// @param ncr NameChangeRequest which failed to send.
+    virtual void operator()(const dhcp_ddns::NameChangeSender::Result result,
+                            dhcp_ddns::NameChangeRequestPtr& ncr) {
+        ++callback_count_;
+        if (simulate_send_failure_) {
+            simulate_send_failure_ = false;
+            D2ClientMgr::operator()(dhcp_ddns::NameChangeSender::ERROR, ncr);
+        } else {
+            D2ClientMgr::operator()(result, ncr);
+        }
+    }
+
+    /// @brief If true simulates a send which completed with a failed status.
+    bool simulate_send_failure_;
+
+    /// @brief Tracks the number times the completion handler is called.
+    int callback_count_;
+
+    /// Expose restricted members.
+    using D2ClientMgr::getSelectFd;
+};
+
 /// @brief Test fixture for exercising D2ClientMgr send management
 /// services.  It inherits from D2ClientMgr to allow overriding various
 /// methods and accessing otherwise restricted member.  In particular it
 /// overrides the NameChangeSender completion completion callback, allowing
 /// the injection of send errors.
-class D2ClientMgrTest : public D2ClientMgr, public ::testing::Test {
+class D2ClientMgrTest : public ::testing::Test {
 public:
-    /// @brief If true simulates a send which completed with a failed status.
-    bool simulate_send_failure_;
+    boost::shared_ptr<D2ClientMgrTestSendHandler> handle_;
+
     /// @brief If true causes an exception throw in the client error handler.
     bool error_handler_throw_;
-    /// @brief Tracks the number times the completion handler is called.
-    int callback_count_;
+
     /// @brief Tracks the number of times the client error handler was called.
     int error_handler_count_;
 
     /// @brief Constructor
-    D2ClientMgrTest() : simulate_send_failure_(false),
-                       error_handler_throw_(false),
-                       callback_count_(0), error_handler_count_(0) {
+    D2ClientMgrTest() : handle_(new D2ClientMgrTestSendHandler()),
+                        error_handler_throw_(false),
+                        error_handler_count_(0) {
     }
 
     /// @brief virtual Destructor
-    virtual ~D2ClientMgrTest(){
+    virtual ~D2ClientMgrTest() {
+        handle_->stop();
+        handle_->stopSender();
     }
 
     /// @brief Updates the D2ClientMgr's configuration to DDNS enabled.
@@ -70,14 +108,13 @@ public:
         IOAddress sender_ip(server_ip.isV4() ? D2ClientConfig::DFT_V4_SENDER_IP :
                             D2ClientConfig::DFT_V6_SENDER_IP);
 
-        ASSERT_NO_THROW(new_cfg.reset(new D2ClientConfig(true,
-                                  server_ip, server_port,
-                                  sender_ip, D2ClientConfig::DFT_SENDER_PORT,
-                                  D2ClientConfig::DFT_MAX_QUEUE_SIZE,
-                                  protocol, dhcp_ddns::FMT_JSON)));
+        ASSERT_NO_THROW(new_cfg.reset(new D2ClientConfig(true, server_ip, server_port,
+                                                         sender_ip, D2ClientConfig::DFT_SENDER_PORT,
+                                                         D2ClientConfig::DFT_MAX_QUEUE_SIZE,
+                                                         protocol, dhcp_ddns::FMT_JSON)));
 
-        ASSERT_NO_THROW(setD2ClientConfig(new_cfg));
-        ASSERT_TRUE(ddnsEnabled());
+        ASSERT_NO_THROW(handle_->setD2ClientConfig(new_cfg));
+        ASSERT_TRUE(handle_->ddnsEnabled());
     }
 
     /// @brief Checks sender's select-fd against an expected state of readiness.
@@ -98,7 +135,7 @@ public:
         int select_fd = -1;
         ASSERT_NO_THROW(
             // cppcheck-suppress redundantAssignment
-            select_fd = getSelectFd()
+            select_fd = handle_->getSelectFd()
         );
 
         FD_SET(select_fd,  &read_fds);
@@ -123,27 +160,6 @@ public:
         }
     }
 
-    /// @brief Overrides base class completion callback.
-    ///
-    /// This method will be invoked each time a send completes. It allows
-    /// intervention prior to calling the production implementation in the
-    /// base.  If simulate_send_failure_ is true, the base call impl will
-    /// be called with an error status, otherwise it will be called with
-    /// the result parameter given.
-    ///
-    /// @param result Result code of the send operation.
-    /// @param ncr NameChangeRequest which failed to send.
-    virtual void operator()(const dhcp_ddns::NameChangeSender::Result result,
-                            dhcp_ddns::NameChangeRequestPtr& ncr) {
-        ++callback_count_;
-        if (simulate_send_failure_) {
-            simulate_send_failure_ = false;
-            D2ClientMgr::operator()(dhcp_ddns::NameChangeSender::ERROR, ncr);
-        } else {
-            D2ClientMgr::operator()(result, ncr);
-        }
-    }
-
     /// @brief Serves as the "application level" client error handler.
     ///
     /// This method is passed into calls to startSender as the client error
@@ -186,78 +202,74 @@ public:
 
         return (dhcp_ddns::NameChangeRequest::fromJSON(ncr_str));
     }
-
-    /// Expose restricted members.
-    using D2ClientMgr::getSelectFd;
 };
 
-
 /// @brief Checks that D2ClientMgr disable and enable a UDP sender.
 TEST_F(D2ClientMgrTest, udpSenderEnableDisable) {
     // Verify DDNS is disabled by default.
-    ASSERT_FALSE(ddnsEnabled());
+    ASSERT_FALSE(handle_->ddnsEnabled());
 
     // Verify we are not in send mode.
-    ASSERT_FALSE(amSending());
+    ASSERT_FALSE(handle_->amSending());
 
     // Enable DDNS with server at 127.0.0.1/prot 53001 via UDP.
     enableDdns("127.0.0.1", 530001, dhcp_ddns::NCR_UDP);
-    ASSERT_FALSE(amSending());
+    ASSERT_FALSE(handle_->amSending());
 
-    ASSERT_NO_THROW(startSender(getErrorHandler()));
-    ASSERT_TRUE(amSending());
+    ASSERT_NO_THROW(handle_->startSender(getErrorHandler()));
+    ASSERT_TRUE(handle_->amSending());
 
     // Verify that we take sender out of send mode.
-    ASSERT_NO_THROW(stopSender());
-    ASSERT_FALSE(amSending());
+    ASSERT_NO_THROW(handle_->stopSender());
+    ASSERT_FALSE(handle_->amSending());
 }
 
 /// @brief Checks D2ClientMgr queuing methods with a UDP sender.
 TEST_F(D2ClientMgrTest, udpSenderQueing) {
     // Enable DDNS with server at 127.0.0.1/prot 53001 via UDP.
     enableDdns("127.0.0.1", 530001, dhcp_ddns::NCR_UDP);
-    ASSERT_FALSE(amSending());
+    ASSERT_FALSE(handle_->amSending());
 
     // Queue should be empty.
-    EXPECT_EQ(0, getQueueSize());
+    EXPECT_EQ(0, handle_->getQueueSize());
 
     // Trying to peek past the end of the queue should throw.
-    EXPECT_THROW(peekAt(1), dhcp_ddns::NcrSenderError);
+    EXPECT_THROW(handle_->peekAt(1), dhcp_ddns::NcrSenderError);
 
     // Trying to send a NCR when not in send mode should fail.
     dhcp_ddns::NameChangeRequestPtr ncr = buildTestNcr();
-    EXPECT_THROW(sendRequest(ncr), D2ClientError);
+    EXPECT_THROW(handle_->sendRequest(ncr), D2ClientError);
 
     // Place sender in send mode.
-    ASSERT_NO_THROW(startSender(getErrorHandler()));
-    ASSERT_TRUE(amSending());
+    ASSERT_NO_THROW(handle_->startSender(getErrorHandler()));
+    ASSERT_TRUE(handle_->amSending());
 
     // Send should succeed now.
-    ASSERT_NO_THROW(sendRequest(ncr));
+    ASSERT_NO_THROW(handle_->sendRequest(ncr));
 
     // Queue should have 1 entry.
-    EXPECT_EQ(1, getQueueSize());
+    EXPECT_EQ(1, handle_->getQueueSize());
 
     // Attempt to fetch the entry we just queued.
     dhcp_ddns::NameChangeRequestPtr ncr2;
-    ASSERT_NO_THROW(ncr2 = peekAt(0));
+    ASSERT_NO_THROW(ncr2 = handle_->peekAt(0));
 
     // Verify what we queued matches what we fetched.
     EXPECT_TRUE(*ncr == *ncr2);
 
     // Clearing the queue while in send mode should fail.
-    ASSERT_THROW(clearQueue(), dhcp_ddns::NcrSenderError);
+    ASSERT_THROW(handle_->clearQueue(), dhcp_ddns::NcrSenderError);
 
     // We should still have 1 in the queue.
-    EXPECT_EQ(1, getQueueSize());
+    EXPECT_EQ(1, handle_->getQueueSize());
 
     // Get out of send mode.
-    ASSERT_NO_THROW(stopSender());
-    ASSERT_FALSE(amSending());
+    ASSERT_NO_THROW(handle_->stopSender());
+    ASSERT_FALSE(handle_->amSending());
 
     // Clear queue should succeed now.
-    ASSERT_NO_THROW(clearQueue());
-    EXPECT_EQ(0, getQueueSize());
+    ASSERT_NO_THROW(handle_->clearQueue());
+    EXPECT_EQ(0, handle_->getQueueSize());
 }
 
 /// @brief Checks that D2ClientMgr can send with a UDP sender and
@@ -267,23 +279,23 @@ TEST_F(D2ClientMgrTest, udpSend) {
     enableDdns("127.0.0.1", 530001, dhcp_ddns::NCR_UDP);
 
     // Trying to fetch the select-fd when not sending should fail.
-    ASSERT_THROW(getSelectFd(), D2ClientError);
+    ASSERT_THROW(handle_->getSelectFd(), D2ClientError);
 
     // Place sender in send mode.
-    ASSERT_NO_THROW(startSender(getErrorHandler()));
+    ASSERT_NO_THROW(handle_->startSender(getErrorHandler()));
 
     // select_fd should evaluate to NOT ready to read.
     selectCheck(false);
 
     // Build a test request and send it.
     dhcp_ddns::NameChangeRequestPtr ncr = buildTestNcr();
-    ASSERT_NO_THROW(sendRequest(ncr));
+    ASSERT_NO_THROW(handle_->sendRequest(ncr));
 
     // select_fd should evaluate to ready to read.
     selectCheck(true);
 
     // Call service handler.
-    runReadyIO();
+    handle_->runReadyIO();
 
     // select_fd should evaluate to not ready to read.
     selectCheck(false);
@@ -297,20 +309,20 @@ TEST_F(D2ClientMgrTest, udpSendExternalIOService) {
 
     // Place sender in send mode using an external IO service.
     asiolink::IOServicePtr io_service(new IOService());
-    ASSERT_NO_THROW(startSender(getErrorHandler(), io_service));
+    ASSERT_NO_THROW(handle_->startSender(getErrorHandler(), io_service));
 
     // select_fd should evaluate to NOT ready to read.
     selectCheck(false);
 
     // Build a test request and send it.
     dhcp_ddns::NameChangeRequestPtr ncr = buildTestNcr();
-    ASSERT_NO_THROW(sendRequest(ncr));
+    ASSERT_NO_THROW(handle_->sendRequest(ncr));
 
     // select_fd should evaluate to ready to read.
     selectCheck(true);
 
     // Call service handler.
-    runReadyIO();
+    handle_->runReadyIO();
 
     // select_fd should evaluate to not ready to read.
     selectCheck(false);
@@ -318,7 +330,7 @@ TEST_F(D2ClientMgrTest, udpSendExternalIOService) {
     // Explicitly stop the sender. This ensures the sender's
     // ASIO socket is closed prior to the local io_service
     // instance goes out of scope.
-    ASSERT_NO_THROW(stopSender());
+    ASSERT_NO_THROW(handle_->stopSender());
 }
 
 /// @brief Checks that D2ClientMgr can send with a UDP sender and
@@ -329,20 +341,20 @@ TEST_F(D2ClientMgrTest, udpSendExternalIOService6) {
 
     // Place sender in send mode using an external IO service.
     asiolink::IOServicePtr io_service(new IOService());
-    ASSERT_NO_THROW(startSender(getErrorHandler(), io_service));
+    ASSERT_NO_THROW(handle_->startSender(getErrorHandler(), io_service));
 
     // select_fd should evaluate to NOT ready to read.
     selectCheck(false);
 
     // Build a test request and send it.
     dhcp_ddns::NameChangeRequestPtr ncr = buildTestNcr();
-    ASSERT_NO_THROW(sendRequest(ncr));
+    ASSERT_NO_THROW(handle_->sendRequest(ncr));
 
     // select_fd should evaluate to ready to read.
     selectCheck(true);
 
     // Call service handler.
-    runReadyIO();
+    handle_->runReadyIO();
 
     // select_fd should evaluate to not ready to read.
     selectCheck(false);
@@ -350,47 +362,45 @@ TEST_F(D2ClientMgrTest, udpSendExternalIOService6) {
     // Explicitly stop the sender. This ensures the sender's
     // ASIO socket is closed prior to the local io_service
     // instance goes out of scope.
-    ASSERT_NO_THROW(stopSender());
+    ASSERT_NO_THROW(handle_->stopSender());
 }
 
-
 /// @brief Checks that D2ClientMgr invokes the client error handler
 /// when send errors occur.
 TEST_F(D2ClientMgrTest, udpSendErrorHandler) {
     // Enable DDNS with server at 127.0.0.1/prot 53001 via UDP.
     // Place sender in send mode.
     enableDdns("127.0.0.1", 530001, dhcp_ddns::NCR_UDP);
-    ASSERT_NO_THROW(startSender(getErrorHandler()));
+    ASSERT_NO_THROW(handle_->startSender(getErrorHandler()));
 
     // Simulate a failed response in the send call back. This should
     // cause the error handler to get invoked.
-    simulate_send_failure_ = true;
+    handle_->simulate_send_failure_ = true;
 
     // Verify error count is zero.
     ASSERT_EQ(0, error_handler_count_);
 
     // Send a test request.
     dhcp_ddns::NameChangeRequestPtr ncr = buildTestNcr();
-    ASSERT_NO_THROW(sendRequest(ncr));
+    ASSERT_NO_THROW(handle_->sendRequest(ncr));
 
     // Call the ready handler. This should complete the message with an error.
-    ASSERT_NO_THROW(runReadyIO());
+    ASSERT_NO_THROW(handle_->runReadyIO());
 
     // If we executed error handler properly, the error count should one.
     ASSERT_EQ(1, error_handler_count_);
 }
 
-
 /// @brief Checks that client error handler exceptions are handled gracefully.
 TEST_F(D2ClientMgrTest, udpSendErrorHandlerThrow) {
     // Enable DDNS with server at 127.0.0.1/prot 53001 via UDP.
     // Place sender in send mode.
     enableDdns("127.0.0.1", 530001, dhcp_ddns::NCR_UDP);
-    ASSERT_NO_THROW(startSender(getErrorHandler()));
+    ASSERT_NO_THROW(handle_->startSender(getErrorHandler()));
 
     // Simulate a failed response in the send call back and
     // force a throw in the error handler.
-    simulate_send_failure_ = true;
+    handle_->simulate_send_failure_ = true;
     error_handler_throw_ = true;
 
     // Verify error count is zero.
@@ -398,11 +408,11 @@ TEST_F(D2ClientMgrTest, udpSendErrorHandlerThrow) {
 
     // Send a test request.
     dhcp_ddns::NameChangeRequestPtr ncr = buildTestNcr();
-    ASSERT_NO_THROW(sendRequest(ncr));
+    ASSERT_NO_THROW(handle_->sendRequest(ncr));
 
     // Call the ready handler. This should complete the message with an error.
     // The handler should throw but the exception should not escape.
-    ASSERT_NO_THROW(runReadyIO());
+    ASSERT_NO_THROW(handle_->runReadyIO());
 
     // If throw flag is false, then we were in the error handler should
     // have thrown.
@@ -418,16 +428,16 @@ TEST_F(D2ClientMgrTest, ifaceRegister) {
     enableDdns("127.0.0.1", 530001, dhcp_ddns::NCR_UDP);
 
     // Place sender in send mode.
-    ASSERT_NO_THROW(startSender(getErrorHandler()));
+    ASSERT_NO_THROW(handle_->startSender(getErrorHandler()));
 
     // Queue three messages.
     for (unsigned i = 0; i < 3; ++i) {
         dhcp_ddns::NameChangeRequestPtr ncr = buildTestNcr();
-        ASSERT_NO_THROW(sendRequest(ncr));
+        ASSERT_NO_THROW(handle_->sendRequest(ncr));
     }
 
     // Make sure queue count is correct.
-    EXPECT_EQ(3, getQueueSize());
+    EXPECT_EQ(3, handle_->getQueueSize());
 
     // select_fd should evaluate to ready to read.
     selectCheck(true);
@@ -436,21 +446,21 @@ TEST_F(D2ClientMgrTest, ifaceRegister) {
     IfaceMgr::instance().receive4(0, 0);
 
     // Verify the callback handler was invoked, no errors counted.
-    EXPECT_EQ(2, getQueueSize());
-    ASSERT_EQ(1, callback_count_);
+    EXPECT_EQ(2, handle_->getQueueSize());
+    ASSERT_EQ(1, handle_->callback_count_);
     ASSERT_EQ(0, error_handler_count_);
 
     // Stop the sender.  This should complete the second message but leave
     // the third in the queue.
-    ASSERT_NO_THROW(stopSender());
-    EXPECT_EQ(1, getQueueSize());
-    ASSERT_EQ(2, callback_count_);
+    ASSERT_NO_THROW(handle_->stopSender());
+    EXPECT_EQ(1, handle_->getQueueSize());
+    ASSERT_EQ(2, handle_->callback_count_);
     ASSERT_EQ(0, error_handler_count_);
 
     // Calling receive again should have no affect.
     IfaceMgr::instance().receive4(0, 0);
-    EXPECT_EQ(1, getQueueSize());
-    ASSERT_EQ(2, callback_count_);
+    EXPECT_EQ(1, handle_->getQueueSize());
+    ASSERT_EQ(2, handle_->callback_count_);
     ASSERT_EQ(0, error_handler_count_);
 }
 
@@ -459,43 +469,43 @@ TEST_F(D2ClientMgrTest, udpSuspendUpdates) {
     // Enable DDNS with server at 127.0.0.1/prot 53001 via UDP.
     // Place sender in send mode.
     enableDdns("127.0.0.1", 530001, dhcp_ddns::NCR_UDP);
-    ASSERT_NO_THROW(startSender(getErrorHandler()));
+    ASSERT_NO_THROW(handle_->startSender(getErrorHandler()));
 
     // Send a test request.
     for (unsigned i = 0; i < 3; ++i) {
         dhcp_ddns::NameChangeRequestPtr ncr = buildTestNcr();
-        ASSERT_NO_THROW(sendRequest(ncr));
+        ASSERT_NO_THROW(handle_->sendRequest(ncr));
     }
-    ASSERT_EQ(3, getQueueSize());
+    ASSERT_EQ(3, handle_->getQueueSize());
 
     // Call the ready handler. This should complete the first message
     // and initiate sending the second message.
-    ASSERT_NO_THROW(runReadyIO());
+    ASSERT_NO_THROW(handle_->runReadyIO());
 
     // Queue count should have gone down by 1.
-    ASSERT_EQ(2, getQueueSize());
+    ASSERT_EQ(2, handle_->getQueueSize());
 
     // Suspend updates. This should disable updates and stop the sender.
-    ASSERT_NO_THROW(suspendUpdates());
+    ASSERT_NO_THROW(handle_->suspendUpdates());
 
-    EXPECT_FALSE(ddnsEnabled());
-    EXPECT_FALSE(amSending());
+    EXPECT_FALSE(handle_->ddnsEnabled());
+    EXPECT_FALSE(handle_->amSending());
 
     // Stopping the sender should have completed the second message's
     // in-progress send, so queue size should be 1.
-    ASSERT_EQ(1, getQueueSize());
+    ASSERT_EQ(1, handle_->getQueueSize());
 }
 
 /// @brief Tests that invokeErrorHandler does not fail if there is no handler.
 TEST_F(D2ClientMgrTest, missingErrorHandler) {
     // Ensure we aren't in send mode.
-    ASSERT_FALSE(ddnsEnabled());
-    ASSERT_FALSE(amSending());
+    ASSERT_FALSE(handle_->ddnsEnabled());
+    ASSERT_FALSE(handle_->amSending());
 
     // There is no error handler at this point, so invoking should not throw.
     dhcp_ddns::NameChangeRequestPtr ncr;
-    ASSERT_NO_THROW(invokeClientErrorHandler(dhcp_ddns::NameChangeSender::ERROR,
-                                             ncr));
+    ASSERT_NO_THROW(handle_->invokeClientErrorHandler(dhcp_ddns::NameChangeSender::ERROR,
+                                                      ncr));
 
     // Verify we didn't invoke the error handler, error count is zero.
     ASSERT_EQ(0, error_handler_count_);
index 5e20fd339aa98152fa9936494422aaa7322200a2..6f26b8c27bd550cab2d5539d7a89b79c03aa0818 100644 (file)
@@ -97,6 +97,7 @@ public:
 
     /// @brief Disables DHCP-DDNS updates.
     void disableD2() {
+        d2_mgr_.stop();
         d2_mgr_.stopSender();
         // Default constructor creates a config with DHCP-DDNS updates
         // disabled.
index 056bcba7b469263eb1352da724aa657c40ceae97..7a8f4f57be6a217b30dbd76b61e99cf7278aa210 100644 (file)
@@ -1845,6 +1845,15 @@ public:
         if (thread_pool_) {
             thread_pool_->stop();
         }
+
+        if (thread_io_service_) {
+            thread_io_service_->restart();
+            try {
+                thread_io_service_->poll();
+            } catch (...) {
+            }
+            thread_io_service_->stop();
+        }
     }
 
     /// @brief Pauses the client's thread pool.
@@ -1963,6 +1972,7 @@ HttpClient::HttpClient(const IOServicePtr& io_service, bool multi_threading_enab
 }
 
 HttpClient::~HttpClient() {
+    impl_->stop();
 }
 
 void