diff --git a/src/cpp/ripple/CallRPC.cpp b/src/cpp/ripple/CallRPC.cpp index 50cd485fd..b84d3ee5b 100644 --- a/src/cpp/ripple/CallRPC.cpp +++ b/src/cpp/ripple/CallRPC.cpp @@ -1,3 +1,9 @@ +// +// This a trusted interface, the user is expected to provide valid input to perform valid requests. +// Error catching and reporting is not a requirement of this command line interface. +// +// Improvements to be more strict and to provide better diagnostics are welcome. +// #include #include @@ -9,6 +15,7 @@ #include #include #include +#include #include #include @@ -55,6 +62,63 @@ std::string EncodeBase64(const std::string& s) return result; } +// TODO New routine for parsing ledger parameters, other routines should standardize on this. +static bool jvParseLedger(Json::Value& jvRequest, const std::string& strLedger) +{ + if (strLedger == "closed") + { + jvRequest["ledger_index"] = -1; + } + else if (strLedger == "current") + { + jvRequest["ledger_index"] = -2; + } + else if (strLedger == "validated") + { + jvRequest["ledger_index"] = -3; + } + else if (strLedger.length() > 12) + { + // YYY Could confirm this is a uint256. + jvRequest["ledger_hash"] = strLedger; + } + else + { + jvRequest["ledger_index"] = lexical_cast_s(strLedger); + } + + return true; +} + +// Build a object { "currency" : "XYZ", "issuer" : "rXYX" } +static Json::Value jvParseCurrencyIssuer(const std::string& strCurrencyIssuer) +{ + static boost::regex reCurIss("\\`([[:alpha:]]{3})(?:/(.+))?\\'"); + + boost::smatch smMatch; + + if (boost::regex_match(strCurrencyIssuer, smMatch, reCurIss)) + { + Json::Value jvResult(Json::objectValue); + std::string strCurrency = smMatch[1]; + std::string strIssuer = smMatch[2]; + + jvResult["currency"] = strCurrency; + + if (strIssuer.length()) + { + // Could confirm issuer is a valid Ripple address. + jvResult["issuer"] = strIssuer; + } + + return jvResult; + } + else + { + return rpcError(rpcINVALID_PARAMS); + } +} + Json::Value RPCParser::parseAsIs(const Json::Value& jvParams) { Json::Value v(Json::objectValue); @@ -145,6 +209,51 @@ Json::Value RPCParser::parseAccountTransactions(const Json::Value& jvParams) return jvRequest; } +// book_offers [ ] +// +// Mnemonic: taker puts --> offer --> taker gets +Json::Value RPCParser::parseBookOffers(const Json::Value& jvParams) +{ + Json::Value jvRequest(Json::objectValue); + + Json::Value jvTakerPuts = jvParseCurrencyIssuer(jvParams[0u].asString()); + Json::Value jvTakerGets = jvParseCurrencyIssuer(jvParams[1u].asString()); + + if (isRpcError(jvTakerPuts)) + { + return jvTakerPuts; + } + else + { + jvRequest["taker_puts"] = jvTakerPuts; + } + + if (isRpcError(jvTakerGets)) + { + return jvTakerGets; + } + else + { + jvRequest["taker_gets"] = jvTakerGets; + } + + if (!jvParseLedger(jvRequest, jvParams[2u].asString())) + return jvRequest; + + if (jvParams.size() >= 4) + { + int iLimit = jvParams[3u].asInt(); + + if (iLimit > 0) + jvRequest["limit"] = iLimit; + } + + if (jvParams.size() == 5) + jvRequest["marker"] = jvParams[4u]; + + return jvRequest; +} + // connect [port] Json::Value RPCParser::parseConnect(const Json::Value& jvParams) { @@ -509,11 +618,11 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams) // Request-response methods // - Returns an error, or the request. // - To modify the method, provide a new method in the request. - { "accept_ledger", &RPCParser::parseAsIs, 0, 0 }, { "account_info", &RPCParser::parseAccountInfo, 1, 2 }, { "account_lines", &RPCParser::parseAccountItems, 1, 2 }, { "account_offers", &RPCParser::parseAccountItems, 1, 2 }, { "account_tx", &RPCParser::parseAccountTransactions, 2, 4 }, + { "book_offers", &RPCParser::parseBookOffers, 3, 5 }, { "connect", &RPCParser::parseConnect, 1, 2 }, { "consensus_info", &RPCParser::parseAsIs, 0, 0 }, { "get_counts", &RPCParser::parseGetCounts, 0, 1 }, @@ -622,7 +731,7 @@ int commandLineRPC(const std::vector& vCmd) jvRequest = rpParser.parseCommand(vCmd[0], jvRpcParams); - // std::cerr << "Request: " << jvRequest << std::endl; + cLog(lsTRACE) << "RPC Request: " << jvRequest << std::endl; if (jvRequest.isMember("error")) { @@ -756,6 +865,8 @@ bool responseRPC( // Build the request. void requestRPC(const std::string& strMethod, const Json::Value& jvParams, const std::map& mHeaders, const std::string& strPath, boost::asio::streambuf& sb, const std::string& strHost) { + cLog(lsDEBUG) << "requestRPC: strPath='" << strPath << "'"; + std::ostream osRequest(&sb); osRequest << @@ -804,7 +915,7 @@ void callRPC( strMethod, jvParams, mapRequestHeaders, - "/", _1, _2), + strPath, _1, _2), RPC_REPLY_MAX_BYTES, boost::posix_time::seconds(RPC_NOTIFY_SECONDS), boost::bind(&responseRPC, callbackFuncP, _1, _2, _3)); diff --git a/src/cpp/ripple/CallRPC.h b/src/cpp/ripple/CallRPC.h index 11cf51812..adde89f70 100644 --- a/src/cpp/ripple/CallRPC.h +++ b/src/cpp/ripple/CallRPC.h @@ -14,6 +14,7 @@ protected: Json::Value parseAccountItems(const Json::Value& jvParams); Json::Value parseAccountTransactions(const Json::Value& jvParams); Json::Value parseAsIs(const Json::Value& jvParams); + Json::Value parseBookOffers(const Json::Value& jvParams); Json::Value parseConnect(const Json::Value& jvParams); #if ENABLE_INSECURE Json::Value parseDataDelete(const Json::Value& jvParams); diff --git a/src/cpp/ripple/RPCErr.cpp b/src/cpp/ripple/RPCErr.cpp index 9e06a5d9d..de5b0a165 100644 --- a/src/cpp/ripple/RPCErr.cpp +++ b/src/cpp/ripple/RPCErr.cpp @@ -88,4 +88,9 @@ Json::Value rpcError(int iError, Json::Value jvResult) return jvResult; } +bool isRpcError(Json::Value jvResult) +{ + return jvResult.isObject() && jvResult.isMember("error"); +} + // vim:ts=4 diff --git a/src/cpp/ripple/RPCErr.h b/src/cpp/ripple/RPCErr.h index 8aa371328..f1f4da097 100644 --- a/src/cpp/ripple/RPCErr.h +++ b/src/cpp/ripple/RPCErr.h @@ -77,6 +77,8 @@ enum { rpcNO_GEN_DECRPYT, }; +bool isRpcError(Json::Value jvResult); Json::Value rpcError(int iError, Json::Value jvResult=Json::Value(Json::objectValue)); + #endif // vim:ts=4 diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 215d239ce..ee8a4f468 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -558,18 +558,6 @@ Json::Value RPCHandler::accountFromString(Ledger::ref lrLedger, RippleAddress& n return Json::Value(Json::objectValue); } -Json::Value RPCHandler::doAcceptLedger(Json::Value jvRequest) -{ - if (!theConfig.RUN_STANDALONE) - return rpcError(rpcNOT_STANDALONE); - - Json::Value jvResult(Json::objectValue); - - jvResult["newLedger"] = theApp->getOPs().acceptLedger(); - - return jvResult; -} - // { // ident : , // account_index : // optional @@ -2807,7 +2795,6 @@ Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole) unsigned int iOptions; } commandsA[] = { // Request-response methods - { "accept_ledger", &RPCHandler::doAcceptLedger, true, optCurrent }, { "account_info", &RPCHandler::doAccountInfo, false, optCurrent }, { "account_lines", &RPCHandler::doAccountLines, false, optCurrent }, { "account_offers", &RPCHandler::doAccountOffers, false, optCurrent }, diff --git a/src/cpp/ripple/RPCHandler.h b/src/cpp/ripple/RPCHandler.h index 47e30c208..ac49c05f1 100644 --- a/src/cpp/ripple/RPCHandler.h +++ b/src/cpp/ripple/RPCHandler.h @@ -43,8 +43,6 @@ class RPCHandler Json::Value accountFromString(Ledger::ref lrLedger, RippleAddress& naAccount, bool& bIndex, const std::string& strIdent, const int iIndex, const bool bStrict); - Json::Value doAcceptLedger(Json::Value jvRequest); - Json::Value doAccountInfo(Json::Value params); Json::Value doAccountLines(Json::Value params); Json::Value doAccountOffers(Json::Value params); diff --git a/src/cpp/ripple/RPCSub.cpp b/src/cpp/ripple/RPCSub.cpp index 2a6ac6af8..779cff0ed 100644 --- a/src/cpp/ripple/RPCSub.cpp +++ b/src/cpp/ripple/RPCSub.cpp @@ -29,6 +29,12 @@ RPCSub::RPCSub(const std::string& strUrl, const std::string& strUsername, const if (mPort < 0) mPort = mSSL ? 443 : 80; + + cLog(lsINFO) << boost::str(boost::format("callRPC sub: ip='%s' port=%d ssl=%d path='%s'") + % mIp + % mPort + % mSSL + % mPath); } // XXX Could probably create a bunch of send jobs in a single get of the lock. diff --git a/src/cpp/ripple/main.cpp b/src/cpp/ripple/main.cpp index 80e55a7e3..1444b1a91 100644 --- a/src/cpp/ripple/main.cpp +++ b/src/cpp/ripple/main.cpp @@ -51,7 +51,6 @@ void startServer() theApp->run(); // Blocks till we get a stop RPC. } - bool init_unit_test() { theApp = new Application(); @@ -66,34 +65,30 @@ void printHelp(const po::options_description& desc) cerr << desc << endl; cerr << "Commands: " << endl; - cerr << " account_domain_set []" << endl; - cerr << " account_email_set []" << endl; - cerr << " account_tx || |( )" << endl; - cerr << " account_lines || []" << endl; - cerr << " account_offers || []" << endl; cerr << " account_info |" << endl; cerr << " account_info || []" << endl; - cerr << " account_message_set " << endl; - cerr << " account_publish_set " << endl; - cerr << " account_rate_set " << endl; - cerr << " account_wallet_set []" << endl; + cerr << " account_lines || []" << endl; + cerr << " account_offers || []" << endl; + cerr << " account_tx || |( )" << endl; + cerr << " book_offers [ ]" << endl; cerr << " connect []" << endl; + cerr << " consensus_info" << endl; +#if ENABLE_INSECURE cerr << " data_delete " << endl; cerr << " data_fetch " << endl; cerr << " data_store " << endl; +#endif + cerr << " get_counts" << endl; cerr << " ledger [|current|lastclosed] [full]" << endl; + cerr << " ledger_accept" << endl; + cerr << " ledger_closed" << endl; + cerr << " ledger_current" << endl; + cerr << " ledger_header " << endl; cerr << " logrotate " << endl; - cerr << " nickname_info " << endl; - cerr << " nickname_set [] []" << endl; - cerr << " offer_create [passive]" << endl; - cerr << " offer_cancel " << endl; - cerr << " password_fund []" << endl; - cerr << " password_set []" << endl; cerr << " peers" << endl; cerr << " random" << endl; cerr << " ripple ..." << endl; -// cerr << " ripple_line_set [] []" << endl; - cerr << " send [] [] []" << endl; +// cerr << " send [] [] []" << endl; cerr << " stop" << endl; cerr << " tx " << endl; cerr << " unl_add | []" << endl; @@ -109,6 +104,19 @@ void printHelp(const po::options_description& desc) cerr << " wallet_claim [] []" << endl; cerr << " wallet_seed [||]" << endl; cerr << " wallet_propose []" << endl; + +// Transaction helpers (that were removed): +// cerr << " account_domain_set []" << endl; +// cerr << " account_email_set []" << endl; +// cerr << " account_rate_set " << endl; +// cerr << " account_wallet_set []" << endl; +// cerr << " nickname_info " << endl; +// cerr << " nickname_set [] []" << endl; +// cerr << " offer_create [passive]" << endl; +// cerr << " offer_cancel " << endl; +// cerr << " password_fund []" << endl; +// cerr << " password_set []" << endl; +// cerr << " trust_set [] []" << endl; } int main(int argc, char* argv[])