diff --git a/changelog.md b/changelog.md index 8158a6a209..3c407b9ff1 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,7 @@ HEAD +- Updates transport code to use shared pointers rather than raw pointers to + prevent asio from retaining pointers to connection methods after the + connection goes out of scope. #293 Thank you otaras for reporting. - Fixes an issue where custom headers couldn't be set for client connections Thank you Jerry Win and Wolfram Schroers for reporting. - Fixes a compile error on visual studio when using interrupts. Thank you Javier diff --git a/websocketpp/connection.hpp b/websocketpp/connection.hpp index c95c32ca60..c8f1bc6061 100644 --- a/websocketpp/connection.hpp +++ b/websocketpp/connection.hpp @@ -216,7 +216,6 @@ template class connection : public config::transport_type::transport_con_type , public config::connection_base - , public lib::enable_shared_from_this< connection > { public: /// Type of this connection @@ -296,6 +295,11 @@ public: m_alog.write(log::alevel::devel,"connection constructor"); } + /// Get a shared pointer to this component + ptr get_shared() { + return lib::static_pointer_cast(transport_con_type::get_shared()); + } + /////////////////////////// // Set Handler Callbacks // /////////////////////////// diff --git a/websocketpp/impl/connection_impl.hpp b/websocketpp/impl/connection_impl.hpp index 26a20f494b..7dde35a831 100644 --- a/websocketpp/impl/connection_impl.hpp +++ b/websocketpp/impl/connection_impl.hpp @@ -131,7 +131,7 @@ lib::error_code connection::send(typename config::message_type::ptr msg) if (needs_writing) { transport_con_type::dispatch(lib::bind( &type::write_frame, - type::shared_from_this() + type::get_shared() )); } @@ -167,7 +167,7 @@ void connection::ping(const std::string& payload, lib::error_code& ec) { config::timeout_pong, lib::bind( &type::handle_pong_timeout, - type::shared_from_this(), + type::get_shared(), payload, lib::placeholders::_1 ) @@ -190,7 +190,7 @@ void connection::ping(const std::string& payload, lib::error_code& ec) { if (needs_writing) { transport_con_type::dispatch(lib::bind( &type::write_frame, - type::shared_from_this() + type::get_shared() )); } @@ -253,7 +253,7 @@ void connection::pong(const std::string& payload, lib::error_code& ec) { if (needs_writing) { transport_con_type::dispatch(lib::bind( &type::write_frame, - type::shared_from_this() + type::get_shared() )); } @@ -308,7 +308,7 @@ lib::error_code connection::interrupt() { return transport_con_type::interrupt( lib::bind( &type::handle_interrupt, - type::shared_from_this() + type::get_shared() ) ); } @@ -593,7 +593,7 @@ void connection::start() { transport_con_type::init( lib::bind( &type::handle_transport_init, - type::shared_from_this(), + type::get_shared(), lib::placeholders::_1 ) ); @@ -650,7 +650,7 @@ void connection::read_handshake(size_t num_bytes) { config::timeout_open_handshake, lib::bind( &type::handle_open_handshake_timeout, - type::shared_from_this(), + type::get_shared(), lib::placeholders::_1 ) ); @@ -661,7 +661,7 @@ void connection::read_handshake(size_t num_bytes) { config::connection_read_buffer_size, lib::bind( &type::handle_read_handshake, - type::shared_from_this(), + type::get_shared(), lib::placeholders::_1, lib::placeholders::_2 ) @@ -785,7 +785,7 @@ void connection::handle_read_handshake(const lib::error_code& ec, config::connection_read_buffer_size, lib::bind( &type::handle_read_handshake, - type::shared_from_this(), + type::get_shared(), lib::placeholders::_1, lib::placeholders::_2 ) @@ -944,7 +944,7 @@ void connection::handle_read_frame(const lib::error_code& ec, config::connection_read_buffer_size, lib::bind( &type::handle_read_frame, - type::shared_from_this(), + type::get_shared(), lib::placeholders::_1, lib::placeholders::_2 ) @@ -1151,7 +1151,7 @@ void connection::send_http_response() { m_handshake_buffer.size(), lib::bind( &type::handle_send_http_response, - type::shared_from_this(), + type::get_shared(), lib::placeholders::_1 ) ); @@ -1257,7 +1257,7 @@ void connection::send_http_request() { config::timeout_open_handshake, lib::bind( &type::handle_open_handshake_timeout, - type::shared_from_this(), + type::get_shared(), lib::placeholders::_1 ) ); @@ -1267,7 +1267,7 @@ void connection::send_http_request() { m_handshake_buffer.size(), lib::bind( &type::handle_send_http_request, - type::shared_from_this(), + type::get_shared(), lib::placeholders::_1 ) ); @@ -1301,7 +1301,7 @@ void connection::handle_send_http_request(const lib::error_code& ec) { config::connection_read_buffer_size, lib::bind( &type::handle_read_http_response, - type::shared_from_this(), + type::get_shared(), lib::placeholders::_1, lib::placeholders::_2 ) @@ -1386,7 +1386,7 @@ void connection::handle_read_http_response(const lib::error_code& ec, config::connection_read_buffer_size, lib::bind( &type::handle_read_http_response, - type::shared_from_this(), + type::get_shared(), lib::placeholders::_1, lib::placeholders::_2 ) @@ -1462,7 +1462,7 @@ void connection::terminate(const lib::error_code & ec) { transport_con_type::async_shutdown( lib::bind( &type::handle_terminate, - type::shared_from_this(), + type::get_shared(), tstat, lib::placeholders::_1 ) @@ -1502,7 +1502,7 @@ void connection::handle_terminate(terminate_status tstat, // If it does, we don't care and should catch and ignore it. if (m_termination_handler) { try { - m_termination_handler(type::shared_from_this()); + m_termination_handler(type::get_shared()); } catch (const std::exception& e) { m_elog.write(log::elevel::warn, std::string("termination_handler call failed. Reason was: ") @@ -1567,7 +1567,7 @@ void connection::write_frame() { m_send_buffer, lib::bind( &type::handle_write_frame, - type::shared_from_this(), + type::get_shared(), m_current_msg->get_terminal(), lib::placeholders::_1 ) @@ -1609,7 +1609,7 @@ void connection::handle_write_frame(bool terminate, if (needs_writing) { transport_con_type::dispatch(lib::bind( &type::write_frame, - type::shared_from_this() + type::get_shared() )); } } @@ -1865,7 +1865,7 @@ lib::error_code connection::send_close_frame(close::status::value code, config::timeout_close_handshake, lib::bind( &type::handle_close_handshake_timeout, - type::shared_from_this(), + type::get_shared(), lib::placeholders::_1 ) ); @@ -1880,7 +1880,7 @@ lib::error_code connection::send_close_frame(close::status::value code, if (needs_writing) { transport_con_type::dispatch(lib::bind( &type::write_frame, - type::shared_from_this() + type::get_shared() )); } diff --git a/websocketpp/transport/asio/connection.hpp b/websocketpp/transport/asio/connection.hpp index e775dd38c6..545dc81849 100644 --- a/websocketpp/transport/asio/connection.hpp +++ b/websocketpp/transport/asio/connection.hpp @@ -93,6 +93,11 @@ public: m_alog.write(log::alevel::devel,"asio con transport constructor"); } + /// Get a shared pointer to this component + ptr get_shared() { + return lib::static_pointer_cast(socket_con_type::get_shared()); + } + bool is_secure() const { return socket_con_type::is_secure(); } @@ -291,7 +296,7 @@ public: new_timer->async_wait( lib::bind( &type::handle_timer, - this, + get_shared(), new_timer, callback, lib::placeholders::_1 @@ -355,7 +360,7 @@ protected: socket_con_type::pre_init( lib::bind( &type::handle_pre_init, - this, + get_shared(), callback, lib::placeholders::_1 ) @@ -394,7 +399,7 @@ protected: config::timeout_socket_post_init, lib::bind( &type::handle_post_init_timeout, - this, + get_shared(), post_timer, callback, lib::placeholders::_1 @@ -404,7 +409,7 @@ protected: socket_con_type::post_init( lib::bind( &type::handle_post_init, - this, + get_shared(), post_timer, callback, lib::placeholders::_1 @@ -482,7 +487,7 @@ protected: m_proxy_data->timeout_proxy, lib::bind( &type::handle_proxy_timeout, - this, + get_shared(), callback, lib::placeholders::_1 ) @@ -494,7 +499,7 @@ protected: m_bufs, lib::bind( &type::handle_proxy_write, - this, + get_shared(), callback, lib::placeholders::_1 ) @@ -565,7 +570,7 @@ protected: "\r\n\r\n", lib::bind( &type::handle_proxy_read, - this, + get_shared(), callback, lib::placeholders::_1, lib::placeholders::_2 @@ -677,7 +682,7 @@ protected: boost::asio::transfer_at_least(num_bytes), lib::bind( &type::handle_async_read, - this, + get_shared(), handler, lib::placeholders::_1, lib::placeholders::_2 @@ -715,7 +720,7 @@ protected: m_bufs, lib::bind( &type::handle_async_write, - this, + get_shared(), handler, lib::placeholders::_1 ) @@ -734,7 +739,7 @@ protected: m_bufs, lib::bind( &type::handle_async_write, - this, + get_shared(), handler, lib::placeholders::_1 ) @@ -796,7 +801,7 @@ protected: config::timeout_socket_shutdown, lib::bind( &type::handle_async_shutdown_timeout, - this, + get_shared(), shutdown_timer, callback, lib::placeholders::_1 @@ -806,7 +811,7 @@ protected: socket_con_type::async_shutdown( lib::bind( &type::handle_async_shutdown, - this, + get_shared(), shutdown_timer, callback, lib::placeholders::_1 diff --git a/websocketpp/transport/asio/security/none.hpp b/websocketpp/transport/asio/security/none.hpp index c0df412ffa..19d9bf6020 100644 --- a/websocketpp/transport/asio/security/none.hpp +++ b/websocketpp/transport/asio/security/none.hpp @@ -28,6 +28,7 @@ #ifndef WEBSOCKETPP_TRANSPORT_SECURITY_NONE_HPP #define WEBSOCKETPP_TRANSPORT_SECURITY_NONE_HPP +#include #include #include @@ -48,7 +49,7 @@ typedef lib::function * transport::asio::basic_socket::connection implements a connection socket * component using Boost ASIO ip::tcp::socket. */ -class connection { +class connection : public lib::enable_shared_from_this { public: /// Type of this connection socket component typedef connection type; @@ -65,6 +66,11 @@ public: // << std::endl; } + /// Get a shared pointer to this component + ptr get_shared() { + return shared_from_this(); + } + /// Check whether or not this connection is secure /** * @return Whether or not this connection is secure diff --git a/websocketpp/transport/asio/security/tls.hpp b/websocketpp/transport/asio/security/tls.hpp index a99275ddf5..1d6ab7e249 100644 --- a/websocketpp/transport/asio/security/tls.hpp +++ b/websocketpp/transport/asio/security/tls.hpp @@ -55,7 +55,7 @@ typedef lib::function(connection_hdl) * transport::asio::tls_socket::connection implements a secure connection socket * component that uses Boost ASIO's ssl::stream to wrap an ip::tcp::socket. */ -class connection { +class connection : public lib::enable_shared_from_this { public: /// Type of this connection socket component typedef connection type; @@ -78,6 +78,11 @@ public: // << std::endl; } + /// Get a shared pointer to this component + ptr get_shared() { + return shared_from_this(); + } + /// Check whether or not this connection is secure /** * @return Whether or not this connection is secure @@ -221,7 +226,7 @@ protected: get_handshake_type(), lib::bind( &type::handle_init, - this, + get_shared(), callback, lib::placeholders::_1 ) diff --git a/websocketpp/transport/iostream/connection.hpp b/websocketpp/transport/iostream/connection.hpp index 98443b4390..24ed580a17 100644 --- a/websocketpp/transport/iostream/connection.hpp +++ b/websocketpp/transport/iostream/connection.hpp @@ -49,7 +49,7 @@ struct timer { }; template -class connection { +class connection : public lib::enable_shared_from_this< connection > { public: /// Type of this connection transport component typedef connection type; @@ -81,6 +81,11 @@ public: m_alog.write(log::alevel::devel,"iostream con transport constructor"); } + /// Get a shared pointer to this component + ptr get_shared() { + return type::shared_from_this(); + } + /// Register a std::ostream with the transport for writing output /** * Register a std::ostream with the transport. All future writes will be