1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2021 The Limenka 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 LIMENKA_RPC_SERVER_H
7 #define LIMENKA_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 virtual ~RPCTimerBase() = default;
46 };
47 48 /**
49 * RPC timer "driver".
50 */
51 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 CRPCCommand(std::string category, std::string name, Actor actor, std::vector<std::pair<std::string, bool>> args, intptr_t unique_id)
91 : category(std::move(category)), name(std::move(name)), actor(std::move(actor)), argNames(std::move(args)),
92 unique_id(unique_id)
93 {
94 }
95 96 //! Simplified constructor taking plain RpcMethodFnType function pointer.
97 CRPCCommand(std::string category, RpcMethodFnType fn)
98 : CRPCCommand(
99 category,
100 fn().m_name,
101 [fn](const JSONRPCRequest& request, UniValue& result, bool) { result = fn().HandleRequest(request); return true; },
102 fn().GetArgNames(),
103 intptr_t(fn))
104 {
105 }
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 the request.strMethod.
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 * Execute a method.
144 * @param method The method to execute
145 * @param request The JSONRPCRequest to execute
146 * @returns Result of the call.
147 * @throws an exception (UniValue) when an error happens.
148 */
149 UniValue execute(const std::string method, const JSONRPCRequest &request) const;
150 151 /**
152 * Returns a list of registered commands
153 * @returns List of registered commands.
154 */
155 std::vector<std::string> listCommands() const;
156 157 /**
158 * Return all named arguments that need to be converted by the client from string to another JSON type
159 */
160 UniValue dumpArgMap(const JSONRPCRequest& request) const;
161 162 /**
163 * Appends a CRPCCommand to the dispatch table.
164 *
165 * Precondition: RPC server is not running
166 *
167 * Commands with different method names but the same unique_id will
168 * be considered aliases, and only the first registered method name will
169 * show up in the help text command listing. Aliased commands do not have
170 * to have the same behavior. Server and client code can distinguish
171 * between calls based on method name, and aliased commands can also
172 * register different names, types, and numbers of parameters.
173 */
174 void appendCommand(const std::string& name, const CRPCCommand* pcmd);
175 bool removeCommand(const std::string& name, const CRPCCommand* pcmd);
176 };
177 178 bool IsDeprecatedRPCEnabled(const std::string& method);
179 180 extern CRPCTable tableRPC;
181 182 void StartRPC();
183 void InterruptRPC();
184 void StopRPC();
185 UniValue JSONRPCExec(const JSONRPCRequest& jreq, bool catch_errors);
186 187 #endif // LIMENKA_RPC_SERVER_H
188