| 346 | }; |
| 347 | |
| 348 | static UniValue CallRPC(BaseRequestHandler *rh, const std::string& strMethod, const std::vector<std::string>& args) |
| 349 | { |
| 350 | std::string host; |
| 351 | // In preference order, we choose the following for the port: |
| 352 | // 1. -rpcport |
| 353 | // 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6) |
| 354 | // 3. default port for chain |
| 355 | int port = BaseParams().RPCPort(); |
| 356 | SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host); |
| 357 | port = gArgs.GetArg("-rpcport", port); |
| 358 | |
| 359 | // Obtain event base |
| 360 | raii_event_base base = obtain_event_base(); |
| 361 | |
| 362 | // Synchronously look up hostname |
| 363 | raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port); |
| 364 | evhttp_connection_set_timeout(evcon.get(), gArgs.GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT)); |
| 365 | |
| 366 | HTTPReply response; |
| 367 | raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response); |
| 368 | if (req == nullptr) |
| 369 | throw std::runtime_error("create http request failed"); |
| 370 | #if LIBEVENT_VERSION_NUMBER >= 0x02010300 |
| 371 | evhttp_request_set_error_cb(req.get(), http_error_cb); |
| 372 | #endif |
| 373 | |
| 374 | // Get credentials |
| 375 | std::string strRPCUserColonPass; |
| 376 | bool failedToGetAuthCookie = false; |
| 377 | if (gArgs.GetArg("-rpcpassword", "") == "") { |
| 378 | // Try fall back to cookie-based authentication if no password is provided |
| 379 | if (!GetAuthCookie(&strRPCUserColonPass)) { |
| 380 | failedToGetAuthCookie = true; |
| 381 | } |
| 382 | } else { |
| 383 | strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", ""); |
| 384 | } |
| 385 | |
| 386 | struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get()); |
| 387 | assert(output_headers); |
| 388 | evhttp_add_header(output_headers, "Host", host.c_str()); |
| 389 | evhttp_add_header(output_headers, "Connection", "close"); |
| 390 | evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str()); |
| 391 | |
| 392 | // Attach request data |
| 393 | std::string strRequest = rh->PrepareRequest(strMethod, args).write() + "\n"; |
| 394 | struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get()); |
| 395 | assert(output_buffer); |
| 396 | evbuffer_add(output_buffer, strRequest.data(), strRequest.size()); |
| 397 | |
| 398 | // check if we should use a special wallet endpoint |
| 399 | std::string endpoint = "/"; |
| 400 | if (!gArgs.GetArgs("-rpcwallet").empty()) { |
| 401 | std::string walletName = gArgs.GetArg("-rpcwallet", ""); |
| 402 | char *encodedURI = evhttp_uriencode(walletName.c_str(), walletName.size(), false); |
| 403 | if (encodedURI) { |
| 404 | endpoint = "/wallet/"+ std::string(encodedURI); |
| 405 | free(encodedURI); |
no test coverage detected