mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-16 13:01:19 +02:00
MOVEONLY: Move CallRPC into its own file
This commit is contained in:
parent
6939698bc5
commit
4f9ed185b8
4 changed files with 159 additions and 134 deletions
|
|
@ -3,6 +3,7 @@
|
|||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "callrpc.h"
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
|
@ -16,19 +17,10 @@
|
|||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <event2/http.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/keyvalq_struct.h>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
|
||||
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
|
||||
|
||||
std::string HelpMessageCli()
|
||||
{
|
||||
const boost::scoped_ptr<CBaseChainParams> defaultBaseParams(CBaseChainParams::Factory(CBaseChainParams::MAIN));
|
||||
|
|
@ -54,20 +46,6 @@ std::string HelpMessageCli()
|
|||
// Start
|
||||
//
|
||||
|
||||
//
|
||||
// Exception thrown on connection error. This error is used to determine
|
||||
// when to wait if -rpcwait is given.
|
||||
//
|
||||
class CConnectionFailed : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
|
||||
explicit inline CConnectionFailed(const std::string& msg) :
|
||||
std::runtime_error(msg)
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
static bool AppInitRPC(int argc, char* argv[])
|
||||
{
|
||||
//
|
||||
|
|
@ -113,117 +91,6 @@ static bool AppInitRPC(int argc, char* argv[])
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/** Reply structure for request_done to fill in */
|
||||
struct HTTPReply
|
||||
{
|
||||
int status;
|
||||
std::string body;
|
||||
};
|
||||
|
||||
static void http_request_done(struct evhttp_request *req, void *ctx)
|
||||
{
|
||||
HTTPReply *reply = static_cast<HTTPReply*>(ctx);
|
||||
|
||||
if (req == NULL) {
|
||||
/* If req is NULL, it means an error occurred while connecting, but
|
||||
* I'm not sure how to find out which one. We also don't really care.
|
||||
*/
|
||||
reply->status = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
reply->status = evhttp_request_get_response_code(req);
|
||||
|
||||
struct evbuffer *buf = evhttp_request_get_input_buffer(req);
|
||||
if (buf)
|
||||
{
|
||||
size_t size = evbuffer_get_length(buf);
|
||||
const char *data = (const char*)evbuffer_pullup(buf, size);
|
||||
if (data)
|
||||
reply->body = std::string(data, size);
|
||||
evbuffer_drain(buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
UniValue CallRPC(const string& strMethod, const UniValue& params)
|
||||
{
|
||||
std::string host = GetArg("-rpcconnect", DEFAULT_RPCCONNECT);
|
||||
int port = GetArg("-rpcport", BaseParams().RPCPort());
|
||||
|
||||
// Create event base
|
||||
struct event_base *base = event_base_new(); // TODO RAII
|
||||
if (!base)
|
||||
throw runtime_error("cannot create event_base");
|
||||
|
||||
// Synchronously look up hostname
|
||||
struct evhttp_connection *evcon = evhttp_connection_base_new(base, NULL, host.c_str(), port); // TODO RAII
|
||||
if (evcon == NULL)
|
||||
throw runtime_error("create connection failed");
|
||||
evhttp_connection_set_timeout(evcon, GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT));
|
||||
|
||||
HTTPReply response;
|
||||
struct evhttp_request *req = evhttp_request_new(http_request_done, (void*)&response); // TODO RAII
|
||||
if (req == NULL)
|
||||
throw runtime_error("create http request failed");
|
||||
|
||||
// Get credentials
|
||||
std::string strRPCUserColonPass;
|
||||
if (mapArgs["-rpcpassword"] == "") {
|
||||
// Try fall back to cookie-based authentication if no password is provided
|
||||
if (!GetAuthCookie(&strRPCUserColonPass)) {
|
||||
throw runtime_error(strprintf(
|
||||
_("Could not locate RPC credentials. No authentication cookie could be found, and no rpcpassword is set in the configuration file (%s)"),
|
||||
GetConfigFile().string().c_str()));
|
||||
|
||||
}
|
||||
} else {
|
||||
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
|
||||
}
|
||||
|
||||
struct evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
|
||||
assert(output_headers);
|
||||
evhttp_add_header(output_headers, "Host", host.c_str());
|
||||
evhttp_add_header(output_headers, "Connection", "close");
|
||||
evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str());
|
||||
|
||||
// Attach request data
|
||||
std::string strRequest = JSONRPCRequest(strMethod, params, 1);
|
||||
struct evbuffer * output_buffer = evhttp_request_get_output_buffer(req);
|
||||
assert(output_buffer);
|
||||
evbuffer_add(output_buffer, strRequest.data(), strRequest.size());
|
||||
|
||||
int r = evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/");
|
||||
if (r != 0) {
|
||||
evhttp_connection_free(evcon);
|
||||
event_base_free(base);
|
||||
throw CConnectionFailed("send http request failed");
|
||||
}
|
||||
|
||||
event_base_dispatch(base);
|
||||
evhttp_connection_free(evcon);
|
||||
event_base_free(base);
|
||||
|
||||
if (response.status == 0)
|
||||
throw CConnectionFailed("couldn't connect to server");
|
||||
else if (response.status == HTTP_UNAUTHORIZED)
|
||||
throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
|
||||
else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
|
||||
throw runtime_error(strprintf("server returned HTTP error %d", response.status));
|
||||
else if (response.body.empty())
|
||||
throw runtime_error("no response from server");
|
||||
|
||||
// Parse reply
|
||||
UniValue valReply(UniValue::VSTR);
|
||||
if (!valReply.read(response.body))
|
||||
throw runtime_error("couldn't parse reply from server");
|
||||
const UniValue& reply = valReply.get_obj();
|
||||
if (reply.empty())
|
||||
throw runtime_error("expected reply to have result, error and id properties");
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
int CommandLineRPC(int argc, char *argv[])
|
||||
{
|
||||
string strPrint;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue