From 8aa729da687fcc6c1b2e745d08df5e98ad2db36f Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 25 May 2019 08:30:05 -0400 Subject: [PATCH 1/3] Fix websocket_client crash on close --- src/network/http/websocket.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/network/http/websocket.cpp b/src/network/http/websocket.cpp index 6d479bf..2a96f26 100644 --- a/src/network/http/websocket.cpp +++ b/src/network/http/websocket.cpp @@ -471,12 +471,13 @@ namespace fc { namespace http { } ~websocket_client_impl() { - if(_connection ) + if( _connection ) { _connection->close(0, "client closed"); _connection.reset(); - _closed->wait(); } + if( _closed ) + _closed->wait(); } fc::promise::ptr _connected; fc::promise::ptr _closed; From c870cd8e27de35b71038e02e147f694520907e2d Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 25 May 2019 09:59:16 -0400 Subject: [PATCH 2/3] Refactor websocket_tls_client_impl with template Removes unnecessary differences between websocket_client_impl and websocket_tls_client_impl. --- src/network/http/websocket.cpp | 79 ++++++---------------------------- 1 file changed, 12 insertions(+), 67 deletions(-) diff --git a/src/network/http/websocket.cpp b/src/network/http/websocket.cpp index 2a96f26..ad9ab4c 100644 --- a/src/network/http/websocket.cpp +++ b/src/network/http/websocket.cpp @@ -167,7 +167,7 @@ namespace fc { namespace http { :_ws_connection(con){ } - ~websocket_connection_impl() + virtual ~websocket_connection_impl() { } @@ -432,16 +432,15 @@ namespace fc { namespace http { typedef websocket_tls_client_type::connection_ptr websocket_tls_client_connection_type; using websocketpp::connection_hdl; - class websocket_client_impl + template + class generic_websocket_client_impl { public: - typedef websocket_client_type::message_ptr message_ptr; - - websocket_client_impl() + generic_websocket_client_impl() :_client_thread( fc::thread::current() ) { _client.clear_access_channels( websocketpp::log::alevel::all ); - _client.set_message_handler( [&]( connection_hdl hdl, message_ptr msg ){ + _client.set_message_handler( [&]( connection_hdl hdl, typename websocketpp::client::message_ptr msg ){ _client_thread.async( [&](){ wdump((msg->get_payload())); //std::cerr<<"recv: "<get_payload()<<"\n"; @@ -469,7 +468,7 @@ namespace fc { namespace http { _client.init_asio( &fc::asio::default_io_service() ); } - ~websocket_client_impl() + virtual ~generic_websocket_client_impl() { if( _connection ) { @@ -482,62 +481,25 @@ namespace fc { namespace http { fc::promise::ptr _connected; fc::promise::ptr _closed; fc::thread& _client_thread; - websocket_client_type _client; + websocketpp::client _client; websocket_connection_ptr _connection; std::string _uri; fc::optional _hdl; }; + class websocket_client_impl : public generic_websocket_client_impl + {}; - - class websocket_tls_client_impl + class websocket_tls_client_impl : public generic_websocket_client_impl { public: - typedef websocket_tls_client_type::message_ptr message_ptr; - websocket_tls_client_impl( const std::string& ca_filename ) - :_client_thread( fc::thread::current() ) + : generic_websocket_client_impl() { // ca_filename has special values: // "_none" disables cert checking (potentially insecure!) // "_default" uses default CA's provided by OS - _client.clear_access_channels( websocketpp::log::alevel::all ); - _client.set_message_handler( [&]( connection_hdl hdl, message_ptr msg ){ - _client_thread.async( [&](){ - wdump((msg->get_payload())); - _connection->on_message( msg->get_payload() ); - }).wait(); - }); - _client.set_close_handler( [=]( connection_hdl hdl ){ - if( _connection ) - { - try { - _client_thread.async( [&](){ - wlog(". ${p}", ("p",uint64_t(_connection.get()))); - if( !_shutting_down && !_closed && _connection ) - _connection->closed(); - _connection.reset(); - } ).wait(); - } catch ( const fc::exception& e ) - { - if( _closed ) _closed->set_exception( e.dynamic_copy_exception() ); - } - if( _closed ) _closed->set_value(); - } - }); - _client.set_fail_handler( [=]( connection_hdl hdl ){ - elog( "." ); - auto con = _client.get_con_from_hdl(hdl); - auto message = con->get_ec().message(); - if( _connection ) - _client_thread.async( [&](){ if( _connection ) _connection->closed(); _connection.reset(); } ).wait(); - if( _connected && !_connected->ready() ) - _connected->set_exception( exception_ptr( new FC_EXCEPTION( exception, "${message}", ("message",message)) ) ); - if( _closed ) - _closed->set_value(); - }); - // // We need ca_filename to be copied into the closure, as the referenced object might be destroyed by the caller by the time // tls_init_handler() is called. According to [1], capture-by-value results in the desired behavior (i.e. creation of @@ -570,18 +532,8 @@ namespace fc { namespace http { return ctx; }); - _client.init_asio( &fc::asio::default_io_service() ); - } - ~websocket_tls_client_impl() - { - if(_connection ) - { - wlog("."); - _shutting_down = true; - _connection->close(0, "client closed"); - _closed->wait(); - } } + virtual ~websocket_tls_client_impl() {} std::string get_host()const { @@ -601,13 +553,6 @@ namespace fc { namespace http { ctx->set_verify_callback( boost::asio::ssl::rfc2818_verification( get_host() ) ); } - bool _shutting_down = false; - fc::promise::ptr _connected; - fc::promise::ptr _closed; - fc::thread& _client_thread; - websocket_tls_client_type _client; - websocket_connection_ptr _connection; - std::string _uri; }; From debc4bd6c30d6a0bd42c969d0addff115550765d Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 25 May 2019 10:23:54 -0400 Subject: [PATCH 3/3] Wrap a long line --- src/network/http/websocket.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/network/http/websocket.cpp b/src/network/http/websocket.cpp index ad9ab4c..1039c88 100644 --- a/src/network/http/websocket.cpp +++ b/src/network/http/websocket.cpp @@ -440,7 +440,8 @@ namespace fc { namespace http { :_client_thread( fc::thread::current() ) { _client.clear_access_channels( websocketpp::log::alevel::all ); - _client.set_message_handler( [&]( connection_hdl hdl, typename websocketpp::client::message_ptr msg ){ + _client.set_message_handler( [&]( connection_hdl hdl, + typename websocketpp::client::message_ptr msg ){ _client_thread.async( [&](){ wdump((msg->get_payload())); //std::cerr<<"recv: "<get_payload()<<"\n";