Skip to content

Commit

Permalink
Enable batch rpc processing
Browse files Browse the repository at this point in the history
* Can be exercised from the command line with json2

* Rewrite Env::do_rpc to call the same code as
  rpc from the command line.  This puts rpc
  handling logic in one place.
  • Loading branch information
HowardHinnant committed Oct 23, 2017
1 parent cafe18c commit a0e55dd
Show file tree
Hide file tree
Showing 10 changed files with 380 additions and 257 deletions.
83 changes: 57 additions & 26 deletions src/ripple/net/impl/RPCCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,14 +497,25 @@ class RPCParser

bool isValidJson2(Json::Value const& jv)
{
if (jv.isArray())
{
if (jv.size() == 0)
return false;
for (auto const& j : jv)
{
if (!isValidJson2(j))
return false;
}
return true;
}
if (jv.isObject())
{
if (jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0" &&
jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0" &&
jv.isMember(jss::id) && jv.isMember(jss::method))
{
if (jv.isMember(jss::params) &&
!(jv[jss::params].isArray() || jv[jss::params].isNull()))
!(jv[jss::params].isArray() || jv[jss::params].isObject()))
return false;
return true;
}
Expand All @@ -519,17 +530,36 @@ class RPCParser
bool valid_parse = reader.parse(jvParams[0u].asString(), jv);
if (valid_parse && isValidJson2(jv))
{
Json::Value jv1{Json::objectValue};
if (jv.isMember(jss::params))
if (jv.isObject())
{
auto const& params = jv[jss::params][0u];
for (auto i = params.begin(); i != params.end(); ++i)
jv1[i.key().asString()] = *i;
Json::Value jv1{Json::objectValue};
if (jv.isMember(jss::params))
{
auto const& params = jv[jss::params];
for (auto i = params.begin(); i != params.end(); ++i)
jv1[i.key().asString()] = *i;
}
jv1[jss::jsonrpc] = jv[jss::jsonrpc];
jv1[jss::ripplerpc] = jv[jss::ripplerpc];
jv1[jss::id] = jv[jss::id];
jv1[jss::method] = jv[jss::method];
return jv1;
}
// else jv.isArray()
Json::Value jv1{Json::arrayValue};
for (Json::UInt j = 0; j < jv.size(); ++j)
{
if (jv[j].isMember(jss::params))
{
auto const& params = jv[j][jss::params];
for (auto i = params.begin(); i != params.end(); ++i)
jv1[j][i.key().asString()] = *i;
}
jv1[j][jss::jsonrpc] = jv[j][jss::jsonrpc];
jv1[j][jss::ripplerpc] = jv[j][jss::ripplerpc];
jv1[j][jss::id] = jv[j][jss::id];
jv1[j][jss::method] = jv[j][jss::method];
}
jv1[jss::jsonrpc] = jv[jss::jsonrpc];
jv1[jss::ripplerpc] = jv[jss::ripplerpc];
jv1[jss::id] = jv[jss::id];
jv1[jss::method] = jv[jss::method];
return jv1;
}
auto jv_error = rpcError(rpcINVALID_PARAMS);
Expand Down Expand Up @@ -1145,7 +1175,6 @@ struct RPCCallImp

Json::Reader reader;
Json::Value jvReply;

if (!reader.parse (strData, jvReply))
Throw<std::runtime_error> ("couldn't parse reply from server");

Expand Down Expand Up @@ -1202,7 +1231,6 @@ rpcCmdLineToJson (std::vector<std::string> const& args,
jvRequest = rpParser.parseCommand (args[0], jvRpcParams, true);

JLOG (j.trace()) << "RPC Request: " << jvRequest << std::endl;

return jvRequest;
}

Expand Down Expand Up @@ -1287,7 +1315,13 @@ rpcClient(std::vector<std::string> const& args,
if (!setup.client.admin_password.empty ())
jvRequest["admin_password"] = setup.client.admin_password;

jvParams.append (jvRequest);
if (jvRequest.isObject())
jvParams.append (jvRequest);
else if (jvRequest.isArray())
{
for (Json::UInt i = 0; i < jvRequest.size(); ++i)
jvParams.append(jvRequest[i]);
}

if (jvRequest.isMember(jss::params))
{
Expand All @@ -1305,7 +1339,10 @@ rpcClient(std::vector<std::string> const& args,
setup.client.password,
"",
jvRequest.isMember (jss::method) // Allow parser to rewrite method.
? jvRequest[jss::method].asString () : args[0],
? jvRequest[jss::method].asString ()
: jvRequest.isArray()
? "batch"
: args[0],
jvParams, // Parsed, execute.
setup.client.secure != 0, // Use SSL
config.quiet(),
Expand All @@ -1314,7 +1351,6 @@ rpcClient(std::vector<std::string> const& args,
std::placeholders::_1));
isService.run(); // This blocks until there is no more outstanding async calls.
}

if (jvOutput.isMember ("result"))
{
// Had a successful JSON-RPC 2.0 call.
Expand Down Expand Up @@ -1343,10 +1379,12 @@ rpcClient(std::vector<std::string> const& args,
if (jvOutput.isMember (jss::error))
{
jvOutput[jss::status] = "error";

nRet = jvOutput.isMember (jss::error_code)
? beast::lexicalCast <int> (jvOutput[jss::error_code].asString ())
: rpcBAD_SYNTAX;
if (jvOutput.isMember(jss::error_code))
nRet = std::stoi(jvOutput[jss::error_code].asString());
else if (jvOutput[jss::error].isMember(jss::error_code))
nRet = std::stoi(jvOutput[jss::error][jss::error_code].asString());
else
nRet = rpcBAD_SYNTAX;
}

// YYY We could have a command line flag for single line output for scripts.
Expand All @@ -1359,13 +1397,6 @@ rpcClient(std::vector<std::string> const& args,
nRet = rpcINTERNAL;
}

if (jvRequest.isMember(jss::jsonrpc))
jvOutput[jss::jsonrpc] = jvRequest[jss::jsonrpc];
if (jvRequest.isMember(jss::ripplerpc))
jvOutput[jss::ripplerpc] = jvRequest[jss::ripplerpc];
if (jvRequest.isMember(jss::id))
jvOutput[jss::id] = jvRequest[jss::id];

return { nRet, std::move(jvOutput) };
}

Expand Down
Loading

0 comments on commit a0e55dd

Please sign in to comment.