2013-10-11 23:09:59 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2015-12-13 14:51:43 +01:00
// Copyright (c) 2009-2015 The Bitcoin Core developers
2022-06-08 01:36:46 +02:00
// Copyright (c) 2014-2022 The Dash 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.
2016-02-04 13:41:58 +01:00
# if defined(HAVE_CONFIG_H)
2022-08-02 18:34:58 +02:00
# include <config/bitcoin-config.h>
2016-02-04 13:41:58 +01:00
# endif
2020-03-19 23:46:56 +01:00
# include <chainparamsbase.h>
# include <clientversion.h>
# include <rpc/client.h>
# include <rpc/protocol.h>
2022-02-27 08:46:53 +01:00
# include <rpc/request.h>
2020-03-19 23:46:56 +01:00
# include <stacktraces.h>
2021-06-27 08:33:13 +02:00
# include <util/strencodings.h>
2022-03-24 05:13:51 +01:00
# include <util/system.h>
# include <util/translation.h>
2013-10-11 23:09:59 +02:00
2022-03-24 05:13:51 +01:00
# include <functional>
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-10-08 03:47:03 +02:00
# include <tuple>
2013-04-13 07:13:08 +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
# include <event2/buffer.h>
# include <event2/keyvalq_struct.h>
2020-03-19 23:46:56 +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>
2019-10-02 18:36:01 +02:00
# include <compat/stdin.h>
2014-07-03 07:45:16 +02:00
2018-08-25 20:20:30 +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 ;
2017-01-10 13:52:49 +01:00
static const bool DEFAULT_NAMED = false ;
2016-11-11 06:16:39 +01:00
static const int CONTINUE_EXECUTION = - 1 ;
2014-05-26 11:38:44 +02:00
2022-05-21 10:27:30 +02:00
static void SetupCliArgs ( ArgsManager & argsman )
2014-05-26 11:38:44 +02:00
{
2022-05-21 10:27:30 +02:00
SetupHelpOptions ( argsman ) ;
2022-05-21 10:12:13 +02:00
2017-05-09 09:29:12 +02:00
const auto defaultBaseParams = CreateBaseChainParams ( CBaseChainParams : : MAIN ) ;
const auto testnetBaseParams = CreateBaseChainParams ( CBaseChainParams : : TESTNET ) ;
2018-09-04 12:45:48 +02:00
const auto regtestBaseParams = CreateBaseChainParams ( CBaseChainParams : : REGTEST ) ;
2021-03-19 16:00:24 +01:00
2022-05-21 10:27:30 +02:00
argsman . AddArg ( " -version " , " Print version and exit " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -conf=<file> " , strprintf ( " Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s) " , BITCOIN_CONF_FILENAME ) , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -datadir=<dir> " , " Specify data directory " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . 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) " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -named " , strprintf ( " Pass named instead of positional arguments (default: %s) " , DEFAULT_NAMED ) , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcclienttimeout=<n> " , strprintf ( " Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d) " , DEFAULT_HTTP_CLIENT_TIMEOUT ) , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcconnect=<ip> " , strprintf ( " Send commands to node running on <ip> (default: %s) " , DEFAULT_RPCCONNECT ) , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpccookiefile=<loc> " , " Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir) " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcpassword=<pw> " , " Password for JSON-RPC connections " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcport=<port> " , strprintf ( " Connect to JSON-RPC on <port> (default: %u, testnet: %u, regtest: %u) " , defaultBaseParams - > RPCPort ( ) , testnetBaseParams - > RPCPort ( ) , regtestBaseParams - > RPCPort ( ) ) , ArgsManager : : ALLOW_ANY | ArgsManager : : NETWORK_ONLY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcuser=<user> " , " Username for JSON-RPC connections " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcwait " , " Wait for RPC server to start " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -rpcwallet=<walletname> " , " Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to dashd). This changes the RPC endpoint used, e.g. http://127.0.0.1:9998/wallet/<walletname> " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . 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. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . 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. When combined with -stdinwalletpassphrase, -stdinrpcpass consumes the first line, and -stdinwalletpassphrase consumes the second. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -stdinwalletpassphrase " , " Read wallet passphrase from standard input as a single line. When combined with -stdin, the first line from standard input is used for the wallet passphrase. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
SetupChainParamsBaseOptions ( argsman ) ;
2014-05-26 11:38:44 +02:00
}
2018-06-07 08:58:06 +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-11 06:16:39 +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
//
2022-05-21 10:27:30 +02:00
SetupCliArgs ( gArgs ) ;
2018-05-30 19:42:58 +02:00
std : : string error ;
if ( ! gArgs . ParseParameters ( argc , argv , error ) ) {
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cerr , " Error parsing command line arguments: %s \n " , error ) ;
2018-05-30 19:42:58 +02:00
return EXIT_FAILURE ;
}
2019-07-02 06:16:11 +02:00
if ( gArgs . IsArgSet ( " -printcrashinfo " ) ) {
std : : cout < < GetCrashInfoStrFromSerializedStr ( gArgs . GetArg ( " -printcrashinfo " , " " ) ) < < std : : endl ;
return true ;
}
2018-04-03 17:51:48 +02:00
if ( argc < 2 | | HelpRequested ( gArgs ) | | gArgs . IsArgSet ( " -version " ) ) {
2018-08-07 10:19:09 +02:00
std : : string strUsage = PACKAGE_NAME " RPC client version " + FormatFullVersion ( ) + " \n " ;
2019-06-24 18:44:27 +02:00
if ( ! gArgs . IsArgSet ( " -version " ) ) {
2018-08-07 10:19:09 +02:00
strUsage + = " \n "
" Usage: dash-cli [options] <command> [params] Send command to " PACKAGE_NAME " \n "
" or: dash-cli [options] -named <command> [name=value]... Send command to " PACKAGE_NAME " (with named arguments) \n "
" or: dash-cli [options] help List commands \n "
" or: dash-cli [options] help <command> Get help for a command \n " ;
2021-03-19 16:00:24 +01:00
strUsage + = " \n " + gArgs . GetHelpMessage ( ) ;
2014-11-22 19:56:25 +01:00
}
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cout , " %s " , strUsage ) ;
2016-11-11 06:16:39 +01:00
if ( argc < 2 ) {
2021-10-24 12:51:47 +02:00
tfm : : format ( std : : cerr , " Error: too few parameters \n " ) ;
2016-11-11 06:16:39 +01:00
return EXIT_FAILURE ;
}
return EXIT_SUCCESS ;
2014-11-22 19:56:25 +01:00
}
2019-04-29 21:46:34 +02:00
if ( ! CheckDataDirOption ( ) ) {
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cerr , " Error: Specified data directory \" %s \" does not exist. \n " , gArgs . GetArg ( " -datadir " , " " ) ) ;
2016-11-11 06:16:39 +01:00
return EXIT_FAILURE ;
2013-10-11 23:09:59 +02:00
}
2018-05-30 19:42:58 +02:00
if ( ! gArgs . ReadConfigFiles ( error , true ) ) {
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cerr , " Error reading configuration file: %s \n " , error ) ;
2016-11-11 06:16:39 +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 {
2020-04-29 12:16:37 +02:00
SelectBaseParams ( gArgs . GetChainName ( ) ) ;
2015-10-27 17:39:42 +01:00
} catch ( const std : : exception & e ) {
2021-10-24 12:51:47 +02:00
tfm : : format ( std : : cerr , " Error: %s \n " , e . what ( ) ) ;
2016-11-11 06:16:39 +01:00
return EXIT_FAILURE ;
2013-11-28 17:28:27 +01:00
}
2016-11-11 06:16:39 +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-26 14:52:56 +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-26 14:52:56 +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-04 22:42:39 +02:00
static const char * http_errorstring ( int code )
2016-09-26 14:52:56 +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 ) ;
2019-08-06 05:08:33 +02:00
if ( req = = nullptr ) {
/* If req is nullptr, it means an error occurred while connecting: the
2016-09-26 14:52:56 +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 ;
}
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 - > status = evhttp_request_get_response_code ( req ) ;
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
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 ) ;
}
}
2014-05-26 11:38:44 +02:00
2016-09-26 14:52:56 +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
2017-09-28 08:33:12 +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 :
2018-02-06 18:05:11 +01:00
virtual ~ BaseRequestHandler ( ) { }
2017-09-28 08:33:12 +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-18 12:05:27 +01:00
if ( ! args . empty ( ) ) {
throw std : : runtime_error ( " -getinfo takes no arguments " ) ;
}
2017-09-28 08:33:12 +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 ( " blocks " , batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " blocks " ] ) ;
2019-10-30 12:38:25 +01:00
result . pushKV ( " headers " , batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " headers " ] ) ;
result . pushKV ( " verificationprogress " , batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " verificationprogress " ] ) ;
2017-09-28 08:33:12 +02:00
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 " ] ) ;
2019-03-11 15:26:38 +01:00
result . pushKV ( " chain " , UniValue ( batch [ ID_BLOCKCHAININFO ] [ " result " ] [ " chain " ] ) ) ;
Merge #17368: cli: fix -getinfo output when compiled with no wallet
3d05d332693ec860626fc77e6ba50dec94e4e83c cli: fix -getinfo output when compiled with no wallet (fanquake)
Pull request description:
master (33b155f28732487854cf0ca29ca17c50f8c6872e):
```bash
src/bitcoin-cli -getinfo
{
"version": 199900,
"protocolversion": 70015,
"blocks": 602348,
"headers": 602348,
"verificationprogress": 0.9999995592310106,
"timeoffset": 0,
"connections": 10,
"proxy": "",
"difficulty": 13691480038694.45,
"chain": "main",
"walletversion": null,
"balance": null,
"keypoololdest": null,
"keypoolsize": null,
"paytxfee": null,
"relayfee": 0.00001000,
"warnings": "This is a pre-release test build - use at your own risk - do not use for mining or merchant applications"
}
```
This PR (3d05d332693ec860626fc77e6ba50dec94e4e83c):
```bash
{
"version": 199900,
"protocolversion": 70015,
"blocks": 602348,
"headers": 602348,
"verificationprogress": 0.9999996313568186,
"timeoffset": 0,
"connections": 10,
"proxy": "",
"difficulty": 13691480038694.45,
"chain": "main",
"relayfee": 0.00001000,
"warnings": "This is a pre-release test build - use at your own risk - do not use for mining or merchant applications"
}
```
ACKs for top commit:
MarcoFalke:
ouch ACK 3d05d332693ec860626fc77e6ba50dec94e4e83c
laanwj:
ACK 3d05d332693ec860626fc77e6ba50dec94e4e83c
darosior:
ACK 3d05d332693ec860626fc77e6ba50dec94e4e83c
Tree-SHA512: 055424e122a082cbfea410da287d9ceb7ed405fd68d53e2f5bef62beea80bc374a7d00366de0479d23faecb7f063b232aca52e9fdbdb97c58ddf46e7749136a9
2019-11-06 11:07:07 +01:00
if ( ! batch [ ID_WALLETINFO ] [ " result " ] . isNull ( ) ) {
2017-09-28 08:33:12 +02:00
result . pushKV ( " balance " , batch [ ID_WALLETINFO ] [ " result " ] [ " balance " ] ) ;
2021-03-17 23:36:11 +01:00
result . pushKV ( " coinjoin_balance " , batch [ ID_WALLETINFO ] [ " result " ] [ " coinjoin_balance " ] ) ;
2017-09-28 08:33:12 +02:00
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-15 22:16:56 +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 ( ) ;
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
2017-01-05 11:10:40 +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
2017-01-05 11:10:40 +01:00
raii_evhttp_connection evcon = obtain_evhttp_connection_base ( base . get ( ) , host , port ) ;
2019-10-16 16:00:39 +02:00
// Set connection timeout
{
const int timeout = gArgs . GetArg ( " -rpcclienttimeout " , DEFAULT_HTTP_CLIENT_TIMEOUT ) ;
if ( timeout > 0 ) {
evhttp_connection_set_timeout ( evcon . get ( ) , timeout ) ;
} else {
// Indefinite request timeouts are not possible in libevent-http, so we
// set the timeout to a very long time period instead.
constexpr int YEAR_IN_SECONDS = 31556952 ; // Average length of year in Gregorian calendar
evhttp_connection_set_timeout ( evcon . get ( ) , 5 * YEAR_IN_SECONDS ) ;
}
}
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 ;
2017-01-05 11:10:40 +01:00
raii_evhttp_request req = obtain_evhttp_request ( http_request_done , ( void * ) & response ) ;
2019-08-06 05:08:33 +02:00
if ( req = = nullptr )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " create http request failed " ) ;
2016-09-26 14:52:56 +02:00
# if LIBEVENT_VERSION_NUMBER >= 0x02010300
2017-01-05 11:10:40 +01:00
evhttp_request_set_error_cb ( req . get ( ) , http_error_cb ) ;
2016-09-26 14:52:56 +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-20 09:36:14 +01:00
bool failedToGetAuthCookie = false ;
2019-06-24 18:44:27 +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-20 09:36:14 +01:00
failedToGetAuthCookie = true ;
2015-07-07 14:53:48 +02:00
}
} else {
2019-06-24 18:44:27 +02:00
strRPCUserColonPass = gArgs . GetArg ( " -rpcuser " , " " ) + " : " + gArgs . GetArg ( " -rpcpassword " , " " ) ;
2015-07-07 14:53:48 +02:00
}
2014-05-26 11:38:44 +02:00
2017-01-05 11:10:40 +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
2017-09-28 08:33:12 +02:00
std : : string strRequest = rh - > PrepareRequest ( strMethod , args ) . write ( ) + " \n " ;
2017-01-05 11:10:40 +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-18 17:15:46 +02:00
// check if we should use a special wallet endpoint
std : : string endpoint = " / " ;
2018-03-07 17:05:08 +01:00
if ( ! gArgs . GetArgs ( " -rpcwallet " ) . empty ( ) ) {
std : : string walletName = gArgs . GetArg ( " -rpcwallet " , " " ) ;
2019-10-28 13:41:45 +01:00
char * encodedURI = evhttp_uriencode ( walletName . data ( ) , walletName . size ( ) , false ) ;
2017-07-18 17:15:46 +02:00
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 ( ) ) ;
2017-01-05 11:10:40 +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
2017-01-05 11:10:40 +01:00
event_base_dispatch ( base . get ( ) ) ;
2014-05-26 11:38:44 +02:00
2018-03-20 09:36:14 +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 dashd 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 (
2021-03-19 18:23:58 +01: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) " ,
2022-03-21 18:28:10 +01:00
GetConfigFile ( gArgs . GetArg ( " -conf " , BITCOIN_CONF_FILENAME ) ) . string ( ) ) ) ;
2018-03-20 09:36:14 +01:00
} 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 11:33:05 +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 11:33:05 +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 11:33:05 +01:00
throw std : : runtime_error ( " couldn't parse reply from server " ) ;
2017-09-28 08:33:12 +02:00
const UniValue reply = rh - > ProcessReply ( valReply ) ;
2014-05-26 11:38:44 +02:00
if ( reply . empty ( ) )
2016-11-25 11:33:05 +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-04 22:42:39 +02:00
static int CommandLineRPC ( int argc , char * argv [ ] )
2014-05-26 11:38:44 +02:00
{
2016-11-25 11:33:05 +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-24 08:35:42 +02:00
std : : string rpcPass ;
if ( gArgs . GetBoolArg ( " -stdinrpcpass " , false ) ) {
2019-10-02 18:36:01 +02:00
NO_STDIN_ECHO ( ) ;
if ( ! StdinReady ( ) ) {
fputs ( " RPC password> " , stderr ) ;
fflush ( stderr ) ;
}
2017-09-07 01:43:16 +02:00
if ( ! std : : getline ( std : : cin , rpcPass ) ) {
2017-08-24 08:35:42 +02:00
throw std : : runtime_error ( " -stdinrpcpass specified but failed to read from standard input " ) ;
2017-09-07 01:43:16 +02:00
}
2019-10-02 18:36:01 +02:00
if ( StdinTerminal ( ) ) {
fputc ( ' \n ' , stdout ) ;
}
2017-08-24 08:35:42 +02:00
gArgs . ForceSetArg ( " -rpcpassword " , rpcPass ) ;
}
2016-02-24 11:33:08 +01:00
std : : vector < std : : string > args = std : : vector < std : : string > ( & argv [ 1 ] , & argv [ argc ] ) ;
2019-10-02 18:36:01 +02:00
if ( gArgs . GetBoolArg ( " -stdinwalletpassphrase " , false ) ) {
NO_STDIN_ECHO ( ) ;
std : : string walletPass ;
if ( args . size ( ) < 1 | | args [ 0 ] . substr ( 0 , 16 ) ! = " walletpassphrase " ) {
throw std : : runtime_error ( " -stdinwalletpassphrase is only applicable for walletpassphrase(change) " ) ;
}
if ( ! StdinReady ( ) ) {
fputs ( " Wallet passphrase> " , stderr ) ;
fflush ( stderr ) ;
}
if ( ! std : : getline ( std : : cin , walletPass ) ) {
throw std : : runtime_error ( " -stdinwalletpassphrase specified but failed to read from standard input " ) ;
}
if ( StdinTerminal ( ) ) {
fputc ( ' \n ' , stdout ) ;
}
args . insert ( args . begin ( ) + 1 , walletPass ) ;
}
2019-06-24 18:44:27 +02:00
if ( gArgs . GetBoolArg ( " -stdin " , false ) ) {
2016-02-24 11:33:08 +01:00
// Read one arg per line from stdin and append
std : : string line ;
2017-09-07 01:43:16 +02:00
while ( std : : getline ( std : : cin , line ) ) {
2016-02-24 11:33:08 +01:00
args . push_back ( line ) ;
2017-09-07 01:43:16 +02:00
}
2019-10-02 18:36:01 +02:00
if ( StdinTerminal ( ) ) {
fputc ( ' \n ' , stdout ) ;
}
2016-02-24 11:33:08 +01:00
}
2017-09-28 08:33:12 +02:00
std : : unique_ptr < BaseRequestHandler > rh ;
std : : string method ;
if ( gArgs . GetBoolArg ( " -getinfo " , false ) ) {
rh . reset ( new GetinfoRequestHandler ( ) ) ;
method = " " ;
2017-01-10 13:52:49 +01:00
} else {
2017-09-28 08:33:12 +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
2017-01-10 13:52:49 +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
2019-06-24 18:44:27 +02:00
const bool fWait = gArgs . GetBoolArg ( " -rpcwait " , false ) ;
2014-10-29 18:08:31 +01:00
do {
try {
2017-09-28 08:33:12 +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 ( ) ;
2014-10-29 18:08:31 +01:00
if ( fWait & & code = = RPC_IN_WARMUP )
throw CConnectionFailed ( " server in warmup " ) ;
2015-05-18 14:02:18 +02:00
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-27 17:51:14 +02:00
if ( errCode . isNum ( ) & & errCode . get_int ( ) = = RPC_WALLET_NOT_SPECIFIED ) {
2019-08-13 18:27:56 +02:00
strPrint + = " \n Try adding \" -rpcwallet=<filename> \" option to dash-cli command line. " ;
2017-07-27 17:51:14 +02:00
}
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 )
2021-07-13 11:31:17 +02:00
UninterruptibleSleep ( std : : chrono : : milliseconds { 1000 } ) ;
2014-10-29 18:08:31 +01:00
else
throw ;
}
} while ( fWait ) ;
2013-10-11 23:09:59 +02:00
}
2014-12-07 13:29:06 +01:00
catch ( const std : : exception & e ) {
2016-11-25 11:33:05 +01:00
strPrint = std : : string ( " error: " ) + e . what ( ) ;
2014-05-26 11:38:44 +02:00
nRet = EXIT_FAILURE ;
}
catch ( . . . ) {
2019-02-21 19:37:16 +01:00
PrintExceptionContinue ( std : : current_exception ( ) , " CommandLineRPC() " ) ;
2014-05-26 11:38:44 +02:00
throw ;
}
2014-06-26 03:09:36 +02:00
if ( strPrint ! = " " ) {
2022-03-21 18:28:10 +01:00
tfm : : format ( nRet = = 0 ? std : : cout : std : : cerr , " %s \n " , strPrint ) ;
2014-05-26 11:38:44 +02:00
}
return nRet ;
2013-10-11 23:09:59 +02:00
}
int main ( int argc , char * argv [ ] )
{
2019-02-21 19:37:16 +01:00
RegisterPrettyTerminateHander ( ) ;
RegisterPrettySignalHandlers ( ) ;
2018-10-08 03:47:03 +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 ( ) ) {
2021-10-24 12:51:47 +02:00
tfm : : format ( std : : cerr , " Error: Initializing networking failed \n " ) ;
2017-09-15 15:12:07 +02:00
return EXIT_FAILURE ;
2015-09-02 16:18:16 +02:00
}
2018-06-07 08:58:06 +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-11 06:16:39 +01:00
int ret = AppInitRPC ( argc , argv ) ;
if ( ret ! = CONTINUE_EXECUTION )
return ret ;
2013-10-11 23:09:59 +02:00
} catch ( . . . ) {
2019-02-21 19:37:16 +01:00
PrintExceptionContinue ( std : : current_exception ( ) , " 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
} catch ( . . . ) {
2019-02-21 19:37:16 +01:00
PrintExceptionContinue ( std : : current_exception ( ) , " 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
}