Commit ff3d254d authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[#691,!395] HAService now registers HTTP client sockets with InterfaceMgr

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
parent 770aeae6
......@@ -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
......@@ -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_;
......
......@@ -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();
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment