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 : class RPCTimerBase 49 : { 50 : public: 51 0 : virtual ~RPCTimerBase() {} 52 : }; 53 : 54 : /** 55 : * RPC timer "driver". 56 : */ 57 : class RPCTimerInterface 58 : { 59 : public: 60 0 : 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 1008 : 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 19230 : CRPCCommand(std::string category, std::string name, Actor actor, std::vector<std::string> args, intptr_t unique_id) 97 9615 : : category(std::move(category)), name(std::move(name)), actor(std::move(actor)), argNames(std::move(args)), 98 9615 : unique_id(unique_id) 99 9615 : { 100 19230 : } 101 : 102 : //! Simplified constructor taking plain RpcMethodFnType function pointer. 103 8600 : CRPCCommand(std::string category, RpcMethodFnType fn) 104 8600 : : CRPCCommand( 105 8600 : category, 106 8600 : fn().m_name, 107 8666 : [fn](const JSONRPCRequest& request, UniValue& result, bool) { result = fn().HandleRequest(request); return true; }, 108 8600 : fn().GetArgNames(), 109 8600 : intptr_t(fn)) 110 : { 111 8600 : } 112 : 113 : std::string category; 114 : std::string name; 115 : Actor actor; 116 : std::vector<std::string> argNames; 117 : intptr_t unique_id; 118 : }; 119 : 120 : /** 121 : * RPC command dispatcher. 122 : */ 123 : class CRPCTable 124 : { 125 : private: 126 : std::map<std::string, std::vector<const CRPCCommand*>> mapCommands; 127 : public: 128 : CRPCTable(); 129 : std::string help(const std::string& name, const JSONRPCRequest& helpreq) const; 130 : 131 : /** 132 : * Execute a method. 133 : * @param request The JSONRPCRequest to execute 134 : * @returns Result of the call. 135 : * @throws an exception (UniValue) when an error happens. 136 : */ 137 : UniValue execute(const JSONRPCRequest &request) const; 138 : 139 : /** 140 : * Returns a list of registered commands 141 : * @returns List of registered commands. 142 : */ 143 : std::vector<std::string> listCommands() const; 144 : 145 : /** 146 : * Return all named arguments that need to be converted by the client from string to another JSON type 147 : */ 148 : UniValue dumpArgMap(const JSONRPCRequest& request) const; 149 : 150 : /** 151 : * Appends a CRPCCommand to the dispatch table. 152 : * 153 : * Precondition: RPC server is not running 154 : * 155 : * Commands with different method names but the same unique_id will 156 : * be considered aliases, and only the first registered method name will 157 : * show up in the help text command listing. Aliased commands do not have 158 : * to have the same behavior. Server and client code can distinguish 159 : * between calls based on method name, and aliased commands can also 160 : * register different names, types, and numbers of parameters. 161 : */ 162 : void appendCommand(const std::string& name, const CRPCCommand* pcmd); 163 : bool removeCommand(const std::string& name, const CRPCCommand* pcmd); 164 : }; 165 : 166 : bool IsDeprecatedRPCEnabled(const std::string& method); 167 : 168 : extern CRPCTable tableRPC; 169 : 170 : void StartRPC(); 171 : void InterruptRPC(); 172 : void StopRPC(); 173 : std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq); 174 : 175 : #endif // BITCOIN_RPC_SERVER_H