diff --git a/include/server/connection.hpp b/include/server/connection.hpp index b47a2a04f9d..0680735f0e3 100644 --- a/include/server/connection.hpp +++ b/include/server/connection.hpp @@ -53,7 +53,9 @@ class Connection : public std::enable_shared_from_this void handle_write(const boost::system::error_code &e); /// Handle read timeout - void handle_timeout(); + void handle_timeout(boost::system::error_code); + + void handle_shutdown(); std::vector compress_buffers(const std::vector &uncompressed_data, const http::compression_type compression_type); diff --git a/src/server/connection.cpp b/src/server/connection.cpp index 5217971948d..e64706d034b 100644 --- a/src/server/connection.cpp +++ b/src/server/connection.cpp @@ -10,7 +10,6 @@ #include #include -#include #include namespace osrm @@ -35,10 +34,13 @@ void Connection::start() boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); - // init async timer - timer.cancel(); - timer.expires_from_now(boost::posix_time::seconds(keepalive_timeout)); - timer.async_wait(boost::bind(&Connection::handle_timeout, this->shared_from_this())); + if (keep_alive) { + //Ok, we know it is not a first request, as we switched to keepalive + timer.cancel(); + timer.expires_from_now(boost::posix_time::seconds(keepalive_timeout)); + timer.async_wait( + std::bind(&Connection::handle_timeout, this->shared_from_this(), std::placeholders::_1)); + } } void Connection::handle_read(const boost::system::error_code &error, std::size_t bytes_transferred) @@ -48,6 +50,11 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t return; } + if (keep_alive) { + timer.cancel(); + timer.expires_from_now(boost::posix_time::seconds(0)); + } + // no error detected, let's parse the request http::compression_type compression_type(http::no_compression); RequestParser::RequestStatus result; @@ -132,8 +139,7 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t /// Handle completion of a write operation. void Connection::handle_write(const boost::system::error_code &error) { - if (!error) - { + if (!error) { if (keep_alive && processed_requests > 0) { --processed_requests; @@ -143,15 +149,27 @@ void Connection::handle_write(const boost::system::error_code &error) } else { - // Initiate graceful connection closure. - handle_timeout(); + handle_shutdown(); } } } -/// Handle completion of a write operation. -void Connection::handle_timeout() +/// Handle completion of a timeout timer.. +void Connection::handle_timeout(boost::system::error_code ec) +{ + // We can get there for 3 reasons: spurious wakeup by timer.cancel(), which should be ignored + // Slow client with a delayed _first_ request, which should be ignored too + // Absent next request during waiting time in the keepalive mode - should stop right there. + if (ec != boost::asio::error::operation_aborted) + { + TCP_socket.cancel(); + handle_shutdown(); + } +} + +void Connection::handle_shutdown() { + // Initiate graceful connection closure. boost::system::error_code ignore_error; TCP_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_error); }