1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2020 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 <amount.h>
10 #include <rpc/request.h>
11 #include <rpc/util.h>
12 
13 #include <functional>
14 #include <map>
15 #include <stdint.h>
16 #include <string>
17 
18 #include <univalue.h>
19 
20 static const unsigned int DEFAULT_RPC_SERIALIZE_VERSION = 1;
21 
22 class CRPCCommand;
23 
24 namespace RPCServer
25 {
26     void OnStarted(std::function<void ()> slot);
27     void OnStopped(std::function<void ()> slot);
28 }
29 
30 /** Query whether RPC is running */
31 bool IsRPCRunning();
32 
33 /** Throw JSONRPCError if RPC is not running */
34 void RpcInterruptionPoint();
35 
36 /**
37  * Set the RPC warmup status.  When this is done, all RPC calls will error out
38  * immediately with RPC_IN_WARMUP.
39  */
40 void SetRPCWarmupStatus(const std::string& newStatus);
41 /* Mark warmup as done.  RPC calls will be processed from now on.  */
42 void SetRPCWarmupFinished();
43 
44 /* returns the current warmup state.  */
45 bool RPCIsInWarmup(std::string *outStatus);
46 
47 /** Opaque base class for timers returned by NewTimerFunc.
48  * This provides no methods at the moment, but makes sure that delete
49  * cleans up the whole state.
50  */
51 class RPCTimerBase
52 {
53 public:
~RPCTimerBase()54     virtual ~RPCTimerBase() {}
55 };
56 
57 /**
58  * RPC timer "driver".
59  */
60 class RPCTimerInterface
61 {
62 public:
~RPCTimerInterface()63     virtual ~RPCTimerInterface() {}
64     /** Implementation name */
65     virtual const char *Name() = 0;
66     /** Factory function for timers.
67      * RPC will call the function to create a timer that will call func in *millis* milliseconds.
68      * @note As the RPC mechanism is backend-neutral, it can use different implementations of timers.
69      * This is needed to cope with the case in which there is no HTTP server, but
70      * only GUI RPC console, and to break the dependency of pcserver on httprpc.
71      */
72     virtual RPCTimerBase* NewTimer(std::function<void()>& func, int64_t millis) = 0;
73 };
74 
75 /** Set the factory function for timers */
76 void RPCSetTimerInterface(RPCTimerInterface *iface);
77 /** Set the factory function for timer, but only, if unset */
78 void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface);
79 /** Unset factory function for timers */
80 void RPCUnsetTimerInterface(RPCTimerInterface *iface);
81 
82 /**
83  * Run func nSeconds from now.
84  * Overrides previous timer <name> (if any).
85  */
86 void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nSeconds);
87 
88 typedef RPCHelpMan (*RpcMethodFnType)();
89 
90 class CRPCCommand
91 {
92 public:
93     //! RPC method handler reading request and assigning result. Should return
94     //! true if request is fully handled, false if it should be passed on to
95     //! subsequent handlers.
96     using Actor = std::function<bool(const JSONRPCRequest& request, UniValue& result, bool last_handler)>;
97 
98     //! Constructor taking Actor callback supporting multiple handlers.
CRPCCommand(std::string category,std::string name,Actor actor,std::vector<std::string> args,intptr_t unique_id)99     CRPCCommand(std::string category, std::string name, Actor actor, std::vector<std::string> args, intptr_t unique_id)
100         : category(std::move(category)), name(std::move(name)), actor(std::move(actor)), argNames(std::move(args)),
101           unique_id(unique_id)
102     {
103     }
104 
105     //! Simplified constructor taking plain RpcMethodFnType function pointer.
CRPCCommand(std::string category,RpcMethodFnType fn)106     CRPCCommand(std::string category, RpcMethodFnType fn)
107         : CRPCCommand(
108               category,
109               fn().m_name,
110               [fn](const JSONRPCRequest& request, UniValue& result, bool) { result = fn().HandleRequest(request); return true; },
111               fn().GetArgNames(),
112               intptr_t(fn))
113     {
114     }
115 
116     std::string category;
117     std::string name;
118     Actor actor;
119     std::vector<std::string> 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 std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq);
177 
178 // Retrieves any serialization flags requested in command line argument
179 int RPCSerializationFlags();
180 
181 #endif // BITCOIN_RPC_SERVER_H
182