| 79 | #endif |
| 80 | |
| 81 | UniValue CallMainChainRPC(const std::string& strMethod, const UniValue& params) |
| 82 | { |
| 83 | std::string host = gArgs.GetArg("-mainchainrpchost", DEFAULT_RPCCONNECT); |
| 84 | int port = gArgs.GetIntArg("-mainchainrpcport", BaseParams().MainchainRPCPort()); |
| 85 | |
| 86 | // Obtain event base |
| 87 | raii_event_base base = obtain_event_base(); |
| 88 | |
| 89 | // Synchronously look up hostname |
| 90 | raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port); |
| 91 | evhttp_connection_set_timeout(evcon.get(), gArgs.GetIntArg("-mainchainrpctimeout", DEFAULT_HTTP_CLIENT_TIMEOUT)); |
| 92 | |
| 93 | HTTPReply response; |
| 94 | raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response); |
| 95 | if (req == NULL) |
| 96 | throw std::runtime_error("create http request failed"); |
| 97 | #if LIBEVENT_VERSION_NUMBER >= 0x02010300 |
| 98 | evhttp_request_set_error_cb(req.get(), http_error_cb); |
| 99 | #endif |
| 100 | |
| 101 | // Get credentials |
| 102 | std::string strRPCUserColonPass; |
| 103 | if (gArgs.GetArg("-mainchainrpcpassword", "") == "") { |
| 104 | // Try fall back to cookie-based authentication if no password is provided |
| 105 | if (!GetMainchainAuthCookie(&strRPCUserColonPass)) { |
| 106 | throw std::runtime_error(strprintf( |
| 107 | _("Could not locate mainchain RPC credentials. No authentication cookie could be found, and no mainchainrpcpassword is set in the configuration file (%s)").translated, |
| 108 | gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME).c_str())); |
| 109 | } |
| 110 | } else { |
| 111 | strRPCUserColonPass = gArgs.GetArg("-mainchainrpcuser", "") + ":" + gArgs.GetArg("-mainchainrpcpassword", ""); |
| 112 | } |
| 113 | |
| 114 | struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get()); |
| 115 | assert(output_headers); |
| 116 | evhttp_add_header(output_headers, "Host", host.c_str()); |
| 117 | evhttp_add_header(output_headers, "Connection", "close"); |
| 118 | evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str()); |
| 119 | |
| 120 | // Attach request data |
| 121 | std::string strRequest = JSONRPCRequestObj(strMethod, params, 1).write() + "\n"; |
| 122 | struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get()); |
| 123 | assert(output_buffer); |
| 124 | evbuffer_add(output_buffer, strRequest.data(), strRequest.size()); |
| 125 | |
| 126 | int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, "/"); |
| 127 | req.release(); // ownership moved to evcon in above call |
| 128 | if (r != 0) { |
| 129 | throw CConnectionFailed("send http request failed"); |
| 130 | } |
| 131 | |
| 132 | event_base_dispatch(base.get()); |
| 133 | |
| 134 | if (response.status == 0) |
| 135 | throw CConnectionFailed(strprintf("couldn't connect to server: %s (code %d)\n(make sure server is running and you are connecting to the correct RPC port)", http_errorstring(response.error), response.error)); |
| 136 | else if (response.status == HTTP_UNAUTHORIZED) |
| 137 | throw std::runtime_error("incorrect mainchainrpcuser or mainchainrpcpassword (authorization failed)"); |
| 138 | else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR) |
no test coverage detected