Changeset View
Changeset View
Standalone View
Standalone View
src/bitcoin-cli.cpp
Show First 20 Lines • Show All 381 Lines • ▼ Show 20 Lines | public: | ||||
} | } | ||||
UniValue ProcessReply(const UniValue &reply) override { | UniValue ProcessReply(const UniValue &reply) override { | ||||
return reply.get_obj(); | return reply.get_obj(); | ||||
} | } | ||||
}; | }; | ||||
static UniValue CallRPC(BaseRequestHandler *rh, const std::string &strMethod, | static UniValue CallRPC(BaseRequestHandler *rh, const std::string &strMethod, | ||||
const std::vector<std::string> &args) { | const std::vector<std::string> &args, | ||||
const std::optional<std::string> &rpcwallet = {}) { | |||||
std::string host; | std::string host; | ||||
// In preference order, we choose the following for the port: | // In preference order, we choose the following for the port: | ||||
// 1. -rpcport | // 1. -rpcport | ||||
// 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6) | // 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6) | ||||
// 3. default port for chain | // 3. default port for chain | ||||
int port = BaseParams().RPCPort(); | int port = BaseParams().RPCPort(); | ||||
SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host); | SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host); | ||||
port = gArgs.GetArg("-rpcport", port); | port = gArgs.GetArg("-rpcport", port); | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | #endif | ||||
std::string strRequest = rh->PrepareRequest(strMethod, args).write() + "\n"; | std::string strRequest = rh->PrepareRequest(strMethod, args).write() + "\n"; | ||||
struct evbuffer *output_buffer = | struct evbuffer *output_buffer = | ||||
evhttp_request_get_output_buffer(req.get()); | evhttp_request_get_output_buffer(req.get()); | ||||
assert(output_buffer); | assert(output_buffer); | ||||
evbuffer_add(output_buffer, strRequest.data(), strRequest.size()); | evbuffer_add(output_buffer, strRequest.data(), strRequest.size()); | ||||
// check if we should use a special wallet endpoint | // check if we should use a special wallet endpoint | ||||
std::string endpoint = "/"; | std::string endpoint = "/"; | ||||
if (!gArgs.GetArgs("-rpcwallet").empty()) { | if (rpcwallet) { | ||||
std::string walletName = gArgs.GetArg("-rpcwallet", ""); | |||||
char *encodedURI = | char *encodedURI = | ||||
evhttp_uriencode(walletName.data(), walletName.size(), false); | evhttp_uriencode(rpcwallet->data(), rpcwallet->size(), false); | ||||
if (encodedURI) { | if (encodedURI) { | ||||
endpoint = "/wallet/" + std::string(encodedURI); | endpoint = "/wallet/" + std::string(encodedURI); | ||||
free(encodedURI); | free(encodedURI); | ||||
} else { | } else { | ||||
throw CConnectionFailed("uri-encode failed"); | throw CConnectionFailed("uri-encode failed"); | ||||
} | } | ||||
} | } | ||||
int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, | int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | #endif | ||||
return reply; | return reply; | ||||
} | } | ||||
/** | /** | ||||
* ConnectAndCallRPC wraps CallRPC with -rpcwait and an exception handler. | * ConnectAndCallRPC wraps CallRPC with -rpcwait and an exception handler. | ||||
* | * | ||||
* @param[in] rh Pointer to RequestHandler. | * @param[in] rh Pointer to RequestHandler. | ||||
* @param[in] strMethod Reference to const string method to forward to CallRPC. | * @param[in] strMethod Reference to const string method to forward to CallRPC. | ||||
* @param[in] rpcwallet Reference to const optional string wallet name to | |||||
* forward to CallRPC. | |||||
* @returns the RPC response as a UniValue object. | * @returns the RPC response as a UniValue object. | ||||
* @throws a CConnectionFailed std::runtime_error if connection failed or RPC | * @throws a CConnectionFailed std::runtime_error if connection failed or RPC | ||||
* server still in warmup. | * server still in warmup. | ||||
*/ | */ | ||||
static UniValue ConnectAndCallRPC(BaseRequestHandler *rh, | static UniValue | ||||
const std::string &strMethod, | ConnectAndCallRPC(BaseRequestHandler *rh, const std::string &strMethod, | ||||
const std::vector<std::string> &args) { | const std::vector<std::string> &args, | ||||
const std::optional<std::string> &rpcwallet = {}) { | |||||
UniValue response(UniValue::VOBJ); | UniValue response(UniValue::VOBJ); | ||||
// Execute and handle connection failures with -rpcwait. | // Execute and handle connection failures with -rpcwait. | ||||
const bool fWait = gArgs.GetBoolArg("-rpcwait", false); | const bool fWait = gArgs.GetBoolArg("-rpcwait", false); | ||||
do { | do { | ||||
try { | try { | ||||
response = CallRPC(rh, strMethod, args); | response = CallRPC(rh, strMethod, args, rpcwallet); | ||||
if (fWait) { | if (fWait) { | ||||
const UniValue &error = find_value(response, "error"); | const UniValue &error = find_value(response, "error"); | ||||
if (!error.isNull() && | if (!error.isNull() && | ||||
error["code"].get_int() == RPC_IN_WARMUP) { | error["code"].get_int() == RPC_IN_WARMUP) { | ||||
throw CConnectionFailed("server in warmup"); | throw CConnectionFailed("server in warmup"); | ||||
} | } | ||||
} | } | ||||
break; // Connection succeeded, no need to retry. | break; // Connection succeeded, no need to retry. | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | try { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"too few parameters (need at least command)"); | "too few parameters (need at least command)"); | ||||
} | } | ||||
method = args[0]; | method = args[0]; | ||||
// Remove trailing method name from arguments vector | // Remove trailing method name from arguments vector | ||||
args.erase(args.begin()); | args.erase(args.begin()); | ||||
} | } | ||||
const UniValue reply = ConnectAndCallRPC(rh.get(), method, args); | std::optional<std::string> wallet_name{}; | ||||
if (gArgs.IsArgSet("-rpcwallet")) { | |||||
wallet_name = gArgs.GetArg("-rpcwallet", ""); | |||||
} | |||||
const UniValue reply = | |||||
ConnectAndCallRPC(rh.get(), method, args, wallet_name); | |||||
// Parse reply | // Parse reply | ||||
UniValue result = find_value(reply, "result"); | UniValue result = find_value(reply, "result"); | ||||
const UniValue &error = find_value(reply, "error"); | const UniValue &error = find_value(reply, "error"); | ||||
if (!error.isNull()) { | if (!error.isNull()) { | ||||
// Error | // Error | ||||
strPrint = "error: " + error.write(); | strPrint = "error: " + error.write(); | ||||
nRet = abs(error["code"].get_int()); | nRet = abs(error["code"].get_int()); | ||||
▲ Show 20 Lines • Show All 75 Lines • Show Last 20 Lines |