httpserver.h raw

   1  // Copyright (c) 2015-present The Bitcoin Core developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  #ifndef BITCOIN_HTTPSERVER_H
   6  #define BITCOIN_HTTPSERVER_H
   7  
   8  #include <atomic>
   9  #include <deque>
  10  #include <functional>
  11  #include <memory>
  12  #include <optional>
  13  #include <span>
  14  #include <stdexcept>
  15  #include <string>
  16  #include <vector>
  17  
  18  #include <netaddress.h>
  19  #include <rpc/protocol.h>
  20  #include <util/byte_units.h>
  21  #include <util/expected.h>
  22  #include <util/sock.h>
  23  #include <util/strencodings.h>
  24  #include <util/string.h>
  25  #include <util/threadinterrupt.h>
  26  #include <util/time.h>
  27  
  28  namespace util {
  29  class SignalInterrupt;
  30  } // namespace util
  31  
  32  /**
  33   * The default value for `-rpcthreads`. This number of threads will be created at startup.
  34   */
  35  static const int DEFAULT_HTTP_THREADS=16;
  36  
  37  /**
  38   * The default value for `-rpcworkqueue`. This is the maximum depth of the work queue,
  39   * we don't allocate this number of work queue items upfront.
  40   */
  41  static const int DEFAULT_HTTP_WORKQUEUE=64;
  42  
  43  static const int DEFAULT_HTTP_SERVER_TIMEOUT=30;
  44  
  45  enum class HTTPRequestMethod {
  46      UNKNOWN,
  47      GET,
  48      POST,
  49      HEAD,
  50      PUT
  51  };
  52  
  53  namespace http_bitcoin {
  54      class HTTPRequest;
  55  }
  56  /** Handler for requests to a certain HTTP path */
  57  using HTTPRequestHandler = std::function<void(http_bitcoin::HTTPRequest* req, const std::string&)>;
  58  
  59  /** Register handler for prefix.
  60   * If multiple handlers match a prefix, the first-registered one will
  61   * be invoked.
  62   */
  63  void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler);
  64  /** Unregister handler for prefix */
  65  void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch);
  66  
  67  namespace http_bitcoin {
  68  using util::LineReader;
  69  
  70  //! Shortest valid request line, used by libevent in evhttp_parse_request_line()
  71  constexpr size_t MIN_REQUEST_LINE_LENGTH = std::string_view("GET / HTTP/1.0").size();
  72  
  73  //! Maximum size of each headers line in an HTTP request,
  74  //! also the maximum size of all headers total.
  75  //! See https://github.com/bitcoin/bitcoin/pull/6859
  76  //! And libevent http.c evhttp_parse_headers_()
  77  constexpr size_t MAX_HEADERS_SIZE{8192};
  78  
  79  //! Maximum size of an HTTP request body
  80  constexpr uint64_t MAX_BODY_SIZE{32_MiB};
  81  
  82  //! Thrown when a request body exceeds MAX_BODY_SIZE (or *will* exceed, in chunked transfer)
  83  //! so the server can reply with more specific code 413 (content too large) vs general 400 (bad request)
  84  struct ContentTooLargeError : std::runtime_error {
  85      using std::runtime_error::runtime_error;
  86  };
  87  
  88  class HTTPHeaders
  89  {
  90  public:
  91      /**
  92       * @param[in] key The field-name of the header to search for
  93       * @returns The value of the first header that matches the provided key
  94       *          nullopt if key is not found
  95       */
  96      std::optional<std::string> FindFirst(std::string_view key) const;
  97      /**
  98       * @param[in] key The field-name of the header to search for
  99       * @returns Views into all values matching the provided key (valid while this object is alive)
 100       */
 101      std::vector<std::string_view> FindAll(std::string_view key) const;
 102      void Write(std::string&& key, std::string&& value);
 103      /**
 104       * @param[in] key The field-name of the header to search for and delete
 105       */
 106      void RemoveAll(std::string_view key);
 107      /**
 108       * @returns false if LineReader hits the end of the buffer before reading an
 109       *                \n, meaning that we are still waiting on more data from the client.
 110       *          true  after reading an entire HTTP headers section, terminated
 111       *                by an empty line and \n.
 112       * @throws on exceeded read limit and on bad headers syntax (e.g. no ":" in a line)
 113       */
 114      bool Read(util::LineReader& reader);
 115      std::string Stringify() const;
 116  
 117  private:
 118      /**
 119       * Headers can have duplicate field names, so we use a vector of key-value pairs instead of a map.
 120       * https://httpwg.org/specs/rfc9110.html#rfc.section.5.2
 121       */
 122      std::vector<std::pair<std::string, std::string>> m_headers;
 123  };
 124  
 125  struct HTTPVersion {
 126      /**
 127       * Default HTTP protocol version 1.1 is used by error responses
 128       * when a request is unreadable.
 129       */
 130      /// @{
 131      uint8_t major{1};
 132      uint8_t minor{1};
 133      /// @}
 134  };
 135  
 136  
 137  class HTTPResponse
 138  {
 139  public:
 140      HTTPVersion m_version;
 141  
 142      HTTPStatusCode m_status{HTTP_INTERNAL_SERVER_ERROR};
 143      HTTPHeaders m_headers;
 144  
 145      std::string StringifyHeaders() const;
 146  };
 147  
 148  class HTTPRemoteClient;
 149  
 150  class HTTPRequest
 151  {
 152  public:
 153      HTTPRequestMethod m_method;
 154      std::string m_target;
 155      HTTPVersion m_version;
 156      HTTPHeaders m_headers;
 157      std::string m_body;
 158  
 159      //! Pointer to the client that made the request so we know who to respond to.
 160      std::shared_ptr<HTTPRemoteClient> m_client;
 161  
 162      //! Response headers may be set in advance before response body is known
 163      HTTPHeaders m_response_headers;
 164  
 165      explicit HTTPRequest(std::shared_ptr<HTTPRemoteClient> client) : m_client{std::move(client)} {}
 166      //! Construct with a null client for unit tests
 167      explicit HTTPRequest() : m_client{} {}
 168  
 169      /**
 170       * Methods that attempt to parse HTTP request fields line-by-line
 171       * from a receive buffer.
 172       * @param[in]   reader  A LineReader object constructed over a span of data.
 173       * @returns     true    If the request field was parsed.
 174       *              false   If there was not enough data in the buffer to complete the field.
 175       * @throws      std::runtime_error if data is invalid.
 176       */
 177      /// @{
 178      bool LoadControlData(LineReader& reader);
 179      bool LoadHeaders(LineReader& reader);
 180      bool LoadBody(LineReader& reader);
 181      /// @}
 182  
 183      void WriteReply(HTTPStatusCode status, std::span<const std::byte> reply_body = {});
 184      void WriteReply(HTTPStatusCode status, std::string_view reply_body_view)
 185      {
 186          WriteReply(status, std::as_bytes(std::span{reply_body_view}));
 187      }
 188  
 189      // These methods reimplement the API from http_libevent::HTTPRequest
 190      // for downstream JSONRPC and REST modules.
 191      std::string GetURI() const { return m_target; }
 192      CService GetPeer() const;
 193      HTTPRequestMethod GetRequestMethod() const { return m_method; }
 194      std::optional<std::string> GetQueryParameter(std::string_view key) const;
 195      std::pair<bool, std::string> GetHeader(std::string_view hdr) const;
 196      std::string ReadBody() const { return m_body; }
 197      void WriteHeader(std::string&& hdr, std::string&& value);
 198  };
 199  
 200  class HTTPServer
 201  {
 202  public:
 203      /**
 204       * Each connection is assigned an unique id of this type.
 205       */
 206      using Id = uint64_t;
 207  
 208      explicit HTTPServer(std::function<void(std::unique_ptr<HTTPRequest>&&)> func)
 209          : m_request_dispatcher{std::move(func)} {}
 210  
 211      virtual ~HTTPServer()
 212      {
 213          Assume(!m_thread_socket_handler.joinable()); // Missing call to JoinSocketsThreads()
 214          Assume(m_connected.empty()); // Missing call to DisconnectClients(), or disconnect flags not set
 215          Assume(m_listen.empty()); // Missing call to StopListening()
 216      }
 217  
 218      /**
 219       * Bind to a new address:port, start listening and add the listen socket to `m_listen`.
 220       * @param[in] to Where to bind.
 221       * @returns {} or the reason for failure.
 222       */
 223      util::Expected<void, std::string> BindAndStartListening(const CService& to);
 224  
 225      /**
 226       * Stop listening by closing all listening sockets.
 227       */
 228      void StopListening();
 229  
 230      /**
 231       * Get the number of sockets the server is bound to and listening on
 232       */
 233      size_t GetListeningSocketCount() const { return m_listen.size(); }
 234  
 235      /**
 236       * Get the number of HTTPRemoteClients we are connected to
 237       */
 238      size_t GetConnectionsCount() const { return m_connected_size.load(std::memory_order_acquire); }
 239  
 240      /**
 241       * Start the necessary threads for sockets IO.
 242       */
 243      void StartSocketsThreads();
 244  
 245      /**
 246       * Join (wait for) the threads started by `StartSocketsThreads()` to exit.
 247       */
 248      void JoinSocketsThreads();
 249  
 250      /**
 251       * Stop network activity
 252       */
 253      void InterruptNet() { m_interrupt_net(); }
 254  
 255      /**
 256       * Start disconnecting clients when possible in the I/O loop
 257       */
 258      void DisconnectAllClients() { m_disconnect_all_clients = true; }
 259  
 260      /**
 261       * Update the request handler method.
 262       * Used for shutdown to reject new requests.
 263       */
 264      void SetRequestHandler(std::function<void(std::unique_ptr<HTTPRequest>&&)> func)
 265          EXCLUSIVE_LOCKS_REQUIRED(!m_request_dispatcher_mutex)
 266      {
 267          WITH_LOCK(m_request_dispatcher_mutex,
 268                    m_request_dispatcher = std::move(func));
 269      }
 270  
 271      /**
 272       * Stop accepting new connections in the I/O loop.
 273       * Must be called first in StopHTTPServer() before DisconnectAllClients().
 274       * A connection accepted after the "wait for 0 connections" loop exits would
 275       * remain in m_connected when the destructor is called.
 276       */
 277      void StopAccepting() { m_stop_accepting = true; }
 278  
 279      /**
 280       * Set the idle client timeout (-rpcservertimeout)
 281       */
 282      void SetServerTimeout(std::chrono::seconds seconds) { m_rpcservertimeout = seconds; }
 283  
 284      /**
 285       * Force-remove all remaining clients from m_connected without waiting for
 286       * graceful disconnection. Must only be called after JoinSocketsThreads().
 287       */
 288      void ClearConnectedClients();
 289  
 290  private:
 291      /**
 292       * List of listening sockets.
 293       */
 294      std::vector<std::shared_ptr<Sock>> m_listen;
 295  
 296      /**
 297       * The id to assign to the next created connection.
 298       */
 299      std::atomic<Id> m_next_id{0};
 300  
 301      /**
 302       * List of HTTPRemoteClients with connected sockets.
 303       * Connections will only be added and removed in the I/O thread, but
 304       * shared pointers may be passed to worker threads to handle requests
 305       * and send replies.
 306       */
 307      std::vector<std::shared_ptr<HTTPRemoteClient>> m_connected;
 308  
 309      /**
 310       * Flag used during shutdown to stop accepting new connections.
 311       * Set by main thread and read by the I/O thread.
 312       */
 313      std::atomic_bool m_stop_accepting{false};
 314  
 315      /**
 316       * Flag used during shutdown.
 317       * Overrides HTTPRemoteClient flags m_keep_alive and m_connection_busy.
 318       * Set by main thread and read by the I/O thread.
 319       */
 320      std::atomic_bool m_disconnect_all_clients{false};
 321  
 322      /**
 323       * The number of connected sockets.
 324       * Updated from the I/O thread but safely readable from
 325       * the main thread without locks.
 326       */
 327      std::atomic<size_t> m_connected_size{0};
 328  
 329      /**
 330       * Info about which socket has which event ready and a reverse map
 331       * back to the HTTPRemoteClient that owns the socket.
 332       */
 333      struct IOReadiness {
 334          /**
 335           * Map of socket -> socket events. For example:
 336           * socket1 -> { requested = SendEvent|RecvEvent, occurred = RecvEvent }
 337           * socket2 -> { requested = SendEvent, occurred = SendEvent }
 338           */
 339          Sock::EventsPerSock events_per_sock;
 340  
 341          /**
 342           * Map of socket -> HTTPRemoteClient. For example:
 343           * socket1 -> HTTPRemoteClient{ id=23 }
 344           * socket2 -> HTTPRemoteClient{ id=56 }
 345           */
 346          std::unordered_map<Sock::EventsPerSock::key_type,
 347                             std::shared_ptr<HTTPRemoteClient>,
 348                             Sock::HashSharedPtrSock,
 349                             Sock::EqualSharedPtrSock>
 350              httpclients_per_sock;
 351      };
 352  
 353      /**
 354       * This is signaled when network activity should cease.
 355       */
 356      CThreadInterrupt m_interrupt_net;
 357  
 358      /**
 359       * Thread that sends to and receives from sockets and accepts connections.
 360       * Executes the I/O loop of the server.
 361       */
 362      std::thread m_thread_socket_handler;
 363  
 364      /*
 365       * What to do with HTTP requests once received, validated and parsed.
 366       * Set in main thread by server start and interrupt but read in
 367       * worker threads.
 368       */
 369      /// @{
 370      mutable Mutex m_request_dispatcher_mutex;
 371      std::function<void(std::unique_ptr<HTTPRequest>&&)> m_request_dispatcher GUARDED_BY(m_request_dispatcher_mutex);
 372      /// @}
 373  
 374      /**
 375       * Idle timeout after which clients are disconnected
 376       */
 377      std::chrono::seconds m_rpcservertimeout{DEFAULT_HTTP_SERVER_TIMEOUT};
 378  
 379      /**
 380       * Accept a connection.
 381       * @param[in] listen_sock Socket on which to accept the connection.
 382       * @param[out] addr Address of the peer that was accepted.
 383       * @return Newly created socket for the accepted connection.
 384       */
 385      std::unique_ptr<Sock> AcceptConnection(const Sock& listen_sock, CService& addr);
 386  
 387      /**
 388       * Generate an id for a newly created connection.
 389       */
 390      Id GetNewId();
 391  
 392      /**
 393       * After a new socket with a client has been created, configure its flags,
 394       * make a new HTTPRemoteClient and Id and save its shared pointer.
 395       * @param[in] sock The newly created socket.
 396       * @param[in] addr Address of the new peer.
 397       */
 398      void NewSockAccepted(std::unique_ptr<Sock>&& sock, const CService& addr);
 399  
 400      /**
 401       * Do the read/write for connected sockets that are ready for IO.
 402       * @param[in] io_readiness Which sockets are ready and their corresponding HTTPRemoteClients.
 403       */
 404      void SocketHandlerConnected(const IOReadiness& io_readiness) const
 405          EXCLUSIVE_LOCKS_REQUIRED(!m_request_dispatcher_mutex);
 406  
 407      /**
 408       * Accept incoming connections, one from each read-ready listening socket.
 409       * @param[in] events_per_sock Sockets that are ready for IO.
 410       */
 411      void SocketHandlerListening(const Sock::EventsPerSock& events_per_sock);
 412  
 413      /**
 414       * Generate a collection of sockets to check for IO readiness.
 415       * @return Sockets to check for readiness plus an aux map to find the
 416       * corresponding HTTPRemoteClient given a socket.
 417       */
 418      IOReadiness GenerateWaitSockets() const;
 419  
 420      /**
 421       * Check connected and listening sockets for IO readiness and process them accordingly.
 422       * This is the main I/O loop of the server.
 423       */
 424      void ThreadSocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_request_dispatcher_mutex);
 425  
 426      /**
 427       * Try to read HTTPRequests from a client's receive buffer.
 428       * Complete requests are dispatched, incomplete requests are
 429       * left in the buffer to wait for more data. Some read errors
 430       * will mark this client for disconnection.
 431       * @param[in] client The HTTPRemoteClient to read requests from
 432       */
 433      void MaybeDispatchRequestsFromClient(const std::shared_ptr<HTTPRemoteClient>& client) const
 434          EXCLUSIVE_LOCKS_REQUIRED(!m_request_dispatcher_mutex);
 435  
 436      /**
 437       * Close underlying socket connections for flagged clients
 438       * by removing their shared pointer from m_connected. If an HTTPRemoteClient
 439       * is busy in a worker thread, its connection will be closed once that
 440       * job is done and the HTTPRequest is out of scope.
 441       */
 442      void DisconnectClients();
 443  };
 444  
 445  std::optional<std::string> GetQueryParameterFromUri(std::string_view uri, std::string_view key);
 446  
 447  class HTTPRemoteClient
 448  {
 449  public:
 450      //! ID provided by HTTPServer upon connection and instantiation
 451      const HTTPServer::Id m_id;
 452  
 453      //! Remote address of connected client
 454      const CService m_addr;
 455  
 456      //! IP:port of connected client, cached for logging purposes
 457      const std::string m_origin;
 458  
 459      /**
 460       * In lieu of an intermediate transport class like p2p uses,
 461       * we copy data from the socket buffer to the client object
 462       * and attempt to read HTTP requests from here.
 463       */
 464      std::vector<std::byte> m_recv_buffer{};
 465  
 466      //! Requests from a client must be processed in the order in which
 467      //! they were received, blocking on a per-client basis. We won't
 468      //! process the next request in the queue if we are currently busy
 469      //! handling a previous request.
 470      std::deque<std::unique_ptr<HTTPRequest>> m_req_queue;
 471  
 472      //! Set to true by the I/O thread when a request is popped off
 473      //! and passed to a worker thread, reset to false by the worker thread.
 474      std::atomic_bool m_req_busy{false};
 475  
 476      /**
 477       * Response data destined for this client.
 478       * Written to by http worker threads, read and erased by HTTPServer I/O thread
 479       */
 480      /// @{
 481      Mutex m_send_mutex;
 482      std::vector<std::byte> m_send_buffer GUARDED_BY(m_send_mutex);
 483      /// @}
 484  
 485      /**
 486      * Set true by worker threads after writing a response to m_send_buffer.
 487      * Set false by the HTTPServer I/O thread after flushing m_send_buffer.
 488      * Checked in the HTTPServer I/O loop to decide whether to poll the socket for
 489      * writeability or readability.
 490      * Guarded by m_send_mutex so it stays consistent with m_send_buffer's emptiness:
 491      * the two must always be updated together under the same lock.
 492      */
 493      bool m_send_ready GUARDED_BY(m_send_mutex){false};
 494  
 495      /**
 496       * Mutex that serializes the Send() and Recv() calls on `m_sock`. Reading
 497       * from the client occurs in the I/O thread but writing back to a client
 498       * may occur in a worker thread.
 499       */
 500      Mutex m_sock_mutex;
 501  
 502      /**
 503       * Underlying socket.
 504       * `shared_ptr` (instead of `unique_ptr`) is used to avoid premature close of the
 505       * underlying file descriptor by one thread while another thread is poll(2)-ing
 506       * it for activity.
 507       * @see https://github.com/bitcoin/bitcoin/issues/21744 for details.
 508       */
 509      std::shared_ptr<Sock> m_sock GUARDED_BY(m_sock_mutex);
 510  
 511      //! Initialized to true while server waits for first request from client.
 512      //! Set to false after data is written to m_send_buffer and then that buffer is flushed to client.
 513      //! Reset to true when we receive new request data from client.
 514      //! Checked during DisconnectClients() and set by read/write operations
 515      //! called in either the HTTPServer I/O loop or by a worker thread during an "optimistic send".
 516      //! `m_connection_busy=true` can be overridden by `m_disconnect=true` (we disconnect).
 517      std::atomic_bool m_connection_busy{true};
 518  
 519      //! Client has requested to keep the connection open after all requests have been responded to.
 520      //! Set by (potentially multiple) worker threads and checked in the HTTPServer I/O loop.
 521      //! `m_keep_alive=true` can be overridden `by HTTPServer.m_disconnect_all_clients` (we disconnect).
 522      std::atomic_bool m_keep_alive{false};
 523  
 524      //! Flag this client for disconnection on next loop.
 525      //! Either we have encountered a permanent error, or both sides of the socket are done
 526      //! with the connection, e.g. our reply to a "Connection: close" request has been sent.
 527      //! Might be set in a worker thread or in the I/O thread. When set to `true` we disconnect,
 528      //! possibly overriding all other disconnect flags.
 529      std::atomic_bool m_disconnect{false};
 530  
 531      //! Timestamp of last send or receive activity, used for -rpcservertimeout.
 532      //! Due to optimistic sends it may be updated in either a worker thread or in the
 533      //! I/O thread. It is checked in the I/O thread to disconnect idle clients.
 534      std::atomic<SteadySeconds> m_idle_since;
 535  
 536      explicit HTTPRemoteClient(HTTPServer::Id id, const CService& addr, std::unique_ptr<Sock> socket)
 537          : m_id(id), m_addr(addr), m_origin(addr.ToStringAddrPort()), m_sock{std::move(socket)}, m_idle_since{Now<SteadySeconds>()} {}
 538  
 539      // Disable copies (should only be used as shared pointers)
 540      HTTPRemoteClient(const HTTPRemoteClient&) = delete;
 541      HTTPRemoteClient& operator=(const HTTPRemoteClient&) = delete;
 542  
 543      /**
 544       * Try to read an HTTP request from the receive buffer.
 545       * @param[in]   req     A HTTPRequest to read into
 546       * @returns true upon reading a complete request, otherwise false (may throw).
 547       */
 548      bool ReadRequest(HTTPRequest& req);
 549  
 550      /**
 551       * Push data (if there is any) from client's m_send_buffer to the connected socket.
 552       * @returns false if we are done with this client and HTTPServer can skip the next read operation from it.
 553       */
 554      bool MaybeSendBytesFromBuffer() EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex, !m_sock_mutex);
 555  };
 556  
 557  /** Initialize HTTP server.
 558   * Call this before RegisterHTTPHandler or EventBase().
 559   */
 560  bool InitHTTPServer();
 561  
 562  /** Start HTTP server.
 563   * This is separate from InitHTTPServer to give users race-condition-free time
 564   * to register their handlers between InitHTTPServer and StartHTTPServer.
 565   */
 566  void StartHTTPServer();
 567  
 568  /** Interrupt HTTP server threads */
 569  void InterruptHTTPServer();
 570  
 571  /** Stop HTTP server */
 572  void StopHTTPServer();
 573  } // namespace http_bitcoin
 574  
 575  #endif // BITCOIN_HTTPSERVER_H
 576