1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #if defined(HAVE_CONFIG_H)
7 #include "config/bitcoin-config.h"
10 #include "chainparamsbase.h"
11 #include "clientversion.h"
13 #include "rpc/client.h"
14 #include "rpc/protocol.h"
16 #include "utilstrencodings.h"
20 #include <event2/buffer.h>
21 #include <event2/keyvalq_struct.h>
22 #include "support/events.h"
26 static const char DEFAULT_RPCCONNECT
[] = "127.0.0.1";
27 static const int DEFAULT_HTTP_CLIENT_TIMEOUT
=900;
28 static const bool DEFAULT_NAMED
=false;
29 static const int CONTINUE_EXECUTION
=-1;
31 std::string
HelpMessageCli()
33 const auto defaultBaseParams
= CreateBaseChainParams(CBaseChainParams::MAIN
);
34 const auto testnetBaseParams
= CreateBaseChainParams(CBaseChainParams::TESTNET
);
36 strUsage
+= HelpMessageGroup(_("Options:"));
37 strUsage
+= HelpMessageOpt("-?", _("This help message"));
38 strUsage
+= HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME
));
39 strUsage
+= HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
40 AppendParamsHelpMessages(strUsage
);
41 strUsage
+= HelpMessageOpt("-named", strprintf(_("Pass named instead of positional arguments (default: %s)"), DEFAULT_NAMED
));
42 strUsage
+= HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), DEFAULT_RPCCONNECT
));
43 strUsage
+= HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), defaultBaseParams
->RPCPort(), testnetBaseParams
->RPCPort()));
44 strUsage
+= HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
45 strUsage
+= HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
46 strUsage
+= HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
47 strUsage
+= HelpMessageOpt("-rpcclienttimeout=<n>", strprintf(_("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT
));
48 strUsage
+= HelpMessageOpt("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases)"));
53 //////////////////////////////////////////////////////////////////////////////
59 // Exception thrown on connection error. This error is used to determine
60 // when to wait if -rpcwait is given.
62 class CConnectionFailed
: public std::runtime_error
66 explicit inline CConnectionFailed(const std::string
& msg
) :
67 std::runtime_error(msg
)
73 // This function returns either one of EXIT_ codes when it's expected to stop the process or
74 // CONTINUE_EXECUTION when it's expected to continue further.
76 static int AppInitRPC(int argc
, char* argv
[])
81 ParseParameters(argc
, argv
);
82 if (argc
<2 || IsArgSet("-?") || IsArgSet("-h") || IsArgSet("-help") || IsArgSet("-version")) {
83 std::string strUsage
= strprintf(_("%s RPC client version"), _(PACKAGE_NAME
)) + " " + FormatFullVersion() + "\n";
84 if (!IsArgSet("-version")) {
85 strUsage
+= "\n" + _("Usage:") + "\n" +
86 " bitcoin-cli [options] <command> [params] " + strprintf(_("Send command to %s"), _(PACKAGE_NAME
)) + "\n" +
87 " bitcoin-cli [options] -named <command> [name=value] ... " + strprintf(_("Send command to %s (with named arguments)"), _(PACKAGE_NAME
)) + "\n" +
88 " bitcoin-cli [options] help " + _("List commands") + "\n" +
89 " bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n";
91 strUsage
+= "\n" + HelpMessageCli();
94 fprintf(stdout
, "%s", strUsage
.c_str());
96 fprintf(stderr
, "Error: too few parameters\n");
101 if (!fs::is_directory(GetDataDir(false))) {
102 fprintf(stderr
, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str());
106 ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME
));
107 } catch (const std::exception
& e
) {
108 fprintf(stderr
,"Error reading configuration file: %s\n", e
.what());
111 // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
113 SelectBaseParams(ChainNameFromCommandLine());
114 } catch (const std::exception
& e
) {
115 fprintf(stderr
, "Error: %s\n", e
.what());
118 if (GetBoolArg("-rpcssl", false))
120 fprintf(stderr
, "Error: SSL mode for RPC (-rpcssl) is no longer supported.\n");
123 return CONTINUE_EXECUTION
;
127 /** Reply structure for request_done to fill in */
130 HTTPReply(): status(0), error(-1) {}
137 const char *http_errorstring(int code
)
140 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
141 case EVREQ_HTTP_TIMEOUT
:
142 return "timeout reached";
144 return "EOF reached";
145 case EVREQ_HTTP_INVALID_HEADER
:
146 return "error while reading header, or invalid header";
147 case EVREQ_HTTP_BUFFER_ERROR
:
148 return "error encountered while reading or writing";
149 case EVREQ_HTTP_REQUEST_CANCEL
:
150 return "request was canceled";
151 case EVREQ_HTTP_DATA_TOO_LONG
:
152 return "response body is larger than allowed";
159 static void http_request_done(struct evhttp_request
*req
, void *ctx
)
161 HTTPReply
*reply
= static_cast<HTTPReply
*>(ctx
);
164 /* If req is NULL, it means an error occurred while connecting: the
165 * error code will have been passed to http_error_cb.
171 reply
->status
= evhttp_request_get_response_code(req
);
173 struct evbuffer
*buf
= evhttp_request_get_input_buffer(req
);
176 size_t size
= evbuffer_get_length(buf
);
177 const char *data
= (const char*)evbuffer_pullup(buf
, size
);
179 reply
->body
= std::string(data
, size
);
180 evbuffer_drain(buf
, size
);
184 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
185 static void http_error_cb(enum evhttp_request_error err
, void *ctx
)
187 HTTPReply
*reply
= static_cast<HTTPReply
*>(ctx
);
192 UniValue
CallRPC(const std::string
& strMethod
, const UniValue
& params
)
194 std::string host
= GetArg("-rpcconnect", DEFAULT_RPCCONNECT
);
195 int port
= GetArg("-rpcport", BaseParams().RPCPort());
198 raii_event_base base
= obtain_event_base();
200 // Synchronously look up hostname
201 raii_evhttp_connection evcon
= obtain_evhttp_connection_base(base
.get(), host
, port
);
202 evhttp_connection_set_timeout(evcon
.get(), GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT
));
205 raii_evhttp_request req
= obtain_evhttp_request(http_request_done
, (void*)&response
);
207 throw std::runtime_error("create http request failed");
208 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
209 evhttp_request_set_error_cb(req
.get(), http_error_cb
);
213 std::string strRPCUserColonPass
;
214 if (GetArg("-rpcpassword", "") == "") {
215 // Try fall back to cookie-based authentication if no password is provided
216 if (!GetAuthCookie(&strRPCUserColonPass
)) {
217 throw std::runtime_error(strprintf(
218 _("Could not locate RPC credentials. No authentication cookie could be found, and no rpcpassword is set in the configuration file (%s)"),
219 GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME
)).string().c_str()));
223 strRPCUserColonPass
= GetArg("-rpcuser", "") + ":" + GetArg("-rpcpassword", "");
226 struct evkeyvalq
* output_headers
= evhttp_request_get_output_headers(req
.get());
227 assert(output_headers
);
228 evhttp_add_header(output_headers
, "Host", host
.c_str());
229 evhttp_add_header(output_headers
, "Connection", "close");
230 evhttp_add_header(output_headers
, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass
)).c_str());
232 // Attach request data
233 std::string strRequest
= JSONRPCRequestObj(strMethod
, params
, 1).write() + "\n";
234 struct evbuffer
* output_buffer
= evhttp_request_get_output_buffer(req
.get());
235 assert(output_buffer
);
236 evbuffer_add(output_buffer
, strRequest
.data(), strRequest
.size());
238 int r
= evhttp_make_request(evcon
.get(), req
.get(), EVHTTP_REQ_POST
, "/");
239 req
.release(); // ownership moved to evcon in above call
241 throw CConnectionFailed("send http request failed");
244 event_base_dispatch(base
.get());
246 if (response
.status
== 0)
247 throw CConnectionFailed(strprintf("couldn't connect to server: %s (code %d)\n(make sure server is running and you are connecting to the correct RPC port)", http_errorstring(response
.error
), response
.error
));
248 else if (response
.status
== HTTP_UNAUTHORIZED
)
249 throw std::runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
250 else if (response
.status
>= 400 && response
.status
!= HTTP_BAD_REQUEST
&& response
.status
!= HTTP_NOT_FOUND
&& response
.status
!= HTTP_INTERNAL_SERVER_ERROR
)
251 throw std::runtime_error(strprintf("server returned HTTP error %d", response
.status
));
252 else if (response
.body
.empty())
253 throw std::runtime_error("no response from server");
256 UniValue
valReply(UniValue::VSTR
);
257 if (!valReply
.read(response
.body
))
258 throw std::runtime_error("couldn't parse reply from server");
259 const UniValue
& reply
= valReply
.get_obj();
261 throw std::runtime_error("expected reply to have result, error and id properties");
266 int CommandLineRPC(int argc
, char *argv
[])
268 std::string strPrint
;
272 while (argc
> 1 && IsSwitchChar(argv
[1][0])) {
276 std::vector
<std::string
> args
= std::vector
<std::string
>(&argv
[1], &argv
[argc
]);
277 if (GetBoolArg("-stdin", false)) {
278 // Read one arg per line from stdin and append
280 while (std::getline(std::cin
,line
))
281 args
.push_back(line
);
284 throw std::runtime_error("too few parameters (need at least command)");
285 std::string strMethod
= args
[0];
286 args
.erase(args
.begin()); // Remove trailing method name from arguments vector
289 if(GetBoolArg("-named", DEFAULT_NAMED
)) {
290 params
= RPCConvertNamedValues(strMethod
, args
);
292 params
= RPCConvertValues(strMethod
, args
);
295 // Execute and handle connection failures with -rpcwait
296 const bool fWait
= GetBoolArg("-rpcwait", false);
299 const UniValue reply
= CallRPC(strMethod
, params
);
302 const UniValue
& result
= find_value(reply
, "result");
303 const UniValue
& error
= find_value(reply
, "error");
305 if (!error
.isNull()) {
307 int code
= error
["code"].get_int();
308 if (fWait
&& code
== RPC_IN_WARMUP
)
309 throw CConnectionFailed("server in warmup");
310 strPrint
= "error: " + error
.write();
312 if (error
.isObject())
314 UniValue errCode
= find_value(error
, "code");
315 UniValue errMsg
= find_value(error
, "message");
316 strPrint
= errCode
.isNull() ? "" : "error code: "+errCode
.getValStr()+"\n";
319 strPrint
+= "error message:\n"+errMsg
.get_str();
325 else if (result
.isStr())
326 strPrint
= result
.get_str();
328 strPrint
= result
.write(2);
330 // Connection succeeded, no need to retry.
333 catch (const CConnectionFailed
&) {
341 catch (const boost::thread_interrupted
&) {
344 catch (const std::exception
& e
) {
345 strPrint
= std::string("error: ") + e
.what();
349 PrintExceptionContinue(NULL
, "CommandLineRPC()");
353 if (strPrint
!= "") {
354 fprintf((nRet
== 0 ? stdout
: stderr
), "%s\n", strPrint
.c_str());
359 int main(int argc
, char* argv
[])
362 if (!SetupNetworking()) {
363 fprintf(stderr
, "Error: Initializing networking failed\n");
368 int ret
= AppInitRPC(argc
, argv
);
369 if (ret
!= CONTINUE_EXECUTION
)
372 catch (const std::exception
& e
) {
373 PrintExceptionContinue(&e
, "AppInitRPC()");
376 PrintExceptionContinue(NULL
, "AppInitRPC()");
380 int ret
= EXIT_FAILURE
;
382 ret
= CommandLineRPC(argc
, argv
);
384 catch (const std::exception
& e
) {
385 PrintExceptionContinue(&e
, "CommandLineRPC()");
387 PrintExceptionContinue(NULL
, "CommandLineRPC()");