]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#691,!395] HAService now registers HTTP client sockets with InterfaceMgr
authorThomas Markwalder <tmark@isc.org>
Mon, 24 Jun 2019 19:33:53 +0000 (15:33 -0400)
committerThomas Markwalder <tmark@isc.org>
Thu, 27 Jun 2019 11:49:10 +0000 (07:49 -0400)
src/hooks/dhcp/high_availability/ha_service.cc

    HAService
        clientConnectHandler() - new client connection connect callback
        clientCloseHandler() - new client connection close callback

        asyncSendLeaseUpdate()
        asyncSendHeartbeat()
        asyncDisableDHCPService()
        asyncEnableDHCPService()
        asyncSyncLeasesInternal() - added new call backs to
        HttpClient::asyncSendRequest() invocation

src/lib/http/client.cc
    Connection::resetState() - added reset of close callback

src/hooks/dhcp/high_availability/ha_service.cc
src/hooks/dhcp/high_availability/ha_service.h
src/lib/http/client.cc

index 1abf3e4f1464237ee81c872565993e0ff8f5ea8c..fc5cb59e0efd11638507684bcd7ad883b2e25fb1 100644 (file)
@@ -12,6 +12,7 @@
 #include <ha_service_states.h>
 #include <cc/command_interpreter.h>
 #include <cc/data.h>
+#include <dhcp/iface_mgr.h>
 #include <dhcpsrv/lease_mgr.h>
 #include <dhcpsrv/lease_mgr_factory.h>
 #include <http/date_time.h>
@@ -270,7 +271,7 @@ HAService::readyStateHandler() {
     case HA_HOT_STANDBY_ST:
         verboseTransition(HA_HOT_STANDBY_ST);
         break;
-        
+
     case HA_LOAD_BALANCING_ST:
         verboseTransition(HA_LOAD_BALANCING_ST);
         break;
@@ -852,7 +853,11 @@ HAService::asyncSendLeaseUpdate(const QueryPtrType& query,
                 // Then it returns control to the DHCP server.
                 runModel(HA_LEASE_UPDATES_COMPLETE_EVT);
             }
-        });
+        },
+        HttpClient::RequestTimeout(10000),
+        boost::bind(&HAService::clientConnectHandler, this, _1, _2),
+        boost::bind(&HAService::clientCloseHandler, this, _1)
+    );
 
     // Request scheduled, so update the request counters for the query.
     if (pending_requests_.count(query) == 0) {
@@ -1051,7 +1056,11 @@ HAService::asyncSendHeartbeat() {
             // asynchronous tasks etc. Then it returns control to the DHCP server.
             startHeartbeat();
             runModel(HA_HEARTBEAT_COMPLETE_EVT);
-      });
+        },
+        HttpClient::RequestTimeout(10000),
+        boost::bind(&HAService::clientConnectHandler, this, _1, _2),
+        boost::bind(&HAService::clientCloseHandler, this, _1)
+    );
 }
 
 void
@@ -1137,7 +1146,11 @@ HAService::asyncDisableDHCPService(HttpClient& http_client,
                  post_request_action(error_message.empty(),
                                      error_message);
              }
-    });
+        },
+        HttpClient::RequestTimeout(10000),
+        boost::bind(&HAService::clientConnectHandler, this, _1, _2),
+        boost::bind(&HAService::clientCloseHandler, this, _1)
+    );
 }
 
 void
@@ -1204,7 +1217,11 @@ HAService::asyncEnableDHCPService(HttpClient& http_client,
                  post_request_action(error_message.empty(),
                                      error_message);
              }
-    });
+        },
+        HttpClient::RequestTimeout(10000),
+        boost::bind(&HAService::clientConnectHandler, this, _1, _2),
+        boost::bind(&HAService::clientCloseHandler, this, _1)
+    );
 }
 
 void
@@ -1440,7 +1457,12 @@ HAService::asyncSyncLeasesInternal(http::HttpClient& http_client,
                                  error_message,
                                  dhcp_disabled);
             }
