From b87bfc068ed5b61d37d5b7ab1ff159766c13ee17 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Sun, 3 Nov 2013 12:40:55 -0600 Subject: [PATCH] Allow setting pong and handshake timeouts at runtime --- changelog.md | 1 + websocketpp/connection.hpp | 81 ++++++++++++++++++++++++++++ websocketpp/endpoint.hpp | 80 +++++++++++++++++++++++++++ websocketpp/impl/connection_impl.hpp | 6 +-- websocketpp/impl/endpoint_impl.hpp | 12 ++++- 5 files changed, 176 insertions(+), 4 deletions(-) diff --git a/changelog.md b/changelog.md index 2b1d38a88d..1b390bb577 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,5 @@ HEAD +- Feature: Allow setting pong and handshake timeouts at runtime. - Allows changing the listen backlog queue length. - Fix handler allocation crash with multithreaded io_service. - Split tcp init into pre and post init. diff --git a/websocketpp/connection.hpp b/websocketpp/connection.hpp index c3ce1bf000..0bfb481f55 100644 --- a/websocketpp/connection.hpp +++ b/websocketpp/connection.hpp @@ -294,6 +294,9 @@ public: lib::placeholders::_1 )) , m_user_agent(ua) + , m_open_handshake_timeout_dur(config::timeout_open_handshake) + , m_close_handshake_timeout_dur(config::timeout_close_handshake) + , m_pong_timeout_dur(config::timeout_pong) , m_state(session::state::connecting) , m_internal_state(session::internal_state::USER_INIT) , m_msg_manager(new con_msg_manager_type()) @@ -452,6 +455,79 @@ public: m_message_handler = h; } + ///////////////////////// + // Connection timeouts // + ///////////////////////// + + /// Set open handshake timeout + /** + * Sets the length of time the library will wait after an opening handshake + * has been initiated before cancelling it. This can be used to prevent + * excessive wait times for outgoing clients or excessive resource usage + * from broken clients or DoS attacks on servers. + * + * Connections that time out will have their fail handlers called with the + * open_handshake_timeout error code. + * + * The default value is specified via the compile time config value + * 'timeout_open_handshake'. The default value in the core config + * is 5000ms. + * + * To be effective, the transport you are using must support timers. See + * the documentation for your transport policy for details about its + * timer support. + * + * @param dur The length of the open handshake timeout in ms + */ + void set_open_handshake_timeout(long dur) { + m_open_handshake_timeout_dur = dur; + } + + /// Set close handshake timeout + /** + * Sets the length of time the library will wait after a closing handshake + * has been initiated before cancelling it. This can be used to prevent + * excessive wait times for outgoing clients or excessive resource usage + * from broken clients or DoS attacks on servers. + * + * Connections that time out will have their close handlers called with the + * close_handshake_timeout error code. + * + * The default value is specified via the compile time config value + * 'timeout_close_handshake'. The default value in the core config + * is 5000ms. + * + * To be effective, the transport you are using must support timers. See + * the documentation for your transport policy for details about its + * timer support. + * + * @param dur The length of the close handshake timeout in ms + */ + void set_close_handshake_timeout(long dur) { + m_close_handshake_timeout_dur = dur; + } + + /// Set pong timeout + /** + * Sets the length of time the library will wait for a pong response to a + * ping. This can be used as a keepalive or to detect broken connections. + * + * Pong responses that time out will have the pong timeout handler called. + * + * The default value is specified via the compile time config value + * 'timeout_pong'. The default value in the core config + * is 5000ms. + * + * To be effective, the transport you are using must support timers. See + * the documentation for your transport policy for details about its + * timer support. + * + * @param dur The length of the pong timeout in ms + */ + void set_pong_timeout(long dur) { + m_pong_timeout_dur = dur; + } + ////////////////////////////////// // Uncategorized public methods // ////////////////////////////////// @@ -1227,6 +1303,11 @@ private: validate_handler m_validate_handler; message_handler m_message_handler; + /// constant values + long m_open_handshake_timeout_dur; + long m_close_handshake_timeout_dur; + long m_pong_timeout_dur; + /// External connection state /** * Lock: m_connection_state_lock diff --git a/websocketpp/endpoint.hpp b/websocketpp/endpoint.hpp index 3c72b504b0..139a93179a 100644 --- a/websocketpp/endpoint.hpp +++ b/websocketpp/endpoint.hpp @@ -91,6 +91,9 @@ public: : m_alog(config::alog_level, &std::cout) , m_elog(config::elog_level, &std::cerr) , m_user_agent(::websocketpp::user_agent) + , m_open_handshake_timeout_dur(config::timeout_open_handshake) + , m_close_handshake_timeout_dur(config::timeout_close_handshake) + , m_pong_timeout_dur(config::timeout_pong) , m_is_server(is_server) { m_alog.set_channels(config::alog_level); @@ -269,6 +272,79 @@ public: m_message_handler = h; } + ///////////////////////// + // Connection timeouts // + ///////////////////////// + + /// Set open handshake timeout + /** + * Sets the length of time the library will wait after an opening handshake + * has been initiated before cancelling it. This can be used to prevent + * excessive wait times for outgoing clients or excessive resource usage + * from broken clients or DoS attacks on servers. + * + * Connections that time out will have their fail handlers called with the + * open_handshake_timeout error code. + * + * The default value is specified via the compile time config value + * 'timeout_open_handshake'. The default value in the core config + * is 5000ms. + * + * To be effective, the transport you are using must support timers. See + * the documentation for your transport policy for details about its + * timer support. + * + * @param dur The length of the open handshake timeout in ms + */ + void set_open_handshake_timeout(long dur) { + m_open_handshake_timeout_dur = dur; + } + + /// Set close handshake timeout + /** + * Sets the length of time the library will wait after a closing handshake + * has been initiated before cancelling it. This can be used to prevent + * excessive wait times for outgoing clients or excessive resource usage + * from broken clients or DoS attacks on servers. + * + * Connections that time out will have their close handlers called with the + * close_handshake_timeout error code. + * + * The default value is specified via the compile time config value + * 'timeout_close_handshake'. The default value in the core config + * is 5000ms. + * + * To be effective, the transport you are using must support timers. See + * the documentation for your transport policy for details about its + * timer support. + * + * @param dur The length of the close handshake timeout in ms + */ + void set_close_handshake_timeout(long dur) { + m_close_handshake_timeout_dur = dur; + } + + /// Set pong timeout + /** + * Sets the length of time the library will wait for a pong response to a + * ping. This can be used as a keepalive or to detect broken connections. + * + * Pong responses that time out will have the pong timeout handler called. + * + * The default value is specified via the compile time config value + * 'timeout_pong'. The default value in the core config + * is 5000ms. + * + * To be effective, the transport you are using must support timers. See + * the documentation for your transport policy for details about its + * timer support. + * + * @param dur The length of the pong timeout in ms + */ + void set_pong_timeout(long dur) { + m_pong_timeout_dur = dur; + } + /*************************************/ /* Connection pass through functions */ /*************************************/ @@ -415,6 +491,10 @@ private: validate_handler m_validate_handler; message_handler m_message_handler; + long m_open_handshake_timeout_dur; + long m_close_handshake_timeout_dur; + long m_pong_timeout_dur; + rng_type m_rng; // static settings diff --git a/websocketpp/impl/connection_impl.hpp b/websocketpp/impl/connection_impl.hpp index e07e066c80..478adbe18d 100644 --- a/websocketpp/impl/connection_impl.hpp +++ b/websocketpp/impl/connection_impl.hpp @@ -164,7 +164,7 @@ void connection::ping(const std::string& payload, lib::error_code& ec) { } m_ping_timer = transport_con_type::set_timer( - config::timeout_pong, + m_pong_timeout_dur, lib::bind( &type::handle_pong_timeout, type::get_shared(), @@ -1255,7 +1255,7 @@ void connection::send_http_request() { } m_handshake_timer = transport_con_type::set_timer( - config::timeout_open_handshake, + m_open_handshake_timeout_dur, lib::bind( &type::handle_open_handshake_timeout, type::get_shared(), @@ -1866,7 +1866,7 @@ lib::error_code connection::send_close_frame(close::status::value code, // Start a timer so we don't wait forever for the acknowledgement close // frame m_handshake_timer = transport_con_type::set_timer( - config::timeout_close_handshake, + m_close_handshake_timeout_dur, lib::bind( &type::handle_close_handshake_timeout, type::get_shared(), diff --git a/websocketpp/impl/endpoint_impl.hpp b/websocketpp/impl/endpoint_impl.hpp index e30c0d9df4..1a150b6bf0 100644 --- a/websocketpp/impl/endpoint_impl.hpp +++ b/websocketpp/impl/endpoint_impl.hpp @@ -63,7 +63,17 @@ endpoint::create_connection() { con->set_http_handler(m_http_handler); con->set_validate_handler(m_validate_handler); con->set_message_handler(m_message_handler); - + + if (m_open_handshake_timeout_dur == config::timeout_open_handshake) { + con->set_open_handshake_timeout(m_open_handshake_timeout_dur); + } + if (m_close_handshake_timeout_dur == config::timeout_close_handshake) { + con->set_close_handshake_timeout(m_close_handshake_timeout_dur); + } + if (m_pong_timeout_dur == config::timeout_pong) { + con->set_pong_timeout(m_pong_timeout_dur); + } + lib::error_code ec; ec = transport_type::init(con);