From c6db85fb39c6b9f593ce5b383544f452d72e9253 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Sun, 2 Dec 2012 18:08:45 -0800 Subject: [PATCH] Refactor RPC commands with no arguments. --- src/cpp/ripple/CallRPC.cpp | 126 +++++++++++++++++++------------- src/cpp/ripple/CallRPC.h | 2 + src/cpp/ripple/RPCErr.cpp | 3 + src/cpp/ripple/RPCErr.h | 4 + src/cpp/ripple/RPCHandler.cpp | 45 ++++++++++-- src/cpp/ripple/WSConnection.cpp | 5 +- 6 files changed, 124 insertions(+), 61 deletions(-) diff --git a/src/cpp/ripple/CallRPC.cpp b/src/cpp/ripple/CallRPC.cpp index 1f19e7d1b..e288fadae 100644 --- a/src/cpp/ripple/CallRPC.cpp +++ b/src/cpp/ripple/CallRPC.cpp @@ -113,6 +113,11 @@ Json::Value RPCParser::parseAccountTransactions(const Json::Value& jvParams) return jvRequest; } +Json::Value RPCParser::parseEvented(const Json::Value& jvParams) +{ + return rpcError(rpcNO_EVENTS); +} + // Convert a rpc method and params to a request. // <-- { method: xyz, params: [... ] } or { error: ..., ... } Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams) @@ -132,55 +137,53 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams) { "accept_ledger", &RPCParser::parseAsIs, 0, 0 }, { "account_info", &RPCParser::parseAccountInfo, 1, 2 }, { "account_tx", &RPCParser::parseAccountTransactions, 2, 3 }, -#if 0 - { "connect", &RPCParser::doConnect, 1, 2, true, false, optNone }, - { "data_delete", &RPCParser::doDataDelete, 1, 1, true, false, optNone }, - { "data_fetch", &RPCParser::doDataFetch, 1, 1, true, false, optNone }, - { "data_store", &RPCParser::doDataStore, 2, 2, true, false, optNone }, - { "get_counts", &RPCParser::doGetCounts, 0, 1, true, false, optNone }, - { "ledger", &RPCParser::doLedger, 0, 2, false, false, optNetwork }, - { "ledger_accept", &RPCParser::doLedgerAccept, 0, 0, true, false, optCurrent }, - { "ledger_closed", &RPCParser::doLedgerClosed, 0, 0, false, false, optClosed }, - { "ledger_current", &RPCParser::doLedgerCurrent, 0, 0, false, false, optCurrent }, - { "ledger_entry", &RPCParser::doLedgerEntry, -1, -1, false, false, optCurrent }, - { "ledger_header", &RPCParser::doLedgerHeader, -1, -1, false, false, optCurrent }, - { "log_level", &RPCParser::doLogLevel, 0, 2, true, false, optNone }, - { "logrotate", &RPCParser::doLogRotate, 0, 0, true, false, optNone }, - { "nickname_info", &RPCParser::doNicknameInfo, 1, 1, false, false, optCurrent }, - { "owner_info", &RPCParser::doOwnerInfo, 1, 2, false, false, optCurrent }, - { "peers", &RPCParser::doPeers, 0, 0, true, false, optNone }, - { "profile", &RPCParser::doProfile, 1, 9, false, false, optCurrent }, - { "ripple_lines_get", &RPCParser::doRippleLinesGet, 1, 2, false, false, optCurrent }, - { "ripple_path_find", &RPCParser::doRipplePathFind, -1, -1, false, false, optCurrent }, - { "submit", &RPCParser::doSubmit, 2, 2, false, false, optCurrent }, - { "submit_json", &RPCParser::doSubmitJson, -1, -1, false, false, optCurrent }, - { "server_info", &RPCParser::doServerInfo, 0, 0, true, false, optNone }, - { "stop", &RPCParser::doStop, 0, 0, true, false, optNone }, - { "transaction_entry", &RPCParser::doTransactionEntry, -1, -1, false, false, optCurrent }, - { "tx", &RPCParser::doTx, 1, 1, true, false, optNone }, - { "tx_history", &RPCParser::doTxHistory, 1, 1, false, false, optNone }, +// { "connect", &RPCParser::doConnect, 1, 2, true, false, optNone }, +// { "data_delete", &RPCParser::doDataDelete, 1, 1, true, false, optNone }, +// { "data_fetch", &RPCParser::doDataFetch, 1, 1, true, false, optNone }, +// { "data_store", &RPCParser::doDataStore, 2, 2, true, false, optNone }, +// { "get_counts", &RPCParser::doGetCounts, 0, 1, true, false, optNone }, +// { "ledger", &RPCParser::doLedger, 0, 2, false, false, optNetwork }, + { "ledger_accept", &RPCParser::parseAsIs, 0, 0 }, + { "ledger_closed", &RPCParser::parseAsIs, 0, 0 }, + { "ledger_current", &RPCParser::parseAsIs, 0, 0 }, +// { "ledger_entry", &RPCParser::doLedgerEntry, -1, -1, false, false, optCurrent }, +// { "ledger_header", &RPCParser::doLedgerHeader, -1, -1, false, false, optCurrent }, +// { "log_level", &RPCParser::doLogLevel, 0, 2, true, false, optNone }, + { "logrotate", &RPCParser::parseAsIs, 0, 0 }, +// { "nickname_info", &RPCParser::doNicknameInfo, 1, 1, false, false, optCurrent }, +// { "owner_info", &RPCParser::doOwnerInfo, 1, 2, false, false, optCurrent }, + { "peers", &RPCParser::parseAsIs, 0, 0 }, +// { "profile", &RPCParser::doProfile, 1, 9, false, false, optCurrent }, +// { "ripple_lines_get", &RPCParser::doRippleLinesGet, 1, 2, false, false, optCurrent }, +// { "ripple_path_find", &RPCParser::doRipplePathFind, -1, -1, false, false, optCurrent }, +// { "submit", &RPCParser::doSubmit, 2, 2, false, false, optCurrent }, +// { "submit_json", &RPCParser::doSubmitJson, -1, -1, false, false, optCurrent }, + { "server_info", &RPCParser::parseAsIs, 0, 0 }, + { "stop", &RPCParser::parseAsIs, 0, 0 }, +// { "transaction_entry", &RPCParser::doTransactionEntry, -1, -1, false, false, optCurrent }, +// { "tx", &RPCParser::doTx, 1, 1, true, false, optNone }, +// { "tx_history", &RPCParser::doTxHistory, 1, 1, false, false, optNone }, +// +// { "unl_add", &RPCParser::doUnlAdd, 1, 2, true, false, optNone }, +// { "unl_delete", &RPCParser::doUnlDelete, 1, 1, true, false, optNone }, + { "unl_list", &RPCParser::parseAsIs, 0, 0 }, + { "unl_load", &RPCParser::parseAsIs, 0, 0 }, + { "unl_network", &RPCParser::parseAsIs, 0, 0 }, + { "unl_reset", &RPCParser::parseAsIs, 0, 0 }, + { "unl_score", &RPCParser::parseAsIs, 0, 0 }, - { "unl_add", &RPCParser::doUnlAdd, 1, 2, true, false, optNone }, - { "unl_delete", &RPCParser::doUnlDelete, 1, 1, true, false, optNone }, - { "unl_list", &RPCParser::doUnlList, 0, 0, true, false, optNone }, - { "unl_load", &RPCParser::doUnlLoad, 0, 0, true, false, optNone }, - { "unl_network", &RPCParser::doUnlNetwork, 0, 0, true, false, optNone }, - { "unl_reset", &RPCParser::doUnlReset, 0, 0, true, false, optNone }, - { "unl_score", &RPCParser::doUnlScore, 0, 0, true, false, optNone }, +// { "validation_create", &RPCParser::doValidationCreate, 0, 1, false, false, optNone }, +// { "validation_seed", &RPCParser::doValidationSeed, 0, 1, false, false, optNone }, - { "validation_create", &RPCParser::doValidationCreate, 0, 1, false, false, optNone }, - { "validation_seed", &RPCParser::doValidationSeed, 0, 1, false, false, optNone }, - - { "wallet_accounts", &RPCParser::doWalletAccounts, 1, 1, false, false, optCurrent }, - { "wallet_propose", &RPCParser::doWalletPropose, 0, 1, false, false, optNone }, - { "wallet_seed", &RPCParser::doWalletSeed, 0, 1, false, false, optNone }, - - { "login", &RPCParser::doLogin, 2, 2, true, false, optNone }, +// { "wallet_accounts", &RPCParser::doWalletAccounts, 1, 1, false, false, optCurrent }, +// { "wallet_propose", &RPCParser::doWalletPropose, 0, 1, false, false, optNone }, +// { "wallet_seed", &RPCParser::doWalletSeed, 0, 1, false, false, optNone }, +// +// { "login", &RPCParser::doLogin, 2, 2, true, false, optNone }, // Evented methods - { "subscribe", &RPCParser::doSubscribe, -1, -1, false, true, optNone }, - { "unsubscribe", &RPCParser::doUnsubscribe, -1, -1, false, true, optNone }, -#endif + { "subscribe", &RPCParser::parseEvented, -1, -1 }, + { "unsubscribe", &RPCParser::parseEvented, -1, -1 }, }; int i = NUMBER(commandsA); @@ -229,7 +232,6 @@ int commandLineRPC(const std::vector& vCmd) if (jvRequest.isMember("error")) { jvOutput = jvRequest; - jvOutput["status"] = "error"; jvOutput["rpc"] = jvRpc; } else @@ -242,20 +244,40 @@ int commandLineRPC(const std::vector& vCmd) jvRequest.isMember("method") // Allow parser to rewrite method. ? jvRequest["method"].asString() : vCmd[0], - jvParams); // Parsed, execute. + jvParams); // Parsed, execute. + if (jvOutput.isMember("result")) + { + // Had a successful JSON-RPC 2.0 call. + jvOutput = jvOutput["result"]; + + // jvOutput may report a server side error. + // It should report "status". + } + else + { + // Transport error. + Json::Value jvRpcError = jvOutput; + + jvOutput = rpcError(rpcJSON_RPC); + jvOutput["result"] = jvRpcError; + } + + // If had an error, supply invokation in result. if (jvOutput.isMember("error")) { - jvOutput["rpc"] = jvRpc; // How the command was seen as method + params. - jvOutput["request"] = jvRequest; // How the command was translated. + jvOutput["rpc"] = jvRpc; // How the command was seen as method + params. + jvOutput["request_sent"] = jvRequest; // How the command was translated. } } if (jvOutput.isMember("error")) { - nRet = jvOutput.isMember("error_code") - ? lexical_cast_s(jvOutput["error_code"].asString()) - : 1; + jvOutput["status"] = "error"; + + nRet = jvOutput.isMember("error_code") + ? lexical_cast_s(jvOutput["error_code"].asString()) + : 1; } // YYY We could have a command line flag for single line output for scripts. diff --git a/src/cpp/ripple/CallRPC.h b/src/cpp/ripple/CallRPC.h index 523c018ac..f799ce93c 100644 --- a/src/cpp/ripple/CallRPC.h +++ b/src/cpp/ripple/CallRPC.h @@ -15,6 +15,8 @@ protected: Json::Value parseAccountInfo(const Json::Value& jvParams); Json::Value parseAccountTransactions(const Json::Value& jvParams); + Json::Value parseEvented(const Json::Value& jvParams); + public: Json::Value parseCommand(std::string strMethod, Json::Value jvParams); }; diff --git a/src/cpp/ripple/RPCErr.cpp b/src/cpp/ripple/RPCErr.cpp index cc0e6ba17..9c4112db1 100644 --- a/src/cpp/ripple/RPCErr.cpp +++ b/src/cpp/ripple/RPCErr.cpp @@ -30,6 +30,7 @@ Json::Value rpcError(int iError, Json::Value jvResult) { rpcINSUF_FUNDS, "insufFunds", "Insufficient funds." }, { rpcINTERNAL, "internal", "Internal error." }, { rpcINVALID_PARAMS, "invalidParams", "Invalid parameters." }, + { rpcJSON_RPC, "json_rpc", "JSON-RPC transport error." }, { rpcLGR_IDXS_INVALID, "lgrIdxsInvalid", "Ledger indexes invalid." }, { rpcLGR_IDX_MALFORMED, "lgrIdxMalformed", "Ledger index malformed." }, { rpcLGR_NOT_FOUND, "lgrNotFound", "Ledger not found." }, @@ -72,8 +73,10 @@ Json::Value rpcError(int iError, Json::Value jvResult) jvResult["error_code"] = iError; if (i >= 0) + { cLog(lsDEBUG) << "rpcError: " << errorInfoA[i].pToken << ": " << errorInfoA[i].pMessage << std::endl; + } return jvResult; } diff --git a/src/cpp/ripple/RPCErr.h b/src/cpp/ripple/RPCErr.h index d22b66b02..f2b73336e 100644 --- a/src/cpp/ripple/RPCErr.h +++ b/src/cpp/ripple/RPCErr.h @@ -7,6 +7,10 @@ enum { rpcSUCCESS, rpcBAD_SYNTAX, // Must be 1 to print usage to command line. + rpcJSON_RPC, + + // Error numbers beyond this line are not stable between versions. + // Programs should use error tokens. // Misc failure rpcLOAD_FAILED, diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 4dbbadd3a..09e2f7c84 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -459,7 +459,7 @@ Json::Value RPCHandler::doOwnerInfo(Json::Value params) return ret; } -Json::Value RPCHandler::doPeers(Json::Value params) +Json::Value RPCHandler::doPeers(Json::Value) { Json::Value obj(Json::objectValue); @@ -1074,7 +1074,7 @@ Json::Value RPCHandler::handleJSONSubmit(Json::Value jvRequest) } } -Json::Value RPCHandler::doServerInfo(Json::Value params) +Json::Value RPCHandler::doServerInfo(Json::Value) { Json::Value ret(Json::objectValue); @@ -1142,7 +1142,7 @@ Json::Value RPCHandler::doTx(Json::Value params) return rpcError(rpcNOT_IMPL); } -Json::Value RPCHandler::doLedgerClosed(Json::Value params) +Json::Value RPCHandler::doLedgerClosed(Json::Value) { Json::Value jvResult; uint256 uLedger = mNetOps->getClosedLedgerHash(); @@ -1153,7 +1153,7 @@ Json::Value RPCHandler::doLedgerClosed(Json::Value params) return jvResult; } -Json::Value RPCHandler::doLedgerCurrent(Json::Value params) +Json::Value RPCHandler::doLedgerCurrent(Json::Value) { Json::Value jvResult; jvResult["ledger_current_index"] = mNetOps->getCurrentLedgerID(); @@ -1408,7 +1408,7 @@ Json::Value RPCHandler::doWalletAccounts(Json::Value params) } } -Json::Value RPCHandler::doLogRotate(Json::Value params) +Json::Value RPCHandler::doLogRotate(Json::Value) { return Log::rotateLog(); } @@ -1573,7 +1573,7 @@ Json::Value RPCHandler::doUnlScore(Json::Value params) return "scoring requested"; } -Json::Value RPCHandler::doStop(Json::Value params) +Json::Value RPCHandler::doStop(Json::Value) { theApp->stop(); @@ -1621,7 +1621,7 @@ Json::Value RPCHandler::doUnlLoad(Json::Value params) return "loading"; } -Json::Value RPCHandler::doLedgerAccept(Json::Value ) +Json::Value RPCHandler::doLedgerAccept(Json::Value) { Json::Value jvResult; @@ -2142,6 +2142,7 @@ Json::Value RPCHandler::doUnsubscribe(Json::Value jvRequest) return jvResult; } +// Provide the JSON-RPC "result" value. Json::Value RPCHandler::doRpcCommand(const std::string& strCommand, Json::Value& jvParams, int iRole) { // cLog(lsTRACE) << "doRpcCommand:" << strCommand << ":" << jvParams; @@ -2153,7 +2154,35 @@ Json::Value RPCHandler::doRpcCommand(const std::string& strCommand, Json::Value& jvRequest["command"] = strCommand; - return doCommand(jvRequest, iRole); + Json::Value jvResult; + + Json::Value jvRaw = doCommand(jvRequest, iRole); + + // Regularize result. + if (jvRaw.isObject()) + { + // Got an object. + jvResult = jvRaw; + } + else + { + // Probably got a string. + jvResult = Json::Value(Json::objectValue); + + jvResult["message"] = jvRaw; + } + + // Always report "status". On an error report the request as received. + if (jvResult.isMember("error")) + { + jvResult["status"] = "error"; + jvResult["request"] = jvRequest; + + } else { + jvResult["status"] = "success"; + } + + return jvResult; } Json::Value RPCHandler::doCommand(Json::Value& jvParams, int iRole) diff --git a/src/cpp/ripple/WSConnection.cpp b/src/cpp/ripple/WSConnection.cpp index 59bb17751..0027fea28 100644 --- a/src/cpp/ripple/WSConnection.cpp +++ b/src/cpp/ripple/WSConnection.cpp @@ -77,11 +77,14 @@ Json::Value WSConnection::invokeCommand(Json::Value& jvRequest) // Currently we will simply unwrap errors returned by the RPC // API, in the future maybe we can make the responses // consistent. + // + // Regularize result. This is duplicate code. if (jvResult["result"].isObject() && jvResult["result"].isMember("error")) { - jvResult = jvResult["result"]; + jvResult = jvResult["result"]; jvResult["status"] = "error"; jvResult["request"] = jvRequest; + } else { jvResult["status"] = "success"; }