Branch data Line data Source code
1 : : // Copyright (c) 2010 Satoshi Nakamoto
2 : : // Copyright (c) 2009-2021 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.
5 : :
6 : : #ifndef BITCOIN_RPC_SERVER_H
7 : : #define BITCOIN_RPC_SERVER_H
8 : :
9 : : #include <rpc/request.h>
10 : : #include <rpc/util.h>
11 : :
12 : : #include <functional>
13 : : #include <map>
14 : : #include <stdint.h>
15 : : #include <string>
16 : :
17 : : #include <univalue.h>
18 : :
19 : : class CRPCCommand;
20 : :
21 : : namespace RPCServer
22 : : {
23 : : void OnStarted(std::function<void ()> slot);
24 : : void OnStopped(std::function<void ()> slot);
25 : : }
26 : :
27 : : /** Query whether RPC is running */
28 : : bool IsRPCRunning();
29 : :
30 : : /** Throw JSONRPCError if RPC is not running */
31 : : void RpcInterruptionPoint();
32 : :
33 : : /**
34 : : * Set the RPC warmup status. When this is done, all RPC calls will error out
35 : : * immediately with RPC_IN_WARMUP.
36 : : */
37 : : void SetRPCWarmupStatus(const std::string& newStatus);
38 : : /* Mark warmup as done. RPC calls will be processed from now on. */
39 : : void SetRPCWarmupFinished();
40 : :
41 : : /* returns the current warmup state. */
42 : : bool RPCIsInWarmup(std::string *outStatus);
43 : :
44 : : /** Opaque base class for timers returned by NewTimerFunc.
45 : : * This provides no methods at the moment, but makes sure that delete
46 : : * cleans up the whole state.
47 : : */
48 [ + - ]: 79 : class RPCTimerBase
49 : : {
50 : : public:
51 : 0 : virtual ~RPCTimerBase() {}
52 : : };
53 : :
54 : : /**
55 : : * RPC timer "driver".
56 : : */
57 : 1157 : class RPCTimerInterface
58 : : {
59 : : public:
60 : : virtual ~RPCTimerInterface() {}
61 : : /** Implementation name */
62 : : virtual const char *Name() = 0;
63 : : /** Factory function for timers.
64 : : * RPC will call the function to create a timer that will call func in *millis* milliseconds.
65 : : * @note As the RPC mechanism is backend-neutral, it can use different implementations of timers.
66 : : * This is needed to cope with the case in which there is no HTTP server, but
67 : : * only GUI RPC console, and to break the dependency of pcserver on httprpc.
68 : : */
69 : : virtual RPCTimerBase* NewTimer(std::function<void()>& func, int64_t millis) = 0;
70 : : };
71 : :
72 : : /** Set the factory function for timers */
73 : : void RPCSetTimerInterface(RPCTimerInterface *iface);
74 : : /** Set the factory function for timer, but only, if unset */
75 : : void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface);
76 : : /** Unset factory function for timers */
77 : : void RPCUnsetTimerInterface(RPCTimerInterface *iface);
78 : :
79 : : /**
80 : : * Run func nSeconds from now.
81 : : * Overrides previous timer <name> (if any).
82 : : */
83 : : void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nSeconds);
84 : :
85 : : typedef RPCHelpMan (*RpcMethodFnType)();
86 : :
87 : : class CRPCCommand
88 : : {
89 : : public:
90 : : //! RPC method handler reading request and assigning result. Should return
91 : : //! true if request is fully handled, false if it should be passed on to
92 : : //! subsequent handlers.
93 : : using Actor = std::function<bool(const JSONRPCRequest& request, UniValue& result, bool last_handler)>;
94 : :
95 : : //! Constructor taking Actor callback supporting multiple handlers.
96 : 211879 : CRPCCommand(std::string category, std::string name, Actor actor, std::vector<std::pair<std::string, bool>> args, intptr_t unique_id)
97 : 211879 : : category(std::move(category)), name(std::move(name)), actor(std::move(actor)), argNames(std::move(args)),
98 : 211879 : unique_id(unique_id)
99 : : {
100 : 211879 : }
101 : :
102 : : //! Simplified constructor taking plain RpcMethodFnType function pointer.
103 : 170812 : CRPCCommand(std::string category, RpcMethodFnType fn)
104 : 170812 : : CRPCCommand(
105 : : category,
106 : 170812 : fn().m_name,
107 [ + - + + ]: 367560 : [fn](const JSONRPCRequest& request, UniValue& result, bool) { result = fn().HandleRequest(request); return true; },
108 [ + - ]: 341624 : fn().GetArgNames(),
109 [ + - + - : 512436 : intptr_t(fn))
+ - ]
110 : : {
111 : 170812 : }
112 : :
113 : : std::string category;
114 : : std::string name;
115 : : Actor actor;
116 : : //! List of method arguments and whether they are named-only. Incoming RPC
117 : : //! requests contain a "params" field that can either be an array containing
118 : : //! unnamed arguments or an object containing named arguments. The
119 : : //! "argNames" vector is used in the latter case to transform the params
120 : : //! object into an array. Each argument in "argNames" gets mapped to a
121 : : //! unique position in the array, based on the order it is listed, unless
122 : : //! the argument is a named-only argument with argNames[x].second set to
123 : : //! true. Named-only arguments are combined into a JSON object that is
124 : : //! appended after other arguments, see transformNamedArguments for details.
125 : : std::vector<std::pair<std::string, bool>> argNames;
126 : : intptr_t unique_id;
127 : : };
128 : :
129 : : /**
130 : : * RPC command dispatcher.
131 : : */
132 : 12 : class CRPCTable
133 : : {
134 : : private:
135 : : std::map<std::string, std::vector<const CRPCCommand*>> mapCommands;
136 : : public:
137 : : CRPCTable();
138 : : std::string help(const std::string& name, const JSONRPCRequest& helpreq) const;
139 : :
140 : : /**
141 : : * Execute a method.
142 : : * @param request The JSONRPCRequest to execute
143 : : * @returns Result of the call.
144 : : * @throws an exception (UniValue) when an error happens.
145 : : */
146 : : UniValue execute(const JSONRPCRequest &request) const;
147 : :
148 : : /**
149 : : * Returns a list of registered commands
150 : : * @returns List of registered commands.
151 : : */
152 : : std::vector<std::string> listCommands() const;
153 : :
154 : : /**
155 : : * Return all named arguments that need to be converted by the client from string to another JSON type
156 : : */
157 : : UniValue dumpArgMap(const JSONRPCRequest& request) const;
158 : :
159 : : /**
160 : : * Appends a CRPCCommand to the dispatch table.
161 : : *
162 : : * Precondition: RPC server is not running
163 : : *
164 : : * Commands with different method names but the same unique_id will
165 : : * be considered aliases, and only the first registered method name will
166 : : * show up in the help text command listing. Aliased commands do not have
167 : : * to have the same behavior. Server and client code can distinguish
168 : : * between calls based on method name, and aliased commands can also
169 : : * register different names, types, and numbers of parameters.
170 : : */
171 : : void appendCommand(const std::string& name, const CRPCCommand* pcmd);
172 : : bool removeCommand(const std::string& name, const CRPCCommand* pcmd);
173 : : };
174 : :
175 : : bool IsDeprecatedRPCEnabled(const std::string& method);
176 : :
177 : : extern CRPCTable tableRPC;
178 : :
179 : : void StartRPC();
180 : : void InterruptRPC();
181 : : void StopRPC();
182 : : UniValue JSONRPCExec(const JSONRPCRequest& jreq, bool catch_errors);
183 : :
184 : : #endif // BITCOIN_RPC_SERVER_H
|