From: Thomas Markwalder Date: Tue, 11 Feb 2014 20:50:50 +0000 (-0500) Subject: [3329] dhcpsrv::D2ClientMgr now registers IfaceMgr X-Git-Tag: bind10-1.2.0beta1-release~45^2~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=45cd4d8881742dbd6bba9c965e01d2c5d206971f;p=thirdparty%2Fkea.git [3329] dhcpsrv::D2ClientMgr now registers IfaceMgr D2ClientMgr now registers and unregisters its runReadyIO method and sender's select-fd with IfaceMgr's external socket monitoring. --- diff --git a/src/lib/dhcpsrv/d2_client_mgr.cc b/src/lib/dhcpsrv/d2_client_mgr.cc index 4c8b34ef87..e43bbdbd22 100644 --- a/src/lib/dhcpsrv/d2_client_mgr.cc +++ b/src/lib/dhcpsrv/d2_client_mgr.cc @@ -12,10 +12,13 @@ // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. +#include #include #include #include +#include + #include using namespace std; @@ -24,11 +27,13 @@ namespace isc { namespace dhcp { D2ClientMgr::D2ClientMgr() : d2_client_config_(new D2ClientConfig()), - name_change_sender_(), private_io_service_(), sender_io_service_(NULL) { + name_change_sender_(), private_io_service_(), + registered_select_fd_(dhcp_ddns::WatchSocket::INVALID_SOCKET) { // Default constructor initializes with a disabled configuration. } D2ClientMgr::~D2ClientMgr(){ + stopSender(); } void @@ -209,14 +214,16 @@ D2ClientMgr::startSender(D2ClientErrorHandler error_handler, // Set the error handler. client_error_handler_ = error_handler; - // Remember the io service being used. - sender_io_service_ = &io_service; - // Start the sender on the given service. - name_change_sender_->startSending(*sender_io_service_); - - /// @todo need to register sender's select-fd with IfaceMgr once 3315 is - /// done. + name_change_sender_->startSending(io_service); + + // Register sender's select-fd with IfaceMgr. + // We need to remember the fd that is registered so we can unregister later. + // IO error handling in the sender may alter its select-fd. + registered_select_fd_ = name_change_sender_->getSelectFd(); + IfaceMgr::instance().addExternalSocket(registered_select_fd_, + boost::bind(&D2ClientMgr::runReadyIO, + this)); } bool @@ -226,14 +233,16 @@ D2ClientMgr::amSending() const { void D2ClientMgr::stopSender() { - if (!name_change_sender_) { - isc_throw(D2ClientError, "D2ClientMgr::stopSender sender is null"); + /// Unregister sender's select-fd. + if (registered_select_fd_ != dhcp_ddns::WatchSocket::INVALID_SOCKET) { + IfaceMgr::instance().deleteExternalSocket(registered_select_fd_); + registered_select_fd_ = dhcp_ddns::WatchSocket::INVALID_SOCKET; } - /// @todo need to unregister sender's select-fd with IfaceMgr once 3315 is - /// done. - - name_change_sender_->stopSending(); + // If its not null, call stop. + if (name_change_sender_) { + name_change_sender_->stopSending(); + } } void @@ -309,17 +318,13 @@ D2ClientMgr::getSelectFd() { void D2ClientMgr::runReadyIO() { - if (!sender_io_service_) { + if (!name_change_sender_) { // This should never happen. isc_throw(D2ClientError, "D2ClientMgr::runReadyIO" - " sender io service is null"); + " name_change_sender is null"); } - // We shouldn't be here if IO isn't ready to execute. - // By running poll we're gauranteed not to hang. - /// @todo Trac# 3325 requests that asiolink::IOService provide a - /// wrapper for poll(). - sender_io_service_->get_io_service().poll(); + name_change_sender_->runReadyIO(); } }; // namespace dhcp diff --git a/src/lib/dhcpsrv/d2_client_mgr.h b/src/lib/dhcpsrv/d2_client_mgr.h index f46007159d..de47c122ec 100644 --- a/src/lib/dhcpsrv/d2_client_mgr.h +++ b/src/lib/dhcpsrv/d2_client_mgr.h @@ -16,7 +16,7 @@ #define D2_CLIENT_MGR_H /// @file d2_client_mgr.h Defines the D2ClientMgr class. -/// This file defines the class Kea uses to act as a client of the +/// This file defines the class Kea uses to act as a client of the /// b10-dhcp-ddns module (aka D2). /// #include @@ -62,13 +62,13 @@ boost::function diff --git a/src/lib/dhcpsrv/tests/d2_udp_unittest.cc b/src/lib/dhcpsrv/tests/d2_udp_unittest.cc index 1bc6091aa4..5b51530173 100644 --- a/src/lib/dhcpsrv/tests/d2_udp_unittest.cc +++ b/src/lib/dhcpsrv/tests/d2_udp_unittest.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -376,4 +377,45 @@ TEST_F(D2ClientMgrTest, udpSendErrorHandler) { ASSERT_EQ(1, error_handler_count_); } +TEST_F(D2ClientMgrTest, ifaceRegister) { + // Enable DDNS with server at 127.0.0.1/prot 53001 via UDP. + enableDdns("127.0.0.1", 530001, dhcp_ddns::NCR_UDP); + + // Place sender in send mode. + ASSERT_NO_THROW(startSender(getErrorHandler())); + + // Queue three messages. + for (int i = 0; i < 3; ++i) { + dhcp_ddns::NameChangeRequestPtr ncr = buildTestNcr(); + ASSERT_NO_THROW(sendRequest(ncr)); + } + + EXPECT_EQ(3, getQueueSize()); + + // select_fd should evaluate to ready to read. + selectCheck(true); + + // Calling receive should complete the first message and start the second. + IfaceMgr::instance().receive4(0, 0); + + // Verify the callback hander was invoked, no errors counted. + EXPECT_EQ(2, getQueueSize()); + ASSERT_EQ(1, 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_EQ(0, error_handler_count_); + + // Calling recevie again should have no affect. + IfaceMgr::instance().receive4(0, 0); + EXPECT_EQ(1, getQueueSize()); + ASSERT_EQ(2, callback_count_); + ASSERT_EQ(0, error_handler_count_); +} + + } // end of anonymous namespace