peerplays-fc/src/json_rpc_stream_connection.cpp

103 lines
3.2 KiB
C++
Raw Normal View History

2012-10-29 23:50:49 +00:00
#include <fc/json_rpc_stream_connection.hpp>
#include <fc/iostream.hpp>
#include <fc/sstream.hpp>
2012-10-29 23:50:49 +00:00
#include <fc/thread.hpp>
2012-10-29 23:50:49 +00:00
namespace fc { namespace json {
2012-10-29 23:50:49 +00:00
class rpc_stream_connection::impl : public fc::retainable {
public:
fc::istream& in;
fc::ostream& out;
rpc_stream_connection& self;
std::function<void()> on_close;
2012-10-29 23:50:49 +00:00
impl( fc::istream& i, fc::ostream& o, rpc_stream_connection& s )
:in(i),out(o),self(s){
slog( "%p", this );
2012-10-29 23:50:49 +00:00
_read_loop_complete = fc::async( [=](){ read_loop(); } );
}
~impl() {
try {
self.cancel_pending_requests();
_read_loop_complete.cancel();
_read_loop_complete.wait();
} catch ( ... ) {}
}
fc::future<void> _read_loop_complete;
void read_loop() {
slog( "%p", this );
fc::string line;
2012-10-29 23:50:49 +00:00
fc::getline( in, line );
while( !in.eof() ) {
try {
fc::value v= fc::json::from_string( line );
slog( "%s", fc::json::to_string(v).c_str() );
self.handle_message(v);
} catch (...) {
wlog( "%s", fc::except_str().c_str() );
}
2012-10-29 23:50:49 +00:00
fc::getline( in, line );
}
slog( "close read loop" );
2012-10-29 23:50:49 +00:00
self.cancel_pending_requests();
if( !!on_close ) on_close();
}
};
2012-10-29 23:50:49 +00:00
rpc_stream_connection::rpc_stream_connection( fc::istream& i, fc::ostream& o )
:my( new impl(i,o,*this) ){
}
rpc_stream_connection::rpc_stream_connection(){ slog( "default" ); }
rpc_stream_connection::rpc_stream_connection(const rpc_stream_connection& c):my(c.my){}
rpc_stream_connection::~rpc_stream_connection(){
// slog( "%p", my.get() );
}
2012-10-29 23:50:49 +00:00
// the life of the streams must exceed the life of all copies
// of this rpc_stream_connection
void rpc_stream_connection::open( fc::istream& i, fc::ostream& o) {
my.reset( new impl(i,o,*this) );
slog( "open... %p", my.get() );
2012-10-29 23:50:49 +00:00
}
// cancels all pending requests, closes the ostream
// results on_close() being called if the stream is not already closed.
void rpc_stream_connection::close() {
if( my ) my->out.close();
my.reset(nullptr);
2012-10-29 23:50:49 +00:00
}
/**
* When the connection is closed, call the given method
*/
void rpc_stream_connection::on_close( const std::function<void()>& oc ) {
2012-10-29 23:50:49 +00:00
my->on_close = oc;
}
2012-10-29 23:50:49 +00:00
void rpc_stream_connection::send_invoke( uint64_t id, const fc::string& m, value&& param ) {
fc::stringstream ss;
ss<<"{\"id\":"<<id<<",\"method\":\""<<m<<"\",\"params\":"<<fc::json::to_string(param)<<"}\n";
fc::string o = ss.str();
my->out.write( o.c_str(), o.size() );
2012-10-29 23:50:49 +00:00
}
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";
fc::string o = ss.str();
my->out.write( o.c_str(), o.size() );
}
2012-10-29 23:50:49 +00:00
void rpc_stream_connection::send_result( uint64_t id, value&& r ) {
fc::stringstream ss;
ss<<"{\"id\":"<<id<<",\"result\":"<<fc::json::to_string(r)<<"}\n";
fc::string o = ss.str();
my->out.write( o.c_str(), o.size() );
}
2012-10-29 23:50:49 +00:00
} } // fc::json