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