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