diff --git a/include/fc/json_rpc_connection.hpp b/include/fc/json_rpc_connection.hpp index f8369f3..a0846ac 100644 --- a/include/fc/json_rpc_connection.hpp +++ b/include/fc/json_rpc_connection.hpp @@ -79,6 +79,8 @@ namespace fc { namespace json { void operator()( const char* name, std::function& meth); template void operator()( const char* name, std::function& meth); + template + void operator()( const char* name, std::function& meth); const fc::ptr& _ptr; fc::json::rpc_connection& _con; @@ -110,7 +112,12 @@ namespace fc { namespace json { typename promise::ptr rtn( r, true ); invoke( detail::pending_result::ptr(r), method, value(detail::named_param::type>::to_value(a)) ); - return rtn; + } + + template + void notice( const fc::string& method, Args&& a = nullptr ){ + send_notice( method, + value(detail::named_param::type>::to_value(a)) ); } template @@ -122,6 +129,7 @@ namespace fc { namespace json { protected: void handle_message( const value& m ); + virtual void send_notice( const fc::string& m, value&& param ) = 0; virtual void send_invoke( uint64_t id, const fc::string& m, value&& param ) = 0; virtual void send_error( uint64_t id, int64_t code, const fc::string& msg ) = 0; virtual void send_result( uint64_t id, value&& r ) = 0; @@ -150,6 +158,11 @@ namespace fc { namespace json { _con.add_method( name, rpc_server_method::ptr( new rpc_server_method_impl,R(A1,A2) >(meth) ) ); } template + template + void add_method_visitor::operator()( const char* name, std::function& meth) { + _con.add_method( name, rpc_server_method::ptr( new rpc_server_method_impl,R(A1,A2,A3) >(meth) ) ); + } + template template void add_method_visitor::operator()( const char* name, std::function& meth) { _con.add_method( name, rpc_server_method::ptr( new rpc_server_method_impl,R() >(meth) ) ); diff --git a/include/fc/json_rpc_ssh_process_client.hpp b/include/fc/json_rpc_ssh_process_client.hpp index d11018b..cadae75 100644 --- a/include/fc/json_rpc_ssh_process_client.hpp +++ b/include/fc/json_rpc_ssh_process_client.hpp @@ -1,26 +1,21 @@ #pragma once #include +#include #include namespace fc { namespace json { template - class rpc_ssh_process_client : public ptr { + class rpc_ssh_process_client : public rpc_client { public: rpc_ssh_process_client(){} bool valid()const { return proc.valid(); } rpc_ssh_process_client( const fc::ssh::process& proc ) - { - con.reset( new fc::json::rpc_stream_connection( proc.out_stream(), proc.in_stream() ) ); - this->_vtable.reset(new fc::detail::vtable() ); - this->_vtable->template visit( fc::json::detail::vtable_visitor(_con) ); - } + :rpc_client(rpc_connection::ptr(new fc::json::rpc_stream_connection( proc.out_stream(), proc.in_stream() ) ) ){} rpc_ssh_process_client& operator = ( const fc::ssh::process& proc ) { - con.reset( new fc::json::rpc_stream_connection( proc.out_stream(), proc.in_stream() ) ); - this->_vtable.reset(new fc::detail::vtable() ); - this->_vtable->template visit( fc::json::detail::vtable_visitor(_con) ); + this->set_connection( rpc_connection::ptr(new fc::json::rpc_stream_connection( proc.out_stream(), proc.in_stream() ) ) ); return *this; } diff --git a/include/fc/json_rpc_stream_connection.hpp b/include/fc/json_rpc_stream_connection.hpp index b0dab25..c6ea8ec 100644 --- a/include/fc/json_rpc_stream_connection.hpp +++ b/include/fc/json_rpc_stream_connection.hpp @@ -29,6 +29,7 @@ namespace fc { protected: ~rpc_stream_connection(); virtual void send_invoke( uint64_t id, const fc::string& m, value&& param ); + virtual void send_notice( const fc::string& m, value&& param ); virtual void send_error( uint64_t id, int64_t code, const fc::string& msg ); virtual void send_result( uint64_t id, value&& r ); diff --git a/include/fc/ssh/process.hpp b/include/fc/ssh/process.hpp index fbc65dc..135b89a 100644 --- a/include/fc/ssh/process.hpp +++ b/include/fc/ssh/process.hpp @@ -40,15 +40,15 @@ namespace fc { /** * @brief returns a stream that writes to the procss' stdin */ - fc::ostream& in_stream(); + fc::ostream& in_stream()const; /** * @brief returns a stream that reads from the process' stdout */ - fc::istream& out_stream(); + fc::istream& out_stream()const; /** * @brief returns a stream that reads from the process' stderr */ - fc::istream& err_stream(); + fc::istream& err_stream()const; private: friend class client; process( client& c, const fc::string& cmd, const fc::string& pty_type = fc::string() ); diff --git a/include/fc/value_cast.hpp b/include/fc/value_cast.hpp index 19f78fb..f244e36 100644 --- a/include/fc/value_cast.hpp +++ b/include/fc/value_cast.hpp @@ -108,6 +108,28 @@ namespace fc { private: value::object& m_out; }; + template<> + struct cast_visitor : value::const_visitor { + cast_visitor( value& out ) + :m_out(out){} + virtual void operator()( const int8_t& v ) { m_out = v; } + virtual void operator()( const int16_t& v ) { m_out = v; } + virtual void operator()( const int32_t& v ) { m_out = v; } + virtual void operator()( const int64_t& v ) { m_out = v; } + virtual void operator()( const uint8_t& v ) { m_out = v; } + virtual void operator()( const uint16_t& v ) { m_out = v; } + virtual void operator()( const uint32_t& v ) { m_out = v; } + virtual void operator()( const uint64_t& v ) { m_out = v; } + virtual void operator()( const float& v ) { m_out = v; } + virtual void operator()( const double& v ) { m_out = v; } + virtual void operator()( const bool& v ) { m_out = v; } + virtual void operator()( const fc::string& v ) { m_out = v; } + virtual void operator()( const value::object& a ) { m_out = a; } + virtual void operator()( const value::array& a ) { m_out = a; } + virtual void operator()( ) { m_out = value(); } + + value& m_out; + }; template struct cast_visitor> : value::const_visitor { diff --git a/src/json_rpc_connection.cpp b/src/json_rpc_connection.cpp index 34bcdb7..e9d908e 100644 --- a/src/json_rpc_connection.cpp +++ b/src/json_rpc_connection.cpp @@ -51,11 +51,12 @@ namespace fc { namespace json { if( m_itr != end ) { fc::string mname = value_cast(m_itr->val); - auto id = value_cast(id_itr->val); + auto smeth = my->_methods.find( mname ); if( smeth == my->_methods.end() ) { if( id_itr != end ) { // TODO: send invalid method reply + auto id = value_cast(id_itr->val); send_error( id, -1, "Unknown method '"+mname+"'"); } // nothing to do, unknown method @@ -67,6 +68,7 @@ namespace fc { namespace json { slog( "params '%s'", to_string( params ).c_str() ); if( id_itr != end ) { // capture reply + auto id = value_cast(id_itr->val); try { send_result( id, smeth->second->call(params) ); } catch ( ... ) { diff --git a/src/json_rpc_stream_connection.cpp b/src/json_rpc_stream_connection.cpp index 2c7e921..7cb0531 100644 --- a/src/json_rpc_stream_connection.cpp +++ b/src/json_rpc_stream_connection.cpp @@ -83,6 +83,12 @@ namespace fc { namespace json { fc::string o = ss.str(); my->out.write( o.c_str(), o.size() ); } + void rpc_stream_connection::send_notice( const fc::string& m, value&& param ) { + fc::stringstream ss; + ss<<"{\"method\":\""<out.write( o.c_str(), o.size() ); + } void rpc_stream_connection::send_error( uint64_t id, int64_t code, const fc::string& msg ) { fc::stringstream ss; ss<<"{\"id\":"<std_in; } /** * @brief returns a stream that reads from the process' stdout */ - fc::istream& process::out_stream() { + fc::istream& process::out_stream()const { return my->std_out; } /** * @brief returns a stream that reads from the process' stderr */ - fc::istream& process::err_stream() { + fc::istream& process::err_stream()const { return my->std_err; }