diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h index eab46a592a..41515b003a 100644 --- a/src/cpp/ripple/NetworkOPs.h +++ b/src/cpp/ripple/NetworkOPs.h @@ -28,6 +28,16 @@ public: virtual ~InfoSub() { ; } virtual void send(const Json::Value& jvObj) = 0; + +protected: + boost::unordered_set mSubAccountInfo; + boost::unordered_set mSubAccountTransaction; + +public: + void insertSubAccountInfo(RippleAddress addr) + { + mSubAccountInfo.insert(addr); + } }; class NetworkOPs diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index fbd24d555f..9d9d1544e7 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -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." }, @@ -1298,7 +1299,7 @@ Json::Value RPCHandler::doLogRotate(const Json::Value& params) return Log::rotateLog(); } -Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& params, int role) +Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& params, int role, InfoSub* sub) { cLog(lsTRACE) << "RPC:" << command; cLog(lsTRACE) << "RPC params:" << params; @@ -1309,53 +1310,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 +1376,10 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param { return rpcError(rpcNO_PERMISSION); } + else if (commandsA[i].mEvented && sub == NULL) + { + return rpcError(rpcNO_EVENTS); + } else if (commandsA[i].iMinParams >= 0 ? commandsA[i].iMaxParams ? (params.size() < commandsA[i].iMinParams @@ -1396,6 +1406,11 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param } else { + if (sub != NULL) + { + isCurrent = sub; + } + try { return (this->*(commandsA[i].dfpFunc))(params); } @@ -1933,4 +1948,191 @@ Json::Value RPCHandler::doLedgerEntry(const Json::Value& jvRequest) return jvResult; } + +boost::unordered_set RPCHandler::parseAccountIds(const Json::Value& jvArray) +{ + boost::unordered_set 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(isCurrent, jvResult); + }else if(streamName=="ledger") + { + mNetOps->subLedger(isCurrent, jvResult); + }else if(streamName=="transactions") + { + mNetOps->subTransactions(isCurrent); + }else if(streamName=="rt_transactions") + { + mNetOps->subRTTransactions(isCurrent); + }else + { + jvResult["error"] = str(boost::format("Unknown stream: %s") % streamName); + } + }else + { + jvResult["error"] = "malformedSteam"; + } + } + } + + if (jvRequest.isMember("rt_accounts")) + { + boost::unordered_set usnaAccoundIds = parseAccountIds(jvRequest["rt_accounts"]); + + if (usnaAccoundIds.empty()) + { + jvResult["error"] = "malformedAccount"; + }else + { + boost::mutex::scoped_lock sl(mLock); + + BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds) + { + isCurrent->insertSubAccountInfo(naAccountID); + } + + mNetOps->subAccount(isCurrent, usnaAccoundIds, true); + } + } + + if (jvRequest.isMember("accounts")) + { + boost::unordered_set usnaAccoundIds = parseAccountIds(jvRequest["accounts"]); + + if (usnaAccoundIds.empty()) + { + jvResult["error"] = "malformedAccount"; + }else + { + boost::mutex::scoped_lock sl(mLock); + + BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds) + { + isCurrent->insertSubAccountInfo(naAccountID); + } + + mNetOps->subAccount(isCurrent, 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(isCurrent); + }else if(streamName=="ledger") + { + mNetOps->unsubLedger(isCurrent); + }else if(streamName=="transactions") + { + mNetOps->unsubTransactions(isCurrent); + }else if(streamName=="rt_transactions") + { + mNetOps->unsubRTTransactions(isCurrent); + }else + { + jvResult["error"] = str(boost::format("Unknown stream: %s") % streamName); + } + }else + { + jvResult["error"] = "malformedSteam"; + } + } + } + + if (jvRequest.isMember("rt_accounts")) + { + boost::unordered_set usnaAccoundIds = parseAccountIds(jvRequest["rt_accounts"]); + + if (usnaAccoundIds.empty()) + { + jvResult["error"] = "malformedAccount"; + }else + { + boost::mutex::scoped_lock sl(mLock); + + BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds) + { + isCurrent->insertSubAccountInfo(naAccountID); + } + + mNetOps->unsubAccount(isCurrent, usnaAccoundIds,true); + } + } + + if (jvRequest.isMember("accounts")) + { + boost::unordered_set usnaAccoundIds = parseAccountIds(jvRequest["accounts"]); + + if (usnaAccoundIds.empty()) + { + jvResult["error"] = "malformedAccount"; + }else + { + boost::mutex::scoped_lock sl(mLock); + + BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds) + { + isCurrent->insertSubAccountInfo(naAccountID); + } + + mNetOps->unsubAccount(isCurrent, usnaAccoundIds,false); + } + } + + return jvResult; +} + // vim:ts=4 diff --git a/src/cpp/ripple/RPCHandler.h b/src/cpp/ripple/RPCHandler.h index ca71d7baca..90cc0132aa 100644 --- a/src/cpp/ripple/RPCHandler.h +++ b/src/cpp/ripple/RPCHandler.h @@ -6,7 +6,9 @@ class NetworkOPs; class RPCHandler { - NetworkOPs* mNetOps; + NetworkOPs* mNetOps; + InfoSub* isCurrent; + boost::mutex mLock; typedef Json::Value (RPCHandler::*doFuncPtr)(const Json::Value ¶ms); enum { @@ -15,6 +17,9 @@ class RPCHandler optClosed = 4+optNetwork, // Need closed ledger }; + // Utilities + void addSubmitPath(Json::Value& txJSON); + boost::unordered_set parseAccountIds(const Json::Value& jvArray); int getParamCount(const Json::Value& params); bool extractString(std::string& param, const Json::Value& params, int index); @@ -84,8 +89,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 +101,7 @@ public: // Misc failure rpcLOAD_FAILED, rpcNO_PERMISSION, + rpcNO_EVENTS, rpcNOT_STANDALONE, // Networking @@ -152,7 +159,7 @@ public: RPCHandler(NetworkOPs* netOps); - Json::Value doCommand(const std::string& command, Json::Value& params,int role); + Json::Value doCommand(const std::string& command, Json::Value& params, int role, InfoSub* sub = NULL); Json::Value rpcError(int iError); Json::Value handleJSONSubmit(const Json::Value& jvRequest); diff --git a/src/cpp/ripple/WSConnection.cpp b/src/cpp/ripple/WSConnection.cpp index 7037836b16..f06c798a5b 100644 --- a/src/cpp/ripple/WSConnection.cpp +++ b/src/cpp/ripple/WSConnection.cpp @@ -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) - ; - Json::Value jvResult(Json::objectValue); - if (i < 0) + // Regular RPC command + jvResult["result"] = theApp->getRPCHandler().doCommand( + jvRequest["command"].asString(), + jvRequest.isMember("params") + ? jvRequest["params"] + : jvRequest, + mHandler->getPublic() ? RPCHandler::GUEST : RPCHandler::ADMIN, + this); + + // 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 WSConnection::parseAccountIds(const Json::Value& jvArray) -{ - boost::unordered_set 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 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 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 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 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 diff --git a/src/cpp/ripple/WSConnection.h b/src/cpp/ripple/WSConnection.h index 47cdf898b8..2bc4914d4c 100644 --- a/src/cpp/ripple/WSConnection.h +++ b/src/cpp/ripple/WSConnection.h @@ -21,10 +21,6 @@ public: protected: typedef void (WSConnection::*doFuncPtr)(Json::Value& jvResult, Json::Value &jvRequest); - boost::mutex mLock; - boost::unordered_set mSubAccountInfo; - boost::unordered_set mSubAccountTransaction; - WSServerHandler* mHandler; connection_ptr mConnection; NetworkOPs& mNetwork; @@ -44,13 +40,6 @@ public: // Utilities Json::Value invokeCommand(Json::Value& jvRequest); - boost::unordered_set 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); }; diff --git a/src/js/remote.js b/src/js/remote.js index a9433bdda9..c87e9d924c 100644 --- a/src/js/remote.js +++ b/src/js/remote.js @@ -429,10 +429,10 @@ Remote.prototype._connect_message = function (ws, json) { if (!request) { unexpected = true; } - else if ('success' === message.result) { + else if ('success' === message.status) { if (this.trace) console.log("message: %s", json); - request.emit('success', message); + request.emit('success', message.result); } else if (message.error) { if (this.trace) console.log("message: %s", json); @@ -515,7 +515,7 @@ Remote.prototype.request_ledger_hash = function () { var request = new Request(this, 'rpc'); - request.message.rpc_command = 'ledger_closed'; + request.message.command = 'ledger_closed'; return request; }; @@ -525,7 +525,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 +540,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 +593,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,7 +624,7 @@ 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); @@ -658,7 +676,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 +703,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 +733,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 +784,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 +824,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.