mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-22 12:05:53 +00:00
Begin moving CLI parsing to CallRPC.
This commit is contained in:
@@ -13,11 +13,16 @@
|
||||
#include "../json/value.h"
|
||||
#include "../json/reader.h"
|
||||
|
||||
#include "CallRPC.h"
|
||||
#include "RPC.h"
|
||||
#include "Log.h"
|
||||
#include "RPCErr.h"
|
||||
#include "Config.h"
|
||||
#include "BitcoinUtil.h"
|
||||
|
||||
#include "CallRPC.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
static inline bool isSwitchChar(char c)
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
@@ -46,73 +51,175 @@ std::string EncodeBase64(const std::string& s)
|
||||
return result;
|
||||
}
|
||||
|
||||
Json::Value RPCParser::parseAsIs(Json::Value jvReq, const Json::Value ¶ms)
|
||||
{
|
||||
return jvReq;
|
||||
}
|
||||
|
||||
// Convert a command plus args to a json request.
|
||||
Json::Value RPCParser::parseCommand(Json::Value jvRequest)
|
||||
{
|
||||
std::string strCommand = jvRequest["method"].asString();
|
||||
Json::Value jvParams = jvRequest["params"];
|
||||
|
||||
cLog(lsTRACE) << "RPC:" << strCommand;
|
||||
cLog(lsTRACE) << "RPC params:" << jvParams;
|
||||
|
||||
static struct {
|
||||
const char* pCommand;
|
||||
parseFuncPtr pfpFunc;
|
||||
int iMinParams;
|
||||
int iMaxParams;
|
||||
} commandsA[] = {
|
||||
// Request-response methods
|
||||
{ "accept_ledger", &RPCParser::parseAsIs, 0, 0 },
|
||||
#if 0
|
||||
{ "account_info", &RPCParser::doAccountInfo, 1, 2, false, false, optCurrent },
|
||||
{ "account_tx", &RPCParser::doAccountTransactions, 2, 3, false, false, optNetwork },
|
||||
{ "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 },
|
||||
|
||||
{ "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 },
|
||||
|
||||
{ "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
|
||||
};
|
||||
|
||||
int i = NUMBER(commandsA);
|
||||
|
||||
while (i-- && strCommand != commandsA[i].pCommand)
|
||||
;
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
return rpcError(rpcBAD_SYNTAX, jvRequest);
|
||||
}
|
||||
else if (commandsA[i].iMinParams >= 0
|
||||
? commandsA[i].iMaxParams
|
||||
? (jvParams.size() < commandsA[i].iMinParams
|
||||
|| (commandsA[i].iMaxParams >= 0 && jvParams.size() > commandsA[i].iMaxParams))
|
||||
: false
|
||||
: jvParams.isArray())
|
||||
{
|
||||
return rpcError(rpcBAD_SYNTAX, jvRequest);
|
||||
}
|
||||
|
||||
return (this->*(commandsA[i].pfpFunc))(jvRequest, jvParams);
|
||||
}
|
||||
|
||||
int commandLineRPC(const std::vector<std::string>& vCmd)
|
||||
{
|
||||
std::string strPrint;
|
||||
int nRet = 0;
|
||||
Json::Value jvOutput;
|
||||
int nRet = 0;
|
||||
Json::Value jvRequest(Json::objectValue);
|
||||
|
||||
try
|
||||
{
|
||||
if (vCmd.empty()) return 1;
|
||||
RPCParser rpParser;
|
||||
Json::Value jvCliParams(Json::arrayValue);
|
||||
|
||||
std::string strMethod = vCmd[0];
|
||||
if (vCmd.empty()) return 1; // 1 = print usage.
|
||||
|
||||
jvRequest["method"] = vCmd[0];
|
||||
|
||||
// Parameters default to strings
|
||||
Json::Value params(Json::arrayValue);
|
||||
for (int i = 1; i != vCmd.size(); i++)
|
||||
params.append(vCmd[i]);
|
||||
jvCliParams.append(vCmd[i]);
|
||||
|
||||
// Execute
|
||||
Json::Value reply = callRPC(strMethod, params);
|
||||
jvRequest["params"] = jvCliParams;
|
||||
|
||||
// Parse reply
|
||||
Json::Value result = reply.get("result", Json::Value());
|
||||
Json::Value error = reply.get("error", Json::Value());
|
||||
jvRequest = rpParser.parseCommand(jvRequest);
|
||||
|
||||
if (result.isString() && (result.asString() == "unknown command"))
|
||||
nRet=1;
|
||||
// std::cerr << "Request: " << jvRequest << std::endl;
|
||||
|
||||
if (!error.isNull())
|
||||
{ // Error
|
||||
strPrint = "error: " + error.toStyledString();
|
||||
int code = error["code"].asInt();
|
||||
nRet = abs(code);
|
||||
}
|
||||
else
|
||||
{ // Result
|
||||
if (result.isNull())
|
||||
strPrint = "";
|
||||
else if (result.isString())
|
||||
strPrint = result.asString();
|
||||
else
|
||||
strPrint = result.toStyledString();
|
||||
Json::Value jvParams(Json::arrayValue);
|
||||
|
||||
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")
|
||||
? lexical_cast_s<int>(jvResult["error_code"].asString())
|
||||
: 1;
|
||||
}
|
||||
|
||||
jvOutput = jvResult;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
strPrint = std::string("error: ") + e.what();
|
||||
nRet = 87;
|
||||
jvRequest["error_what"] = e.what();
|
||||
|
||||
jvOutput = rpcError(rpcINTERNAL, jvRequest);
|
||||
nRet = rpcINTERNAL;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "Exception CommandLineRPC()" << std::endl;
|
||||
jvRequest["error_what"] = "exception";
|
||||
|
||||
jvOutput = rpcError(rpcINTERNAL, jvRequest);
|
||||
nRet = rpcINTERNAL;
|
||||
}
|
||||
|
||||
if (strPrint != "")
|
||||
{
|
||||
std::cout << strPrint << std::endl;
|
||||
}
|
||||
std::cout << jvOutput.toStyledString();
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
|
||||
Json::Value callRPC(const std::string& strMethod, const Json::Value& params)
|
||||
{
|
||||
if (theConfig.RPC_USER.empty() && theConfig.RPC_PASSWORD.empty())
|
||||
throw std::runtime_error("You must set rpcpassword=<password> in the configuration file"
|
||||
throw std::runtime_error("You must set rpcpassword=<password> in the configuration file. "
|
||||
"If the file does not exist, create it with owner-readable-only file permissions.");
|
||||
|
||||
// Connect to localhost
|
||||
std::cout << "Connecting to: " << theConfig.RPC_IP << ":" << theConfig.RPC_PORT << std::endl;
|
||||
if (!theConfig.QUIET)
|
||||
std::cerr << "Connecting to: " << theConfig.RPC_IP << ":" << theConfig.RPC_PORT << std::endl;
|
||||
|
||||
boost::asio::ip::tcp::endpoint
|
||||
endpoint(boost::asio::ip::address::from_string(theConfig.RPC_IP), theConfig.RPC_PORT);
|
||||
@@ -128,11 +235,11 @@ Json::Value callRPC(const std::string& strMethod, const Json::Value& params)
|
||||
|
||||
// Send request
|
||||
std::string strRequest = JSONRPCRequest(strMethod, params, Json::Value(1));
|
||||
std::cout << "send request " << strMethod << " : " << strRequest << std::endl;
|
||||
cLog(lsDEBUG) << "send request " << strMethod << " : " << strRequest << std::endl;
|
||||
std::string strPost = createHTTPPost(strRequest, mapRequestHeaders);
|
||||
stream << strPost << std::flush;
|
||||
|
||||
// std::cout << "post " << strPost << std::endl;
|
||||
// std::cerr << "post " << strPost << std::endl;
|
||||
|
||||
// Receive reply
|
||||
std::map<std::string, std::string> mapHeaders;
|
||||
@@ -146,11 +253,14 @@ Json::Value callRPC(const std::string& strMethod, const Json::Value& params)
|
||||
throw std::runtime_error("no response from server");
|
||||
|
||||
// Parse reply
|
||||
std::cout << "RPC reply: " << strReply << std::endl;
|
||||
cLog(lsDEBUG) << "RPC reply: " << strReply << std::endl;
|
||||
|
||||
Json::Reader reader;
|
||||
Json::Value valReply;
|
||||
|
||||
if (!reader.parse(strReply, valReply))
|
||||
throw std::runtime_error("couldn't parse reply from server");
|
||||
|
||||
if (valReply.isNull())
|
||||
throw std::runtime_error("expected reply to have result, error and id properties");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user