7
7
#include < config.h>
8
8
9
9
#include < asiolink/asio_wrapper.h>
10
+ #include < dhcp/iface_mgr.h>
10
11
#include < http/connection.h>
11
12
#include < http/connection_pool.h>
12
13
#include < http/http_log.h>
15
16
#include < functional>
16
17
17
18
using namespace isc ::asiolink;
19
+ using namespace isc ::dhcp;
20
+ using namespace isc ::util;
18
21
namespace ph = std::placeholders;
19
22
20
23
namespace {
@@ -80,7 +83,8 @@ HttpConnection::HttpConnection(const asiolink::IOServicePtr& io_service,
80
83
connection_pool_(connection_pool),
81
84
response_creator_(response_creator),
82
85
acceptor_callback_(callback),
83
- use_external_(false ) {
86
+ use_external_(false ),
87
+ watch_socket_() {
84
88
if (!tls_context) {
85
89
tcp_socket_.reset (new asiolink::TCPSocket<SocketCallback>(io_service));
86
90
} else {
@@ -131,13 +135,22 @@ HttpConnection::recordParameters(const HttpRequestPtr& request) const {
131
135
132
136
void
133
137
HttpConnection::shutdownCallback (const boost::system::error_code&) {
138
+ if (use_external_) {
139
+ IfaceMgr::instance ().deleteExternalSocket (tls_socket_->getNative ());
140
+ closeWatchSocket ();
141
+ }
142
+
134
143
tls_socket_->close ();
135
144
}
136
145
137
146
void
138
147
HttpConnection::shutdown () {
139
148
request_timer_.cancel ();
140
149
if (tcp_socket_) {
150
+ if (use_external_) {
151
+ IfaceMgr::instance ().deleteExternalSocket (tcp_socket_->getNative ());
152
+ closeWatchSocket ();
153
+ }
141
154
tcp_socket_->close ();
142
155
return ;
143
156
}
@@ -153,14 +166,36 @@ HttpConnection::shutdown() {
153
166
isc_throw (Unexpected, " internal error: unable to shutdown the socket" );
154
167
}
155
168
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
+
156
183
void
157
184
HttpConnection::close () {
158
185
request_timer_.cancel ();
159
186
if (tcp_socket_) {
187
+ if (use_external_) {
188
+ IfaceMgr::instance ().deleteExternalSocket (tcp_socket_->getNative ());
189
+ closeWatchSocket ();
190
+ }
160
191
tcp_socket_->close ();
161
192
return ;
162
193
}
163
194
if (tls_socket_) {
195
+ if (use_external_) {
196
+ IfaceMgr::instance ().deleteExternalSocket (tls_socket_->getNative ());
197
+ closeWatchSocket ();
198
+ }
164
199
tls_socket_->close ();
165
200
return ;
166
201
}
@@ -214,6 +249,17 @@ HttpConnection::asyncAccept() {
214
249
}
215
250
tls_acceptor->asyncAccept (*tls_socket_, cb);
216
251
}
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
+ }
217
263
} catch (const std::exception & ex) {
218
264
isc_throw (HttpConnectionError, " unable to start accepting TCP "
219
265
" connections: " << ex.what ());
@@ -236,7 +282,12 @@ HttpConnection::doHandshake() {
236
282
ph::_1)); // error
237
283
try {
238
284
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
+ }
240
291
} catch (const std::exception & ex) {
241
292
isc_throw (HttpConnectionError, " unable to perform TLS handshake: "
242
293
<< ex.what ());
@@ -296,12 +347,26 @@ HttpConnection::doWrite(HttpConnection::TransactionPtr transaction) {
296
347
tcp_socket_->asyncSend (transaction->getOutputBufData (),
297
348
transaction->getOutputBufSize (),
298
349
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
+ }
299
357
return ;
300
358
}
301
359
if (tls_socket_) {
302
360
tls_socket_->asyncSend (transaction->getOutputBufData (),
303
361
transaction->getOutputBufSize (),
304
362
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
+ }
305
370
return ;
306
371
}
307
372
} else {
@@ -366,6 +431,15 @@ HttpConnection::acceptorCallback(const boost::system::error_code& ec) {
366
431
367
432
void
368
433
HttpConnection::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
+ }
369
443
if (ec) {
370
444
LOG_INFO (http_logger, HTTP_CONNECTION_HANDSHAKE_FAILED)
371
445
.arg (getRemoteEndpointAddressAsText ())
@@ -477,6 +551,15 @@ HttpConnection::socketReadCallback(HttpConnection::TransactionPtr transaction,
477
551
void
478
552
HttpConnection::socketWriteCallback (HttpConnection::TransactionPtr transaction,
479
553
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
+ }
480
563
if (ec) {
481
564
// IO service has been stopped and the connection is probably
482
565
// going to be shutting down.
0 commit comments