updates for ssh / json rpc

This commit is contained in:
Daniel Larimer 2012-11-16 17:13:12 -05:00
parent 9edcfcf947
commit 8cbbf8994c
8 changed files with 58 additions and 17 deletions

View file

@ -79,6 +79,8 @@ namespace fc { namespace json {
void operator()( const char* name, std::function<R(A1)>& meth);
template<typename R, typename A1, typename A2>
void operator()( const char* name, std::function<R(A1,A2)>& meth);
template<typename R, typename A1, typename A2, typename A3>
void operator()( const char* name, std::function<R(A1,A2,A3)>& meth);
const fc::ptr<InterfaceType>& _ptr;
fc::json::rpc_connection& _con;
@ -110,7 +112,12 @@ namespace fc { namespace json {
typename promise<R>::ptr rtn( r, true );
invoke( detail::pending_result::ptr(r), method,
value(detail::named_param<typename fc::deduce<Args>::type>::to_value(a)) );
return rtn;
}
template<typename Args >
void notice( const fc::string& method, Args&& a = nullptr ){
send_notice( method,
value(detail::named_param<typename fc::deduce<Args>::type>::to_value(a)) );
}
template<typename InterfaceType>
@ -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,tuple<A1,A2>,R(A1,A2) >(meth) ) );
}
template<typename InterfaceType>
template<typename R, typename A1, typename A2, typename A3>
void add_method_visitor<InterfaceType>::operator()( const char* name, std::function<R(A1,A2,A3)>& meth) {
_con.add_method( name, rpc_server_method::ptr( new rpc_server_method_impl<R,tuple<A1,A2,A3>,R(A1,A2,A3) >(meth) ) );
}
template<typename InterfaceType>
template<typename R>
void add_method_visitor<InterfaceType>::operator()( const char* name, std::function<R()>& meth) {
_con.add_method( name, rpc_server_method::ptr( new rpc_server_method_impl<R,tuple<>,R() >(meth) ) );

View file

@ -1,26 +1,21 @@
#pragma once
#include <fc/json_rpc_client.hpp>
#include <fc/json_rpc_stream_connection.hpp>
#include <fc/ssh/process.hpp>
namespace fc { namespace json {
template<typename InterfaceType>
class rpc_ssh_process_client : public ptr<InterfaceType,fc::json::detail::rpc_member> {
class rpc_ssh_process_client : public rpc_client<InterfaceType> {
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<InterfaceType,fc::json::detail::rpc_member>() );
this->_vtable->template visit<InterfaceType>( fc::json::detail::vtable_visitor(_con) );
}
:rpc_client<InterfaceType>(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<InterfaceType,fc::json::detail::rpc_member>() );
this->_vtable->template visit<InterfaceType>( 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;
}

View file

@ -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 );

View file

@ -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() );

View file

@ -108,6 +108,28 @@ namespace fc {
private:
value::object& m_out;
};
template<>
struct cast_visitor<fc::value> : 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<typename T>
struct cast_visitor<fc::vector<T>> : value::const_visitor {

View file

@ -51,11 +51,12 @@ namespace fc { namespace json {
if( m_itr != end ) {
fc::string mname = value_cast<fc::string>(m_itr->val);
auto id = value_cast<uint64_t>(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<uint64_t>(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<uint64_t>(id_itr->val);
try {
send_result( id, smeth->second->call(params) );
} catch ( ... ) {

View file

@ -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\":\""<<m<<"\",\"params\":"<<fc::json::to_string(param)<<"}\n";
fc::string o = ss.str();
my->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\":"<<id<<",\"error\":{\"code\":"<<code<<",\"message\":"<<fc::json::to_string(fc::value(msg))<<"}}\n";

View file

@ -641,6 +641,8 @@ namespace fc { namespace ssh {
process::process()
{}
process::~process()
{}
bool process::valid()const {
@ -656,19 +658,19 @@ namespace fc { namespace ssh {
/**
* @brief returns a stream that writes to the procss' stdin
*/
fc::ostream& process::in_stream() {
fc::ostream& process::in_stream()const {
return my->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;
}