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