Bitcoin ABC  0.22.13
P2P Digital Currency
server.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2018 The Bitcoin Core developers
3 // Copyright (c) 2018-2019 The Bitcoin developers
4 // Distributed under the MIT software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include <rpc/server.h>
8 
9 #include <config.h>
10 #include <rpc/util.h>
11 #include <shutdown.h>
12 #include <sync.h>
13 #include <util/strencodings.h>
14 
15 #include <boost/algorithm/string/classification.hpp>
16 #include <boost/algorithm/string/split.hpp>
17 #include <boost/signals2/signal.hpp>
18 
19 #include <memory> // for unique_ptr
20 #include <set>
21 #include <unordered_map>
22 
24 static std::atomic<bool> g_rpc_running{false};
25 static bool fRPCInWarmup GUARDED_BY(cs_rpcWarmup) = true;
26 static std::string
27  rpcWarmupStatus GUARDED_BY(cs_rpcWarmup) = "RPC server started";
28 /* Timer-creating functions */
30 /* Map of name to timer. */
32 static std::map<std::string, std::unique_ptr<RPCTimerBase>>
33  deadlineTimers GUARDED_BY(g_deadline_timers_mutex);
34 static bool ExecuteCommand(Config &config, const CRPCCommand &command,
35  const JSONRPCRequest &request, UniValue &result,
36  bool last_handler);
37 
39  std::string method;
40  int64_t start;
41 };
42 
43 struct RPCServerInfo {
45  std::list<RPCCommandExecutionInfo> active_commands GUARDED_BY(mutex);
46 };
47 
49 
51  std::list<RPCCommandExecutionInfo>::iterator it;
52  explicit RPCCommandExecution(const std::string &method) {
53  LOCK(g_rpc_server_info.mutex);
54  it = g_rpc_server_info.active_commands.insert(
55  g_rpc_server_info.active_commands.cend(),
56  {method, GetTimeMicros()});
57  }
59  LOCK(g_rpc_server_info.mutex);
60  g_rpc_server_info.active_commands.erase(it);
61  }
62 };
63 
65  const JSONRPCRequest &request) const {
66  // Return immediately if in warmup
67  // This is retained from the old RPC implementation because a lot of state
68  // is set during warmup that RPC commands may depend on. This can be
69  // safely removed once global variable usage has been eliminated.
70  {
71  LOCK(cs_rpcWarmup);
72  if (fRPCInWarmup) {
73  throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus);
74  }
75  }
76 
77  std::string commandName = request.strMethod;
78  {
79  auto commandsReadView = commands.getReadView();
80  auto iter = commandsReadView->find(commandName);
81  if (iter != commandsReadView.end()) {
82  return iter->second.get()->Execute(request);
83  }
84  }
85 
86  // TODO Remove the below call to tableRPC.execute() and only call it for
87  // context-free RPC commands via an implementation of RPCCommand.
88 
89  // Check if context-free RPC method is valid and execute it
90  return tableRPC.execute(config, request);
91 }
92 
93 void RPCServer::RegisterCommand(std::unique_ptr<RPCCommand> command) {
94  if (command != nullptr) {
95  const std::string &commandName = command->GetName();
96  commands.getWriteView()->insert(
97  std::make_pair(commandName, std::move(command)));
98  }
99 }
100 
101 static struct CRPCSignals {
102  boost::signals2::signal<void()> Started;
103  boost::signals2::signal<void()> Stopped;
104 } g_rpcSignals;
105 
106 void RPCServerSignals::OnStarted(std::function<void()> slot) {
107  g_rpcSignals.Started.connect(slot);
108 }
109 
110 void RPCServerSignals::OnStopped(std::function<void()> slot) {
111  g_rpcSignals.Stopped.connect(slot);
112 }
113 
114 std::string CRPCTable::help(Config &config, const std::string &strCommand,
115  const JSONRPCRequest &helpreq) const {
116  std::string strRet;
117  std::string category;
118  std::set<intptr_t> setDone;
119  std::vector<std::pair<std::string, const CRPCCommand *>> vCommands;
120 
121  for (const auto &entry : mapCommands) {
122  vCommands.push_back(
123  std::make_pair(entry.second.front()->category + entry.first,
124  entry.second.front()));
125  }
126  sort(vCommands.begin(), vCommands.end());
127 
128  JSONRPCRequest jreq(helpreq);
129  jreq.fHelp = true;
130  jreq.params = UniValue();
131 
132  for (const std::pair<std::string, const CRPCCommand *> &command :
133  vCommands) {
134  const CRPCCommand *pcmd = command.second;
135  std::string strMethod = pcmd->name;
136  if ((strCommand != "" || pcmd->category == "hidden") &&
137  strMethod != strCommand) {
138  continue;
139  }
140 
141  jreq.strMethod = strMethod;
142  try {
143  UniValue unused_result;
144  if (setDone.insert(pcmd->unique_id).second) {
145  pcmd->actor(config, jreq, unused_result,
146  true /* last_handler */);
147  }
148  } catch (const std::exception &e) {
149  // Help text is returned in an exception
150  std::string strHelp = std::string(e.what());
151  if (strCommand == "") {
152  if (strHelp.find('\n') != std::string::npos) {
153  strHelp = strHelp.substr(0, strHelp.find('\n'));
154  }
155 
156  if (category != pcmd->category) {
157  if (!category.empty()) {
158  strRet += "\n";
159  }
160  category = pcmd->category;
161  strRet += "== " + Capitalize(category) + " ==\n";
162  }
163  }
164  strRet += strHelp + "\n";
165  }
166  }
167  if (strRet == "") {
168  strRet = strprintf("help: unknown command: %s\n", strCommand);
169  }
170 
171  strRet = strRet.substr(0, strRet.size() - 1);
172  return strRet;
173 }
174 
175 static UniValue help(Config &config, const JSONRPCRequest &jsonRequest) {
176  if (jsonRequest.fHelp || jsonRequest.params.size() > 1) {
177  throw std::runtime_error(RPCHelpMan{
178  "help",
179  "List all commands, or get help for a specified command.\n",
180  {
181  {"command", RPCArg::Type::STR, /* default */ "all commands",
182  "The command to get help on"},
183  },
184  RPCResult{RPCResult::Type::STR, "", "The help text"},
185  RPCExamples{""},
186  }
187  .ToString());
188  }
189 
190  std::string strCommand;
191  if (jsonRequest.params.size() > 0) {
192  strCommand = jsonRequest.params[0].get_str();
193  }
194 
195  return tableRPC.help(config, strCommand, jsonRequest);
196 }
197 
198 static UniValue stop(const Config &config, const JSONRPCRequest &jsonRequest) {
199  static const std::string RESULT{PACKAGE_NAME " stopping"};
200  // Accept the deprecated and ignored 'detach' boolean argument
201  // Also accept the hidden 'wait' integer argument (milliseconds)
202  // For instance, 'stop 1000' makes the call wait 1 second before returning
203  // to the client (intended for testing)
204  if (jsonRequest.fHelp || jsonRequest.params.size() > 1) {
205  throw std::runtime_error(RPCHelpMan{
206  "stop",
207  "\nRequest a graceful shutdown of " PACKAGE_NAME ".",
208  {},
210  "A string with the content '" + RESULT + "'"},
211  RPCExamples{""},
212  }
213  .ToString());
214  }
215 
216  // Event loop will exit after current HTTP requests have been handled, so
217  // this reply will get back to the client.
218  StartShutdown();
219  if (jsonRequest.params[0].isNum()) {
221  std::chrono::milliseconds{jsonRequest.params[0].get_int()});
222  }
223  return RESULT;
224 }
225 
226 static UniValue uptime(const Config &config, const JSONRPCRequest &request) {
227  RPCHelpMan{
228  "uptime",
229  "Returns the total uptime of the server.\n",
230  {},
232  "The number of seconds that the server has been running"},
233  RPCExamples{HelpExampleCli("uptime", "") +
234  HelpExampleRpc("uptime", "")},
235  }
236  .Check(request);
237 
238  return GetTime() - GetStartupTime();
239 }
240 
241 static UniValue getrpcinfo(const Config &config,
242  const JSONRPCRequest &request) {
243  RPCHelpMan{
244  "getrpcinfo",
245  "Returns details of the RPC server.\n",
246  {},
248  "",
249  "",
250  {
252  "active_commands",
253  "All active commands",
254  {
256  "",
257  "Information about an active command",
258  {
259  {RPCResult::Type::STR, "method",
260  "The name of the RPC command"},
261  {RPCResult::Type::NUM, "duration",
262  "The running time in microseconds"},
263  }},
264  }},
265  {RPCResult::Type::STR, "logpath",
266  "The complete file path to the debug log"},
267  }},
268  RPCExamples{HelpExampleCli("getrpcinfo", "") +
269  HelpExampleRpc("getrpcinfo", "")},
270  }
271  .Check(request);
272 
273  LOCK(g_rpc_server_info.mutex);
274  UniValue active_commands(UniValue::VARR);
275  for (const RPCCommandExecutionInfo &info :
276  g_rpc_server_info.active_commands) {
277  UniValue entry(UniValue::VOBJ);
278  entry.pushKV("method", info.method);
279  entry.pushKV("duration", GetTimeMicros() - info.start);
280  active_commands.push_back(entry);
281  }
282 
283  UniValue result(UniValue::VOBJ);
284  result.pushKV("active_commands", active_commands);
285 
286  const std::string path = LogInstance().m_file_path.string();
287  UniValue log_path(UniValue::VSTR, path);
288  result.pushKV("logpath", log_path);
289 
290  return result;
291 }
292 
293 // clang-format off
294 static const CRPCCommand vRPCCommands[] = {
295  // category name actor (function) argNames
296  // ------------------- ------------------------ ---------------------- ----------
297  /* Overall control/query calls */
298  { "control", "getrpcinfo", getrpcinfo, {} },
299  { "control", "help", help, {"command"} },
300  { "control", "stop", stop, {"wait"} },
301  { "control", "uptime", uptime, {} },
302 };
303 // clang-format on
304 
306  unsigned int vcidx;
307  for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0]));
308  vcidx++) {
309  const CRPCCommand *pcmd;
310 
311  pcmd = &vRPCCommands[vcidx];
312  mapCommands[pcmd->name].push_back(pcmd);
313  }
314 }
315 
316 bool CRPCTable::appendCommand(const std::string &name,
317  const CRPCCommand *pcmd) {
318  if (IsRPCRunning()) {
319  return false;
320  }
321 
322  mapCommands[name].push_back(pcmd);
323  return true;
324 }
325 
326 bool CRPCTable::removeCommand(const std::string &name,
327  const CRPCCommand *pcmd) {
328  auto it = mapCommands.find(name);
329  if (it != mapCommands.end()) {
330  auto new_end = std::remove(it->second.begin(), it->second.end(), pcmd);
331  if (it->second.end() != new_end) {
332  it->second.erase(new_end, it->second.end());
333  return true;
334  }
335  }
336  return false;
337 }
338 
339 void StartRPC() {
340  LogPrint(BCLog::RPC, "Starting RPC\n");
341  g_rpc_running = true;
343 }
344 
345 void InterruptRPC() {
346  LogPrint(BCLog::RPC, "Interrupting RPC\n");
347  // Interrupt e.g. running longpolls
348  g_rpc_running = false;
349 }
350 
351 void StopRPC() {
352  LogPrint(BCLog::RPC, "Stopping RPC\n");
353  WITH_LOCK(g_deadline_timers_mutex, deadlineTimers.clear());
356 }
357 
358 bool IsRPCRunning() {
359  return g_rpc_running;
360 }
361 
363  if (!IsRPCRunning()) {
364  throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
365  }
366 }
367 
368 void SetRPCWarmupStatus(const std::string &newStatus) {
369  LOCK(cs_rpcWarmup);
370  rpcWarmupStatus = newStatus;
371 }
372 
374  LOCK(cs_rpcWarmup);
375  assert(fRPCInWarmup);
376  fRPCInWarmup = false;
377 }
378 
379 bool RPCIsInWarmup(std::string *outStatus) {
380  LOCK(cs_rpcWarmup);
381  if (outStatus) {
382  *outStatus = rpcWarmupStatus;
383  }
384  return fRPCInWarmup;
385 }
386 
388  const std::string &method) {
389  const std::vector<std::string> enabled_methods =
390  args.GetArgs("-deprecatedrpc");
391 
392  return find(enabled_methods.begin(), enabled_methods.end(), method) !=
393  enabled_methods.end();
394 }
395 
396 static UniValue JSONRPCExecOne(Config &config, RPCServer &rpcServer,
397  JSONRPCRequest jreq, const UniValue &req) {
398  UniValue rpc_result(UniValue::VOBJ);
399 
400  try {
401  jreq.parse(req);
402 
403  UniValue result = rpcServer.ExecuteCommand(config, jreq);
404  rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id);
405  } catch (const UniValue &objError) {
406  rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id);
407  } catch (const std::exception &e) {
408  rpc_result = JSONRPCReplyObj(
409  NullUniValue, JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
410  }
411 
412  return rpc_result;
413 }
414 
415 std::string JSONRPCExecBatch(Config &config, RPCServer &rpcServer,
416  const JSONRPCRequest &jreq, const UniValue &vReq) {
418  for (size_t i = 0; i < vReq.size(); i++) {
419  ret.push_back(JSONRPCExecOne(config, rpcServer, jreq, vReq[i]));
420  }
421 
422  return ret.write() + "\n";
423 }
424 
429 static inline JSONRPCRequest
431  const std::vector<std::string> &argNames) {
432  JSONRPCRequest out = in;
434  // Build a map of parameters, and remove ones that have been processed, so
435  // that we can throw a focused error if there is an unknown one.
436  const std::vector<std::string> &keys = in.params.getKeys();
437  const std::vector<UniValue> &values = in.params.getValues();
438  std::unordered_map<std::string, const UniValue *> argsIn;
439  for (size_t i = 0; i < keys.size(); ++i) {
440  argsIn[keys[i]] = &values[i];
441  }
442  // Process expected parameters.
443  int hole = 0;
444  for (const std::string &argNamePattern : argNames) {
445  std::vector<std::string> vargNames;
446  boost::algorithm::split(vargNames, argNamePattern,
447  boost::algorithm::is_any_of("|"));
448  auto fr = argsIn.end();
449  for (const std::string &argName : vargNames) {
450  fr = argsIn.find(argName);
451  if (fr != argsIn.end()) {
452  break;
453  }
454  }
455  if (fr != argsIn.end()) {
456  for (int i = 0; i < hole; ++i) {
457  // Fill hole between specified parameters with JSON nulls, but
458  // not at the end (for backwards compatibility with calls that
459  // act based on number of specified parameters).
460  out.params.push_back(UniValue());
461  }
462  hole = 0;
463  out.params.push_back(*fr->second);
464  argsIn.erase(fr);
465  } else {
466  hole += 1;
467  }
468  }
469  // If there are still arguments in the argsIn map, this is an error.
470  if (!argsIn.empty()) {
472  "Unknown named parameter " + argsIn.begin()->first);
473  }
474  // Return request with named arguments transformed to positional arguments
475  return out;
476 }
477 
479  const JSONRPCRequest &request) const {
480  // Return immediately if in warmup
481  {
482  LOCK(cs_rpcWarmup);
483  if (fRPCInWarmup) {
484  throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus);
485  }
486  }
487 
488  // Find method
489  auto it = mapCommands.find(request.strMethod);
490  if (it != mapCommands.end()) {
491  UniValue result;
492  for (const auto &command : it->second) {
493  if (ExecuteCommand(config, *command, request, result,
494  &command == &it->second.back())) {
495  return result;
496  }
497  }
498  }
499  throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
500 }
501 
502 static bool ExecuteCommand(Config &config, const CRPCCommand &command,
503  const JSONRPCRequest &request, UniValue &result,
504  bool last_handler) {
505  try {
506  RPCCommandExecution execution(request.strMethod);
507  // Execute, convert arguments to array if necessary
508  if (request.params.isObject()) {
509  return command.actor(
510  config, transformNamedArguments(request, command.argNames),
511  result, last_handler);
512  } else {
513  return command.actor(config, request, result, last_handler);
514  }
515  } catch (const std::exception &e) {
516  throw JSONRPCError(RPC_MISC_ERROR, e.what());
517  }
518 }
519 
520 std::vector<std::string> CRPCTable::listCommands() const {
521  std::vector<std::string> commandList;
522  for (const auto &i : mapCommands) {
523  commandList.emplace_back(i.first);
524  }
525  return commandList;
526 }
527 
529  if (!timerInterface) {
530  timerInterface = iface;
531  }
532 }
533 
535  timerInterface = iface;
536 }
537 
539  if (timerInterface == iface) {
540  timerInterface = nullptr;
541  }
542 }
543 
544 void RPCRunLater(const std::string &name, std::function<void()> func,
545  int64_t nSeconds) {
546  if (!timerInterface) {
548  "No timer handler registered for RPC");
549  }
550  LOCK(g_deadline_timers_mutex);
551  deadlineTimers.erase(name);
552  LogPrint(BCLog::RPC, "queue run of timer %s in %i seconds (using %s)\n",
553  name, nSeconds, timerInterface->Name());
554  deadlineTimers.emplace(
555  name, std::unique_ptr<RPCTimerBase>(
556  timerInterface->NewTimer(func, nSeconds * 1000)));
557 }
558 
560  return 0;
561 }
562 
static UniValue help(Config &config, const JSONRPCRequest &jsonRequest)
Definition: server.cpp:175
bool isObject() const
Definition: univalue.h:96
UniValue ExecuteCommand(Config &config, const JSONRPCRequest &request) const
Attempts to execute an RPC command from the given request.
Definition: server.cpp:64
std::string Capitalize(std::string str)
Capitalizes the first character of the given string.
RPC timer "driver".
Definition: server.h:98
bool IsDeprecatedRPCEnabled(const ArgsManager &args, const std::string &method)
Definition: server.cpp:387
std::string category
Definition: server.h:188
boost::signals2::signal< void()> Started
Definition: server.cpp:102
const std::vector< UniValue > & getValues() const
static JSONRPCRequest transformNamedArguments(const JSONRPCRequest &in, const std::vector< std::string > &argNames)
Process named arguments into a vector of positional arguments, based on the passed-in specification f...
Definition: server.cpp:430
BCLog::Logger & LogInstance()
Definition: logging.cpp:15
Bitcoin RPC command dispatcher.
Definition: server.h:198
#define LogPrint(category,...)
Definition: logging.h:192
bool IsRPCRunning()
Query whether RPC is running.
Definition: server.cpp:358
void SetRPCWarmupStatus(const std::string &newStatus)
Set the RPC warmup status.
Definition: server.cpp:368
Actor actor
Definition: server.h:190
fs::path m_file_path
Definition: logging.h:99
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
static bool fRPCInWarmup GUARDED_BY(cs_rpcWarmup)
static std::atomic< bool > g_rpc_running
Definition: server.cpp:24
bool removeCommand(const std::string &name, const CRPCCommand *pcmd)
Definition: server.cpp:326
void InterruptRPC()
Definition: server.cpp:345
const std::string & get_str() const
bool isNum() const
Definition: univalue.h:94
const std::vector< std::string > & getKeys() const
static const CRPCCommand vRPCCommands[]
Definition: server.cpp:294
void RPCRunLater(const std::string &name, std::function< void()> func, int64_t nSeconds)
Run func nSeconds from now.
Definition: server.cpp:544
std::string JSONRPCExecBatch(Config &config, RPCServer &rpcServer, const JSONRPCRequest &jreq, const UniValue &vReq)
Definition: server.cpp:415
bool appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:316
Client still warming up.
Definition: protocol.h:58
std::string method
Definition: server.cpp:39
std::vector< std::string > argNames
Definition: server.h:191
Invalid, missing or duplicate parameter.
Definition: protocol.h:46
static RPCServerInfo g_rpc_server_info
Definition: server.cpp:48
static Mutex g_deadline_timers_mutex
Definition: server.cpp:31
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
Unset factory function for timers.
Definition: server.cpp:538
void DeleteAuthCookie()
Delete RPC authentication cookie from disk.
Definition: request.cpp:129
std::string strMethod
Definition: request.h:36
void SetRPCWarmupFinished()
Mark warmup as done.
Definition: server.cpp:373
void OnStarted(std::function< void()> slot)
Definition: server.cpp:106
std::string name
Definition: server.h:189
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:143
CRPCTable tableRPC
Definition: server.cpp:563
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:52
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
Mutex mutex
Definition: server.cpp:44
Definition: config.h:19
UniValue params
Definition: request.h:37
#define LOCK(cs)
Definition: sync.h:230
const char * name
Definition: rest.cpp:43
std::string help(Config &config, const std::string &name, const JSONRPCRequest &helpreq) const
Definition: server.cpp:114
static RPCTimerInterface * timerInterface
Definition: server.cpp:29
UniValue id
Definition: request.h:35
static UniValue getrpcinfo(const Config &config, const JSONRPCRequest &request)
Definition: server.cpp:241
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
General application defined errors std::exception thrown in command handling.
Definition: protocol.h:38
Class for registering and managing all RPC calls.
Definition: server.h:41
RPCCommandExecution(const std::string &method)
Definition: server.cpp:52
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
static UniValue uptime(const Config &config, const JSONRPCRequest &request)
Definition: server.cpp:226
int get_int() const
void StartRPC()
Definition: server.cpp:339
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:138
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:261
static struct CRPCSignals g_rpcSignals
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
Set the factory function for timer, but only, if unset.
Definition: server.cpp:528
virtual RPCTimerBase * NewTimer(std::function< void()> &func, int64_t millis)=0
Factory function for timers.
int64_t GetTimeMicros()
Returns the system time (not mockable)
Definition: time.cpp:67
bool fHelp
Definition: request.h:38
void parse(const UniValue &valRequest)
Definition: request.cpp:157
void StopRPC()
Definition: server.cpp:351
int64_t GetStartupTime()
Server/client environment: argument handling, config file parsing, thread wrappers, startup time.
Definition: system.cpp:1348
void UninterruptibleSleep(const std::chrono::microseconds &n)
Definition: time.cpp:20
void RegisterCommand(std::unique_ptr< RPCCommand > command)
Register an RPC command.
Definition: server.cpp:93
int RPCSerializationFlags()
Retrieves any serialization flags requested in command line argument.
Definition: server.cpp:559
void RpcInterruptionPoint()
Throw JSONRPCError if RPC is not running.
Definition: server.cpp:362
void RPCSetTimerInterface(RPCTimerInterface *iface)
Set the factory function for timers.
Definition: server.cpp:534
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:33
std::list< RPCCommandExecutionInfo >::iterator it
Definition: server.cpp:51
static UniValue stop(const Config &config, const JSONRPCRequest &jsonRequest)
Definition: server.cpp:198
bool RPCIsInWarmup(std::string *outStatus)
Returns the current warmup state.
Definition: server.cpp:379
const UniValue NullUniValue
Definition: univalue.cpp:13
void StartShutdown()
Definition: shutdown.cpp:12
virtual const char * Name()=0
Implementation name.
UniValue execute(Config &config, const JSONRPCRequest &request) const
Execute a method.
Definition: server.cpp:478
size_t size() const
Definition: univalue.h:80
static bool ExecuteCommand(Config &config, const CRPCCommand &command, const JSONRPCRequest &request, UniValue &result, bool last_handler)
Definition: server.cpp:502
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
Definition: system.cpp:381
static RecursiveMutex cs_rpcWarmup
Definition: server.cpp:23
intptr_t unique_id
Definition: server.h:192
int64_t GetTime()
Return system time (or mocked time, if set)
Definition: time.cpp:27
std::vector< std::string > listCommands() const
Returns a list of registered commands.
Definition: server.cpp:520
boost::signals2::signal< void()> Stopped
Definition: server.cpp:103
P2P client errors Bitcoin is not connected.
Definition: protocol.h:69
void OnStopped(std::function< void()> slot)
Definition: server.cpp:110
CRPCTable()
Definition: server.cpp:305
static UniValue JSONRPCExecOne(Config &config, RPCServer &rpcServer, JSONRPCRequest jreq, const UniValue &req)
Definition: server.cpp:396