Make a simple way to extend the RPC command set without modifying core server code.

This makes it easy to add self-contained modules that can be controlled and is also
useful for one-off and troubleshooting commands.
This commit is contained in:
JoelKatz
2013-01-13 22:46:42 -08:00
parent fc78cb38ed
commit 5fa43cc770
4 changed files with 80 additions and 1 deletions

View File

@@ -53,7 +53,23 @@ std::string EncodeBase64(const std::string& s)
Json::Value RPCParser::parseAsIs(const Json::Value& jvParams)
{
return Json::Value(Json::objectValue);
Json::Value v(Json::objectValue);
if (jvParams.isArray() && (jvParams.size() > 0))
v["params"] = jvParams;
return v;
}
Json::Value RPCParser::parseInternal(const Json::Value& jvParams)
{
Json::Value v(Json::objectValue);
v["internal_command"] = jvParams[0u];
Json::Value params(Json::arrayValue);
for (unsigned i = 1; i < jvParams.size(); ++i)
params.append(jvParams[i]);
v["params"] = params;
return v;
}
// account_info <account>|<nickname>|<account_public_key>
@@ -481,6 +497,8 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams)
{ "wallet_propose", &RPCParser::parseWalletPropose, 0, 1 },
{ "wallet_seed", &RPCParser::parseWalletSeed, 0, 1 },
{ "internal", &RPCParser::parseInternal, 1, -1 },
#if ENABLE_INSECURE
// XXX Unnecessary commands which should be removed.
{ "login", &RPCParser::parseLogin, 2, 2 },

View File

@@ -23,6 +23,7 @@ protected:
Json::Value parseEvented(const Json::Value& jvParams);
Json::Value parseGetCounts(const Json::Value& jvParams);
Json::Value parseLedger(const Json::Value& jvParams);
Json::Value parseInternal(const Json::Value& jvParams);
#if ENABLE_INSECURE
Json::Value parseLogin(const Json::Value& jvParams);
#endif

View File

@@ -2432,6 +2432,13 @@ Json::Value RPCHandler::doRpcCommand(const std::string& strMethod, Json::Value&
return jvResult;
}
Json::Value RPCHandler::doInternal(Json::Value jvRequest)
{ // Used for debug or special-purpose RPC commands
if (!jvRequest.isMember("internal_command"))
return rpcError(rpcINVALID_PARAMS);
return RPCInternalHandler::runHandler(jvRequest["internal_command"].asString(), jvRequest["params"]);
}
Json::Value RPCHandler::doCommand(Json::Value& jvRequest, int iRole)
{
if (!jvRequest.isMember("command"))
@@ -2460,6 +2467,7 @@ Json::Value RPCHandler::doCommand(Json::Value& jvRequest, int iRole)
{ "account_tx", &RPCHandler::doAccountTransactions, false, optNetwork },
{ "connect", &RPCHandler::doConnect, true, optNone },
{ "get_counts", &RPCHandler::doGetCounts, true, optNone },
{ "internal", &RPCHandler::doInternal, true, optNone },
{ "ledger", &RPCHandler::doLedger, false, optNetwork },
{ "ledger_accept", &RPCHandler::doLedgerAccept, true, optCurrent },
{ "ledger_closed", &RPCHandler::doLedgerClosed, false, optClosed },
@@ -2571,4 +2579,29 @@ Json::Value RPCHandler::doCommand(Json::Value& jvRequest, int iRole)
}
}
RPCInternalHandler* RPCInternalHandler::sHeadHandler = NULL;
RPCInternalHandler::RPCInternalHandler(const std::string& name, handler_t Handler) : mName(name), mHandler(Handler)
{
mNextHandler = sHeadHandler;
sHeadHandler = this;
}
Json::Value RPCInternalHandler::runHandler(const std::string& name, const Json::Value& params)
{
RPCInternalHandler* h = sHeadHandler;
while (h != NULL)
{
if (name == h->mName)
{
cLog(lsWARNING) << "Internal command " << name << ": " << params;
Json::Value ret = h->mHandler(params);
cLog(lsWARNING) << "Internal command returns: " << ret;
return ret;
}
h = h->mNextHandler;
}
return rpcError(rpcBAD_SYNTAX);
}
// vim:ts=4

View File

@@ -1,8 +1,17 @@
#ifndef __RPCHANDLER__
#define __RPCHANDLER__
#include <boost/unordered_set.hpp>
#include "../json/value.h"
#include "RippleAddress.h"
#include "SerializedTypes.h"
#include "Ledger.h"
// used by the RPCServer or WSDoor to carry out these RPC commands
class NetworkOPs;
class InfoSub;
class RPCHandler
{
@@ -46,6 +55,7 @@ class RPCHandler
Json::Value doDataStore(Json::Value params);
#endif
Json::Value doGetCounts(Json::Value params);
Json::Value doInternal(Json::Value params);
Json::Value doLedger(Json::Value params);
Json::Value doLogLevel(Json::Value params);
Json::Value doLogRotate(Json::Value params);
@@ -106,5 +116,22 @@ public:
Json::Value doRpcCommand(const std::string& strCommand, Json::Value& jvParams, int iRole);
};
class RPCInternalHandler
{
public:
typedef Json::Value (*handler_t)(const Json::Value&);
protected:
static RPCInternalHandler* sHeadHandler;
RPCInternalHandler* mNextHandler;
std::string mName;
handler_t mHandler;
public:
RPCInternalHandler(const std::string& name, handler_t handler);
static Json::Value runHandler(const std::string& name, const Json::Value& params);
};
#endif
// vim:ts=4