- Add four-argument version of json-rpc call function

- fix bug in json parser that prevented correct parsing of
  a true/false/null at the end of input
- prevent infinite recursion in a json helper function
This commit is contained in:
Eric Frias 2014-04-21 14:34:46 -04:00
parent 7849cc7ada
commit cd34f696ce
4 changed files with 91 additions and 30 deletions

View file

@ -56,7 +56,7 @@ namespace fc
template<typename T> template<typename T>
static void save_to_file( const T& v, const string& p, bool pretty = true ) static void save_to_file( const T& v, const string& p, bool pretty = true )
{ {
save_to_file( variant(v), p, pretty ); save_to_file( variant(v), fc::path(p), pretty );
} }
}; };

View file

@ -76,6 +76,12 @@ namespace fc { namespace rpc {
const variant& a2, const variant& a2,
const variant& a3 ); const variant& a3 );
future<variant> async_call( const fc::string& method,
const variant& a1,
const variant& a2,
const variant& a3,
const variant& a4 );
template<typename Result> template<typename Result>
Result call( const fc::string& method, Result call( const fc::string& method,
const variant& a1, const variant& a1,
@ -86,6 +92,17 @@ namespace fc { namespace rpc {
return async_call( method, a1, a2, a3 ).wait(timeout).as<Result>(); return async_call( method, a1, a2, a3 ).wait(timeout).as<Result>();
} }
template<typename Result>
Result call( const fc::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<Result>();
}
template<typename Result> template<typename Result>
Result call( const fc::string& method, Result call( const fc::string& method,
const variant& a1, const variant& a1,

View file

@ -264,37 +264,58 @@ namespace fc
variant token_from_stream( T& in ) variant token_from_stream( T& in )
{ {
fc::stringstream ss; fc::stringstream ss;
while( char c = in.peek() ) bool parsed_unexpected_character = false;
bool received_eof = false;
try
{ {
switch( c ) char c;
{ while( (c = in.peek()) && !parsed_unexpected_character)
case 'n': {
case 'u': switch( c )
case 'l': {
case 't': case 'n':
case 'r': case 'u':
case 'e': case 'l':
case 'f': case 't':
case 'a': case 'r':
case 's': case 'e':
ss.put( in.get() ); case 'f':
break; case 'a':
default: case 's':
{ ss.put( in.get() );
fc::string str = ss.str(); break;
if( str == "null" ) return variant(); default:
if( str == "true" ) return true; parsed_unexpected_character = true;
if( str == "false" ) return false; break;
else }
{ }
return str; }
// FC_THROW_EXCEPTION( parse_error_exception, "Invalid token '${token}'", catch (fc::eof_exception&)
// ("token",str) ); {
} received_eof = true;
} }
}
// we can get here either by processing a delimiter as in "null,"
// an EOF like "null<EOF>", or an invalid token like "nullZ"
fc::string str = ss.str();
if( str == "null" ) return variant();
if( str == "true" ) return true;
if( str == "false" ) return false;
else
{
if (received_eof)
FC_THROW_EXCEPTION( parse_error_exception, "Unexpected EOF" );
else
{
// I'm not sure why we do this, a comment would be helpful.
// if we've reached this point, we've either seen a partial
// token ("tru<EOF>") or something our simple parser couldn't
// make out ("falfe")
return str;
// FC_THROW_EXCEPTION( parse_error_exception, "Invalid token '${token}'",
// ("token",str) );
}
} }
FC_THROW_EXCEPTION( parse_error_exception, "Unexpected EOF" );
} }

View file

@ -406,7 +406,30 @@ namespace fc { namespace rpc {
return my->_awaiting[id]; return my->_awaiting[id];
} }
future<variant> json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2, const variant& a3, const variant& a4 )
{
auto id = my->_next_id++;
my->_awaiting[id] = fc::promise<variant>::ptr( new fc::promise<variant>() );
{
fc::scoped_lock<fc::mutex> 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<variant> json_connection::async_call( const fc::string& method, mutable_variant_object named_args ) future<variant> json_connection::async_call( const fc::string& method, mutable_variant_object named_args )
{ {