6 #if defined(HAVE_CONFIG_H)
7 #include "config/bitcoin-config.h"
17 #include <boost/filesystem/operations.hpp>
20 #include <event2/buffer.h>
21 #include <event2/keyvalq_struct.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;
37 strUsage +=
HelpMessageOpt(
"-datadir=<dir>",
_(
"Specify data directory"));
39 strUsage +=
HelpMessageOpt(
"-named",
strprintf(
_(
"Pass named instead of positional arguments (default: %s)"), DEFAULT_NAMED));
40 strUsage +=
HelpMessageOpt(
"-rpcconnect=<ip>",
strprintf(
_(
"Send commands to node running on <ip> (default: %s)"), DEFAULT_RPCCONNECT));
42 strUsage +=
HelpMessageOpt(
"-rpcwait",
_(
"Wait for RPC server to start"));
43 strUsage +=
HelpMessageOpt(
"-rpcuser=<user>",
_(
"Username for JSON-RPC connections"));
44 strUsage +=
HelpMessageOpt(
"-rpcpassword=<pw>",
_(
"Password for JSON-RPC connections"));
45 strUsage +=
HelpMessageOpt(
"-rpcclienttimeout=<n>",
strprintf(
_(
"Timeout during HTTP requests (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT));
46 strUsage +=
HelpMessageOpt(
"-stdin",
_(
"Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases)"));
65 std::runtime_error(msg)
74 static int AppInitRPC(
int argc,
char* argv[])
83 strUsage +=
"\n" +
_(
"Usage:") +
"\n" +
84 " dogecoin-cli [options] <command> [params] " +
strprintf(
_(
"Send command to %s"),
_(PACKAGE_NAME)) +
"\n" +
85 " dogecoin-cli [options] -named <command> [name=value] ... " +
strprintf(
_(
"Send command to %s (with named arguments)"),
_(PACKAGE_NAME)) +
"\n" +
86 " dogecoin-cli [options] help " +
_(
"List commands") +
"\n" +
87 " dogecoin-cli [options] help <command> " +
_(
"Get help for a command") +
"\n";
92 fprintf(stdout,
"%s", strUsage.c_str());
94 fprintf(stderr,
"Error: too few parameters\n");
99 if (!boost::filesystem::is_directory(
GetDataDir(
false))) {
100 fprintf(stderr,
"Error: Specified data directory \"%s\" does not exist.\n",
GetArg(
"-datadir",
"").c_str());
105 }
catch (
const std::exception& e) {
106 fprintf(stderr,
"Error reading configuration file: %s\n", e.what());
112 }
catch (
const std::exception& e) {
113 fprintf(stderr,
"Error: %s\n", e.what());
118 fprintf(stderr,
"Error: SSL mode for RPC (-rpcssl) is no longer supported.\n");
121 return CONTINUE_EXECUTION;
138 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
139 case EVREQ_HTTP_TIMEOUT:
140 return "timeout reached";
142 return "EOF reached";
143 case EVREQ_HTTP_INVALID_HEADER:
144 return "error while reading header, or invalid header";
145 case EVREQ_HTTP_BUFFER_ERROR:
146 return "error encountered while reading or writing";
147 case EVREQ_HTTP_REQUEST_CANCEL:
148 return "request was canceled";
149 case EVREQ_HTTP_DATA_TOO_LONG:
150 return "response body is larger than allowed";
157 static void http_request_done(
struct evhttp_request *req,
void *ctx)
169 reply->
status = evhttp_request_get_response_code(req);
171 struct evbuffer *buf = evhttp_request_get_input_buffer(req);
174 size_t size = evbuffer_get_length(buf);
175 const char *data = (
const char*)evbuffer_pullup(buf, size);
177 reply->
body = std::string(data, size);
178 evbuffer_drain(buf, size);
182 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
183 static void http_error_cb(
enum evhttp_request_error err,
void *ctx)
192 std::string host =
GetArg(
"-rpcconnect", DEFAULT_RPCCONNECT);
200 evhttp_connection_set_timeout(evcon.get(),
GetArg(
"-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT));
205 throw std::runtime_error(
"create http request failed");
206 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
207 evhttp_request_set_error_cb(req.get(), http_error_cb);
211 std::string strRPCUserColonPass;
212 if (
GetArg(
"-rpcpassword",
"") ==
"") {
216 _(
"Could not locate RPC credentials. No authentication cookie could be found, and no rpcpassword is set in the configuration file (%s)"),
221 strRPCUserColonPass =
GetArg(
"-rpcuser",
"") +
":" +
GetArg(
"-rpcpassword",
"");
224 struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get());
225 assert(output_headers);
226 evhttp_add_header(output_headers,
"Host", host.c_str());
227 evhttp_add_header(output_headers,
"Connection",
"close");
228 evhttp_add_header(output_headers,
"Authorization", (std::string(
"Basic ") +
EncodeBase64(strRPCUserColonPass)).c_str());
232 struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get());
233 assert(output_buffer);
234 evbuffer_add(output_buffer, strRequest.data(), strRequest.size());
236 int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST,
"/");
242 event_base_dispatch(
base.get());
247 throw std::runtime_error(
"incorrect rpcuser or rpcpassword (authorization failed)");
249 throw std::runtime_error(
strprintf(
"server returned HTTP error %d", response.
status));
250 else if (response.
body.empty())
251 throw std::runtime_error(
"no response from server");
256 throw std::runtime_error(
"couldn't parse reply from server");
259 throw std::runtime_error(
"expected reply to have result, error and id properties");
266 std::string strPrint;
274 std::vector<std::string> args = std::vector<std::string>(&argv[1], &argv[argc]);
278 while (std::getline(std::cin,line))
279 args.push_back(line);
282 throw std::runtime_error(
"too few parameters (need at least command)");
283 std::string strMethod = args[0];
284 args.erase(args.begin());
294 const bool fWait =
GetBoolArg(
"-rpcwait",
false);
303 if (!
error.isNull()) {
305 int code =
error[
"code"].get_int();
308 strPrint =
"error: " +
error.write();
310 if (
error.isObject())
314 strPrint = errCode.
isNull() ?
"" :
"error code: "+errCode.
getValStr()+
"\n";
317 strPrint +=
"error message:\n"+errMsg.
get_str();
323 else if (result.
isStr())
326 strPrint = result.
write(2);
339 catch (
const boost::thread_interrupted&) {
342 catch (
const std::exception& e) {
343 strPrint = std::string(
"error: ") + e.what();
351 if (strPrint !=
"") {
352 fprintf((nRet == 0 ? stdout : stderr),
"%s\n", strPrint.c_str());
357 int main(
int argc,
char* argv[])
361 fprintf(stderr,
"Error: Initializing networking failed\n");
366 int ret = AppInitRPC(argc, argv);
367 if (ret != CONTINUE_EXECUTION)
370 catch (
const std::exception& e) {
378 int ret = EXIT_FAILURE;
382 catch (
const std::exception& e) {
int main(int argc, char *argv[])
std::string HelpMessageCli()
int CommandLineRPC(int argc, char *argv[])
const char * http_errorstring(int code)
UniValue CallRPC(const std::string &strMethod, const UniValue ¶ms)
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
std::string ChainNameFromCommandLine()
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
void SelectBaseParams(const std::string &chain)
Sets the params returned by Params() to those for the given network.
void AppendParamsHelpMessages(std::string &strUsage, bool debugHelp)
Append the help messages for the chainparams options to the parameter string.
static const std::string TESTNET
static const std::string MAIN
BIP70 chain name strings (main, test or regtest)
CConnectionFailed(const std::string &msg)
const std::string & get_str() const
const UniValue & get_obj() const
const std::string & getValStr() const
bool read(const char *raw)
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert named arguments to command-specific RPC representation.
std::string FormatFullVersion()
raii_evhttp_request obtain_evhttp_request(void(*cb)(struct evhttp_request *, void *), void *arg)
raii_evhttp_connection obtain_evhttp_connection_base(struct event_base *base, std::string host, uint16_t port)
raii_event_base obtain_event_base()
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
UniValue JSONRPCRequestObj(const string &strMethod, const UniValue ¶ms, const UniValue &id)
JSON-RPC protocol.
@ HTTP_INTERNAL_SERVER_ERROR
@ RPC_IN_WARMUP
Client still warming up.
Reply structure for request_done to fill in.
const UniValue & find_value(const UniValue &obj, const std::string &name)
boost::filesystem::path GetConfigFile(const std::string &confPath)
std::string GetArg(const std::string &strArg, const std::string &strDefault)
Return string argument or default value.
void ParseParameters(int argc, const char *const argv[])
void ReadConfigFile(const std::string &confPath)
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
const char *const BITCOIN_CONF_FILENAME
bool IsArgSet(const std::string &strArg)
Return true if the given argument has been manually set.
std::string HelpMessageOpt(const std::string &option, const std::string &message)
Format a string to be used as option description in help messages.
bool error(const char *fmt, const Args &... args)
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result.
bool IsSwitchChar(char c)
string EncodeBase64(const unsigned char *pch, size_t len)
void MilliSleep(int64_t n)