77#include < config.h>
88
99#include < asiolink/asio_wrapper.h>
10+ #include < dhcp/iface_mgr.h>
1011#include < http/connection.h>
1112#include < http/connection_pool.h>
1213#include < http/http_log.h>
1516#include < functional>
1617
1718using namespace isc ::asiolink;
19+ using namespace isc ::dhcp;
20+ using namespace isc ::util;
1821namespace ph = std::placeholders;
1922
2023namespace {
@@ -80,7 +83,8 @@ HttpConnection::HttpConnection(const asiolink::IOServicePtr& io_service,
8083 connection_pool_(connection_pool),
8184 response_creator_(response_creator),
8285 acceptor_callback_(callback),
83- use_external_(false ) {
86+ use_external_(false ),
87+ watch_socket_() {
8488 if (!tls_context) {
8589 tcp_socket_.reset (new asiolink::TCPSocket<SocketCallback>(io_service));
8690 } else {
@@ -131,13 +135,22 @@ HttpConnection::recordParameters(const HttpRequestPtr& request) const {
131135
132136void
133137HttpConnection::shutdownCallback (const boost::system::error_code&) {
138+ if (use_external_) {
139+ IfaceMgr::instance ().deleteExternalSocket (tls_socket_->getNative ());
140+ closeWatchSocket ();
141+ }
142+
134143 tls_socket_->close ();
135144}
136145
137146void
138147HttpConnection::shutdown () {
139148 request_timer_.cancel ();
140149 if (tcp_socket_) {
150+ if (use_external_) {
151+ IfaceMgr::instance ().deleteExternalSocket (tcp_socket_->getNative ());
152+ closeWatchSocket ();
153+ }
141154 tcp_socket_->close ();
142155 return ;
143156 }
@@ -153,14 +166,36 @@ HttpConnection::shutdown() {
153166 isc_throw (Unexpected, " internal error: unable to shutdown the socket" );
154167}
155168
169+ void
170+ HttpConnection::closeWatchSocket () {
171+ if (!watch_socket_) {
172+ // / Should not happen...
173+ return ;
174+ }
175+ IfaceMgr::instance ().deleteExternalSocket (watch_socket_->getSelectFd ());
176+ // Close watch socket and log errors if occur.
177+ std::string watch_error;
178+ if (!watch_socket_->closeSocket (watch_error)) {
179+ // / log
180+ }
181+ }
182+
156183void
157184HttpConnection::close () {
158185 request_timer_.cancel ();
159186 if (tcp_socket_) {
187+ if (use_external_) {
188+ IfaceMgr::instance ().deleteExternalSocket (tcp_socket_->getNative ());
189+ closeWatchSocket ();
190+ }
160191 tcp_socket_->close ();
161192 return ;
162193 }
163194 if (tls_socket_) {
195+ if (use_external_) {
196+ IfaceMgr::instance ().deleteExternalSocket (tls_socket_->getNative ());
197+ closeWatchSocket ();
198+ }
164199 tls_socket_->close ();
165200 return ;
166201 }
@@ -214,6 +249,17 @@ HttpConnection::asyncAccept() {
214249 }
215250 tls_acceptor->asyncAccept (*tls_socket_, cb);
216251 }
252+ if (use_external_) {
253+ auto & iface_mgr = IfaceMgr::instance ();
254+ if (tcp_socket_) {
255+ iface_mgr.addExternalSocket (tcp_socket_->getNative (), 0 );
256+ }
257+ if (tls_socket_) {
258+ iface_mgr.addExternalSocket (tls_socket_->getNative (), 0 );
259+ }
260+ watch_socket_.reset (new WatchSocket ());
261+ iface_mgr.addExternalSocket (watch_socket_->getSelectFd (), 0 );
262+ }
217263 } catch (const std::exception& ex) {
218264 isc_throw (HttpConnectionError, " unable to start accepting TCP "
219265 " connections: " << ex.what ());
@@ -236,7 +282,12 @@ HttpConnection::doHandshake() {
236282 ph::_1)); // error
237283 try {
238284 tls_socket_->handshake (cb);
239-
285+ if (use_external_) {
286+ // Asynchronous handshake has been scheduled and we need to
287+ // indicate this to break the synchronous select(). The handler
288+ // should clear this status when invoked.
289+ watch_socket_->markReady ();
290+ }
240291 } catch (const std::exception& ex) {
241292 isc_throw (HttpConnectionError, " unable to perform TLS handshake: "
242293 << ex.what ());
@@ -296,12 +347,26 @@ HttpConnection::doWrite(HttpConnection::TransactionPtr transaction) {
296347 tcp_socket_->asyncSend (transaction->getOutputBufData (),
297348 transaction->getOutputBufSize (),
298349 cb);
350+ if (use_external_) {
351+ // Asynchronous send has been scheduled and we
352+ // need to indicate this to break the synchronous
353+ // select(). The handler should clear this status
354+ // when invoked.
355+ watch_socket_->markReady ();
356+ }
299357 return ;
300358 }
301359 if (tls_socket_) {
302360 tls_socket_->asyncSend (transaction->getOutputBufData (),
303361 transaction->getOutputBufSize (),
304362 cb);
363+ if (use_external_) {
364+ // Asynchronous send has been scheduled and we
365+ // need to indicate this to break the synchronous
366+ // select(). The handler should clear this status
367+ // when invoked.
368+ watch_socket_->markReady ();
369+ }
305370 return ;
306371 }
307372 } else {
@@ -366,6 +431,15 @@ HttpConnection::acceptorCallback(const boost::system::error_code& ec) {
366431
367432void
368433HttpConnection::handshakeCallback (const boost::system::error_code& ec) {
434+ if (use_external_) {
435+ // Clear the watch socket so as the future send operation can
436+ // mark it again to interrupt the synchronous select() call.
437+ try {
438+ watch_socket_->clearReady ();
439+ } catch (const std::exception& ex) {
440+ // log.
441+ }
442+ }
369443 if (ec) {
370444 LOG_INFO (http_logger, HTTP_CONNECTION_HANDSHAKE_FAILED)
371445 .arg (getRemoteEndpointAddressAsText ())
@@ -477,6 +551,15 @@ HttpConnection::socketReadCallback(HttpConnection::TransactionPtr transaction,
477551void
478552HttpConnection::socketWriteCallback (HttpConnection::TransactionPtr transaction,
479553 boost::system::error_code ec, size_t length) {
554+ if (use_external_) {
555+ // Clear the watch socket so as the future send operation can
556+ // mark it again to interrupt the synchronous select() call.
557+ try {
558+ watch_socket_->clearReady ();
559+ } catch (const std::exception& ex) {
560+ // log.
561+ }
562+ }
480563 if (ec) {
481564 // IO service has been stopped and the connection is probably
482565 // going to be shutting down.
0 commit comments