16 #include <boost/signals2/signal.hpp>
22 #include <unordered_map>
33 static std::map<std::string, std::unique_ptr<RPCTimerBase>>
52 std::list<RPCCommandExecutionInfo>::iterator
it;
57 {method, GetTimeMicros()});
78 std::string commandName = request.
strMethod;
81 auto iter = commandsReadView->find(commandName);
82 if (iter != commandsReadView.end()) {
83 return iter->second.get()->Execute(request);
95 if (command !=
nullptr) {
96 const std::string &commandName = command->GetName();
98 std::make_pair(commandName, std::move(command)));
118 std::string category;
119 std::set<intptr_t> setDone;
120 std::vector<std::pair<std::string, const CRPCCommand *>> vCommands;
124 std::make_pair(entry.second.front()->category + entry.first,
125 entry.second.front()));
127 sort(vCommands.begin(), vCommands.end());
133 for (
const std::pair<std::string, const CRPCCommand *> &command :
136 std::string strMethod = pcmd->
name;
137 if ((strCommand !=
"" || pcmd->
category ==
"hidden") &&
138 strMethod != strCommand) {
145 if (setDone.insert(pcmd->
unique_id).second) {
146 pcmd->
actor(config, jreq, unused_result,
149 }
catch (
const std::exception &e) {
151 std::string strHelp = std::string(e.what());
152 if (strCommand ==
"") {
153 if (strHelp.find(
'\n') != std::string::npos) {
154 strHelp = strHelp.substr(0, strHelp.find(
'\n'));
158 if (!category.empty()) {
162 strRet +=
"== " +
Capitalize(category) +
" ==\n";
165 strRet += strHelp +
"\n";
169 strRet =
strprintf(
"help: unknown command: %s\n", strCommand);
172 strRet = strRet.substr(0, strRet.size() - 1);
179 "List all commands, or get help for a specified command.\n",
182 "The command to get help on"},
191 std::string strCommand;
192 if (jsonRequest.params.size() > 0) {
193 strCommand = jsonRequest.params[0].
get_str();
195 if (strCommand ==
"dump_all_command_conversions") {
206 static const std::string RESULT{PACKAGE_NAME
" stopping"};
212 "\nRequest a graceful shutdown of " PACKAGE_NAME
".",
217 "how long to wait in ms",
223 "A string with the content '" + RESULT +
"'"},
230 if (jsonRequest.params[0].isNum()) {
232 std::chrono::milliseconds{jsonRequest.params[0].get_int()});
242 "Returns the total uptime of the server.\n",
245 "The number of seconds that the server has been running"},
257 "Returns details of the RPC server.\n",
265 "All active commands",
269 "Information about an active command",
272 "The name of the RPC command"},
274 "The running time in microseconds"},
278 "The complete file path to the debug log"},
296 result.
pushKV(
"active_commands", active_commands);
300 result.
pushKV(
"logpath", log_path);
312 {
"control",
help, },
313 {
"control",
stop, },
336 auto new_end = std::remove(it->second.begin(), it->second.end(), pcmd);
337 if (it->second.end() != new_end) {
338 it->second.erase(new_end, it->second.end());
352 static std::once_flag g_rpc_interrupt_flag;
355 std::call_once(g_rpc_interrupt_flag, []() {
363 static std::once_flag g_rpc_stop_flag;
367 std::call_once(g_rpc_stop_flag, []() {
387 rpcWarmupStatus = newStatus;
393 fRPCInWarmup =
false;
399 *outStatus = rpcWarmupStatus;
405 const std::string &method) {
406 const std::vector<std::string> enabled_methods =
407 args.
GetArgs(
"-deprecatedrpc");
409 return find(enabled_methods.begin(), enabled_methods.end(), method) !=
410 enabled_methods.end();
422 }
catch (
const UniValue &objError) {
424 }
catch (
const std::exception &e) {
435 for (
size_t i = 0; i < vReq.
size(); i++) {
439 return ret.
write() +
"\n";
448 const std::vector<std::string> &argNames) {
455 std::unordered_map<std::string, const UniValue *> argsIn;
456 for (
size_t i = 0; i < keys.size(); ++i) {
457 argsIn[keys[i]] = &values[i];
461 for (
const std::string &argNamePattern : argNames) {
462 std::vector<std::string> vargNames =
SplitString(argNamePattern,
'|');
463 auto fr = argsIn.end();
464 for (
const std::string &argName : vargNames) {
465 fr = argsIn.find(argName);
466 if (fr != argsIn.end()) {
470 if (fr != argsIn.end()) {
471 for (
int i = 0; i < hole; ++i) {
485 if (!argsIn.empty()) {
487 "Unknown named parameter " + argsIn.begin()->first);
494 const std::vector<const CRPCCommand *> &commands,
496 for (
const auto &command : commands) {
498 &command == &commands.back())) {
533 return command.
actor(
535 result, last_handler);
537 return command.
actor(config, request, result, last_handler);
539 }
catch (
const std::exception &e) {
545 std::vector<std::string> commandList;
547 commandList.emplace_back(i.first);
561 for (
const auto &values : result.
getValues()) {
589 "No timer handler registered for RPC");
592 deadlineTimers.erase(
name);
595 deadlineTimers.emplace(
596 name, std::unique_ptr<RPCTimerBase>(
#define CHECK_NONFATAL(condition)
Identity function.
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
std::vector< std::string > argNames
std::map< std::string, std::vector< const CRPCCommand * > > mapCommands
bool removeCommand(const std::string &name, const CRPCCommand *pcmd)
std::string help(const Config &config, const std::string &name, const JSONRPCRequest &helpreq) const
std::vector< std::string > listCommands() const
Returns a list of registered commands.
UniValue execute(const Config &config, const JSONRPCRequest &request) const
Execute a method.
void appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
UniValue dumpArgMap(const Config &config, const JSONRPCRequest &request) const
Return all named arguments that need to be converted by the client from string to another JSON type.
Different type to mark Mutex at global scope.
enum JSONRPCRequest::Mode mode
void parse(const UniValue &valRequest)
Class for registering and managing all RPC calls.
UniValue ExecuteCommand(const Config &config, const JSONRPCRequest &request) const
Attempts to execute an RPC command from the given request.
RWCollection< RPCCommandMap > commands
void RegisterCommand(std::unique_ptr< RPCCommand > command)
Register an RPC command.
virtual RPCTimerBase * NewTimer(std::function< void()> &func, int64_t millis)=0
Factory function for timers.
virtual const char * Name()=0
Implementation name.
ReadView getReadView() const
const std::string & get_str() const
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
const std::vector< UniValue > & getValues() const
const std::vector< std::string > & getKeys() const
bool push_back(const UniValue &val)
bool pushKV(const std::string &key, const UniValue &val)
BCLog::Logger & LogInstance()
#define LogPrint(category,...)
void OnStarted(std::function< void()> slot)
void OnStopped(std::function< void()> slot)
UniValue JSONRPCError(int code, const std::string &message)
void DeleteAuthCookie()
Delete RPC authentication cookie from disk.
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
@ RPC_MISC_ERROR
General application defined errors std::exception thrown in command handling.
@ RPC_CLIENT_NOT_CONNECTED
P2P client errors Bitcoin is not connected.
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
@ RPC_IN_WARMUP
Client still warming up.
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
Set the factory function for timer, but only, if unset.
void SetRPCWarmupFinished()
Mark warmup as done.
bool IsDeprecatedRPCEnabled(const ArgsManager &args, const std::string &method)
static RPCHelpMan uptime()
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
Unset factory function for timers.
static RPCHelpMan getrpcinfo()
void RPCRunLater(const std::string &name, std::function< void()> func, int64_t nSeconds)
Run func nSeconds from now.
bool RPCIsInWarmup(std::string *outStatus)
Returns the current warmup state.
static UniValue JSONRPCExecOne(const Config &config, RPCServer &rpcServer, JSONRPCRequest jreq, const UniValue &req)
static RPCTimerInterface * timerInterface
static std::atomic< bool > g_rpc_running
static GlobalMutex g_deadline_timers_mutex
bool IsRPCRunning()
Query whether RPC is running.
static bool ExecuteCommands(const Config &config, const std::vector< const CRPCCommand * > &commands, const JSONRPCRequest &request, UniValue &result)
int RPCSerializationFlags()
Retrieves any serialization flags requested in command line argument.
static struct CRPCSignals g_rpcSignals
static bool fRPCInWarmup GUARDED_BY(g_rpc_warmup_mutex)
static GlobalMutex g_rpc_warmup_mutex
static bool ExecuteCommand(const Config &config, const CRPCCommand &command, const JSONRPCRequest &request, UniValue &result, bool last_handler)
static RPCServerInfo g_rpc_server_info
static const CRPCCommand vRPCCommands[]
std::string JSONRPCExecBatch(const Config &config, RPCServer &rpcServer, const JSONRPCRequest &jreq, const UniValue &vReq)
void SetRPCWarmupStatus(const std::string &newStatus)
Set the RPC warmup status.
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...
void RPCSetTimerInterface(RPCTimerInterface *iface)
Set the factory function for timers.
void RpcInterruptionPoint()
Throw JSONRPCError if RPC is not running.
void StartShutdown()
Request shutdown of the application.
std::string Capitalize(std::string str)
Capitalizes the first character of the given string.
std::vector< std::string > SplitString(std::string_view str, char sep)
boost::signals2::signal< void()> Started
boost::signals2::signal< void()> Stopped
@ OMITTED_NAMED_ARG
Optional arg that is a named argument and has a default value of null.
RPCCommandExecution(const std::string &method)
std::list< RPCCommandExecutionInfo >::iterator it
@ ANY
Special type to disable type checks (for testing only)
std::list< RPCCommandExecutionInfo > active_commands GUARDED_BY(mutex)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
int64_t GetStartupTime()
Server/client environment: argument handling, config file parsing, thread wrappers,...
int64_t GetTimeMicros()
Returns the system time (not mockable)
void UninterruptibleSleep(const std::chrono::microseconds &n)
const UniValue NullUniValue