server.h raw

   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