2013-10-11 23:09:59 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2018-07-27 00:36:45 +02:00
// Copyright (c) 2009-2018 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.
2015-12-09 11:53:12 +01:00
# if defined(HAVE_CONFIG_H)
2017-11-10 01:57:53 +01:00
# include <config/bitcoin-config.h>
2015-12-09 11:53:12 +01:00
# endif
2017-11-10 01:57:53 +01:00
# include <chainparamsbase.h>
# include <clientversion.h>
# include <fs.h>
# include <rpc/client.h>
# include <rpc/protocol.h>
# include <util.h>
# include <utilstrencodings.h>
2013-10-11 23:09:59 +02:00
2018-04-02 20:31:40 +02:00
# include <memory>
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>
2018-08-05 18:38:25 +02:00
# include <tuple>
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 <event2/buffer.h>
# include <event2/keyvalq_struct.h>
2017-11-10 01:57:53 +01:00
# include <support/events.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
2018-08-13 22:13:29 +02:00
const std : : function < std : : string ( const char * ) > G_TRANSLATION_FUN = nullptr ;
2015-06-27 21:21:41 +02:00
static const char DEFAULT_RPCCONNECT [ ] = " 127.0.0.1 " ;
2015-09-18 15:45:38 +02:00
static const int DEFAULT_HTTP_CLIENT_TIMEOUT = 900 ;
2016-11-22 14:56:29 +01:00
static const bool DEFAULT_NAMED = false ;
2016-11-02 19:59:09 +01:00
static const int CONTINUE_EXECUTION = - 1 ;
2015-09-18 15:45:38 +02:00
2018-04-28 22:54:58 +02:00
static void SetupCliArgs ( )
2014-05-26 11:38:44 +02:00
{
2015-05-22 03:50:01 +02:00
const auto defaultBaseParams = CreateBaseChainParams ( CBaseChainParams : : MAIN ) ;
const auto testnetBaseParams = CreateBaseChainParams ( CBaseChainParams : : TESTNET ) ;
2018-08-21 01:46:34 +02:00
const auto regtestBaseParams = CreateBaseChainParams ( CBaseChainParams : : REGTEST ) ;
2014-05-26 11:38:44 +02:00
2018-05-29 18:49:44 +02:00
gArgs . AddArg ( " -? " , " This help message " , false , OptionsCategory : : OPTIONS ) ;
2018-07-20 20:14:08 +02:00
gArgs . AddArg ( " -version " , " Print version and exit " , false , OptionsCategory : : OPTIONS ) ;
2018-05-29 18:49:44 +02:00
gArgs . AddArg ( " -conf=<file> " , strprintf ( " Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s) " , BITCOIN_CONF_FILENAME ) , false , OptionsCategory : : OPTIONS ) ;
gArgs . AddArg ( " -datadir=<dir> " , " Specify data directory " , false , OptionsCategory : : OPTIONS ) ;
gArgs . AddArg ( " -getinfo " , " Get general information from the remote server. Note that unlike server-side RPC calls, the results of -getinfo is the result of multiple non-atomic requests. Some entries in the result may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported) " , false , OptionsCategory : : OPTIONS ) ;
2018-04-28 22:54:58 +02:00
SetupChainParamsBaseOptions ( ) ;
2018-05-29 18:49:44 +02:00
gArgs . AddArg ( " -named " , strprintf ( " Pass named instead of positional arguments (default: %s) " , DEFAULT_NAMED ) , false , OptionsCategory : : OPTIONS ) ;
gArgs . AddArg ( " -rpcclienttimeout=<n> " , strprintf ( " Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d) " , DEFAULT_HTTP_CLIENT_TIMEOUT ) , false , OptionsCategory : : OPTIONS ) ;
gArgs . AddArg ( " -rpcconnect=<ip> " , strprintf ( " Send commands to node running on <ip> (default: %s) " , DEFAULT_RPCCONNECT ) , false , OptionsCategory : : OPTIONS ) ;
2018-09-10 13:08:25 +02:00
gArgs . AddArg ( " -rpccookiefile=<loc> " , " Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir) " , false , OptionsCategory : : OPTIONS ) ;
2018-05-29 18:49:44 +02:00
gArgs . AddArg ( " -rpcpassword=<pw> " , " Password for JSON-RPC connections " , false , OptionsCategory : : OPTIONS ) ;
2018-08-21 01:46:34 +02:00
gArgs . AddArg ( " -rpcport=<port> " , strprintf ( " Connect to JSON-RPC on <port> (default: %u, testnet: %u, regtest: %u) " , defaultBaseParams - > RPCPort ( ) , testnetBaseParams - > RPCPort ( ) , regtestBaseParams - > RPCPort ( ) ) , false , OptionsCategory : : OPTIONS ) ;
2018-05-29 18:49:44 +02:00
gArgs . AddArg ( " -rpcuser=<user> " , " Username for JSON-RPC connections " , false , OptionsCategory : : OPTIONS ) ;
gArgs . AddArg ( " -rpcwait " , " Wait for RPC server to start " , false , OptionsCategory : : OPTIONS ) ;
gArgs . AddArg ( " -rpcwallet=<walletname> " , " Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind) " , false , OptionsCategory : : OPTIONS ) ;
2018-08-07 20:11:52 +02:00
gArgs . AddArg ( " -stdin " , " Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password. " , false , OptionsCategory : : OPTIONS ) ;
gArgs . AddArg ( " -stdinrpcpass " , " Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password. " , false , OptionsCategory : : OPTIONS ) ;
2018-04-29 01:40:51 +02:00
// Hidden
gArgs . AddArg ( " -h " , " " , false , OptionsCategory : : HIDDEN ) ;
gArgs . AddArg ( " -help " , " " , false , OptionsCategory : : HIDDEN ) ;
2014-05-26 11:38:44 +02:00
}
2018-06-04 20:55:00 +02:00
/** libevent event log callback */
static void libevent_log_cb ( int severity , const char * msg )
{
# ifndef EVENT_LOG_ERR // EVENT_LOG_ERR was added in 2.0.19; but before then _EVENT_LOG_ERR existed.
# define EVENT_LOG_ERR _EVENT_LOG_ERR
# endif
// Ignore everything other than errors
if ( severity > = EVENT_LOG_ERR ) {
throw std : : runtime_error ( strprintf ( " libevent error: %s " , msg ) ) ;
}
}
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 )
{ }
} ;
2016-11-02 19:59:09 +01:00
//
// This function returns either one of EXIT_ codes when it's expected to stop the process or
// CONTINUE_EXECUTION when it's expected to continue further.
//
static int AppInitRPC ( int argc , char * argv [ ] )
2013-10-11 23:09:59 +02:00
{
//
// Parameters
//
2018-04-28 22:54:58 +02:00
SetupCliArgs ( ) ;
2018-04-29 01:40:51 +02:00
std : : string error ;
if ( ! gArgs . ParseParameters ( argc , argv , error ) ) {
fprintf ( stderr , " Error parsing command line arguments: %s \n " , error . c_str ( ) ) ;
return EXIT_FAILURE ;
}
2018-03-30 22:47:36 +02:00
if ( argc < 2 | | HelpRequested ( gArgs ) | | gArgs . IsArgSet ( " -version " ) ) {
2018-05-08 17:31:21 +02:00
std : : string strUsage = PACKAGE_NAME " RPC client version " + FormatFullVersion ( ) + " \n " ;
2017-08-01 21:17:40 +02:00
if ( ! gArgs . IsArgSet ( " -version " ) ) {
2018-05-08 17:31:21 +02:00
strUsage + = " \n "
" Usage: bitcoin-cli [options] <command> [params] Send command to " PACKAGE_NAME " \n "
" or: bitcoin-cli [options] -named <command> [name=value]... Send command to " PACKAGE_NAME " (with named arguments) \n "
" or: bitcoin-cli [options] help List commands \n "
" or: bitcoin-cli [options] help <command> Get help for a command \n " ;
2018-04-28 22:54:58 +02:00
strUsage + = " \n " + gArgs . GetHelpMessage ( ) ;
2014-11-22 19:56:25 +01:00
}
fprintf ( stdout , " %s " , strUsage . c_str ( ) ) ;
2016-11-02 19:59:09 +01:00
if ( argc < 2 ) {
fprintf ( stderr , " Error: too few parameters \n " ) ;
return EXIT_FAILURE ;
}
return EXIT_SUCCESS ;
2014-11-22 19:56:25 +01:00
}
2017-03-01 17:05:50 +01:00
if ( ! fs : : is_directory ( GetDataDir ( false ) ) ) {
2017-08-01 21:17:40 +02:00
fprintf ( stderr , " Error: Specified data directory \" %s \" does not exist. \n " , gArgs . GetArg ( " -datadir " , " " ) . c_str ( ) ) ;
2016-11-02 19:59:09 +01:00
return EXIT_FAILURE ;
2013-10-11 23:09:59 +02:00
}
2018-04-29 01:40:51 +02:00
if ( ! gArgs . ReadConfigFiles ( error , true ) ) {
fprintf ( stderr , " Error reading configuration file: %s \n " , error . c_str ( ) ) ;
2016-11-02 19:59:09 +01:00
return EXIT_FAILURE ;
2014-04-07 10:10:01 +02:00
}
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 {
2018-03-29 07:00:00 +02:00
SelectBaseParams ( gArgs . GetChainName ( ) ) ;
2015-10-27 17:39:42 +01:00
} catch ( const std : : exception & e ) {
2015-05-25 09:00:17 +02:00
fprintf ( stderr , " Error: %s \n " , e . what ( ) ) ;
2016-11-02 19:59:09 +01:00
return EXIT_FAILURE ;
2013-11-28 17:28:27 +01:00
}
2016-11-02 19:59:09 +01:00
return CONTINUE_EXECUTION ;
2013-10-11 23:09:59 +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 structure for request_done to fill in */
struct HTTPReply
2014-05-26 11:38:44 +02:00
{
2016-09-14 15:08:34 +02:00
HTTPReply ( ) : status ( 0 ) , error ( - 1 ) { }
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 ;
2016-09-14 15:08:34 +02:00
int error ;
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
std : : string body ;
} ;
2018-05-02 17:14:48 +02:00
static const char * http_errorstring ( int code )
2016-09-14 15:08:34 +02:00
{
switch ( code ) {
# if LIBEVENT_VERSION_NUMBER >= 0x02010300
case EVREQ_HTTP_TIMEOUT :
return " timeout reached " ;
case EVREQ_HTTP_EOF :
return " EOF reached " ;
case EVREQ_HTTP_INVALID_HEADER :
return " error while reading header, or invalid header " ;
case EVREQ_HTTP_BUFFER_ERROR :
return " error encountered while reading or writing " ;
case EVREQ_HTTP_REQUEST_CANCEL :
return " request was canceled " ;
case EVREQ_HTTP_DATA_TOO_LONG :
return " response body is larger than allowed " ;
# endif
default :
return " unknown " ;
}
}
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
static void http_request_done ( struct evhttp_request * req , void * ctx )
{
HTTPReply * reply = static_cast < HTTPReply * > ( ctx ) ;
2017-08-07 07:36:37 +02:00
if ( req = = nullptr ) {
/* If req is nullptr, it means an error occurred while connecting: the
2016-09-14 15:08:34 +02:00
* error code will have been passed to http_error_cb .
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 = 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 ) ;
}
}
2016-09-14 15:08:34 +02:00
# if LIBEVENT_VERSION_NUMBER >= 0x02010300
static void http_error_cb ( enum evhttp_request_error err , void * ctx )
{
HTTPReply * reply = static_cast < HTTPReply * > ( ctx ) ;
reply - > error = err ;
}
# endif
2016-09-29 16:45:19 +02:00
/** Class that handles the conversion from a command-line to a JSON-RPC request,
* as well as converting back to a JSON object that can be shown as result .
*/
class BaseRequestHandler
{
public :
2017-12-29 16:20:28 +01:00
virtual ~ BaseRequestHandler ( ) { }
2016-09-29 16:45:19 +02:00
virtual UniValue PrepareRequest ( const std : : string & method , const std : : vector < std : : string > & args ) = 0 ;
virtual UniValue ProcessReply ( const UniValue & batch_in ) = 0 ;
} ;
/** Process getinfo requests */
class GetinfoRequestHandler : public BaseRequestHandler
{
public :
const int ID_NETWORKINFO = 0 ;
const int ID_BLOCKCHAININFO = 1 ;
const int ID_WALLETINFO = 2 ;
/** Create a simulated `getinfo` request. */
UniValue PrepareRequest ( const std : : string & method , const std : : vector < std : : string > & args ) override
{
2017-11-17 14:11:02 +01:00
if ( ! args . empty ( ) ) {
throw std : : runtime_error ( " -getinfo takes no arguments " ) ;
}
2016-09-29 16:45:19 +02:00
UniValue result ( UniValue : : VARR ) ;
result . push_back ( JSONRPCRequestObj ( " getnetworkinfo " , NullUniValue , ID_NETWORKINFO ) ) ;
result . push_back ( JSONRPCRequestObj ( " getblockchaininfo " , NullUniValue , ID_BLOCKCHAININFO ) ) ;
result . push_back ( JSONRPCRequestObj ( " getwalletinfo " , NullUniValue , ID_WALLETINFO ) ) ;
return result ;
}
/** Collect values from the batch and form a simulated `getinfo` reply. */
UniValue ProcessReply ( const UniValue & batch_in ) override
{
UniValue result ( UniValue : : VOBJ ) ;
std : : vector < UniValue > batch = JSONRPCProcessBatchReply ( batch_in , 3 ) ;
// Errors in getnetworkinfo() and getblockchaininfo() are fatal, pass them on
// getwalletinfo() is allowed to fail in case there is no wallet.
if ( ! batch [ ID_NETWORKINFO ] [ " error " ] . isNull ( ) ) {
return batch [ ID_NETWORKINFO ] ;
}
if ( ! batch [ ID_BLOCKCHAININFO ] [ " error " ] . isNull ( ) ) {
return batch [ ID_BLOCKCHAININFO ] ;
}
result . pushKV ( " version " , batch [ ID_NETWORKINFO ] [ " result " ] [ " version " ] ) ;
result . pushKV ( " protocolversion " , batch [ ID_NETWORKINFO ] [ " result " ] [ " protocolversion " ] ) ;
if ( ! batch [ ID_WALLETINFO ] . isNull ( ) ) {
result . pushKV ( " walletversion " , batch [ ID_WALLETINFO ] [ " result " ] [ " walletversion " ] ) ;
result . pushKV ( " balance " , batch [ ID_WALLETINFO ] [ " result " ] [ " balance " ] ) ;
}
result . pushKV ( " blocks " , batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " blocks " ] ) ;
result . pushKV ( " timeoffset " , batch [ ID_NETWORKINFO ] [ " result " ] [ " timeoffset " ] ) ;
result . pushKV ( " connections " , batch [ ID_NETWORKINFO ] [ " result " ] [ " connections " ] ) ;
result . pushKV ( " proxy " , batch [ ID_NETWORKINFO ] [ " result " ] [ " networks " ] [ 0 ] [ " proxy " ] ) ;
result . pushKV ( " difficulty " , batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " difficulty " ] ) ;
result . pushKV ( " testnet " , UniValue ( batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " chain " ] . get_str ( ) = = " test " ) ) ;
if ( ! batch [ ID_WALLETINFO ] . isNull ( ) ) {
result . pushKV ( " walletversion " , batch [ ID_WALLETINFO ] [ " result " ] [ " walletversion " ] ) ;
result . pushKV ( " balance " , batch [ ID_WALLETINFO ] [ " result " ] [ " balance " ] ) ;
result . pushKV ( " keypoololdest " , batch [ ID_WALLETINFO ] [ " result " ] [ " keypoololdest " ] ) ;
result . pushKV ( " keypoolsize " , batch [ ID_WALLETINFO ] [ " result " ] [ " keypoolsize " ] ) ;
if ( ! batch [ ID_WALLETINFO ] [ " result " ] [ " unlocked_until " ] . isNull ( ) ) {
result . pushKV ( " unlocked_until " , batch [ ID_WALLETINFO ] [ " result " ] [ " unlocked_until " ] ) ;
}
result . pushKV ( " paytxfee " , batch [ ID_WALLETINFO ] [ " result " ] [ " paytxfee " ] ) ;
}
result . pushKV ( " relayfee " , batch [ ID_NETWORKINFO ] [ " result " ] [ " relayfee " ] ) ;
result . pushKV ( " warnings " , batch [ ID_NETWORKINFO ] [ " result " ] [ " warnings " ] ) ;
return JSONRPCReplyObj ( result , NullUniValue , 1 ) ;
}
} ;
/** Process default single requests */
class DefaultRequestHandler : public BaseRequestHandler {
public :
UniValue PrepareRequest ( const std : : string & method , const std : : vector < std : : string > & args ) override
{
UniValue params ;
if ( gArgs . GetBoolArg ( " -named " , DEFAULT_NAMED ) ) {
params = RPCConvertNamedValues ( method , args ) ;
} else {
params = RPCConvertValues ( method , args ) ;
}
return JSONRPCRequestObj ( method , params , 1 ) ;
}
UniValue ProcessReply ( const UniValue & reply ) override
{
return reply . get_obj ( ) ;
}
} ;
static UniValue CallRPC ( BaseRequestHandler * rh , const std : : string & strMethod , const std : : vector < std : : string > & args )
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
{
2017-07-12 22:59:09 +02:00
std : : string host ;
// In preference order, we choose the following for the port:
// 1. -rpcport
// 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6)
// 3. default port for chain
int port = BaseParams ( ) . RPCPort ( ) ;
2017-08-01 21:17:40 +02:00
SplitHostPort ( gArgs . GetArg ( " -rpcconnect " , DEFAULT_RPCCONNECT ) , port , host ) ;
port = gArgs . GetArg ( " -rpcport " , port ) ;
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
2016-12-20 12:46:11 +01:00
// Obtain event base
raii_event_base base = obtain_event_base ( ) ;
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
// Synchronously look up hostname
2016-12-20 12:46:11 +01:00
raii_evhttp_connection evcon = obtain_evhttp_connection_base ( base . get ( ) , host , port ) ;
2017-08-01 21:17:40 +02:00
evhttp_connection_set_timeout ( evcon . get ( ) , gArgs . 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 ;
2016-12-20 12:46:11 +01:00
raii_evhttp_request req = obtain_evhttp_request ( http_request_done , ( void * ) & response ) ;
2017-08-07 07:36:37 +02:00
if ( req = = nullptr )
2016-11-25 09:17:57 +01:00
throw std : : runtime_error ( " create http request failed " ) ;
2016-09-14 15:08:34 +02:00
# if LIBEVENT_VERSION_NUMBER >= 0x02010300
2016-12-20 12:46:11 +01:00
evhttp_request_set_error_cb ( req . get ( ) , http_error_cb ) ;
2016-09-14 15:08:34 +02:00
# endif
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
// Get credentials
2015-07-07 14:53:48 +02:00
std : : string strRPCUserColonPass ;
2018-03-09 06:09:57 +01:00
bool failedToGetAuthCookie = false ;
2017-08-01 21:17:40 +02:00
if ( gArgs . GetArg ( " -rpcpassword " , " " ) = = " " ) {
2015-07-07 14:53:48 +02:00
// Try fall back to cookie-based authentication if no password is provided
if ( ! GetAuthCookie ( & strRPCUserColonPass ) ) {
2018-03-09 06:09:57 +01:00
failedToGetAuthCookie = true ;
2015-07-07 14:53:48 +02:00
}
} else {
2017-08-01 21:17:40 +02:00
strRPCUserColonPass = gArgs . GetArg ( " -rpcuser " , " " ) + " : " + gArgs . GetArg ( " -rpcpassword " , " " ) ;
2015-07-07 14:53:48 +02:00
}
2016-12-20 12:46:11 +01:00
struct evkeyvalq * output_headers = evhttp_request_get_output_headers ( req . get ( ) ) ;
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
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
2016-09-29 16:45:19 +02:00
std : : string strRequest = rh - > PrepareRequest ( strMethod , args ) . write ( ) + " \n " ;
2016-12-20 12:46:11 +01:00
struct evbuffer * output_buffer = evhttp_request_get_output_buffer ( req . get ( ) ) ;
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
assert ( output_buffer ) ;
evbuffer_add ( output_buffer , strRequest . data ( ) , strRequest . size ( ) ) ;
2017-07-13 17:06:27 +02:00
// check if we should use a special wallet endpoint
std : : string endpoint = " / " ;
2017-11-15 21:44:36 +01:00
if ( ! gArgs . GetArgs ( " -rpcwallet " ) . empty ( ) ) {
std : : string walletName = gArgs . GetArg ( " -rpcwallet " , " " ) ;
2017-07-13 17:06:27 +02:00
char * encodedURI = evhttp_uriencode ( walletName . c_str ( ) , walletName . size ( ) , false ) ;
if ( encodedURI ) {
endpoint = " /wallet/ " + std : : string ( encodedURI ) ;
free ( encodedURI ) ;
}
else {
throw CConnectionFailed ( " uri-encode failed " ) ;
}
}
int r = evhttp_make_request ( evcon . get ( ) , req . get ( ) , EVHTTP_REQ_POST , endpoint . c_str ( ) ) ;
2016-12-20 12:46:11 +01:00
req . release ( ) ; // ownership moved to evcon in above call
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 ( r ! = 0 ) {
throw CConnectionFailed ( " send http request failed " ) ;
}
2014-05-26 11:38:44 +02:00
2016-12-20 12:46:11 +01:00
event_base_dispatch ( base . get ( ) ) ;
2014-05-26 11:38:44 +02:00
2018-03-09 06:09:57 +01:00
if ( response . status = = 0 ) {
std : : string responseErrorMessage ;
if ( response . error ! = - 1 ) {
responseErrorMessage = strprintf ( " (error code %d - \" %s \" ) " , response . error , http_errorstring ( response . error ) ) ;
}
throw CConnectionFailed ( strprintf ( " Could not connect to the server %s:%d%s \n \n Make sure the bitcoind server is running and that you are connecting to the correct RPC port. " , host , port , responseErrorMessage ) ) ;
} else if ( response . status = = HTTP_UNAUTHORIZED ) {
if ( failedToGetAuthCookie ) {
throw std : : runtime_error ( strprintf (
2018-05-29 18:49:44 +02:00
" Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s) " ,
2018-03-09 06:09:57 +01:00
GetConfigFile ( gArgs . GetArg ( " -conf " , BITCOIN_CONF_FILENAME ) ) . string ( ) . c_str ( ) ) ) ;
} else {
throw std : : runtime_error ( " Authorization failed: Incorrect rpcuser or rpcpassword " ) ;
}
} else if ( response . status > = 400 & & response . status ! = HTTP_BAD_REQUEST & & response . status ! = HTTP_NOT_FOUND & & response . status ! = HTTP_INTERNAL_SERVER_ERROR )
2016-11-25 09:17:57 +01:00
throw std : : runtime_error ( strprintf ( " server returned HTTP error %d " , response . status ) ) ;
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 . body . empty ( ) )
2016-11-25 09:17:57 +01:00
throw std : : runtime_error ( " no response from server " ) ;
2014-05-26 11:38:44 +02:00
// 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 ) )
2016-11-25 09:17:57 +01:00
throw std : : runtime_error ( " couldn't parse reply from server " ) ;
2016-09-29 16:45:19 +02:00
const UniValue reply = rh - > ProcessReply ( valReply ) ;
2014-05-26 11:38:44 +02:00
if ( reply . empty ( ) )
2016-11-25 09:17:57 +01:00
throw std : : runtime_error ( " expected reply to have result, error and id properties " ) ;
2014-05-26 11:38:44 +02:00
return reply ;
}
2018-05-02 17:14:48 +02:00
static int CommandLineRPC ( int argc , char * argv [ ] )
2014-05-26 11:38:44 +02:00
{
2016-11-25 09:17:57 +01:00
std : : string strPrint ;
2014-05-26 11:38:44 +02:00
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 + + ;
}
2017-08-23 20:48:00 +02:00
std : : string rpcPass ;
if ( gArgs . GetBoolArg ( " -stdinrpcpass " , false ) ) {
2017-08-24 19:35:06 +02:00
if ( ! std : : getline ( std : : cin , rpcPass ) ) {
2017-08-23 20:48:00 +02:00
throw std : : runtime_error ( " -stdinrpcpass specified but failed to read from standard input " ) ;
2017-08-24 19:35:06 +02:00
}
2017-08-23 20:48:00 +02:00
gArgs . ForceSetArg ( " -rpcpassword " , rpcPass ) ;
}
2016-02-17 15:03:38 +01:00
std : : vector < std : : string > args = std : : vector < std : : string > ( & argv [ 1 ] , & argv [ argc ] ) ;
2017-08-01 21:17:40 +02:00
if ( gArgs . GetBoolArg ( " -stdin " , false ) ) {
2016-02-17 15:03:38 +01:00
// Read one arg per line from stdin and append
std : : string line ;
2017-08-24 19:35:06 +02:00
while ( std : : getline ( std : : cin , line ) ) {
2016-02-17 15:03:38 +01:00
args . push_back ( line ) ;
2017-08-24 19:35:06 +02:00
}
2016-02-17 15:03:38 +01:00
}
2016-09-29 16:45:19 +02:00
std : : unique_ptr < BaseRequestHandler > rh ;
std : : string method ;
if ( gArgs . GetBoolArg ( " -getinfo " , false ) ) {
rh . reset ( new GetinfoRequestHandler ( ) ) ;
method = " " ;
2016-11-22 14:56:29 +01:00
} else {
2016-09-29 16:45:19 +02:00
rh . reset ( new DefaultRequestHandler ( ) ) ;
if ( args . size ( ) < 1 ) {
throw std : : runtime_error ( " too few parameters (need at least command) " ) ;
}
method = args [ 0 ] ;
args . erase ( args . begin ( ) ) ; // Remove trailing method name from arguments vector
2016-11-22 14:56:29 +01:00
}
2014-05-26 11:38:44 +02:00
2014-10-29 18:08:31 +01:00
// Execute and handle connection failures with -rpcwait
2017-08-01 21:17:40 +02:00
const bool fWait = gArgs . GetBoolArg ( " -rpcwait " , false ) ;
2014-10-29 18:08:31 +01:00
do {
try {
2016-09-29 16:45:19 +02:00
const UniValue reply = CallRPC ( rh . get ( ) , method , args ) ;
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 ( ) ;
2017-07-17 11:42:30 +02:00
if ( errCode . isNum ( ) & & errCode . get_int ( ) = = RPC_WALLET_NOT_SPECIFIED ) {
strPrint + = " \n Try adding \" -rpcwallet=<filename> \" option to bitcoin-cli command line. " ;
}
2015-07-07 12:15:44 +02:00
}
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 ) {
2016-11-25 09:17:57 +01:00
strPrint = std : : string ( " error: " ) + e . what ( ) ;
2014-05-26 11:38:44 +02:00
nRet = EXIT_FAILURE ;
}
catch ( . . . ) {
2017-08-07 07:36:37 +02:00
PrintExceptionContinue ( nullptr , " CommandLineRPC() " ) ;
2014-05-26 11:38:44 +02:00
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 [ ] )
{
2018-08-05 18:38:25 +02:00
# ifdef WIN32
util : : WinCmdLineArgs winArgs ;
std : : tie ( argc , argv ) = winArgs . get ( ) ;
# endif
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 " ) ;
2016-05-02 18:48:04 +02:00
return EXIT_FAILURE ;
2015-09-02 16:18:16 +02:00
}
2018-06-04 20:55:00 +02:00
event_set_log_callback ( & libevent_log_cb ) ;
2014-05-13 12:15:00 +02:00
2014-06-26 03:09:36 +02:00
try {
2016-11-02 19:59:09 +01:00
int ret = AppInitRPC ( argc , argv ) ;
if ( ret ! = CONTINUE_EXECUTION )
return ret ;
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 ( . . . ) {
2017-08-07 07:36:37 +02:00
PrintExceptionContinue ( nullptr , " 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 ( . . . ) {
2017-08-07 07:36:37 +02:00
PrintExceptionContinue ( nullptr , " CommandLineRPC() " ) ;
2013-10-11 23:09:59 +02:00
}
2014-02-24 14:08:56 +01:00
return ret ;
2013-10-11 23:09:59 +02:00
}