Skip to content

Commit 9ce24c2

Browse files
authored
Merge pull request #136 from bitshares/ws-client-fix
Fix websocket client crash on quit
2 parents 397830b + debc4bd commit 9ce24c2

File tree

1 file changed

+16
-69
lines changed

1 file changed

+16
-69
lines changed

src/network/http/websocket.cpp

+16-69
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ namespace fc { namespace http {
167167
:_ws_connection(con){
168168
}
169169

170-
~websocket_connection_impl()
170+
virtual ~websocket_connection_impl()
171171
{
172172
}
173173

@@ -432,16 +432,16 @@ namespace fc { namespace http {
432432
typedef websocket_tls_client_type::connection_ptr websocket_tls_client_connection_type;
433433
using websocketpp::connection_hdl;
434434

435-
class websocket_client_impl
435+
template<typename T>
436+
class generic_websocket_client_impl
436437
{
437438
public:
438-
typedef websocket_client_type::message_ptr message_ptr;
439-
440-
websocket_client_impl()
439+
generic_websocket_client_impl()
441440
:_client_thread( fc::thread::current() )
442441
{
443442
_client.clear_access_channels( websocketpp::log::alevel::all );
444-
_client.set_message_handler( [&]( connection_hdl hdl, message_ptr msg ){
443+
_client.set_message_handler( [&]( connection_hdl hdl,
444+
typename websocketpp::client<T>::message_ptr msg ){
445445
_client_thread.async( [&](){
446446
wdump((msg->get_payload()));
447447
//std::cerr<<"recv: "<<msg->get_payload()<<"\n";
@@ -469,74 +469,38 @@ namespace fc { namespace http {
469469

470470
_client.init_asio( &fc::asio::default_io_service() );
471471
}
472-
~websocket_client_impl()
472+
virtual ~generic_websocket_client_impl()
473473
{
474-
if(_connection )
474+
if( _connection )
475475
{
476476
_connection->close(0, "client closed");
477477
_connection.reset();
478-
_closed->wait();
479478
}
479+
if( _closed )
480+
_closed->wait();
480481
}
481482
fc::promise<void>::ptr _connected;
482483
fc::promise<void>::ptr _closed;
483484
fc::thread& _client_thread;
484-
websocket_client_type _client;
485+
websocketpp::client<T> _client;
485486
websocket_connection_ptr _connection;
486487
std::string _uri;
487488
fc::optional<connection_hdl> _hdl;
488489
};
489490

491+
class websocket_client_impl : public generic_websocket_client_impl<asio_with_stub_log>
492+
{};
490493

491-
492-
class websocket_tls_client_impl
494+
class websocket_tls_client_impl : public generic_websocket_client_impl<asio_tls_stub_log>
493495
{
494496
public:
495-
typedef websocket_tls_client_type::message_ptr message_ptr;
496-
497497
websocket_tls_client_impl( const std::string& ca_filename )
498-
:_client_thread( fc::thread::current() )
498+
: generic_websocket_client_impl()
499499
{
500500
// ca_filename has special values:
501501
// "_none" disables cert checking (potentially insecure!)
502502
// "_default" uses default CA's provided by OS
503503

504-
_client.clear_access_channels( websocketpp::log::alevel::all );
505-
_client.set_message_handler( [&]( connection_hdl hdl, message_ptr msg ){
506-
_client_thread.async( [&](){
507-
wdump((msg->get_payload()));
508-
_connection->on_message( msg->get_payload() );
509-
}).wait();
510-
});
511-
_client.set_close_handler( [=]( connection_hdl hdl ){
512-
if( _connection )
513-
{
514-
try {
515-
_client_thread.async( [&](){
516-
wlog(". ${p}", ("p",uint64_t(_connection.get())));
517-
if( !_shutting_down && !_closed && _connection )
518-
_connection->closed();
519-
_connection.reset();
520-
} ).wait();
521-
} catch ( const fc::exception& e )
522-
{
523-
if( _closed ) _closed->set_exception( e.dynamic_copy_exception() );
524-
}
525-
if( _closed ) _closed->set_value();
526-
}
527-
});
528-
_client.set_fail_handler( [=]( connection_hdl hdl ){
529-
elog( "." );
530-
auto con = _client.get_con_from_hdl(hdl);
531-
auto message = con->get_ec().message();
532-
if( _connection )
533-
_client_thread.async( [&](){ if( _connection ) _connection->closed(); _connection.reset(); } ).wait();
534-
if( _connected && !_connected->ready() )
535-
_connected->set_exception( exception_ptr( new FC_EXCEPTION( exception, "${message}", ("message",message)) ) );
536-
if( _closed )
537-
_closed->set_value();
538-
});
539-
540504
//
541505
// We need ca_filename to be copied into the closure, as the referenced object might be destroyed by the caller by the time
542506
// tls_init_handler() is called. According to [1], capture-by-value results in the desired behavior (i.e. creation of
@@ -569,18 +533,8 @@ namespace fc { namespace http {
569533
return ctx;
570534
});
571535

572-
_client.init_asio( &fc::asio::default_io_service() );
573-
}
574-
~websocket_tls_client_impl()
575-
{
576-
if(_connection )
577-
{
578-
wlog(".");
579-
_shutting_down = true;
580-
_connection->close(0, "client closed");
581-
_closed->wait();
582-
}
583536
}
537+
virtual ~websocket_tls_client_impl() {}
584538

585539
std::string get_host()const
586540
{
@@ -600,13 +554,6 @@ namespace fc { namespace http {
600554
ctx->set_verify_callback( boost::asio::ssl::rfc2818_verification( get_host() ) );
601555
}
602556

603-
bool _shutting_down = false;
604-
fc::promise<void>::ptr _connected;
605-
fc::promise<void>::ptr _closed;
606-
fc::thread& _client_thread;
607-
websocket_tls_client_type _client;
608-
websocket_connection_ptr _connection;
609-
std::string _uri;
610557
};
611558

612559

0 commit comments

Comments
 (0)