diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dbd63e..ca61666 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -238,7 +238,6 @@ set( fc_sources src/interprocess/file_mapping.cpp src/rpc/cli.cpp src/rpc/http_api.cpp - src/rpc/json_connection.cpp src/rpc/state.cpp src/rpc/websocket_api.cpp src/log/log_message.cpp diff --git a/include/fc/rpc/json_connection.hpp b/include/fc/rpc/json_connection.hpp deleted file mode 100644 index 0208173..0000000 --- a/include/fc/rpc/json_connection.hpp +++ /dev/null @@ -1,318 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace fc { namespace rpc { - - namespace detail { class json_connection_impl; } - - /** - * @brief Implements JSON-RPC 2.0 over a set of io streams - * - * Each JSON RPC message is expected to be on its own line, violators - * will be prosecuted to the fullest extent of the law. - */ - class json_connection - { - public: - typedef std::function method; - typedef std::function named_param_method; - - json_connection( fc::buffered_istream_ptr in, fc::buffered_ostream_ptr out, uint32_t max_depth ); - ~json_connection(); - - /** - * Starts processing messages from input - */ - future exec(); - - bool is_open(); - void close(); - - void set_on_disconnected_callback(std::function callback); - - logger get_logger()const; - void set_logger( const logger& l ); - - /** - * @name server interface - * - * Adding methods to the interface allows the remote side - * to call them. - */ - ///@{ - void add_method( const std::string& name, method ); - void add_named_param_method( const std::string& name, named_param_method ); - void remove_method( const std::string& name ); - //@} - - /** - * @name client interface - */ - ///@{ - void notice( const std::string& method ); - void notice( const std::string& method, const variants& args ); - void notice( const std::string& method, const variant_object& named_args ); - - /// args will be handled as named params - future async_call( const std::string& method, - const variant_object& args ); - - future async_call( const std::string& method, mutable_variant_object args ); - - /// Sending in an array of variants will be handled as positional arguments - future async_call( const std::string& method, - const variants& args ); - - future async_call( const std::string& method ); - - future async_call( const std::string& method, - const variant& a1 ); - - future async_call( const std::string& method, - const variant& a1, - const variant& a2 ); - - future async_call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3 ); - - future async_call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4 ); - - future async_call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5 ); - - future async_call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6 ); - - future async_call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - const variant& a7 - ); - - future async_call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - const variant& a7, - const variant& a8 - ); - future async_call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - const variant& a7, - const variant& a8, - const variant& a9 - ); - future async_call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - const variant& a7, - const variant& a8, - const variant& a9, - const variant& a10 - ); - - template - Result call( const std::string& method, - const variants& args, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, args ).wait(timeout).as(); - } - - template - Result call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, a1, a2, a3 ).wait(timeout).as(); - } - - template - Result call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, a1, a2, a3, a4).wait(timeout).as(); - } - - template - Result call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, a1, a2, a3, a4, a5).wait(timeout).as(); - } - - template - Result call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, a1, a2, a3, a4, a5, a6).wait(timeout).as(); - } - template - Result call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - const variant& a7, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, a1, a2, a3, a4, a5, a6, a7).wait(timeout).as(); - } - - template - Result call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - const variant& a7, - const variant& a8, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, a1, a2, a3, a4, a5, a6, a7, a8).wait(timeout).as(); - } - - template - Result call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - const variant& a7, - const variant& a8, - const variant& a9, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, a1, a2, a3, a4, a5, a6, a7, a8, a9).wait(timeout).as(); - } - - template - Result call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - const variant& a7, - const variant& a8, - const variant& a9, - const variant& a10, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10).wait(timeout).as(); - } - - template - Result call( const std::string& method, - const variant& a1, - const variant& a2, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, a1, a2 ).wait(timeout).as(); - } - - template - Result call( const std::string& method, - const variant& a1, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, a1 ).wait(timeout).as(); - } - - template - Result call( const std::string& method, - variant_object a1, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, std::move(a1) ).wait(timeout).as(); - } - template - Result call( const std::string& method, - mutable_variant_object a1, - microseconds timeout = microseconds::maximum()) - { - return async_call( method, variant_object( std::move(a1) ) ).wait(timeout).as(); - } - - - template - Result call( const std::string& method, microseconds timeout = microseconds::maximum() ) - { - return async_call( method ).wait(timeout).as(); - } - - /// Sending in a variant_object will be issued as named parameters - variant call( const std::string& method, const variant_object& named_args ); - ///@} - - protected: - const uint32_t _max_conversion_depth; // for nested structures, json, variant etc. - - private: - std::unique_ptr my; - }; - typedef std::shared_ptr json_connection_ptr; - -}} // fc::rpc - - - diff --git a/src/rpc/json_connection.cpp b/src/rpc/json_connection.cpp deleted file mode 100644 index 8eea0df..0000000 --- a/src/rpc/json_connection.cpp +++ /dev/null @@ -1,717 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fc { namespace rpc { - - namespace detail - { - class json_connection_impl - { - public: - json_connection_impl( fc::buffered_istream_ptr&& in, fc::buffered_ostream_ptr&& out, uint32_t max_depth ) - :_in(std::move(in)),_out(std::move(out)),_eof(false),_next_id(0),_logger("json_connection"),_max_depth(max_depth){} - - fc::buffered_istream_ptr _in; - fc::buffered_ostream_ptr _out; - - fc::future _done; - fc::future _handle_message_future; - bool _eof; - - uint64_t _next_id; - boost::unordered_map::ptr> _awaiting; - boost::unordered_map _methods; - boost::unordered_map _named_param_methods; - - fc::mutex _write_mutex; - std::function _on_close; - - logger _logger; - uint32_t _max_depth; - - void send_result( variant id, variant result ) - { - ilog( "send: {\"id\": ${i}, \"result\": ${r}}", ("i",id)("r",result) ); - { - fc::scoped_lock lock(_write_mutex); - *_out << "{\"id\":"; - json::to_stream( *_out, id, json::stringify_large_ints_and_doubles, _max_depth ); - *_out << ",\"result\":"; - json::to_stream( *_out, result, json::stringify_large_ints_and_doubles, _max_depth ); - *_out << "}\n"; - _out->flush(); - } - } - void send_error( variant id, fc::exception& e ) - { - ilog( "send: {\"id\": ${i}, \"error\":{\"message\": ${what},\"code\":0,\"data\":${data}}}", - ("i",id)("what",e.what())("data", e) ); - { - fc::scoped_lock lock(_write_mutex); - *_out << "{\"id\":"; - json::to_stream( *_out, id, json::stringify_large_ints_and_doubles, _max_depth ); - *_out << ",\"error\":{\"message\":"; - json::to_stream( *_out, std::string(e.what()) ); - *_out <<",\"code\":0,\"data\":"; - json::to_stream( *_out, variant(e, _max_depth), json::stringify_large_ints_and_doubles, _max_depth ); - *_out << "}}\n"; - _out->flush(); - } - //wlog( "exception: ${except}", ("except", variant(e)) ); - } - - void handle_message( const variant_object& obj ) - { - wlog( "recv: ${msg}", ("msg", obj) ); - fc::exception_ptr eptr; - try - { - auto m = obj.find("method"); - auto i = obj.find("id"); - if( m != obj.end() ) - { - fc::exception except; - bool exception_caught = false; - try - { - auto p = obj.find("params"); - variant result; - if( p == obj.end() ) - { - auto pmi = _methods.find(m->value().as_string()); - auto nmi = _named_param_methods.find(m->value().as_string()); - if( pmi != _methods.end() ) - { - result = pmi->second( variants() ); - } - else if( nmi != _named_param_methods.end() ) - { - result = nmi->second( variant_object() ); - } - else // invalid method - { - FC_THROW_EXCEPTION( exception, "Invalid Method '${method}'", ("method",m->value().as_string())); - } - } - else if( p->value().is_array() ) - { - auto pmi = _methods.find(m->value().as_string()); - if( pmi != _methods.end() ) - { - result = pmi->second( p->value().get_array() ); - } - else // invalid method / param combo - { - FC_THROW_EXCEPTION( exception, "Invalid method or params '${method}'", - ("method",m->value().as_string())); - } - - } - else if( p->value().is_object() ) - { - auto nmi = _named_param_methods.find(m->value().as_string()); - if( nmi != _named_param_methods.end() ) - { - result = nmi->second( p->value().get_object() ); - } - else // invalid method / param combo? - { - FC_THROW_EXCEPTION( exception, "Invalid method or params '${method}'", - ("method",m->value().as_string())); - } - } - else // invalid params - { - FC_THROW_EXCEPTION( exception, "Invalid Params for method ${method}", - ("method",m->value().as_string())); - } - if( i != obj.end() ) - { - send_result( i->value(), result ); - } - } - catch ( fc::exception& e ) - { - exception_caught = true; - except = e; - } - if( exception_caught && i != obj.end() ) - send_error( i->value(), except ); - else - fc_wlog( _logger, "json rpc exception: ${exception}", ("exception",except) ); - } - else if( i != obj.end() ) //handle any received JSON response - { - uint64_t id = i->value().as_int64(); - auto await = _awaiting.find(id); - if( await != _awaiting.end() ) - { - auto r = obj.find("result"); - auto e = obj.find("error"); - if( r != obj.end() ) //if regular result response - { - await->second->set_value( r->value() ); - } - else if( e != obj.end() ) //if error response - { - fc::exception_ptr eptr; - try - { - auto err = e->value().get_object(); - auto data = err.find( "data" ); - if( data != err.end() ) - await->second->set_exception( data->value().as(_max_depth).dynamic_copy_exception() ); - else - await->second->set_exception( exception_ptr(new FC_EXCEPTION( exception, "${error}", ("error",e->value()) ) ) ); - } - catch ( fc::exception& e ) - { - elog( "Error parsing exception: ${e}", ("e", e.to_detail_string() ) ); - eptr = e.dynamic_copy_exception(); - } - if( eptr ) await->second->set_exception( eptr ); - } - else // id found without error, result, nor method field - { - fc_wlog( _logger, "no error or result specified in '${message}'", ("message",obj) ); - } - } - } - else // no method nor request id... invalid message - { - - } - } - catch ( fc::exception& e ) // catch all other errors... - { - fc_elog( _logger, "json rpc exception: ${exception}", ("exception",e )); - elog( "json rpc exception: ${exception}", ("exception",e )); - eptr = e.dynamic_copy_exception(); - } - if( eptr ) { close(eptr); } - } - - void read_loop() - { - fc::exception_ptr eptr; - try - { - std::string line; - while( !_done.canceled() ) - { - variant v = json::from_stream( *_in, json::legacy_parser, _max_depth ); - ///ilog( "input: ${in}", ("in", v ) ); - //wlog( "recv: ${line}", ("line", line) ); - _handle_message_future = fc::async([=](){ handle_message(v.get_object()); }, "json_connection handle_message"); - } - } - catch ( eof_exception& eof ) - { - _eof = true; - eptr = eof.dynamic_copy_exception(); - } - catch ( exception& e ) - { - eptr = e.dynamic_copy_exception(); - } - catch ( ... ) - { - eptr = fc::exception_ptr(new FC_EXCEPTION( unhandled_exception, "json connection read error" )); - } - if( eptr ) close( eptr ); - } - - void close( fc::exception_ptr e ) - { - wlog( "close ${reason}", ("reason", e->to_detail_string() ) ); - if( _on_close ) - _on_close(e); - for( auto itr = _awaiting.begin(); itr != _awaiting.end(); ++itr ) - { - itr->second->set_exception( e->dynamic_copy_exception() ); - } - } - }; - }//namespace detail - - json_connection::json_connection( fc::buffered_istream_ptr in, fc::buffered_ostream_ptr out, uint32_t max_depth ) - :_max_conversion_depth(max_depth),my( new detail::json_connection_impl(std::move(in),std::move(out),max_depth) ) - {} - - json_connection::~json_connection() - { - close(); - } - - fc::future json_connection::exec() - { - if( my->_done.valid() ) - { - FC_THROW_EXCEPTION( assert_exception, "start should only be called once" ); - } - return my->_done = fc::async( [=](){ my->read_loop(); }, "json_connection read_loop" ); - } - - void json_connection::close() - { - try - { - if( my->_handle_message_future.valid() && !my->_handle_message_future.ready() ) - my->_handle_message_future.cancel_and_wait(__FUNCTION__); - if( my->_done.valid() && !my->_done.ready() ) - { - my->_done.cancel("json_connection is destructing"); - my->_out->close(); - my->_done.wait(); - } - } - catch ( fc::canceled_exception& ){} // expected exception - catch ( fc::eof_exception& ){} // expected exception - catch ( fc::exception& e ) - { - // unhandled, unexpected exception cannot throw from destructor, so log it. - wlog( "${exception}", ("exception",e.to_detail_string()) ); - } - } - - void json_connection::set_on_disconnected_callback(std::function callback) - { - my->_on_close = callback; - } - - void json_connection::add_method( const std::string& name, method m ) - { - ilog( "add method ${name}", ("name",name) ); - my->_methods.emplace(std::pair(name,std::move(m))); - } - void json_connection::add_named_param_method( const std::string& name, named_param_method m ) - { - ilog( "add named param method ${name}", ("name",name) ); - my->_named_param_methods.emplace(std::pair(name,std::move(m))); - } - void json_connection::remove_method( const std::string& name ) - { - my->_methods.erase(name); - my->_named_param_methods.erase(name); - } - void json_connection::notice( const std::string& method, const variants& args ) - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"method\":"; - json::to_stream( *my->_out, method ); - if( args.size() ) - { - *my->_out << ",\"params\":"; - fc::json::to_stream( *my->_out, args ); - *my->_out << "}\n"; - } - else - { - *my->_out << ",\"params\":[]}\n"; - } - } - void json_connection::notice( const std::string& method, const variant_object& named_args ) - { - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":"; - fc::json::to_stream( *my->_out, named_args ); - *my->_out << "}\n"; - my->_out->flush(); - } - } - void json_connection::notice( const std::string& method ) - { - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << "}\n"; - my->_out->flush(); - } - } - - - future json_connection::async_call( const std::string& method, const variants& args ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - if( args.size() ) - { - *my->_out << ",\"params\":"; - fc::json::to_stream( *my->_out, args ); - *my->_out << "}\n"; - } - else - { - *my->_out << ",\"params\":[]}\n"; - } - my->_out->flush(); - } - return my->_awaiting[id]; - } - - future json_connection::async_call( const std::string& method, const variant& a1 ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":["; - fc::json::to_stream( *my->_out, a1 ); - *my->_out << "]}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - future json_connection::async_call( const std::string& method, const variant& a1, const variant& a2 ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":["; - fc::json::to_stream( *my->_out, a1 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a2 ); - *my->_out << "]}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - future json_connection::async_call( const std::string& method, const variant& a1, const variant& a2, const variant& a3 ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":["; - fc::json::to_stream( *my->_out, a1 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a2 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a3 ); - *my->_out << "]}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - - future json_connection::async_call( const std::string& method, const variant& a1, const variant& a2, const variant& a3, const variant& a4 ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":["; - fc::json::to_stream( *my->_out, a1 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a2 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a3 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a4 ); - *my->_out << "]}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - - future json_connection::async_call( const std::string& method, const variant& a1, const variant& a2, const variant& a3, const variant& a4, const variant& a5 ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":["; - fc::json::to_stream( *my->_out, a1 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a2 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a3 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a4 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a5 ); - *my->_out << "]}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - - future json_connection::async_call( const std::string& method, const variant& a1, const variant& a2, const variant& a3, const variant& a4, const variant& a5, const variant& a6 ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":["; - fc::json::to_stream( *my->_out, a1 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a2 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a3 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a4 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a5 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a6 ); - *my->_out << "]}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - future json_connection::async_call( const std::string& method, const variant& a1, const variant& a2, const variant& a3, const variant& a4, const variant& a5, const variant& a6, const variant& a7 ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":["; - fc::json::to_stream( *my->_out, a1 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a2 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a3 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a4 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a5 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a6 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a7 ); - *my->_out << "]}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - future json_connection::async_call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - const variant& a7, - const variant& a8 ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":["; - fc::json::to_stream( *my->_out, a1 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a2 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a3 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a4 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a5 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a6 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a7 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a8 ); - *my->_out << "]}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - future json_connection::async_call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - const variant& a7, - const variant& a8, - const variant& a9 ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":["; - fc::json::to_stream( *my->_out, a1 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a2 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a3 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a4 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a5 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a6 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a7 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a8 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a9 ); - *my->_out << "]}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - future json_connection::async_call( const std::string& method, - const variant& a1, - const variant& a2, - const variant& a3, - const variant& a4, - const variant& a5, - const variant& a6, - const variant& a7, - const variant& a8, - const variant& a9, - const variant& a10 ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - - { - fc::scoped_lock lock(my->_write_mutex); - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":["; - fc::json::to_stream( *my->_out, a1 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a2 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a3 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a4 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a5 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a6 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a7 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a8 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a9 ); - *my->_out << ","; - fc::json::to_stream( *my->_out, a10 ); - *my->_out << "]}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - - future json_connection::async_call( const std::string& method, mutable_variant_object named_args ) - { - return async_call( method, variant_object( std::move(named_args) ) ); - } - future json_connection::async_call( const std::string& method, const variant_object& named_args ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - fc::scoped_lock lock(my->_write_mutex); - { - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << ",\"params\":"; - fc::json::to_stream( *my->_out, named_args ); - *my->_out << "}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - future json_connection::async_call( const std::string& method ) - { - auto id = my->_next_id++; - my->_awaiting[id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); - fc::scoped_lock lock(my->_write_mutex); - { - *my->_out << "{\"id\":"; - *my->_out << id; - *my->_out << ",\"method\":"; - json::to_stream( *my->_out, method ); - *my->_out << "}\n"; - my->_out->flush(); - } - return my->_awaiting[id]; - } - - logger json_connection::get_logger()const - { - return my->_logger; - } - - void json_connection::set_logger( const logger& l ) - { - my->_logger = l; - } - -}}