Regularize RPC calling.

This commit is contained in:
Arthur Britto
2012-12-02 16:06:20 -08:00
parent fed1250218
commit ee3a2a0857
2 changed files with 53 additions and 49 deletions

View File

@@ -51,18 +51,16 @@ std::string EncodeBase64(const std::string& s)
return result; return result;
} }
Json::Value RPCParser::parseAsIs(Json::Value jvReq, const Json::Value &params) Json::Value RPCParser::parseAsIs(const Json::Value &params)
{ {
return jvReq; return Json::Value(Json::objectValue);
} }
// Convert a command plus args to a json request. // Convert a rpc method and params to a request.
Json::Value RPCParser::parseCommand(Json::Value jvRequest) // <-- { method: xyz, params: [... ] } or { error: ..., ... }
Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams)
{ {
std::string strCommand = jvRequest["method"].asString(); cLog(lsTRACE) << "RPC method:" << strMethod;
Json::Value jvParams = jvRequest["params"];
cLog(lsTRACE) << "RPC:" << strCommand;
cLog(lsTRACE) << "RPC params:" << jvParams; cLog(lsTRACE) << "RPC params:" << jvParams;
static struct { static struct {
@@ -128,24 +126,20 @@ Json::Value RPCParser::parseCommand(Json::Value jvRequest)
int i = NUMBER(commandsA); int i = NUMBER(commandsA);
while (i-- && strCommand != commandsA[i].pCommand) while (i-- && strMethod != commandsA[i].pCommand)
; ;
if (i < 0) if (i < 0)
{ {
return rpcError(rpcBAD_SYNTAX, jvRequest); return rpcError(rpcBAD_SYNTAX);
} }
else if (commandsA[i].iMinParams >= 0 else if ((commandsA[i].iMinParams >= 0 && jvParams.size() < commandsA[i].iMinParams)
? commandsA[i].iMaxParams
? (jvParams.size() < commandsA[i].iMinParams
|| (commandsA[i].iMaxParams >= 0 && jvParams.size() > commandsA[i].iMaxParams)) || (commandsA[i].iMaxParams >= 0 && jvParams.size() > commandsA[i].iMaxParams))
: false
: jvParams.isArray())
{ {
return rpcError(rpcBAD_SYNTAX, jvRequest); return rpcError(rpcBAD_SYNTAX);
} }
return (this->*(commandsA[i].pfpFunc))(jvRequest, jvParams); return (this->*(commandsA[i].pfpFunc))(jvParams);
} }
int commandLineRPC(const std::vector<std::string>& vCmd) int commandLineRPC(const std::vector<std::string>& vCmd)
@@ -157,52 +151,62 @@ int commandLineRPC(const std::vector<std::string>& vCmd)
try try
{ {
RPCParser rpParser; RPCParser rpParser;
Json::Value jvCliParams(Json::arrayValue); Json::Value jvRpcParams(Json::arrayValue);
if (vCmd.empty()) return 1; // 1 = print usage. if (vCmd.empty()) return 1; // 1 = print usage.
jvRequest["method"] = vCmd[0];
for (int i = 1; i != vCmd.size(); i++) for (int i = 1; i != vCmd.size(); i++)
jvCliParams.append(vCmd[i]); jvRpcParams.append(vCmd[i]);
jvRequest["params"] = jvCliParams; Json::Value jvRpc = Json::Value(Json::objectValue);
jvRequest = rpParser.parseCommand(jvRequest); jvRpc["method"] = vCmd[0];
jvRpc["params"] = jvRpcParams;
jvRequest = rpParser.parseCommand(vCmd[0], jvRpcParams);
// std::cerr << "Request: " << jvRequest << std::endl; // std::cerr << "Request: " << jvRequest << std::endl;
Json::Value jvParams(Json::arrayValue); if (jvRequest.isMember("error"))
jvParams.append(jvRequest);
Json::Value jvResult;
jvResult = jvRequest.isMember("error")
? jvRequest // Parse failed, return error.
: callRPC(jvRequest["method"].asString(), jvParams); // Parsed, execute.
if (jvResult.isMember("error"))
{ {
nRet = jvResult.isMember("error_code") jvOutput = jvRequest;
? lexical_cast_s<int>(jvResult["error_code"].asString()) jvOutput["status"] = "error";
jvOutput["rpc"] = jvRpc;
}
else
{
jvOutput = callRPC(
jvRequest.isMember("method")
? jvRequest["method"].asString()
: vCmd[0],
jvRequest["params"]); // Parsed, execute.
if (jvOutput.isMember("error"))
{
jvOutput["rpc"] = jvRpc;
}
}
if (jvOutput.isMember("error"))
{
nRet = jvOutput.isMember("error_code")
? lexical_cast_s<int>(jvOutput["error_code"].asString())
: 1; : 1;
} }
jvOutput = jvResult; // YYY We could have a command line flag for single line output for scripts.
// YYY We would intercept output here and simplify it.
} }
catch (std::exception& e) catch (std::exception& e)
{ {
jvRequest["error_what"] = e.what(); jvOutput = rpcError(rpcINTERNAL);
jvOutput["error_what"] = e.what();
jvOutput = rpcError(rpcINTERNAL, jvRequest);
nRet = rpcINTERNAL; nRet = rpcINTERNAL;
} }
catch (...) catch (...)
{ {
jvRequest["error_what"] = "exception"; jvOutput = rpcError(rpcINTERNAL);
jvOutput["error_what"] = "exception";
jvOutput = rpcError(rpcINTERNAL, jvRequest);
nRet = rpcINTERNAL; nRet = rpcINTERNAL;
} }

View File

@@ -9,12 +9,12 @@
class RPCParser class RPCParser
{ {
protected: protected:
typedef Json::Value (RPCParser::*parseFuncPtr)(Json::Value jvRet, const Json::Value &jvParams); typedef Json::Value (RPCParser::*parseFuncPtr)(const Json::Value &jvParams);
Json::Value parseAsIs(Json::Value jvRet, const Json::Value &jvParams); Json::Value parseAsIs(const Json::Value &jvParams);
public: public:
Json::Value parseCommand(Json::Value jvRequest); Json::Value parseCommand(std::string strMethod, Json::Value jvParams);
}; };
extern int commandLineRPC(const std::vector<std::string>& vCmd); extern int commandLineRPC(const std::vector<std::string>& vCmd);