From 85a9da6f27cc447f796a5a051c56d67a1b20aba9 Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Wed, 9 Apr 2014 18:29:59 -0400 Subject: [PATCH] Add to tcp_socket to enable TCP keepalives --- include/fc/network/tcp_socket.hpp | 3 ++- src/network/tcp_socket.cpp | 38 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/fc/network/tcp_socket.hpp b/include/fc/network/tcp_socket.hpp index a6affb3..3229f87 100644 --- a/include/fc/network/tcp_socket.hpp +++ b/include/fc/network/tcp_socket.hpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace fc { namespace ip { class endpoint; } @@ -13,6 +14,7 @@ namespace fc { void connect_to( const fc::ip::endpoint& remote_endpoint ); void connect_to( const fc::ip::endpoint& remote_endpoint, const fc::ip::endpoint& local_endpoint ); + void enable_keep_alives(const fc::microseconds& interval); fc::ip::endpoint remote_endpoint()const; void get( char& c ) @@ -58,7 +60,6 @@ namespace fc { void listen( uint16_t port ); void listen( const fc::ip::endpoint& ep ); uint16_t get_port()const; - private: // non copyable tcp_server( const tcp_server& ); diff --git a/src/network/tcp_socket.cpp b/src/network/tcp_socket.cpp index e71d759..0cca7bc 100644 --- a/src/network/tcp_socket.cpp +++ b/src/network/tcp_socket.cpp @@ -6,6 +6,10 @@ #include #include +#if defined _WIN32 || defined WIN32 || defined OS_WIN64 || defined _WIN64 || defined WIN64 || defined WINNT +# include +#endif + namespace fc { class tcp_socket::impl { @@ -64,6 +68,40 @@ namespace fc { fc::asio::tcp::connect(my->_sock, fc::asio::tcp::endpoint( boost::asio::ip::address_v4(remote_endpoint.get_address()), remote_endpoint.port() ) ); } + void tcp_socket::enable_keep_alives(const fc::microseconds& interval) + { + if (interval.count()) + { + boost::asio::socket_base::keep_alive option(true); + my->_sock.set_option(option); +#if defined _WIN32 || defined WIN32 || defined OS_WIN64 || defined _WIN64 || defined WIN64 || defined WINNT + struct tcp_keepalive keepalive_settings; + keepalive_settings.onoff = 1; + keepalive_settings.keepalivetime = interval.count() / fc::milliseconds(1).count(); + keepalive_settings.keepaliveinterval = interval.count() / fc::milliseconds(1).count(); + + DWORD dwBytesRet = 0; + if (WSAIoctl(my->_sock.native(), SIO_KEEPALIVE_VALS, &keepalive_settings, sizeof(keepalive_settings), + NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR) + wlog("Error setting TCP keepalive values"); +#else + // This should work for modern Linuxes and for OSX >= Mountain Lion + int timeout_sec = interval.count() / fc::seconds(1).count(); + if (setsockopt(my->_sock.native(), SOL_TCP, TCP_KEEPIDLE, + (char*)&timeout_sec, sizeof(timeout_sec)) < 0) + wlog("Error setting TCP keepalive idle time"); + if (setsockopt(my->_sock.native(), SOL_TCP, TCP_KEEPINTVL, + (char*)&timeout_sec, sizeof(timeout_sec)) < 0) + wlog("Error setting TCP keepalive interval"); +#endif + } + else + { + boost::asio::socket_base::keep_alive option(false); + my->_sock.set_option(option); + } + } + class tcp_server::impl { public: impl(uint16_t port)