fix crash in websocket

This commit is contained in:
Daniel Larimer 2015-05-06 16:34:55 -04:00
parent 3599850bb9
commit 4df08d8efe
3 changed files with 25 additions and 8 deletions

View file

@ -91,7 +91,7 @@ namespace fc {
return _methods[method_id](args); return _methods[method_id](args);
} }
fc::api_connection& get_connection(){ return *_api_connection; } fc::api_connection& get_connection(){ auto tmp = _api_connection.lock(); FC_ASSERT( tmp, "connection closed"); return *tmp; }
private: private:
@ -133,7 +133,7 @@ namespace fc {
struct api_visitor struct api_visitor
{ {
api_visitor( generic_api& a, const std::shared_ptr<fc::api_connection>& s ):api(a),_api_con(s){ } api_visitor( generic_api& a, const std::weak_ptr<fc::api_connection>& s ):api(a),_api_con(s){ }
template<typename Interface, typename Adaptor, typename ... Args> template<typename Interface, typename Adaptor, typename ... Args>
std::function<variant(const fc::variants&)> to_generic( const std::function<api<Interface,Adaptor>(Args...)>& f )const; std::function<variant(const fc::variants&)> to_generic( const std::function<api<Interface,Adaptor>(Args...)>& f )const;
@ -154,11 +154,11 @@ namespace fc {
} }
generic_api& api; generic_api& api;
const std::shared_ptr<fc::api_connection>& _api_con; const std::weak_ptr<fc::api_connection>& _api_con;
}; };
std::shared_ptr<fc::api_connection> _api_connection; std::weak_ptr<fc::api_connection> _api_connection;
fc::any _api; fc::any _api;
std::map< std::string, uint32_t > _by_name; std::map< std::string, uint32_t > _by_name;
std::vector< std::function<variant(const variants&)> > _methods; std::vector< std::function<variant(const variants&)> > _methods;
@ -325,7 +325,7 @@ namespace fc {
generic_api::generic_api( const Api& a, const std::shared_ptr<fc::api_connection>& c ) generic_api::generic_api( const Api& a, const std::shared_ptr<fc::api_connection>& c )
:_api_connection(c),_api(a) :_api_connection(c),_api(a)
{ {
boost::any_cast<const Api&>(a)->visit( api_visitor( *this, _api_connection ) ); boost::any_cast<const Api&>(a)->visit( api_visitor( *this, c ) );
} }
template<typename Interface, typename Adaptor, typename ... Args> template<typename Interface, typename Adaptor, typename ... Args>
@ -335,8 +335,11 @@ namespace fc {
auto api_con = _api_con; auto api_con = _api_con;
auto gapi = &api; auto gapi = &api;
return [=]( const variants& args ) { return [=]( const variants& args ) {
auto con = api_con.lock();
FC_ASSERT( con, "not connected" );
auto api_result = gapi->call_generic( f, args.begin(), args.end() ); auto api_result = gapi->call_generic( f, args.begin(), args.end() );
return api_con->register_api( api_result ); return con->register_api( api_result );
}; };
} }
template<typename Interface, typename Adaptor, typename ... Args> template<typename Interface, typename Adaptor, typename ... Args>
@ -346,9 +349,12 @@ namespace fc {
auto api_con = _api_con; auto api_con = _api_con;
auto gapi = &api; auto gapi = &api;
return [=]( const variants& args )-> fc::variant { return [=]( const variants& args )-> fc::variant {
auto con = api_con.lock();
FC_ASSERT( con, "not connected" );
auto api_result = gapi->call_generic( f, args.begin(), args.end() ); auto api_result = gapi->call_generic( f, args.begin(), args.end() );
if( api_result ) if( api_result )
return api_con->register_api( *api_result ); return con->register_api( *api_result );
return variant(); return variant();
}; };
} }

View file

@ -10,6 +10,10 @@ namespace fc { namespace rpc {
class websocket_api_connection : public api_connection class websocket_api_connection : public api_connection
{ {
public: public:
~websocket_api_connection()
{
}
websocket_api_connection( fc::http::websocket_connection& c ) websocket_api_connection( fc::http::websocket_connection& c )
:_connection(c) :_connection(c)
{ {

View file

@ -69,7 +69,12 @@ namespace fc { namespace http {
{ {
public: public:
websocket_connection_impl( T con ) websocket_connection_impl( T con )
:_ws_connection(con){} :_ws_connection(con){
}
~websocket_connection_impl()
{
}
virtual void send_message( const std::string& message )override virtual void send_message( const std::string& message )override
{ {
@ -110,6 +115,7 @@ namespace fc { namespace http {
}); });
_server.set_close_handler( [&]( connection_hdl hdl ){ _server.set_close_handler( [&]( connection_hdl hdl ){
_server_thread.async( [&](){ _server_thread.async( [&](){
_connections[hdl]->closed();
_connections.erase( hdl ); _connections.erase( hdl );
}).wait(); }).wait();
}); });
@ -118,6 +124,7 @@ namespace fc { namespace http {
if( _server.is_listening() ) if( _server.is_listening() )
{ {
_server_thread.async( [&](){ _server_thread.async( [&](){
_connections[hdl]->closed();
_connections.erase( hdl ); _connections.erase( hdl );
}).wait(); }).wait();
} }