| 172 | #endif |
| 173 | |
| 174 | UniValue CallRPC(const string& strMethod, const UniValue& params) |
| 175 | { |
| 176 | std::string host = GetArg("-rpcconnect", "127.0.0.1"); |
| 177 | int port = GetArg("-rpcport", BaseParams().RPCPort()); |
| 178 | |
| 179 | // Obtain event base |
| 180 | raii_event_base base = obtain_event_base(); |
| 181 | |
| 182 | // Synchronously look up hostname |
| 183 | raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port); |
| 184 | evhttp_connection_set_timeout(evcon.get(), GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT)); |
| 185 | |
| 186 | HTTPReply response; |
| 187 | raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response); |
| 188 | if (req == NULL) |
| 189 | throw runtime_error("create http request failed"); |
| 190 | #if LIBEVENT_VERSION_NUMBER >= 0x02010300 |
| 191 | evhttp_request_set_error_cb(req.get(), http_error_cb); |
| 192 | #endif |
| 193 | |
| 194 | // Get credentials |
| 195 | std::string strRPCUserColonPass; |
| 196 | if (mapArgs["-rpcpassword"] == "") { |
| 197 | throw runtime_error(strprintf( |
| 198 | _("rpcpassword is not set in the configuration file (%s)"), |
| 199 | GetConfigFile().string().c_str())); |
| 200 | } else { |
| 201 | strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; |
| 202 | } |
| 203 | |
| 204 | struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get()); |
| 205 | assert(output_headers); |
| 206 | evhttp_add_header(output_headers, "Host", host.c_str()); |
| 207 | evhttp_add_header(output_headers, "Connection", "close"); |
| 208 | evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str()); |
| 209 | |
| 210 | // Attach request data |
| 211 | std::string strRequest = JSONRPCRequest(strMethod, params, 1); |
| 212 | struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get()); |
| 213 | assert(output_buffer); |
| 214 | evbuffer_add(output_buffer, strRequest.data(), strRequest.size()); |
| 215 | |
| 216 | int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, "/"); |
| 217 | req.release(); // ownership moved to evcon in above call |
| 218 | if (r != 0) { |
| 219 | throw CConnectionFailed("send http request failed"); |
| 220 | } |
| 221 | |
| 222 | event_base_dispatch(base.get()); |
| 223 | |
| 224 | if (response.status == 0) |
| 225 | 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)); |
| 226 | else if (response.status == HTTP_UNAUTHORIZED) |
| 227 | throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); |
| 228 | else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR) |
| 229 | throw runtime_error(strprintf("server returned HTTP error %d", response.status)); |
| 230 | else if (response.body.empty()) |
| 231 | throw runtime_error("no response from server"); |
no test coverage detected