Skip to content

Commit 9e5db5d

Browse files
committed
[#3478] Checkpoint: server connection
1 parent 59f20f0 commit 9e5db5d

File tree

2 files changed

+94
-3
lines changed

2 files changed

+94
-3
lines changed

src/lib/http/connection.cc

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
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>
@@ -15,6 +16,8 @@
1516
#include <functional>
1617

1718
using namespace isc::asiolink;
19+
using namespace isc::dhcp;
20+
using namespace isc::util;
1821
namespace ph = std::placeholders;
1922

2023
namespace {
@@ -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

132136
void
133137
HttpConnection::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

137146
void
138147
HttpConnection::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+
156183
void
157184
HttpConnection::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

367432
void
368433
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+
}
369443
if (ec) {
370444
LOG_INFO(http_logger, HTTP_CONNECTION_HANDSHAKE_FAILED)
371445
.arg(getRemoteEndpointAddressAsText())
@@ -477,6 +551,15 @@ HttpConnection::socketReadCallback(HttpConnection::TransactionPtr transaction,
477551
void
478552
HttpConnection::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.

src/lib/http/connection.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <http/http_acceptor.h>
1313
#include <http/request_parser.h>
1414
#include <http/response_creator_factory.h>
15+
#include <util/watch_socket.h>
1516
#include <boost/enable_shared_from_this.hpp>
1617
#include <boost/system/error_code.hpp>
1718
#include <boost/shared_ptr.hpp>
@@ -398,9 +399,12 @@ class HttpConnection : public boost::enable_shared_from_this<HttpConnection> {
398399
/// @brief Stops current connection.
399400
void stopThisConnection();
400401

401-
/// @brief returns remote address in textual form
402+
/// @brief Returns remote address in textual form
402403
std::string getRemoteEndpointAddressAsText() const;
403404

405+
/// @brief Close the watch socket.
406+
void closeWatchSocket();
407+
404408
/// @brief Timer used to detect Request Timeout.
405409
asiolink::IntervalTimer request_timer_;
406410

@@ -435,6 +439,10 @@ class HttpConnection : public boost::enable_shared_from_this<HttpConnection> {
435439

436440
/// @brief Use external sockets flag.
437441
bool use_external_;
442+
443+
/// @brief Pointer to watch socket instance used to signal that the socket
444+
/// is ready for read or write when use external sockets is true.
445+
util::WatchSocketPtr watch_socket_;
438446
};
439447

440448
} // end of namespace isc::http

0 commit comments

Comments
 (0)