From 59f20f0770b6eebb7cc60eab8aa610288cd79a39 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Wed, 31 Jul 2024 13:53:01 +0200 Subject: [PATCH] [#3478] Checkpoint: handle acceptor --- src/lib/http/Makefile.am | 3 ++- src/lib/http/connection.cc | 8 +++++++- src/lib/http/connection.h | 11 ++++++++++ src/lib/http/listener.cc | 5 +++++ src/lib/http/listener.h | 8 ++++++++ src/lib/http/listener_impl.cc | 20 ++++++++++++++++++- src/lib/http/listener_impl.h | 11 ++++++++++ src/lib/http/tests/Makefile.am | 1 + .../http/tests/request_parser_unittests.cc | 2 +- 9 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/lib/http/Makefile.am b/src/lib/http/Makefile.am index 94c5569581..e71bde1d7c 100644 --- a/src/lib/http/Makefile.am +++ b/src/lib/http/Makefile.am @@ -49,7 +49,8 @@ libkea_http_la_CPPFLAGS = $(AM_CPPFLAGS) libkea_http_la_LDFLAGS = $(AM_LDFLAGS) libkea_http_la_LDFLAGS += -no-undefined -version-info 81:0:0 -libkea_http_la_LIBADD = $(top_builddir)/src/lib/hooks/libkea-hooks.la +libkea_http_la_LIBADD = $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la +libkea_http_la_LIBADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la libkea_http_la_LIBADD += $(top_builddir)/src/lib/cc/libkea-cc.la libkea_http_la_LIBADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la libkea_http_la_LIBADD += $(top_builddir)/src/lib/log/libkea-log.la diff --git a/src/lib/http/connection.cc b/src/lib/http/connection.cc index 86cc3749cd..487566c198 100644 --- a/src/lib/http/connection.cc +++ b/src/lib/http/connection.cc @@ -79,7 +79,8 @@ HttpConnection::HttpConnection(const asiolink::IOServicePtr& io_service, acceptor_(acceptor), connection_pool_(connection_pool), response_creator_(response_creator), - acceptor_callback_(callback) { + acceptor_callback_(callback), + use_external_(false) { if (!tls_context) { tcp_socket_.reset(new asiolink::TCPSocket(io_service)); } else { @@ -92,6 +93,11 @@ HttpConnection::~HttpConnection() { close(); } +void +HttpConnection::addExternalSockets(bool use_external) { + use_external_ = use_external; +} + void HttpConnection::recordParameters(const HttpRequestPtr& request) const { if (!request) { diff --git a/src/lib/http/connection.h b/src/lib/http/connection.h index f9e0d43e27..cea7724451 100644 --- a/src/lib/http/connection.h +++ b/src/lib/http/connection.h @@ -255,6 +255,14 @@ public: /// Closes current connection. virtual ~HttpConnection(); + /// @brief Use external sockets flag. + /// + /// Add sockets as external sockets of the interface manager + /// so available I/O on them makes a waiting select to return. + /// + /// @param use_external True add external sockets (default false). + void addExternalSockets(bool use_external = false); + /// @brief Asynchronously accepts new connection. /// /// When the connection is established successfully, the timeout timer is @@ -424,6 +432,9 @@ protected: /// @brief External TCP acceptor callback. HttpAcceptorCallback acceptor_callback_; + + /// @brief Use external sockets flag. + bool use_external_; }; } // end of namespace isc::http diff --git a/src/lib/http/listener.cc b/src/lib/http/listener.cc index 544a4b46e7..18f81f529c 100644 --- a/src/lib/http/listener.cc +++ b/src/lib/http/listener.cc @@ -47,6 +47,11 @@ HttpListener::getNative() const { return (impl_->getNative()); } +void +HttpListener::addExternalSockets(bool use_external) { + impl_->addExternalSockets(use_external); +} + void HttpListener::start() { impl_->start(); diff --git a/src/lib/http/listener.h b/src/lib/http/listener.h index c05a60d1db..3d513019c8 100644 --- a/src/lib/http/listener.h +++ b/src/lib/http/listener.h @@ -118,6 +118,14 @@ public: /// @brief file descriptor of the underlying acceptor socket. int getNative() const; + /// @brief Use external sockets flag. + /// + /// Add sockets as external sockets of the interface manager + /// so available I/O on them makes a waiting select to return. + /// + /// @param use_external True add external sockets (default false). + void addExternalSockets(bool use_external = false); + /// @brief Starts accepting new connections. /// /// This method starts accepting and handling new HTTP connections on diff --git a/src/lib/http/listener_impl.cc b/src/lib/http/listener_impl.cc index 771b6e9469..cd68e09011 100644 --- a/src/lib/http/listener_impl.cc +++ b/src/lib/http/listener_impl.cc @@ -6,11 +6,13 @@ #include #include +#include #include #include #include using namespace isc::asiolink; +using namespace isc::dhcp; namespace ph = std::placeholders; namespace isc { @@ -26,7 +28,8 @@ HttpListenerImpl::HttpListenerImpl(const IOServicePtr& io_service, : io_service_(io_service), tls_context_(tls_context), acceptor_(), endpoint_(), connections_(), creator_factory_(creator_factory), - request_timeout_(request_timeout), idle_timeout_(idle_timeout) { + request_timeout_(request_timeout), idle_timeout_(idle_timeout), + use_external_(false) { // Create the TCP or TLS acceptor. if (!tls_context) { acceptor_.reset(new HttpAcceptor(io_service)); @@ -72,10 +75,18 @@ HttpListenerImpl::getNative() const { return (acceptor_ ? acceptor_->getNative() : -1); } +void +HttpListenerImpl::addExternalSockets(bool use_external) { + use_external_ = use_external; +} + void HttpListenerImpl::start() { try { acceptor_->open(*endpoint_); + if (use_external_) { + IfaceMgr::instance().addExternalSocket(acceptor_->getNative(), 0); + } acceptor_->setOption(HttpAcceptor::ReuseAddress(true)); acceptor_->bind(*endpoint_); acceptor_->listen(); @@ -92,6 +103,9 @@ HttpListenerImpl::start() { void HttpListenerImpl::stop() { connections_.stopAll(); + if (use_external_) { + IfaceMgr::instance().deleteExternalSocket(acceptor_->getNative()); + } acceptor_->close(); } @@ -105,6 +119,10 @@ HttpListenerImpl::accept() { std::bind(&HttpListenerImpl::acceptHandler, this, ph::_1); HttpConnectionPtr conn = createConnection(response_creator, acceptor_callback); + // Transmit the use external sockets flag. + if (use_external_) { + conn->addExternalSockets(true); + } // Add this new connection to the pool. connections_.start(conn); } diff --git a/src/lib/http/listener_impl.h b/src/lib/http/listener_impl.h index 1608c94553..246ead4e27 100644 --- a/src/lib/http/listener_impl.h +++ b/src/lib/http/listener_impl.h @@ -62,6 +62,14 @@ public: /// @brief file descriptor of the underlying acceptor socket. int getNative() const; + /// @brief Use external sockets flag. + /// + /// Add sockets as external sockets of the interface manager + /// so available I/O on them makes a waiting select to return. + /// + /// @param use_external True add external sockets. + void addExternalSockets(bool use_external); + /// @brief Starts accepting new connections. /// /// This method starts accepting and handling new HTTP connections on @@ -130,6 +138,9 @@ protected: /// @brief Timeout after which idle persistent connection is closed by /// the server. long idle_timeout_; + + /// @brief Use external sockets flag. + bool use_external_; }; diff --git a/src/lib/http/tests/Makefile.am b/src/lib/http/tests/Makefile.am index fcd3398739..92f1bb7c5e 100644 --- a/src/lib/http/tests/Makefile.am +++ b/src/lib/http/tests/Makefile.am @@ -60,6 +60,7 @@ libhttp_unittests_CXXFLAGS = $(AM_CXXFLAGS) libhttp_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS) libhttp_unittests_LDADD = $(top_builddir)/src/lib/http/libkea-http.la +libhttp_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la libhttp_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la libhttp_unittests_LDADD += $(top_builddir)/src/lib/testutils/libkea-testutils.la libhttp_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la diff --git a/src/lib/http/tests/request_parser_unittests.cc b/src/lib/http/tests/request_parser_unittests.cc index 0756711219..8f1701d091 100644 --- a/src/lib/http/tests/request_parser_unittests.cc +++ b/src/lib/http/tests/request_parser_unittests.cc @@ -91,7 +91,7 @@ TEST_F(HttpRequestParserTest, postHttpRequestWithJson) { // Simulate receiving HTTP request in chunks. for (size_t i = 0; i < http_req.size(); i += http_req.size() / 10) { bool done = false; - // Get the size of the data chunk. + // Get the size of the data chunk. size_t chunk = http_req.size() / 10; // When we're near the end of the data stream, the chunk length may // vary.