mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -28,6 +28,19 @@ public:
|
||||
virtual ~InfoSub() { ; }
|
||||
|
||||
virtual void send(const Json::Value& jvObj) = 0;
|
||||
|
||||
protected:
|
||||
boost::unordered_set<RippleAddress> mSubAccountInfo;
|
||||
boost::unordered_set<RippleAddress> mSubAccountTransaction;
|
||||
|
||||
boost::mutex mLock;
|
||||
|
||||
public:
|
||||
void insertSubAccountInfo(RippleAddress addr)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
mSubAccountInfo.insert(addr);
|
||||
}
|
||||
};
|
||||
|
||||
class NetworkOPs
|
||||
|
||||
@@ -51,6 +51,7 @@ Json::Value RPCHandler::rpcError(int iError)
|
||||
{ rpcNO_ACCOUNT, "noAccount", "No such account." },
|
||||
{ rpcNO_CLOSED, "noClosed", "Closed ledger is unavailable." },
|
||||
{ rpcNO_CURRENT, "noCurrent", "Current ledger is unavailable." },
|
||||
{ rpcNO_EVENTS, "noEvents", "Current transport does not support events." },
|
||||
{ rpcNO_GEN_DECRPYT, "noGenDectypt", "Password failed to decrypt master public generator." },
|
||||
{ rpcNO_NETWORK, "noNetwork", "Network not available." },
|
||||
{ rpcNO_PERMISSION, "noPermission", "You don't have permission for this command." },
|
||||
@@ -92,6 +93,13 @@ Json::Value RPCHandler::rpcError(int iError)
|
||||
RPCHandler::RPCHandler(NetworkOPs* netOps)
|
||||
{
|
||||
mNetOps=netOps;
|
||||
mInfoSub=NULL;
|
||||
}
|
||||
|
||||
RPCHandler::RPCHandler(NetworkOPs* netOps, InfoSub* infoSub)
|
||||
{
|
||||
mNetOps=netOps;
|
||||
mInfoSub=infoSub;
|
||||
}
|
||||
|
||||
int RPCHandler::getParamCount(const Json::Value& params)
|
||||
@@ -1309,53 +1317,58 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param
|
||||
int iMinParams;
|
||||
int iMaxParams;
|
||||
bool mAdminRequired;
|
||||
bool mEvented;
|
||||
unsigned int iOptions;
|
||||
} commandsA[] = {
|
||||
// Request-response methods
|
||||
{ "accept_ledger", &RPCHandler::doAcceptLedger, 0, 0, true },
|
||||
{ "account_info", &RPCHandler::doAccountInfo, 1, 2, false, optCurrent },
|
||||
{ "account_tx", &RPCHandler::doAccountTransactions, 2, 3, false, optNetwork },
|
||||
{ "connect", &RPCHandler::doConnect, 1, 2, true },
|
||||
{ "data_delete", &RPCHandler::doDataDelete, 1, 1, true },
|
||||
{ "data_fetch", &RPCHandler::doDataFetch, 1, 1, true },
|
||||
{ "data_store", &RPCHandler::doDataStore, 2, 2, true },
|
||||
{ "get_counts", &RPCHandler::doGetCounts, 0, 1, true },
|
||||
{ "ledger", &RPCHandler::doLedger, 0, 2, false, optNetwork },
|
||||
{ "ledger_accept", &RPCHandler::doLedgerAccept, 0, 0, true, optCurrent },
|
||||
{ "ledger_closed", &RPCHandler::doLedgerClosed, 0, 0, false, optClosed },
|
||||
{ "ledger_current", &RPCHandler::doLedgerCurrent, 0, 0, false, optCurrent },
|
||||
{ "ledger_entry", &RPCHandler::doLedgerEntry, -1, -1, false, optCurrent },
|
||||
{ "log_level", &RPCHandler::doLogLevel, 0, 2, true },
|
||||
{ "logrotate", &RPCHandler::doLogRotate, 0, 0, true },
|
||||
{ "nickname_info", &RPCHandler::doNicknameInfo, 1, 1, false, optCurrent },
|
||||
{ "owner_info", &RPCHandler::doOwnerInfo, 1, 2, false, optCurrent },
|
||||
{ "account_info", &RPCHandler::doAccountInfo, 1, 2, false, false, optCurrent },
|
||||
{ "account_tx", &RPCHandler::doAccountTransactions, 2, 3, false, false, optNetwork },
|
||||
{ "connect", &RPCHandler::doConnect, 1, 2, true },
|
||||
{ "data_delete", &RPCHandler::doDataDelete, 1, 1, true },
|
||||
{ "data_fetch", &RPCHandler::doDataFetch, 1, 1, true },
|
||||
{ "data_store", &RPCHandler::doDataStore, 2, 2, true },
|
||||
{ "get_counts", &RPCHandler::doGetCounts, 0, 1, true },
|
||||
{ "ledger", &RPCHandler::doLedger, 0, 2, false, false, optNetwork },
|
||||
{ "ledger_accept", &RPCHandler::doLedgerAccept, 0, 0, true, false, optCurrent },
|
||||
{ "ledger_closed", &RPCHandler::doLedgerClosed, 0, 0, false, false, optClosed },
|
||||
{ "ledger_current", &RPCHandler::doLedgerCurrent, 0, 0, false, false, optCurrent },
|
||||
{ "ledger_entry", &RPCHandler::doLedgerEntry, -1, -1, false, false, optCurrent },
|
||||
{ "log_level", &RPCHandler::doLogLevel, 0, 2, true },
|
||||
{ "logrotate", &RPCHandler::doLogRotate, 0, 0, true },
|
||||
{ "nickname_info", &RPCHandler::doNicknameInfo, 1, 1, false, false, optCurrent },
|
||||
{ "owner_info", &RPCHandler::doOwnerInfo, 1, 2, false, false, optCurrent },
|
||||
{ "peers", &RPCHandler::doPeers, 0, 0, true },
|
||||
{ "profile", &RPCHandler::doProfile, 1, 9, false, optCurrent },
|
||||
{ "ripple_lines_get", &RPCHandler::doRippleLinesGet, 1, 2, false, optCurrent },
|
||||
{ "submit", &RPCHandler::doSubmit, 2, 2, false, optCurrent },
|
||||
{ "submit_json", &RPCHandler::doSubmitJson, -1, -1, false, optCurrent },
|
||||
{ "server_info", &RPCHandler::doServerInfo, 0, 0, true },
|
||||
{ "stop", &RPCHandler::doStop, 0, 0, true },
|
||||
{ "transaction_entry", &RPCHandler::doTransactionEntry, -1, -1, false, optCurrent },
|
||||
{ "tx", &RPCHandler::doTx, 1, 1, true },
|
||||
{ "tx_history", &RPCHandler::doTxHistory, 1, 1, false, },
|
||||
{ "profile", &RPCHandler::doProfile, 1, 9, false, false, optCurrent },
|
||||
{ "ripple_lines_get", &RPCHandler::doRippleLinesGet, 1, 2, false, false, optCurrent },
|
||||
{ "submit", &RPCHandler::doSubmit, 2, 2, false, false, optCurrent },
|
||||
{ "submit_json", &RPCHandler::doSubmitJson, -1, -1, false, false, optCurrent },
|
||||
{ "server_info", &RPCHandler::doServerInfo, 0, 0, true },
|
||||
{ "stop", &RPCHandler::doStop, 0, 0, true },
|
||||
{ "transaction_entry", &RPCHandler::doTransactionEntry, -1, -1, false, false, optCurrent },
|
||||
{ "tx", &RPCHandler::doTx, 1, 1, true },
|
||||
{ "tx_history", &RPCHandler::doTxHistory, 1, 1, false, },
|
||||
|
||||
{ "unl_add", &RPCHandler::doUnlAdd, 1, 2, true },
|
||||
{ "unl_delete", &RPCHandler::doUnlDelete, 1, 1, true },
|
||||
{ "unl_list", &RPCHandler::doUnlList, 0, 0, true },
|
||||
{ "unl_load", &RPCHandler::doUnlLoad, 0, 0, true },
|
||||
{ "unl_network", &RPCHandler::doUnlNetwork, 0, 0, true },
|
||||
{ "unl_reset", &RPCHandler::doUnlReset, 0, 0, true },
|
||||
{ "unl_score", &RPCHandler::doUnlScore, 0, 0, true },
|
||||
{ "unl_add", &RPCHandler::doUnlAdd, 1, 2, true },
|
||||
{ "unl_delete", &RPCHandler::doUnlDelete, 1, 1, true },
|
||||
{ "unl_list", &RPCHandler::doUnlList, 0, 0, true },
|
||||
{ "unl_load", &RPCHandler::doUnlLoad, 0, 0, true },
|
||||
{ "unl_network", &RPCHandler::doUnlNetwork, 0, 0, true },
|
||||
{ "unl_reset", &RPCHandler::doUnlReset, 0, 0, true },
|
||||
{ "unl_score", &RPCHandler::doUnlScore, 0, 0, true },
|
||||
|
||||
{ "validation_create", &RPCHandler::doValidationCreate, 0, 1, false },
|
||||
{ "validation_seed", &RPCHandler::doValidationSeed, 0, 1, false },
|
||||
{ "validation_create", &RPCHandler::doValidationCreate, 0, 1, false },
|
||||
{ "validation_seed", &RPCHandler::doValidationSeed, 0, 1, false },
|
||||
|
||||
{ "wallet_accounts", &RPCHandler::doWalletAccounts, 1, 1, false, optCurrent },
|
||||
{ "wallet_propose", &RPCHandler::doWalletPropose, 0, 1, false, },
|
||||
{ "wallet_seed", &RPCHandler::doWalletSeed, 0, 1, false, },
|
||||
{ "wallet_accounts", &RPCHandler::doWalletAccounts, 1, 1, false, false, optCurrent },
|
||||
{ "wallet_propose", &RPCHandler::doWalletPropose, 0, 1, false, },
|
||||
{ "wallet_seed", &RPCHandler::doWalletSeed, 0, 1, false, },
|
||||
|
||||
{ "login", &RPCHandler::doLogin, 2, 2, true },
|
||||
};
|
||||
{ "login", &RPCHandler::doLogin, 2, 2, true },
|
||||
|
||||
// Evented methods
|
||||
{ "subscribe", &RPCHandler::doSubscribe, -1, -1, false, true },
|
||||
{ "unsubscribe", &RPCHandler::doUnsubscribe, -1, -1, false, true }, };
|
||||
|
||||
int i = NUMBER(commandsA);
|
||||
|
||||
@@ -1370,6 +1383,10 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param
|
||||
{
|
||||
return rpcError(rpcNO_PERMISSION);
|
||||
}
|
||||
else if (commandsA[i].mEvented && mInfoSub == NULL)
|
||||
{
|
||||
return rpcError(rpcNO_EVENTS);
|
||||
}
|
||||
else if (commandsA[i].iMinParams >= 0
|
||||
? commandsA[i].iMaxParams
|
||||
? (params.size() < commandsA[i].iMinParams
|
||||
@@ -1933,4 +1950,183 @@ Json::Value RPCHandler::doLedgerEntry(const Json::Value& jvRequest)
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
|
||||
boost::unordered_set<RippleAddress> RPCHandler::parseAccountIds(const Json::Value& jvArray)
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaResult;
|
||||
|
||||
for (Json::Value::const_iterator it = jvArray.begin(); it != jvArray.end(); it++)
|
||||
{
|
||||
RippleAddress naString;
|
||||
|
||||
if (!(*it).isString() || !naString.setAccountID((*it).asString()))
|
||||
{
|
||||
usnaResult.clear();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) usnaResult.insert(naString);
|
||||
}
|
||||
}
|
||||
|
||||
return usnaResult;
|
||||
}
|
||||
|
||||
/*
|
||||
server : Sends a message anytime the server status changes such as network connectivity.
|
||||
ledger : Sends a message at every ledger close.
|
||||
transactions : Sends a message for every transaction that makes it into a ledger.
|
||||
rt_transactions
|
||||
accounts
|
||||
rt_accounts
|
||||
*/
|
||||
Json::Value RPCHandler::doSubscribe(const Json::Value& jvRequest)
|
||||
{
|
||||
Json::Value jvResult(Json::objectValue);
|
||||
|
||||
if (jvRequest.isMember("streams"))
|
||||
{
|
||||
for (Json::Value::iterator it = jvRequest["streams"].begin(); it != jvRequest["streams"].end(); it++)
|
||||
{
|
||||
if ((*it).isString())
|
||||
{
|
||||
std::string streamName=(*it).asString();
|
||||
|
||||
if(streamName=="server")
|
||||
{
|
||||
mNetOps->subServer(mInfoSub, jvResult);
|
||||
}else if(streamName=="ledger")
|
||||
{
|
||||
mNetOps->subLedger(mInfoSub, jvResult);
|
||||
}else if(streamName=="transactions")
|
||||
{
|
||||
mNetOps->subTransactions(mInfoSub);
|
||||
}else if(streamName=="rt_transactions")
|
||||
{
|
||||
mNetOps->subRTTransactions(mInfoSub);
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = str(boost::format("Unknown stream: %s") % streamName);
|
||||
}
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = "malformedSteam";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("rt_accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["rt_accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mInfoSub->insertSubAccountInfo(naAccountID);
|
||||
}
|
||||
|
||||
mNetOps->subAccount(mInfoSub, usnaAccoundIds, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mInfoSub->insertSubAccountInfo(naAccountID);
|
||||
}
|
||||
|
||||
mNetOps->subAccount(mInfoSub, usnaAccoundIds, false);
|
||||
}
|
||||
}
|
||||
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
Json::Value RPCHandler::doUnsubscribe(const Json::Value& jvRequest)
|
||||
{
|
||||
Json::Value jvResult(Json::objectValue);
|
||||
|
||||
if (jvRequest.isMember("streams"))
|
||||
{
|
||||
for (Json::Value::iterator it = jvRequest["streams"].begin(); it != jvRequest["streams"].end(); it++)
|
||||
{
|
||||
if ((*it).isString() )
|
||||
{
|
||||
std::string streamName=(*it).asString();
|
||||
|
||||
if(streamName=="server")
|
||||
{
|
||||
mNetOps->unsubServer(mInfoSub);
|
||||
}else if(streamName=="ledger")
|
||||
{
|
||||
mNetOps->unsubLedger(mInfoSub);
|
||||
}else if(streamName=="transactions")
|
||||
{
|
||||
mNetOps->unsubTransactions(mInfoSub);
|
||||
}else if(streamName=="rt_transactions")
|
||||
{
|
||||
mNetOps->unsubRTTransactions(mInfoSub);
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = str(boost::format("Unknown stream: %s") % streamName);
|
||||
}
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = "malformedSteam";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("rt_accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["rt_accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mInfoSub->insertSubAccountInfo(naAccountID);
|
||||
}
|
||||
|
||||
mNetOps->unsubAccount(mInfoSub, usnaAccoundIds,true);
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mInfoSub->insertSubAccountInfo(naAccountID);
|
||||
}
|
||||
|
||||
mNetOps->unsubAccount(mInfoSub, usnaAccoundIds,false);
|
||||
}
|
||||
}
|
||||
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -6,7 +6,8 @@ class NetworkOPs;
|
||||
|
||||
class RPCHandler
|
||||
{
|
||||
NetworkOPs* mNetOps;
|
||||
NetworkOPs* mNetOps;
|
||||
InfoSub* mInfoSub;
|
||||
|
||||
typedef Json::Value (RPCHandler::*doFuncPtr)(const Json::Value ¶ms);
|
||||
enum {
|
||||
@@ -15,6 +16,9 @@ class RPCHandler
|
||||
optClosed = 4+optNetwork, // Need closed ledger
|
||||
};
|
||||
|
||||
// Utilities
|
||||
void addSubmitPath(Json::Value& txJSON);
|
||||
boost::unordered_set<RippleAddress> parseAccountIds(const Json::Value& jvArray);
|
||||
int getParamCount(const Json::Value& params);
|
||||
bool extractString(std::string& param, const Json::Value& params, int index);
|
||||
|
||||
@@ -84,8 +88,9 @@ class RPCHandler
|
||||
Json::Value doLedgerEntry(const Json::Value& params);
|
||||
Json::Value doTransactionEntry(const Json::Value& params);
|
||||
|
||||
Json::Value doSubscribe(const Json::Value& params);
|
||||
Json::Value doUnsubscribe(const Json::Value& params);
|
||||
|
||||
void addSubmitPath(Json::Value& txJSON);
|
||||
|
||||
public:
|
||||
|
||||
@@ -95,6 +100,7 @@ public:
|
||||
// Misc failure
|
||||
rpcLOAD_FAILED,
|
||||
rpcNO_PERMISSION,
|
||||
rpcNO_EVENTS,
|
||||
rpcNOT_STANDALONE,
|
||||
|
||||
// Networking
|
||||
@@ -151,8 +157,9 @@ public:
|
||||
enum { GUEST, USER, ADMIN };
|
||||
|
||||
RPCHandler(NetworkOPs* netOps);
|
||||
RPCHandler(NetworkOPs* netOps, InfoSub* infoSub);
|
||||
|
||||
Json::Value doCommand(const std::string& command, Json::Value& params,int role);
|
||||
Json::Value doCommand(const std::string& command, Json::Value& params, int role);
|
||||
Json::Value rpcError(int iError);
|
||||
|
||||
Json::Value handleJSONSubmit(const Json::Value& jvRequest);
|
||||
|
||||
@@ -26,7 +26,7 @@ SETUP_LOG();
|
||||
#endif
|
||||
|
||||
RPCServer::RPCServer(boost::asio::io_service& io_service , NetworkOPs* nopNetwork)
|
||||
: mNetOps(nopNetwork), mRPCHandler(nopNetwork), mSocket(io_service)
|
||||
: mNetOps(nopNetwork), mSocket(io_service)
|
||||
{
|
||||
|
||||
mRole = RPCHandler::GUEST;
|
||||
@@ -142,6 +142,8 @@ std::string RPCServer::handleRequest(const std::string& requestStr)
|
||||
else if (!valParams.isArray())
|
||||
return(HTTPReply(400, "params unparseable"));
|
||||
|
||||
RPCHandler mRPCHandler(mNetOps);
|
||||
|
||||
cLog(lsTRACE) << valParams;
|
||||
Json::Value result = mRPCHandler.doCommand(strMethod, valParams,mRole);
|
||||
cLog(lsTRACE) << result;
|
||||
|
||||
@@ -22,9 +22,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
|
||||
NetworkOPs* mNetOps;
|
||||
RPCHandler mRPCHandler;
|
||||
|
||||
boost::asio::ip::tcp::socket mSocket;
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ WSConnection::~WSConnection()
|
||||
mNetwork.unsubRTTransactions(this);
|
||||
mNetwork.unsubLedger(this);
|
||||
mNetwork.unsubServer(this);
|
||||
mNetwork.unsubAccount(this, mSubAccountInfo,true);
|
||||
mNetwork.unsubAccount(this, mSubAccountInfo,false);
|
||||
mNetwork.unsubAccount(this, mSubAccountInfo, true);
|
||||
mNetwork.unsubAccount(this, mSubAccountInfo, false);
|
||||
}
|
||||
|
||||
void WSConnection::send(const Json::Value& jvObj)
|
||||
@@ -33,17 +33,6 @@ void WSConnection::send(const Json::Value& jvObj)
|
||||
|
||||
Json::Value WSConnection::invokeCommand(Json::Value& jvRequest)
|
||||
{
|
||||
static struct {
|
||||
const char* pCommand;
|
||||
doFuncPtr dfpFunc;
|
||||
} commandsA[] = {
|
||||
// Request-Response Commands:
|
||||
{ "submit", &WSConnection::doSubmit },
|
||||
{ "subscribe", &WSConnection::doSubscribe },
|
||||
{ "unsubscribe", &WSConnection::doUnsubscribe },
|
||||
{ "rpc", &WSConnection::doRPC },
|
||||
};
|
||||
|
||||
if (!jvRequest.isMember("command"))
|
||||
{
|
||||
Json::Value jvResult(Json::objectValue);
|
||||
@@ -56,22 +45,27 @@ Json::Value WSConnection::invokeCommand(Json::Value& jvRequest)
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
std::string strCommand = jvRequest["command"].asString();
|
||||
|
||||
int i = NUMBER(commandsA);
|
||||
|
||||
while (i-- && strCommand != commandsA[i].pCommand)
|
||||
;
|
||||
|
||||
RPCHandler mRPCHandler(&mNetwork, this);
|
||||
Json::Value jvResult(Json::objectValue);
|
||||
|
||||
if (i < 0)
|
||||
// Regular RPC command
|
||||
jvResult["result"] = mRPCHandler.doCommand(
|
||||
jvRequest["command"].asString(),
|
||||
jvRequest.isMember("params")
|
||||
? jvRequest["params"]
|
||||
: jvRequest,
|
||||
mHandler->getPublic() ? RPCHandler::GUEST : RPCHandler::ADMIN);
|
||||
|
||||
// Currently we will simply unwrap errors returned by the RPC
|
||||
// API, in the future maybe we can make the responses
|
||||
// consistent.
|
||||
if (jvResult["result"].isObject() && jvResult["result"].isMember("error"))
|
||||
{
|
||||
jvResult["error"] = "unknownCommand"; // Unknown command.
|
||||
}
|
||||
else
|
||||
{
|
||||
(this->*(commandsA[i].dfpFunc))(jvResult, jvRequest);
|
||||
jvResult = jvResult["result"];
|
||||
jvResult["status"] = "error";
|
||||
jvResult["request"] = jvRequest;
|
||||
} else {
|
||||
jvResult["status"] = "success";
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("id"))
|
||||
@@ -79,237 +73,9 @@ Json::Value WSConnection::invokeCommand(Json::Value& jvRequest)
|
||||
jvResult["id"] = jvRequest["id"];
|
||||
}
|
||||
|
||||
if (jvResult.isMember("error"))
|
||||
{
|
||||
jvResult["result"] = "error";
|
||||
jvResult["request"] = jvRequest;
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["result"] = "success";
|
||||
}
|
||||
|
||||
jvResult["type"] = "response";
|
||||
jvResult["type"] = "response";
|
||||
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
boost::unordered_set<RippleAddress> WSConnection::parseAccountIds(const Json::Value& jvArray)
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaResult;
|
||||
|
||||
for (Json::Value::const_iterator it = jvArray.begin(); it != jvArray.end(); it++)
|
||||
{
|
||||
RippleAddress naString;
|
||||
|
||||
if (!(*it).isString() || !naString.setAccountID((*it).asString()))
|
||||
{
|
||||
usnaResult.clear();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) usnaResult.insert(naString);
|
||||
}
|
||||
}
|
||||
|
||||
return usnaResult;
|
||||
}
|
||||
|
||||
//
|
||||
// Commands
|
||||
//
|
||||
|
||||
/*
|
||||
server : Sends a message anytime the server status changes such as network connectivity.
|
||||
ledger : Sends a message at every ledger close.
|
||||
transactions : Sends a message for every transaction that makes it into a ledger.
|
||||
rt_transactions
|
||||
accounts
|
||||
rt_accounts
|
||||
*/
|
||||
void WSConnection::doSubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (jvRequest.isMember("streams"))
|
||||
{
|
||||
for (Json::Value::iterator it = jvRequest["streams"].begin(); it != jvRequest["streams"].end(); it++)
|
||||
{
|
||||
if ((*it).isString())
|
||||
{
|
||||
std::string streamName=(*it).asString();
|
||||
|
||||
if(streamName=="server")
|
||||
{
|
||||
mNetwork.subServer(this, jvResult);
|
||||
}else if(streamName=="ledger")
|
||||
{
|
||||
mNetwork.subLedger(this, jvResult);
|
||||
}else if(streamName=="transactions")
|
||||
{
|
||||
mNetwork.subTransactions(this);
|
||||
}else if(streamName=="rt_transactions")
|
||||
{
|
||||
mNetwork.subRTTransactions(this);
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = str(boost::format("Unknown stream: %s") % streamName);
|
||||
}
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = "malformedSteam";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("rt_accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["rt_accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.subAccount(this, usnaAccoundIds,true);
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.subAccount(this, usnaAccoundIds,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (jvRequest.isMember("streams"))
|
||||
{
|
||||
for (Json::Value::iterator it = jvRequest["streams"].begin(); it != jvRequest["streams"].end(); it++)
|
||||
{
|
||||
if ((*it).isString() )
|
||||
{
|
||||
std::string streamName=(*it).asString();
|
||||
|
||||
if(streamName=="server")
|
||||
{
|
||||
mNetwork.unsubServer(this);
|
||||
}else if(streamName=="ledger")
|
||||
{
|
||||
mNetwork.unsubLedger(this);
|
||||
}else if(streamName=="transactions")
|
||||
{
|
||||
mNetwork.unsubTransactions(this);
|
||||
}else if(streamName=="rt_transactions")
|
||||
{
|
||||
mNetwork.unsubRTTransactions(this);
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = str(boost::format("Unknown stream: %s") % streamName);
|
||||
}
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = "malformedSteam";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("rt_accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["rt_accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.unsubAccount(this, usnaAccoundIds,true);
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.unsubAccount(this, usnaAccoundIds,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doRPC(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (jvRequest.isMember("rpc_command") )
|
||||
{
|
||||
jvResult = theApp->getRPCHandler().doCommand(
|
||||
jvRequest["rpc_command"].asString(),
|
||||
jvRequest.isMember("params")
|
||||
? jvRequest["params"]
|
||||
: jvRequest,
|
||||
mHandler->getPublic() ? RPCHandler::GUEST : RPCHandler::ADMIN);
|
||||
|
||||
jvResult["type"] = "response";
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["error"] = "fieldNotCommand";
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Currently requires secret. Allow signed transaction as an alternative.
|
||||
void WSConnection::doSubmit(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!jvRequest.isMember("tx_json"))
|
||||
{
|
||||
jvResult["error"] = "fieldNotFoundTxJson";
|
||||
}else if (!jvRequest.isMember("secret"))
|
||||
{
|
||||
jvResult["error"] = "fieldNotFoundSecret";
|
||||
}else
|
||||
{
|
||||
jvResult=theApp->getRPCHandler().handleJSONSubmit(jvRequest);
|
||||
|
||||
// TODO: track the transaction mNetwork.subSubmit(this, jvResult["tx hash"] );
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -21,10 +21,6 @@ public:
|
||||
protected:
|
||||
typedef void (WSConnection::*doFuncPtr)(Json::Value& jvResult, Json::Value &jvRequest);
|
||||
|
||||
boost::mutex mLock;
|
||||
boost::unordered_set<RippleAddress> mSubAccountInfo;
|
||||
boost::unordered_set<RippleAddress> mSubAccountTransaction;
|
||||
|
||||
WSServerHandler<websocketpp::WSDOOR_SERVER>* mHandler;
|
||||
connection_ptr mConnection;
|
||||
NetworkOPs& mNetwork;
|
||||
@@ -44,13 +40,6 @@ public:
|
||||
|
||||
// Utilities
|
||||
Json::Value invokeCommand(Json::Value& jvRequest);
|
||||
boost::unordered_set<RippleAddress> parseAccountIds(const Json::Value& jvArray);
|
||||
|
||||
// Commands
|
||||
void doSubmit(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doRPC(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doSubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
|
||||
};
|
||||
|
||||
|
||||
167
src/js/remote.js
167
src/js/remote.js
@@ -147,6 +147,21 @@ Request.prototype.ripple_state = function (account, issuer, currency) {
|
||||
return this;
|
||||
};
|
||||
|
||||
Request.prototype.accounts = function (accounts) {
|
||||
if ("object" !== typeof accounts) {
|
||||
accounts = [accounts];
|
||||
}
|
||||
|
||||
// Process accounts parameters
|
||||
var procAccounts = [];
|
||||
for (var i = 0, l = accounts.length; i < l; i++) {
|
||||
procAccounts.push(UInt160.json_rewrite(accounts[i]));
|
||||
}
|
||||
this.message.accounts = procAccounts;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
//
|
||||
// Remote - access to a remote Ripple server via websocket.
|
||||
//
|
||||
@@ -429,13 +444,13 @@ Remote.prototype._connect_message = function (ws, json) {
|
||||
if (!request) {
|
||||
unexpected = true;
|
||||
}
|
||||
else if ('success' === message.result) {
|
||||
if (this.trace) console.log("message: %s", json);
|
||||
else if ('success' === message.status) {
|
||||
if (this.trace) console.log("remote: response: %s", json);
|
||||
|
||||
request.emit('success', message);
|
||||
request.emit('success', message.result);
|
||||
}
|
||||
else if (message.error) {
|
||||
if (this.trace) console.log("message: %s", json);
|
||||
if (this.trace) console.log("remote: error: %s", json);
|
||||
|
||||
request.emit('error', {
|
||||
'error' : 'remoteError',
|
||||
@@ -509,13 +524,33 @@ Remote.prototype.request = function (request) {
|
||||
}
|
||||
};
|
||||
|
||||
Remote.prototype.request_server_info = function () {
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.command = 'server_info';
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
Remote.prototype.request_ledger = function (params) {
|
||||
// XXX Does this require the server to be trusted?
|
||||
//assert(this.trusted);
|
||||
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.command = 'ledger';
|
||||
request.message.params = params;
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
// Only for unit testing.
|
||||
Remote.prototype.request_ledger_hash = function () {
|
||||
assert(this.trusted); // If not trusted, need to check proof.
|
||||
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.rpc_command = 'ledger_closed';
|
||||
request.message.command = 'ledger_closed';
|
||||
|
||||
return request;
|
||||
};
|
||||
@@ -525,7 +560,7 @@ Remote.prototype.request_ledger_hash = function () {
|
||||
Remote.prototype.request_ledger_current = function () {
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.rpc_command = 'ledger_current';
|
||||
request.message.command = 'ledger_current';
|
||||
|
||||
return request;
|
||||
};
|
||||
@@ -540,7 +575,7 @@ Remote.prototype.request_ledger_entry = function (type) {
|
||||
var self = this;
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.rpc_command = 'ledger_entry';
|
||||
request.message.command = 'ledger_entry';
|
||||
|
||||
if (type)
|
||||
this.type = type;
|
||||
@@ -593,10 +628,28 @@ Remote.prototype.request_ledger_entry = function (type) {
|
||||
return request;
|
||||
};
|
||||
|
||||
Remote.prototype.request_subscribe = function () {
|
||||
Remote.prototype.request_subscribe = function (streams) {
|
||||
var request = new Request(this, 'subscribe');
|
||||
|
||||
request.message.streams = [ 'ledger', 'server' ];
|
||||
if (streams) {
|
||||
if ("object" !== typeof streams) {
|
||||
streams = [streams];
|
||||
}
|
||||
request.message.streams = streams;
|
||||
}
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
Remote.prototype.request_unsubscribe = function (streams) {
|
||||
var request = new Request(this, 'unsubscribe');
|
||||
|
||||
if (streams) {
|
||||
if ("object" !== typeof streams) {
|
||||
streams = [streams];
|
||||
}
|
||||
request.message.streams = streams;
|
||||
}
|
||||
|
||||
return request;
|
||||
};
|
||||
@@ -606,18 +659,55 @@ Remote.prototype.request_transaction_entry = function (hash) {
|
||||
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.rpc_command = 'transaction_entry';
|
||||
request.message.command = 'transaction_entry';
|
||||
|
||||
return request
|
||||
.tx_hash(hash);
|
||||
};
|
||||
|
||||
Remote.prototype.request_ripple_lines_get = function (accountID) {
|
||||
// XXX Does this require the server to be trusted?
|
||||
//assert(this.trusted);
|
||||
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.command = 'ripple_lines_get';
|
||||
// XXX Convert API call to JSON
|
||||
request.message.params = [accountID];
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
Remote.prototype.request_wallet_accounts = function (key) {
|
||||
// XXX Does this require the server to be trusted?
|
||||
//assert(this.trusted);
|
||||
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.command = 'wallet_accounts';
|
||||
// XXX Convert API call to JSON
|
||||
request.message.params = [key];
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
Remote.prototype.request_account_tx = function (accountID, minLedger, maxLedger) {
|
||||
// XXX Does this require the server to be trusted?
|
||||
//assert(this.trusted);
|
||||
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.command = 'account_tx';
|
||||
// XXX Convert API call to JSON
|
||||
request.message.params = [accountID, minLedger, maxLedger];
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
// Submit a transaction.
|
||||
Remote.prototype.submit = function (transaction) {
|
||||
var self = this;
|
||||
|
||||
if (this.trace) console.log("remote: submit: %s", JSON.stringify(transaction.tx_json));
|
||||
|
||||
if (transaction.secret && !this.trusted)
|
||||
{
|
||||
transaction.emit('error', {
|
||||
@@ -658,7 +748,7 @@ Remote.prototype.submit = function (transaction) {
|
||||
else {
|
||||
var submit_request = new Request(this, 'rpc');
|
||||
|
||||
submit_request.message.rpc_command = 'submit_json';
|
||||
submit_request.message.command = 'submit_json';
|
||||
|
||||
submit_request.tx_json(transaction.tx_json);
|
||||
submit_request.secret(transaction.secret);
|
||||
@@ -685,7 +775,7 @@ Remote.prototype.submit = function (transaction) {
|
||||
Remote.prototype._server_subscribe = function () {
|
||||
var self = this;
|
||||
|
||||
this.request_subscribe()
|
||||
this.request_subscribe([ 'ledger', 'server' ])
|
||||
.on('success', function (message) {
|
||||
self.stand_alone = !!message.stand_alone;
|
||||
|
||||
@@ -715,7 +805,7 @@ Remote.prototype.ledger_accept = function () {
|
||||
{
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.rpc_command = 'ledger_accept';
|
||||
request.message.command = 'ledger_accept';
|
||||
|
||||
request
|
||||
.request();
|
||||
@@ -766,7 +856,7 @@ Remote.prototype.set_account_seq = function (account, seq) {
|
||||
var account = UInt160.json_rewrite(account);
|
||||
|
||||
if (!this.accounts[account]) this.accounts[account] = {};
|
||||
|
||||
|
||||
this.accounts[account].seq = seq;
|
||||
}
|
||||
|
||||
@@ -806,7 +896,7 @@ Remote.prototype.account_seq_cache = function (account, current) {
|
||||
account_info.caching_seq_request = request;
|
||||
}
|
||||
|
||||
return request
|
||||
return request;
|
||||
};
|
||||
|
||||
// Mark an account's root node as dirty.
|
||||
@@ -861,6 +951,49 @@ Remote.prototype.request_ripple_balance = function (account, issuer, currency, c
|
||||
});
|
||||
}
|
||||
|
||||
Remote.prototype.request_unl_list = function () {
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.command = 'unl_list';
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
Remote.prototype.request_unl_add = function (addr, note) {
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.command = 'unl_add';
|
||||
request.message.params = [addr, note];
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
Remote.prototype.request_unl_delete = function (publicKey) {
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.command = 'unl_delete';
|
||||
request.message.params = [publicKey];
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
Remote.prototype.request_peers = function () {
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.command = 'peers';
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
Remote.prototype.request_connect = function (ip, port) {
|
||||
var request = new Request(this, 'rpc');
|
||||
|
||||
request.message.command = 'connect';
|
||||
request.message.params = [ip, port];
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
Remote.prototype.transaction = function () {
|
||||
return new Transaction(this);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user