diff options
author | Marcin Siodelski <marcin@isc.org> | 2017-01-13 13:06:23 +0100 |
---|---|---|
committer | Marcin Siodelski <marcin@isc.org> | 2017-01-13 13:06:23 +0100 |
commit | 4a9d027f7d7250d2b2afab47637507a961f9550b (patch) | |
tree | 7a3fe8cf1ba8fa74a73ab268c8bcf2a405236ead /src/lib/http/connection.cc | |
parent | [5099] Protect against exceptions in the HttpListener and HttpConnection. (diff) | |
download | kea-4a9d027f7d7250d2b2afab47637507a961f9550b.tar.xz kea-4a9d027f7d7250d2b2afab47637507a961f9550b.zip |
[5099] Handle HTTP timeouts.
Diffstat (limited to 'src/lib/http/connection.cc')
-rw-r--r-- | src/lib/http/connection.cc | 109 |
1 files changed, 52 insertions, 57 deletions
diff --git a/src/lib/http/connection.cc b/src/lib/http/connection.cc index 0081f55610..0febee328d 100644 --- a/src/lib/http/connection.cc +++ b/src/lib/http/connection.cc @@ -18,6 +18,9 @@ namespace http { void HttpConnection:: SocketCallback::operator()(boost::system::error_code ec, size_t length) { + if (ec.value() == boost::asio::error::operation_aborted) { + return; + } callback_(ec, length); } @@ -25,8 +28,11 @@ HttpConnection:: HttpConnection(asiolink::IOService& io_service, HttpAcceptor& acceptor, HttpConnectionPool& connection_pool, const HttpResponseCreatorPtr& response_creator, - const HttpAcceptorCallback& callback) - : socket_(io_service), + const HttpAcceptorCallback& callback, + const long request_timeout) + : request_timer_(io_service), + request_timeout_(request_timeout), + socket_(io_service), socket_callback_(boost::bind(&HttpConnection::socketReadCallback, this, _1, _2)), socket_write_callback_(boost::bind(&HttpConnection::socketWriteCallback, @@ -46,6 +52,19 @@ HttpConnection::~HttpConnection() { } void +HttpConnection::close() { + socket_.close(); +} + +void +HttpConnection::stopThisConnection() { + try { + connection_pool_.stop(shared_from_this()); + } catch (...) { + } +} + +void HttpConnection::asyncAccept() { HttpAcceptorCallback cb = boost::bind(&HttpConnection::acceptorCallback, this, _1); @@ -59,11 +78,6 @@ HttpConnection::asyncAccept() { } void -HttpConnection::close() { - socket_.close(); -} - -void HttpConnection::doRead() { try { TCPEndpoint endpoint; @@ -71,52 +85,47 @@ HttpConnection::doRead() { 0, &endpoint, socket_callback_); } catch (const std::exception& ex) { - isc_throw(HttpConnectionError, "unable to start asynchronous HTTP message" - " receive over TCP socket: " << ex.what()); + stopThisConnection(); } } void HttpConnection::doWrite() { - if (!output_buf_.empty()) { - try { + try { + if (!output_buf_.empty()) { socket_.asyncSend(output_buf_.data(), output_buf_.length(), socket_write_callback_); - - } catch (const std::exception& ex) { - isc_throw(HttpConnectionError, "unable to start asynchronous HTTP" - " message write over TCP socket: " << ex.what()); } + } catch (const std::exception& ex) { + stopThisConnection(); } } void +HttpConnection::asyncSendResponse(const ConstHttpResponsePtr& response) { + output_buf_ = response->toString(); + doWrite(); +} + + +void HttpConnection::acceptorCallback(const boost::system::error_code& ec) { if (!acceptor_.isOpen()) { return; } - try { - if (ec) { - connection_pool_.stop(shared_from_this()); - } - } catch (...) { + if (ec) { + stopThisConnection(); } acceptor_callback_(ec); - try { - if (!ec) { - doRead(); - } - } catch (const std::exception& ex) { - try { - connection_pool_.stop(shared_from_this()); - } catch (...) { - } + if (!ec) { + request_timer_.setup(boost::bind(&HttpConnection::requestTimeoutCallback, this), + request_timeout_, IntervalTimer::ONE_SHOT); + doRead(); } - } void @@ -125,31 +134,16 @@ HttpConnection::socketReadCallback(boost::system::error_code ec, size_t length) parser_->postBuffer(static_cast<void*>(buf_.data()), length); parser_->poll(); if (parser_->needData()) { - try { - doRead(); - } catch (const std::exception& ex) { - try { - connection_pool_.stop(shared_from_this()); - } catch (...) { - } - } + doRead(); } else { try { request_->finalize(); } catch (...) { } - HttpResponsePtr response = response_creator_->createHttpResponse(request_); - output_buf_ = response->toString(); - try { - doWrite(); - } catch (const std::exception& ex) { - try { - connection_pool_.stop(shared_from_this()); - } catch (...) { - } - } + HttpResponsePtr response = response_creator_->createHttpResponse(request_); + asyncSendResponse(response); } } @@ -158,21 +152,22 @@ HttpConnection::socketWriteCallback(boost::system::error_code ec, size_t length) { if (length <= output_buf_.size()) { output_buf_.erase(0, length); - try { - doWrite(); - - } catch (const std::exception& ex) { - try { - connection_pool_.stop(shared_from_this()); - } catch (...) { - } - } + doWrite(); } else { output_buf_.clear(); } } +void +HttpConnection::requestTimeoutCallback() { + HttpResponsePtr response = + response_creator_->createStockHttpResponse(request_, + HttpStatusCode::REQUEST_TIMEOUT); + asyncSendResponse(response); +} + + } // end of namespace isc::http } // end of namespace isc |