8 #if defined(HAVE_CONFIG_H)
23 #include <event2/buffer.h>
24 #include <event2/keyvalq_struct.h>
29 static const char DEFAULT_RPCCONNECT[] =
"127.0.0.1";
30 static const bool DEFAULT_NAMED=
false;
31 static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
32 static const int CONTINUE_EXECUTION=-1;
42 strUsage +=
HelpMessageOpt(
"-datadir=<dir>",
"Specify data directory");
44 strUsage +=
HelpMessageOpt(
"-named",
strprintf(
"Pass named instead of positional arguments (default: %s)", DEFAULT_NAMED));
45 strUsage +=
HelpMessageOpt(
"-rpcconnect=<ip>",
strprintf(
"Send commands to node running on <ip> (default: %s)", DEFAULT_RPCCONNECT));
46 strUsage +=
HelpMessageOpt(
"-rpcport=<port>",
strprintf(
"Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()));
47 strUsage +=
HelpMessageOpt(
"-rpcwait",
"Wait for RPC server to start");
48 strUsage +=
HelpMessageOpt(
"-rpcuser=<user>",
"Username for JSON-RPC connections");
49 strUsage +=
HelpMessageOpt(
"-rpcpassword=<pw>",
"Password for JSON-RPC connections");
50 strUsage +=
HelpMessageOpt(
"-rpcclienttimeout=<n>",
strprintf(
"Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)", DEFAULT_HTTP_CLIENT_TIMEOUT));
51 strUsage +=
HelpMessageOpt(
"-rpcwallet=<walletname>",
"Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to pivxd)");
57 static void libevent_log_cb(
int severity,
const char *msg)
60 # define EVENT_LOG_ERR _EVENT_LOG_ERR
64 throw std::runtime_error(
strprintf(
"libevent error: %s", msg));
89 static int AppInitRPC(
int argc,
char*
argv[])
99 "Usage: pivx-cli [options] <command> [params] Send command to " PACKAGE_NAME "\n"
100 "or: pivx-cli [options] -named <command> [name=value]... Send command to " PACKAGE_NAME " (with named arguments)\n"
101 "or: pivx-cli [options] help List commands\n"
102 "or: pivx-cli [options] help <command> Get help for a command\n";
106 fprintf(stdout,
"%s", strUsage.c_str());
108 fprintf(stderr,
"Error: too few parameters\n");
114 fprintf(stderr,
"Error: Specified data directory \"%s\" does not exist.\n",
gArgs.
GetArg(
"-datadir",
"").c_str());
119 }
catch (
const std::exception& e) {
120 fprintf(stderr,
"Error reading configuration file: %s\n", e.what());
126 }
catch(
const std::exception& e) {
127 fprintf(stderr,
"Error: %s\n", e.what());
132 fprintf(stderr,
"Error: SSL mode for RPC (-rpcssl) is no longer supported.\n");
135 return CONTINUE_EXECUTION;
152 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
153 case EVREQ_HTTP_TIMEOUT:
154 return "timeout reached";
156 return "EOF reached";
157 case EVREQ_HTTP_INVALID_HEADER:
158 return "error while reading header, or invalid header";
159 case EVREQ_HTTP_BUFFER_ERROR:
160 return "error encountered while reading or writing";
161 case EVREQ_HTTP_REQUEST_CANCEL:
162 return "request was canceled";
163 case EVREQ_HTTP_DATA_TOO_LONG:
164 return "response body is larger than allowed";
171 static void http_request_done(
struct evhttp_request *req,
void *ctx)
175 if (req ==
nullptr) {
183 reply->
status = evhttp_request_get_response_code(req);
185 struct evbuffer *buf = evhttp_request_get_input_buffer(req);
188 size_t size = evbuffer_get_length(buf);
189 const char *data = (
const char*)evbuffer_pullup(buf, size);
191 reply->
body = std::string(data, size);
192 evbuffer_drain(buf, size);
196 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
197 static void http_error_cb(
enum evhttp_request_error err,
void *ctx)
206 std::string host =
gArgs.
GetArg(
"-rpcconnect", DEFAULT_RPCCONNECT);
214 evhttp_connection_set_timeout(evcon.get(),
gArgs.
GetArg(
"-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT));
219 throw std::runtime_error(
"create http request failed");
220 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
221 evhttp_request_set_error_cb(req.get(), http_error_cb);
225 std::string strRPCUserColonPass;
230 _(
"Could not locate RPC credentials. No authentication cookie could be found, and no rpcpassword is set in the configuration file (%s)"),
238 struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get());
239 assert(output_headers);
240 evhttp_add_header(output_headers,
"Host", host.c_str());
241 evhttp_add_header(output_headers,
"Connection",
"close");
242 evhttp_add_header(output_headers,
"Authorization", (std::string(
"Basic ") +
EncodeBase64(strRPCUserColonPass)).c_str());
246 struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get());
247 assert(output_buffer);
248 evbuffer_add(output_buffer, strRequest.data(), strRequest.size());
251 std::string endpoint =
"/";
253 std::string walletName =
gArgs.
GetArg(
"-rpcwallet",
"");
254 char* encodedURI = evhttp_uriencode(walletName.c_str(), walletName.size(),
false);
256 endpoint =
"/wallet/"+ std::string(encodedURI);
262 int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST,
"/");
268 event_base_dispatch(base.get());
273 throw std::runtime_error(
"incorrect rpcuser or rpcpassword (authorization failed)");
275 throw std::runtime_error(
strprintf(
"server returned HTTP error %d", response.
status));
276 else if (response.
body.empty())
277 throw std::runtime_error(
"no response from server");
282 throw std::runtime_error(
"couldn't parse reply from server");
285 throw std::runtime_error(
"expected reply to have result, error and id properties");
292 std::string strPrint;
303 throw std::runtime_error(
"too few parameters");
304 std::string strMethod =
argv[1];
307 std::vector<std::string> strParams(&
argv[2], &
argv[argc]);
325 if (!
error.isNull()) {
327 int code =
error[
"code"].get_int();
330 strPrint =
"error: " +
error.write();
332 if (
error.isObject()) {
335 strPrint = errCode.
isNull() ?
"" :
"error code: "+errCode.
getValStr()+
"\n";
338 strPrint +=
"error message:\n"+errMsg.
get_str();
341 strPrint +=
"\nTry adding \"-rpcwallet=<filename>\" option to pivx-cli command line.";
348 else if (result.
isStr())
351 strPrint = result.
write(2);
362 }
catch (
const boost::thread_interrupted&) {
364 }
catch (
const std::exception& e) {
365 strPrint = std::string(
"error: ") + e.what();
372 if (strPrint !=
"") {
373 fprintf((nRet == 0 ? stdout : stderr),
"%s\n", strPrint.c_str());
384 __declspec(dllexport)
int main(
int argc,
char*
argv[])
386 util::WinCmdLineArgs winArgs;
387 std::tie(argc,
argv) = winArgs.get();
394 fprintf(stderr,
"Error: Initializing networking failed\n");
397 event_set_log_callback(&libevent_log_cb);
400 int ret = AppInitRPC(argc,
argv);
401 if (ret != CONTINUE_EXECUTION)
403 }
catch (
const std::exception& e) {
411 int ret = EXIT_FAILURE;
414 }
catch (
const std::exception& e) {
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
void SelectBaseParams(const std::string &chain)
Sets the params returned by Params() to those for the given network.
std::unique_ptr< CBaseChainParams > CreateBaseChainParams(const std::string &chain)
Creates and returns a std::unique_ptr<CBaseChainParams> of the chosen chain.
void AppendParamsHelpMessages(std::string &strUsage, bool debugHelp)
Append the help messages for the chainparams options to the parameter string.
void ReadConfigFile(const std::string &confPath)
void ParseParameters(int argc, const char *const argv[])
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
static const std::string TESTNET
static const std::string MAIN
Chain name strings.
CConnectionFailed(const std::string &msg)
const std::string & get_str() const
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
const UniValue & get_obj() const
const std::string & getValStr() const
bool read(const char *raw, size_t len)
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()
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)
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue ¶ms, const UniValue &id)
JSON-RPC protocol.
@ HTTP_INTERNAL_SERVER_ERROR
@ RPC_WALLET_NOT_SPECIFIED
No wallet specified (error when there are multiple wallets loaded)
@ RPC_IN_WARMUP
Transaction already in chain.
Reply structure for request_done to fill in.
const char *const PIVX_CONF_FILENAME
bool CheckDataDirOption()
fs::path GetConfigFile(const std::string &confPath)
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.
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 Optional result.
bool IsSwitchChar(char c)
const UniValue & find_value(const UniValue &obj, const std::string &name)
std::string EncodeBase64(Span< const unsigned char > input)
void MilliSleep(int64_t n)