2013-10-11 23:09:59 +02:00
|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
2014-12-17 02:47:57 +01:00
|
|
|
// Copyright (c) 2009-2013 The Bitcoin Core developers
|
2014-12-13 05:09:33 +01:00
|
|
|
// Distributed under the MIT software license, see the accompanying
|
2013-10-11 23:09:59 +02:00
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
2014-09-14 12:43:56 +02:00
|
|
|
#include "chainparamsbase.h"
|
2014-10-29 02:33:23 +01:00
|
|
|
#include "clientversion.h"
|
2013-11-20 14:18:57 +01:00
|
|
|
#include "rpcclient.h"
|
2014-02-24 14:08:56 +01:00
|
|
|
#include "rpcprotocol.h"
|
2014-09-14 12:43:56 +02:00
|
|
|
#include "util.h"
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
#include "utilstrencodings.h"
|
2013-10-11 23:09:59 +02:00
|
|
|
|
2013-04-13 07:13:08 +02:00
|
|
|
#include <boost/filesystem/operations.hpp>
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <event2/event.h>
|
|
|
|
#include <event2/http.h>
|
|
|
|
#include <event2/buffer.h>
|
|
|
|
#include <event2/keyvalq_struct.h>
|
2013-04-13 07:13:08 +02:00
|
|
|
|
2015-09-04 16:11:34 +02:00
|
|
|
#include <univalue.h>
|
2015-05-18 14:02:18 +02:00
|
|
|
|
2014-06-16 16:30:38 +02:00
|
|
|
using namespace std;
|
2014-05-26 11:38:44 +02:00
|
|
|
|
2015-09-18 15:45:38 +02:00
|
|
|
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
|
|
|
|
|
2014-05-26 11:38:44 +02:00
|
|
|
std::string HelpMessageCli()
|
|
|
|
{
|
|
|
|
string strUsage;
|
2015-02-04 09:11:49 +01:00
|
|
|
strUsage += HelpMessageGroup(_("Options:"));
|
|
|
|
strUsage += HelpMessageOpt("-?", _("This help message"));
|
|
|
|
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf"));
|
|
|
|
strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
|
2015-05-25 09:00:17 +02:00
|
|
|
AppendParamsHelpMessages(strUsage);
|
2015-02-04 09:11:49 +01:00
|
|
|
strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), "127.0.0.1"));
|
|
|
|
strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), 8332, 18332));
|
|
|
|
strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
|
|
|
|
strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
|
|
|
|
strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
|
2015-09-18 15:45:38 +02:00
|
|
|
strUsage += HelpMessageOpt("-rpcclienttimeout=<n>", strprintf(_("Timeout during HTTP requests (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT));
|
2014-05-26 11:38:44 +02:00
|
|
|
|
|
|
|
return strUsage;
|
|
|
|
}
|
|
|
|
|
2013-10-11 23:09:59 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Start
|
|
|
|
//
|
2014-10-29 18:08:31 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// 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)
|
|
|
|
{}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2013-10-11 23:09:59 +02:00
|
|
|
static bool AppInitRPC(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Parameters
|
|
|
|
//
|
|
|
|
ParseParameters(argc, argv);
|
2015-10-18 12:02:36 +02:00
|
|
|
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) {
|
2014-11-22 19:56:25 +01:00
|
|
|
std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n";
|
|
|
|
if (!mapArgs.count("-version")) {
|
|
|
|
strUsage += "\n" + _("Usage:") + "\n" +
|
|
|
|
" bitcoin-cli [options] <command> [params] " + _("Send command to Bitcoin Core") + "\n" +
|
|
|
|
" bitcoin-cli [options] help " + _("List commands") + "\n" +
|
|
|
|
" bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n";
|
|
|
|
|
|
|
|
strUsage += "\n" + HelpMessageCli();
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stdout, "%s", strUsage.c_str());
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-26 03:09:36 +02:00
|
|
|
if (!boost::filesystem::is_directory(GetDataDir(false))) {
|
2013-10-11 23:09:59 +02:00
|
|
|
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
|
|
|
|
return false;
|
|
|
|
}
|
2014-04-07 10:10:01 +02:00
|
|
|
try {
|
|
|
|
ReadConfigFile(mapArgs, mapMultiArgs);
|
2014-12-07 13:29:06 +01:00
|
|
|
} catch (const std::exception& e) {
|
2014-04-07 10:10:01 +02:00
|
|
|
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-19 15:10:04 +02:00
|
|
|
// Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
|
2015-05-25 09:00:17 +02:00
|
|
|
try {
|
|
|
|
SelectBaseParams(ChainNameFromCommandLine());
|
|
|
|
} catch(std::exception &e) {
|
|
|
|
fprintf(stderr, "Error: %s\n", e.what());
|
2013-11-28 17:28:27 +01:00
|
|
|
return false;
|
|
|
|
}
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
if (GetBoolArg("-rpcssl", false))
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Error: SSL mode for RPC (-rpcssl) is no longer supported.\n");
|
|
|
|
return false;
|
|
|
|
}
|
2013-10-11 23:09:59 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
|
|
|
|
/** Reply structure for request_done to fill in */
|
|
|
|
struct HTTPReply
|
2014-05-26 11:38:44 +02:00
|
|
|
{
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
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;
|
|
|
|
}
|
2014-05-26 11:38:44 +02:00
|
|
|
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
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", "127.0.0.1");
|
|
|
|
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");
|
2015-09-18 15:45:38 +02:00
|
|
|
evhttp_connection_set_timeout(evcon, GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT));
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
|
|
|
|
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
|
2015-07-07 14:53:48 +02:00
|
|
|
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(
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
_("Could not locate RPC credentials. No authentication cookie could be found, and no rpcpassword is set in the configuration file (%s)"),
|
2015-07-07 14:53:48 +02:00
|
|
|
GetConfigFile().string().c_str()));
|
|
|
|
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
|
|
|
|
}
|
|
|
|
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
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");
|
|
|
|
}
|
2014-05-26 11:38:44 +02:00
|
|
|
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
event_base_dispatch(base);
|
|
|
|
evhttp_connection_free(evcon);
|
|
|
|
event_base_free(base);
|
2014-05-26 11:38:44 +02:00
|
|
|
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
if (response.status == 0)
|
|
|
|
throw CConnectionFailed("couldn't connect to server");
|
|
|
|
else if (response.status == HTTP_UNAUTHORIZED)
|
2014-05-26 11:38:44 +02:00
|
|
|
throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
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())
|
2014-05-26 11:38:44 +02:00
|
|
|
throw runtime_error("no response from server");
|
|
|
|
|
|
|
|
// Parse reply
|
2015-05-13 21:29:19 +02:00
|
|
|
UniValue valReply(UniValue::VSTR);
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
if (!valReply.read(response.body))
|
2014-05-26 11:38:44 +02:00
|
|
|
throw runtime_error("couldn't parse reply from server");
|
2015-05-18 14:02:18 +02:00
|
|
|
const UniValue& reply = valReply.get_obj();
|
2014-05-26 11:38:44 +02:00
|
|
|
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;
|
|
|
|
int nRet = 0;
|
2014-06-26 03:09:36 +02:00
|
|
|
try {
|
2014-05-26 11:38:44 +02:00
|
|
|
// Skip switches
|
2014-06-26 03:09:36 +02:00
|
|
|
while (argc > 1 && IsSwitchChar(argv[1][0])) {
|
2014-05-26 11:38:44 +02:00
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method
|
|
|
|
if (argc < 2)
|
|
|
|
throw runtime_error("too few parameters");
|
|
|
|
string strMethod = argv[1];
|
|
|
|
|
|
|
|
// Parameters default to strings
|
|
|
|
std::vector<std::string> strParams(&argv[2], &argv[argc]);
|
2015-05-13 21:29:19 +02:00
|
|
|
UniValue params = RPCConvertValues(strMethod, strParams);
|
2014-05-26 11:38:44 +02:00
|
|
|
|
2014-10-29 18:08:31 +01:00
|
|
|
// Execute and handle connection failures with -rpcwait
|
|
|
|
const bool fWait = GetBoolArg("-rpcwait", false);
|
|
|
|
do {
|
|
|
|
try {
|
2015-05-13 21:29:19 +02:00
|
|
|
const UniValue reply = CallRPC(strMethod, params);
|
2014-10-29 18:08:31 +01:00
|
|
|
|
|
|
|
// Parse reply
|
2015-05-18 14:02:18 +02:00
|
|
|
const UniValue& result = find_value(reply, "result");
|
|
|
|
const UniValue& error = find_value(reply, "error");
|
2014-10-29 18:08:31 +01:00
|
|
|
|
2014-08-20 21:15:16 +02:00
|
|
|
if (!error.isNull()) {
|
2014-10-29 18:08:31 +01:00
|
|
|
// Error
|
2014-08-20 21:15:16 +02:00
|
|
|
int code = error["code"].get_int();
|
2015-05-18 14:02:18 +02:00
|
|
|
if (fWait && code == RPC_IN_WARMUP)
|
|
|
|
throw CConnectionFailed("server in warmup");
|
|
|
|
strPrint = "error: " + error.write();
|
2014-10-29 18:08:31 +01:00
|
|
|
nRet = abs(code);
|
2015-07-07 12:15:44 +02:00
|
|
|
if (error.isObject())
|
|
|
|
{
|
|
|
|
UniValue errCode = find_value(error, "code");
|
|
|
|
UniValue errMsg = find_value(error, "message");
|
|
|
|
strPrint = errCode.isNull() ? "" : "error code: "+errCode.getValStr()+"\n";
|
|
|
|
|
|
|
|
if (errMsg.isStr())
|
|
|
|
strPrint += "error message:\n"+errMsg.get_str();
|
|
|
|
}
|
2014-10-29 18:08:31 +01:00
|
|
|
} else {
|
|
|
|
// Result
|
2014-08-20 21:15:16 +02:00
|
|
|
if (result.isNull())
|
2014-10-29 18:08:31 +01:00
|
|
|
strPrint = "";
|
2014-08-20 21:15:16 +02:00
|
|
|
else if (result.isStr())
|
2014-10-29 18:08:31 +01:00
|
|
|
strPrint = result.get_str();
|
|
|
|
else
|
2014-08-20 21:15:16 +02:00
|
|
|
strPrint = result.write(2);
|
2014-10-29 18:08:31 +01:00
|
|
|
}
|
|
|
|
// Connection succeeded, no need to retry.
|
|
|
|
break;
|
|
|
|
}
|
2014-12-07 13:29:06 +01:00
|
|
|
catch (const CConnectionFailed&) {
|
2014-10-29 18:08:31 +01:00
|
|
|
if (fWait)
|
|
|
|
MilliSleep(1000);
|
|
|
|
else
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
} while (fWait);
|
2014-05-26 11:38:44 +02:00
|
|
|
}
|
2014-12-07 13:29:06 +01:00
|
|
|
catch (const boost::thread_interrupted&) {
|
2014-05-26 11:38:44 +02:00
|
|
|
throw;
|
|
|
|
}
|
2014-12-07 13:29:06 +01:00
|
|
|
catch (const std::exception& e) {
|
2014-05-26 11:38:44 +02:00
|
|
|
strPrint = string("error: ") + e.what();
|
|
|
|
nRet = EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
catch (...) {
|
|
|
|
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
|
2014-06-26 03:09:36 +02:00
|
|
|
if (strPrint != "") {
|
2014-05-26 11:38:44 +02:00
|
|
|
fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
|
|
|
|
}
|
|
|
|
return nRet;
|
|
|
|
}
|
|
|
|
|
2013-10-11 23:09:59 +02:00
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
2014-05-13 12:15:00 +02:00
|
|
|
SetupEnvironment();
|
2015-09-02 16:18:16 +02:00
|
|
|
if (!SetupNetworking()) {
|
|
|
|
fprintf(stderr, "Error: Initializing networking failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
2014-05-13 12:15:00 +02:00
|
|
|
|
2014-06-26 03:09:36 +02:00
|
|
|
try {
|
2013-10-11 23:09:59 +02:00
|
|
|
if(!AppInitRPC(argc, argv))
|
2014-06-13 04:26:46 +02:00
|
|
|
return EXIT_FAILURE;
|
2013-10-11 23:09:59 +02:00
|
|
|
}
|
2014-12-07 13:29:06 +01:00
|
|
|
catch (const std::exception& e) {
|
2013-10-11 23:09:59 +02:00
|
|
|
PrintExceptionContinue(&e, "AppInitRPC()");
|
2014-06-13 04:26:46 +02:00
|
|
|
return EXIT_FAILURE;
|
2013-10-11 23:09:59 +02:00
|
|
|
} catch (...) {
|
|
|
|
PrintExceptionContinue(NULL, "AppInitRPC()");
|
2014-06-13 04:26:46 +02:00
|
|
|
return EXIT_FAILURE;
|
2013-10-11 23:09:59 +02:00
|
|
|
}
|
|
|
|
|
2014-06-13 04:26:46 +02:00
|
|
|
int ret = EXIT_FAILURE;
|
2014-06-26 03:09:36 +02:00
|
|
|
try {
|
2014-02-24 14:08:56 +01:00
|
|
|
ret = CommandLineRPC(argc, argv);
|
2013-10-11 23:09:59 +02:00
|
|
|
}
|
2014-12-07 13:29:06 +01:00
|
|
|
catch (const std::exception& e) {
|
2013-10-11 23:09:59 +02:00
|
|
|
PrintExceptionContinue(&e, "CommandLineRPC()");
|
|
|
|
} catch (...) {
|
|
|
|
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
|
|
|
}
|
2014-02-24 14:08:56 +01:00
|
|
|
return ret;
|
2013-10-11 23:09:59 +02:00
|
|
|
}
|