-    }, HttpClient::RequestTimeout(config_->getSyncTimeout()));
+        },
+        HttpClient::RequestTimeout(config_->getSyncTimeout()),
+        boost::bind(&HAService::clientConnectHandler, this, _1, _2),
+        boost::bind(&HAService::clientCloseHandler, this, _1)
+    );
+
 }
 
 ConstElementPtr
@@ -1596,6 +1618,30 @@ HAService::verifyAsyncResponse(const HttpResponsePtr& response) {
     return (args);
 }
 
+bool
+HAService::clientConnectHandler(const boost::system::error_code& ec, int tcp_native_fd) {
+    if (!ec || ec.value() == boost::asio::error::in_progress) {
+        IfaceMgr::instance().addExternalSocket(tcp_native_fd,
+            [this]() {
+                    // Callback is a NOP. Ready events handlers are run by an explicit
+                    // call IOService ready in kea-dhcp<n> code. We are registering
+                    // the socket to interrupt main-thread select().
+        });
+    }
+
+    // If ec.value() == boost::asio::error::already_connected, we should already
+    // be registered, so nothing to do.  If it is any other value, than connect
+    // failed and Connection logic should handle that, not us, so no matter
+    // what happens we're returning true.
+    return (true);
+}
+
+void
+HAService::clientCloseHandler(int tcp_native_fd) {
+    if (tcp_native_fd >= 0) {
+        IfaceMgr::instance().deleteExternalSocket(tcp_native_fd);
+    }
+};
 
 } // end of namespace isc::ha
 } // end of namespace isc
index 6acc3ac4f8d8d635d0e6918237de2812ed41e285..770b7add985753ca73d6a82943e00baa05230a28 100644 (file)
@@ -727,6 +727,26 @@ protected:
     /// @throw CtrlChannelError if response is invalid or contains an error.
     data::ConstElementPtr verifyAsyncResponse(const http::HttpResponsePtr& response);
 
+    /// @brief HttpClient connect callback handler
+    ///
+    /// Passed into HttpClient calls to allow registration of client's TCP socket
+    /// with an external monitor (such as IfaceMgr's  main-thread select()).
+    ///
+    /// @param ec Error status of the ASIO connect
+    /// @param tcp_native_fd socket descriptor to register
+    /// @param returns true. Registeration cannot fail, and if ec indicates a real
+    /// error we want Connection logic to process it.
+    virtual bool clientConnectHandler(const boost::system::error_code& ec, int tcp_native_fd);
+
+    /// @brief HttpClient close callback handler
+    ///
+    /// Passed into HttpClient calls to allow unregistration of client's
+    /// TCP socket with an external monitor (such as IfaceMgr's
+    /// main-thread select()).
+    ///
+    /// @param tcp_native_fd socket descriptor to register
+    virtual void clientCloseHandler(int tcp_native_fd);
+
     /// @brief Pointer to the IO service object shared between this hooks
     /// library and the DHCP server.
     asiolink::IOServicePtr io_service_;
index db6473115ea67e9dc2b8598ca141fbda1cc653c9..b9bafda0bbd8737149623cf5078cec6247c9f38e 100644 (file)
@@ -500,6 +500,7 @@ Connection::resetState() {
     current_response_.reset();
     parser_.reset();
     current_callback_ = HttpClient::RequestHandler();
+    close_callback_ = HttpClient::CloseHandler();
 }
 
 void
@@ -529,8 +530,8 @@ Connection::doTransaction(const HttpRequestPtr& request,
         // data over this socket, when the peer may close the connection. In this
         // case we'll need to re-transmit but we don't handle it here.
         if (socket_.getASIOSocket().is_open() && !socket_.isUsable()) {
-            if (close_callback) {
-                close_callback(socket_.getNative());
+            if (close_callback_) {
+                close_callback_(socket_.getNative());
             }
             socket_.close();
         }