Recognize ripplerpc 2.0 requests and respond in kind:

* Force jtx to request/receive the 2.0 API
* Force the JSON and WebSocket tests to use 2.0 API
*  This specifically allows the Websocket to create 2.0 json/ripple
   and get back a 2.0 response.
* Add test for malformed json2
* Add check for parse failure
* Add check for params to be in array form.
* Correct type-o discovered in tests due to stricter checking.
* Add API version to the WSClient & JSONRPCClient test
* Update source.dox with more headers
This commit is contained in:
Howard Hinnant
2016-10-25 16:08:48 -04:00
committed by Nik Bougalis
parent cdf470e68d
commit 2fd0540ed4
20 changed files with 1178 additions and 62 deletions

View File

@@ -487,7 +487,7 @@ private:
if (!jvRequest.isObject ())
return rpcError (rpcINVALID_PARAMS);
jvRequest["method"] = jvParams[0u];
jvRequest[jss::method] = jvParams[0u];
return jvRequest;
}
@@ -495,6 +495,53 @@ private:
return rpcError (rpcINVALID_PARAMS);
}
bool isValidJson2(Json::Value const& jv)
{
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()))
return false;
return true;
}
}
return false;
}
Json::Value parseJson2(Json::Value const& jvParams)
{
Json::Reader reader;
Json::Value jv;
bool valid_parse = reader.parse(jvParams[0u].asString(), jv);
if (valid_parse && isValidJson2(jv))
{
Json::Value jv1{Json::objectValue};
if (jv.isMember(jss::params))
{
auto const& params = jv[jss::params][0u];
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;
}
auto jv_error = rpcError(rpcINVALID_PARAMS);
if (jv.isMember(jss::jsonrpc))
jv_error[jss::jsonrpc] = jv[jss::jsonrpc];
if (jv.isMember(jss::ripplerpc))
jv_error[jss::ripplerpc] = jv[jss::ripplerpc];
if (jv.isMember(jss::id))
jv_error[jss::id] = jv[jss::id];
return jv_error;
}
// ledger [id|index|current|closed|validated] [full|tx]
Json::Value parseLedger (Json::Value const& jvParams)
{
@@ -1003,6 +1050,7 @@ public:
{ "gateway_balances", &RPCParser::parseGatewayBalances , 1, -1 },
{ "get_counts", &RPCParser::parseGetCounts, 0, 1 },
{ "json", &RPCParser::parseJson, 2, 2 },
{ "json2", &RPCParser::parseJson2, 1, 1 },
{ "ledger", &RPCParser::parseLedger, 0, 2 },
{ "ledger_accept", &RPCParser::parseAsIs, 0, 0 },
{ "ledger_closed", &RPCParser::parseAsIs, 0, 0 },
@@ -1181,7 +1229,7 @@ rpcCmdLineToJson (std::vector<std::string> const& args,
retParams = Json::Value (Json::objectValue);
retParams["method"] = args[0];
retParams[jss::method] = args[0];
retParams[jss::params] = jvRpcParams;
jvRequest = rpParser.parseCommand (args[0], jvRpcParams, true);
@@ -1210,6 +1258,12 @@ cmdLineToJSONRPC (std::vector<std::string> const& args, beast::Journal j)
auto& paramsArray = Json::setArray (jv, jss::params);
paramsArray.append (paramsObj);
}
if (paramsObj.isMember(jss::jsonrpc))
jv[jss::jsonrpc] = paramsObj[jss::jsonrpc];
if (paramsObj.isMember(jss::ripplerpc))
jv[jss::ripplerpc] = paramsObj[jss::ripplerpc];
if (paramsObj.isMember(jss::id))
jv[jss::id] = paramsObj[jss::id];
return jv;
}
@@ -1267,6 +1321,12 @@ rpcClient(std::vector<std::string> const& args,
jvParams.append (jvRequest);
if (jvRequest.isMember(jss::params))
{
auto const& params = jvRequest[jss::params];
assert(params.size() == 1);
jvParams.append(params[0u]);
}
{
boost::asio::io_service isService;
RPCCall::fromNetwork (
@@ -1276,8 +1336,8 @@ rpcClient(std::vector<std::string> const& args,
setup.client.user,
setup.client.password,
"",
jvRequest.isMember ("method") // Allow parser to rewrite method.
? jvRequest["method"].asString () : args[0],
jvRequest.isMember (jss::method) // Allow parser to rewrite method.
? jvRequest[jss::method].asString () : args[0],
jvParams, // Parsed, execute.
setup.client.secure != 0, // Use SSL
config.quiet(),
@@ -1331,6 +1391,13 @@ 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) };
}