httpserver.cpp 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  #include <bitcoin-build-config.h> // IWYU pragma: keep
   6  
   7  #include <httpserver.h>
   8  
   9  #include <chainparamsbase.h>
  10  #include <common/args.h>
  11  #include <common/messages.h>
  12  #include <common/url.h>
  13  #include <compat/compat.h>
  14  #include <logging.h>
  15  #include <netbase.h>
  16  #include <node/interface_ui.h>
  17  #include <rpc/protocol.h>
  18  #include <span.h>
  19  #include <sync.h>
  20  #include <util/check.h>
  21  #include <util/signalinterrupt.h>
  22  #include <util/sock.h>
  23  #include <util/strencodings.h>
  24  #include <util/thread.h>
  25  #include <util/threadnames.h>
  26  #include <util/threadpool.h>
  27  #include <util/time.h>
  28  #include <util/translation.h>
  29  
  30  #include <condition_variable>
  31  #include <cstdio>
  32  #include <cstdlib>
  33  #include <deque>
  34  #include <memory>
  35  #include <optional>
  36  #include <span>
  37  #include <string>
  38  #include <string_view>
  39  #include <thread>
  40  #include <unordered_map>
  41  #include <vector>
  42  
  43  #include <sys/types.h>
  44  #include <sys/stat.h>
  45  
  46  //! The set of sockets cannot be modified while waiting, so
  47  //! the sleep time needs to be small to avoid new sockets stalling.
  48  static constexpr auto SELECT_TIMEOUT{50ms};
  49  
  50  //! Explicit alias for setting socket option methods.
  51  static constexpr int SOCKET_OPTION_TRUE{1};
  52  
  53  using common::InvalidPortErrMsg;
  54  using http_bitcoin::HTTPRequest;
  55  
  56  struct HTTPPathHandler
  57  {
  58      HTTPPathHandler(std::string _prefix, bool _exactMatch, HTTPRequestHandler _handler):
  59          prefix(_prefix), exactMatch(_exactMatch), handler(_handler)
  60      {
  61      }
  62      std::string prefix;
  63      bool exactMatch;
  64      HTTPRequestHandler handler;
  65  };
  66  
  67  /** HTTP module state */
  68  
  69  static std::unique_ptr<http_bitcoin::HTTPServer> g_http_server{nullptr};
  70  //! List of subnets to allow RPC connections from
  71  static std::vector<CSubNet> rpc_allow_subnets;
  72  //! Handlers for (sub)paths
  73  static GlobalMutex g_httppathhandlers_mutex;
  74  static std::vector<HTTPPathHandler> pathHandlers GUARDED_BY(g_httppathhandlers_mutex);
  75  /// \anchor http_pool
  76  //! Http thread pool - future: encapsulate in HttpContext
  77  static ThreadPool g_threadpool_http("http");
  78  static int g_max_queue_depth{100};
  79  
  80  /** Check if a network address is allowed to access the HTTP server */
  81  static bool ClientAllowed(const CNetAddr& netaddr)
  82  {
  83      if (!netaddr.IsValid())
  84          return false;
  85      for(const CSubNet& subnet : rpc_allow_subnets)
  86          if (subnet.Match(netaddr))
  87              return true;
  88      return false;
  89  }
  90  
  91  /** Initialize ACL list for HTTP server */
  92  static bool InitHTTPAllowList()
  93  {
  94      rpc_allow_subnets.clear();
  95      rpc_allow_subnets.emplace_back(LookupHost("127.0.0.1", false).value(), 8);  // always allow IPv4 local subnet
  96      rpc_allow_subnets.emplace_back(LookupHost("::1", false).value());  // always allow IPv6 localhost
  97      for (const std::string& strAllow : gArgs.GetArgs("-rpcallowip")) {
  98          const CSubNet subnet{LookupSubNet(strAllow)};
  99          if (!subnet.IsValid()) {
 100              uiInterface.ThreadSafeMessageBox(
 101                  Untranslated(strprintf("Invalid -rpcallowip subnet specification: %s. Valid values are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0), a network/CIDR (e.g. 1.2.3.4/24), all ipv4 (0.0.0.0/0), or all ipv6 (::/0). RFC4193 is allowed only if -cjdnsreachable=0.", strAllow)),
 102                  CClientUIInterface::MSG_ERROR);
 103              return false;
 104          }
 105          rpc_allow_subnets.push_back(subnet);
 106      }
 107      std::string strAllowed;
 108      for (const CSubNet& subnet : rpc_allow_subnets)
 109          strAllowed += subnet.ToString() + " ";
 110      LogDebug(BCLog::HTTP, "Allowing HTTP connections from: %s\n", strAllowed);
 111      return true;
 112  }
 113  
 114  /** HTTP request method as string - use for logging only */
 115  std::string_view RequestMethodString(HTTPRequestMethod m)
 116  {
 117      switch (m) {
 118      using enum HTTPRequestMethod;
 119      case GET: return "GET";
 120      case POST: return "POST";
 121      case HEAD: return "HEAD";
 122      case PUT: return "PUT";
 123      case UNKNOWN: return "unknown";
 124      } // no default case, so the compiler can warn about missing cases
 125      assert(false);
 126  }
 127  
 128  static void MaybeDispatchRequestToWorker(std::shared_ptr<HTTPRequest> hreq)
 129  {
 130      // Early address-based allow check
 131      if (!ClientAllowed(hreq->GetPeer())) {
 132          LogDebug(BCLog::HTTP, "HTTP request from %s rejected: Client network is not allowed RPC access\n",
 133                   hreq->GetPeer().ToStringAddrPort());
 134          hreq->WriteReply(HTTP_FORBIDDEN);
 135          return;
 136      }
 137  
 138      // Early reject unknown HTTP methods
 139      if (hreq->GetRequestMethod() == HTTPRequestMethod::UNKNOWN) {
 140          LogDebug(BCLog::HTTP, "HTTP request from %s rejected: Unknown HTTP request method\n",
 141                   hreq->GetPeer().ToStringAddrPort());
 142          hreq->WriteReply(HTTP_BAD_METHOD);
 143          return;
 144      }
 145  
 146      // Find registered handler for prefix
 147      std::string strURI = hreq->GetURI();
 148      std::string path;
 149      LOCK(g_httppathhandlers_mutex);
 150      std::vector<HTTPPathHandler>::const_iterator i = pathHandlers.begin();
 151      std::vector<HTTPPathHandler>::const_iterator iend = pathHandlers.end();
 152      for (; i != iend; ++i) {
 153          bool match = false;
 154          if (i->exactMatch)
 155              match = (strURI == i->prefix);
 156          else
 157              match = strURI.starts_with(i->prefix);
 158          if (match) {
 159              path = strURI.substr(i->prefix.size());
 160              break;
 161          }
 162      }
 163  
 164      // Dispatch to worker thread
 165      if (i != iend) {
 166          if (static_cast<int>(g_threadpool_http.WorkQueueSize()) >= g_max_queue_depth) {
 167              LogWarning("Request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting");
 168              hreq->WriteReply(HTTP_SERVICE_UNAVAILABLE, "Work queue depth exceeded");
 169              return;
 170          }
 171  
 172          auto item = [req = hreq, in_path = std::move(path), fn = i->handler]() {
 173              std::string err_msg;
 174              try {
 175                  fn(req.get(), in_path);
 176                  return;
 177              } catch (const std::exception& e) {
 178                  LogWarning("Unexpected error while processing request for '%s'. Error msg: '%s'", req->GetURI(), e.what());
 179                  err_msg = e.what();
 180              } catch (...) {
 181                  LogWarning("Unknown error while processing request for '%s'", req->GetURI());
 182                  err_msg = "unknown error";
 183              }
 184              // Reply so the client doesn't hang waiting for the response.
 185              req->WriteHeader("Connection", "close");
 186              // TODO: Implement specific error formatting for the REST and JSON-RPC servers responses.
 187              req->WriteReply(HTTP_INTERNAL_SERVER_ERROR, err_msg);
 188          };
 189  
 190          if (auto res = g_threadpool_http.Submit(std::move(item)); !res.has_value()) {
 191              Assume(hreq.use_count() == 1); // ensure request will be deleted
 192              // Both SubmitError::Inactive and SubmitError::Interrupted mean shutdown
 193              LogWarning("HTTP request rejected during server shutdown: '%s'", SubmitErrorString(res.error()));
 194              hreq->WriteReply(HTTP_SERVICE_UNAVAILABLE, "Request rejected during server shutdown");
 195              return;
 196          }
 197      } else {
 198          hreq->WriteReply(HTTP_NOT_FOUND);
 199      }
 200  }
 201  
 202  static void RejectRequest(std::unique_ptr<http_bitcoin::HTTPRequest> hreq)
 203  {
 204      LogDebug(BCLog::HTTP, "Rejecting request while shutting down");
 205      hreq->WriteReply(HTTP_SERVICE_UNAVAILABLE);
 206  }
 207  
 208  static std::vector<std::pair<std::string, uint16_t>> GetBindAddresses()
 209  {
 210      uint16_t http_port{static_cast<uint16_t>(gArgs.GetIntArg("-rpcport", BaseParams().RPCPort()))};
 211      std::vector<std::pair<std::string, uint16_t>> endpoints;
 212  
 213      // Determine what addresses to bind to
 214      // To prevent misconfiguration and accidental exposure of the RPC
 215      // interface, require -rpcallowip and -rpcbind to both be specified
 216      // together. If either is missing, ignore both values, bind to localhost
 217      // instead, and log warnings.
 218      if (gArgs.GetArgs("-rpcallowip").empty() || gArgs.GetArgs("-rpcbind").empty()) { // Default to loopback if not allowing external IPs
 219          endpoints.emplace_back("::1", http_port);
 220          endpoints.emplace_back("127.0.0.1", http_port);
 221          if (!gArgs.GetArgs("-rpcallowip").empty()) {
 222              LogWarning("Option -rpcallowip was specified without -rpcbind; this doesn't usually make sense");
 223          }
 224          if (!gArgs.GetArgs("-rpcbind").empty()) {
 225              LogWarning("Option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect");
 226          }
 227      } else { // Specific bind addresses
 228          for (const std::string& strRPCBind : gArgs.GetArgs("-rpcbind")) {
 229              uint16_t port{http_port};
 230              std::string host;
 231              if (!SplitHostPort(strRPCBind, port, host)) {
 232                  LogError("%s\n", InvalidPortErrMsg("-rpcbind", strRPCBind).original);
 233                  return {}; // empty
 234              }
 235              endpoints.emplace_back(host, port);
 236          }
 237      }
 238      return endpoints;
 239  }
 240  
 241  void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
 242  {
 243      LogDebug(BCLog::HTTP, "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
 244      LOCK(g_httppathhandlers_mutex);
 245      pathHandlers.emplace_back(prefix, exactMatch, handler);
 246  }
 247  
 248  void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
 249  {
 250      LOCK(g_httppathhandlers_mutex);
 251      std::vector<HTTPPathHandler>::iterator i = pathHandlers.begin();
 252      std::vector<HTTPPathHandler>::iterator iend = pathHandlers.end();
 253      for (; i != iend; ++i)
 254          if (i->prefix == prefix && i->exactMatch == exactMatch)
 255              break;
 256      if (i != iend)
 257      {
 258          LogDebug(BCLog::HTTP, "Unregistering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
 259          pathHandlers.erase(i);
 260      }
 261  }
 262  
 263  namespace http_bitcoin {
 264  using util::Split;
 265  
 266  std::optional<std::string> HTTPHeaders::FindFirst(const std::string_view key) const
 267  {
 268      for (const auto& item : m_headers) {
 269          if (CaseInsensitiveEqual(key, item.first)) {
 270              return item.second;
 271          }
 272      }
 273      return std::nullopt;
 274  }
 275  
 276  std::vector<std::string_view> HTTPHeaders::FindAll(const std::string_view key) const
 277  {
 278      std::vector<std::string_view> ret;
 279      for (const auto& item : m_headers) {
 280          if (CaseInsensitiveEqual(key, item.first)) {
 281              ret.push_back(item.second);
 282          }
 283      }
 284      return ret;
 285  }
 286  
 287  void HTTPHeaders::Write(std::string&& key, std::string&& value)
 288  {
 289      m_headers.emplace_back(std::move(key), std::move(value));
 290  }
 291  
 292  void HTTPHeaders::RemoveAll(std::string_view key)
 293  {
 294      auto moved = std::ranges::remove_if(m_headers, [key] (auto& pair) {
 295          return CaseInsensitiveEqual(key, pair.first);
 296      });
 297      m_headers.erase(moved.begin(), moved.end());
 298  }
 299  
 300  bool HTTPHeaders::Read(util::LineReader& reader)
 301  {
 302      // Headers https://httpwg.org/specs/rfc9110.html#rfc.section.6.3
 303      // A sequence of Field Lines https://httpwg.org/specs/rfc9110.html#rfc.section.5.2
 304      while (auto maybe_line = reader.ReadLine()) {
 305          if (reader.Consumed() > MAX_HEADERS_SIZE) throw std::runtime_error("HTTP headers exceed size limit");
 306  
 307          const std::string_view& line = *maybe_line;
 308  
 309          // An empty line indicates end of the headers section https://www.rfc-editor.org/rfc/rfc2616#section-4
 310          if (line.empty()) return true;
 311  
 312          // "Field values containing CR, LF, or NUL characters are invalid and dangerous"
 313          // https://httpwg.org/specs/rfc9110.html#rfc.section.5.5
 314          // A sender MUST NOT generate a bare CR (a CR character not immediately followed by LF)
 315          // within any protocol elements other than the content.
 316          // A recipient of such a bare CR MUST consider that element to be invalid...
 317          // https://httpwg.org/specs/rfc9112.html#rfc.section.2.2
 318          if (line.find_first_of("\r\n\0", 0, 3) != std::string_view::npos) throw std::runtime_error("Header contains invalid character");
 319  
 320          // Header line must have at least one ":"
 321          // keys are not allowed to have delimiters like ":" but values are
 322          // https://httpwg.org/specs/rfc9110.html#rfc.section.5.6.2
 323          const size_t pos{line.find(':')};
 324          if (pos == std::string_view::npos) throw std::runtime_error("HTTP header missing colon (:)");
 325  
 326          // Whitespace is strictly not allowed in the field-name (key)
 327          // https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6.2
 328          std::string_view key = line.substr(0, pos);
 329          if (key.find_first_of(" \t\n\r\f\v") != std::string_view::npos) throw std::runtime_error("Invalid header field-name contains whitespace");
 330          // Whitespace is optional in the value and can be trimmed
 331          std::string value = util::TrimString(std::string_view(line).substr(pos + 1));
 332  
 333          // Header keys are Field Names: https://httpwg.org/specs/rfc9110.html#fields.names
 334          // which consist of "tokens": https://httpwg.org/specs/rfc9110.html#rfc.section.5.6.2
 335          // that can not be empty.
 336          if (key.empty()) throw std::runtime_error("Empty HTTP header name");
 337  
 338          Write(std::string(key), std::move(value));
 339      }
 340  
 341      return false;
 342  }
 343  
 344  std::string HTTPHeaders::Stringify() const
 345  {
 346      std::string out;
 347      for (const auto& [key, value] : m_headers) {
 348          out += key + ": " + value + "\r\n";
 349      }
 350  
 351      // Headers are terminated by an empty line
 352      out += "\r\n";
 353  
 354      return out;
 355  }
 356  
 357  std::string HTTPResponse::StringifyHeaders() const
 358  {
 359      return strprintf("HTTP/%d.%d %d %s\r\n%s",
 360                       m_version.major,
 361                       m_version.minor,
 362                       m_status,
 363                       HTTPStatusReasonString(m_status),
 364                       m_headers.Stringify());
 365  }
 366  
 367  bool HTTPRequest::LoadControlData(LineReader& reader)
 368  {
 369      auto maybe_line = reader.ReadLine();
 370      if (!maybe_line) return false;
 371      const std::string_view& request_line = *maybe_line;
 372  
 373      // Request Line aka Control Data https://httpwg.org/specs/rfc9110.html#rfc.section.6.2
 374      // Three words separated by spaces, terminated by \n or \r\n
 375      if (request_line.length() < MIN_REQUEST_LINE_LENGTH) throw std::runtime_error("HTTP request line too short");
 376  
 377      // NUL is not a valid tchar and would silently truncate
 378      // C-string-based parsers rather than being rejected as malformed.
 379      // tchar: https://www.rfc-editor.org/info/rfc7230/#section-3.2.6
 380      if (request_line.find('\0') != std::string_view::npos) throw std::runtime_error("Invalid request line contains NUL");
 381  
 382      const std::vector<std::string_view> parts{Split<std::string_view>(request_line, " ")};
 383      if (parts.size() != 3) throw std::runtime_error("HTTP request line malformed");
 384  
 385      if (parts[0] == "GET") {
 386          m_method = HTTPRequestMethod::GET;
 387      } else if (parts[0] == "POST") {
 388          m_method = HTTPRequestMethod::POST;
 389      } else if (parts[0] == "HEAD") {
 390          m_method = HTTPRequestMethod::HEAD;
 391      } else if (parts[0] == "PUT") {
 392          m_method = HTTPRequestMethod::PUT;
 393      } else {
 394          m_method = HTTPRequestMethod::UNKNOWN;
 395      }
 396  
 397      m_target = parts[1];
 398  
 399      if (parts[2].rfind("HTTP/") != 0) throw std::runtime_error("HTTP request line malformed");
 400  
 401      // Version is exactly two decimal digits separated by a decimal point
 402      // https://httpwg.org/specs/rfc9110.html#rfc.section.2.5
 403      const std::vector<std::string_view> version_parts{Split<std::string_view>(parts[2].substr(5), ".")};
 404      if (version_parts.size() != 2) throw std::runtime_error("HTTP request line malformed");
 405      if (version_parts[0].size() != 1 || version_parts[1].size() != 1) throw std::runtime_error("HTTP bad version");
 406      auto major = ToIntegral<uint8_t>(version_parts[0]);
 407      auto minor = ToIntegral<uint8_t>(version_parts[1]);
 408      if (!major || !minor || major != 1 || minor > 9) throw std::runtime_error("HTTP bad version");
 409      m_version.major = major.value();
 410      m_version.minor = minor.value();
 411  
 412      return true;
 413  }
 414  
 415  bool HTTPRequest::LoadHeaders(LineReader& reader)
 416  {
 417      return m_headers.Read(reader);
 418  }
 419  
 420  bool HTTPRequest::LoadBody(LineReader& reader)
 421  {
 422      // https://httpwg.org/specs/rfc9112.html#message.body
 423      auto transfer_encoding_header = m_headers.FindFirst("Transfer-Encoding");
 424      if (transfer_encoding_header && ToLower(transfer_encoding_header.value()) == "chunked") {
 425          // Transfer-Encoding: https://datatracker.ietf.org/doc/html/rfc7230.html#section-3.3.1
 426          // Chunked Transfer Coding: https://datatracker.ietf.org/doc/html/rfc7230.html#section-4.1
 427          // see evhttp_handle_chunked_read() in libevent http.c
 428          while (reader.Remaining() > 0) {
 429              auto maybe_chunk_size = reader.ReadLine();
 430              if (!maybe_chunk_size) return false;
 431  
 432              // Allow (but ignore) Chunk Extensions
 433              // See https://www.rfc-editor.org/rfc/rfc9112.html#name-chunk-extensions
 434              std::string_view chunk_size_noext{maybe_chunk_size.value()};
 435              const auto semicolon_pos = chunk_size_noext.find(';');
 436              if (semicolon_pos != chunk_size_noext.npos) {
 437                  chunk_size_noext.remove_suffix(chunk_size_noext.size() - semicolon_pos);
 438              }
 439  
 440              const auto chunk_size{ToIntegral<uint64_t>(util::TrimStringView(chunk_size_noext), /*base=*/16)};
 441              if (!chunk_size) throw std::runtime_error("Cannot parse chunk length value");
 442  
 443              if ((m_body.size() > MAX_BODY_SIZE) ||
 444                  (*chunk_size > MAX_BODY_SIZE - m_body.size()))
 445                  throw ContentTooLargeError("Chunk will exceed max body size");
 446  
 447              // Last chunk has size 0
 448              if (*chunk_size == 0) {
 449                  // Allow (but ignore) Chunked Trailer section, by
 450                  // reading CRLF-terminated lines until we read an empty line,
 451                  // which indicates the end of this request.
 452                  // See https://httpwg.org/specs/rfc9112.html#rfc.section.7.1.2
 453                  const size_t trailer_start{reader.Consumed()};
 454                  while (true) {
 455                      auto maybe_trailer = reader.ReadLine();
 456                      if (reader.Consumed() - trailer_start > MAX_HEADERS_SIZE) {
 457                          throw std::runtime_error("HTTP chunked trailer exceeds size limit");
 458                      }
 459                      if (!maybe_trailer) return false;
 460                      if (maybe_trailer->empty()) break;
 461                  }
 462                  // Complete request has been parsed, reader is now pointing
 463                  // to beginning of next request or end of the buffer.
 464                  return true;
 465              }
 466  
 467              // We are still expecting more data for this chunk
 468              if (reader.Remaining() < *chunk_size) {
 469                  return false;
 470              }
 471  
 472              // Pack chunk onto body
 473              m_body += reader.ReadLength(*chunk_size);
 474  
 475              // Even though every chunk size is explicitly declared,
 476              // they are still terminated by a CRLF we don't need,
 477              // just consume it here.
 478              auto crlf = reader.ReadLine();
 479              if (!crlf) {
 480                  // CRLF not found before end of buffer: it has not been received by our socket yet.
 481                  return false;
 482              }
 483              // CRLF was found but there was unexpected data after the chunk_sized chunk
 484              if (!crlf.value().empty()) throw std::runtime_error("Improperly terminated chunk");
 485          }
 486  
 487          // We read all the chunks but never got the last chunk, wait for client to send more
 488          return false;
 489      } else {
 490          // No Content-length or Transfer-Encoding header means no body, see libevent evhttp_get_body()
 491          auto content_length_values{m_headers.FindAll("Content-Length")};
 492          if (content_length_values.empty()) return true;
 493  
 494          // Duplicate Content-Length headers are allowed only if they all have the same value
 495          // https://www.rfc-editor.org/rfc/rfc7230#section-3.3.3
 496          const auto& first_content_length_value{content_length_values[0]};
 497          for (size_t i = 1; i < content_length_values.size(); ++i) {
 498              if (content_length_values[i] != first_content_length_value) throw std::runtime_error("Differing Content-Length values");
 499          }
 500  
 501          const auto content_length{ToIntegral<uint64_t>(first_content_length_value)};
 502          if (!content_length) throw std::runtime_error("Cannot parse Content-Length value");
 503  
 504          if (*content_length > MAX_BODY_SIZE) throw ContentTooLargeError("Max body size exceeded");
 505  
 506          // Not enough data in buffer for expected body
 507          if (reader.Remaining() < *content_length) return false;
 508  
 509          m_body = reader.ReadLength(*content_length);
 510  
 511          return true;
 512      }
 513  }
 514  
 515  void HTTPRequest::WriteReply(HTTPStatusCode status, std::span<const std::byte> reply_body)
 516  {
 517      HTTPResponse res;
 518  
 519      // Some response headers are determined in advance and stored in the request
 520      res.m_headers = std::move(m_response_headers);
 521  
 522      // Response version matches request version
 523      res.m_version = m_version;
 524  
 525      // Add response code
 526      res.m_status = status;
 527  
 528      // See libevent evhttp_response_needs_body()
 529      // Response headers are different if no body is needed
 530      bool needs_body{status != HTTP_NO_CONTENT && (status < 100 || status >= 200)};
 531      bool needs_content_length{false};
 532  
 533      bool keep_alive{false};
 534  
 535      // See libevent evhttp_make_header_response()
 536      // Expected response headers depend on protocol version
 537      if (m_version.major == 1) {
 538          // HTTP/1.0
 539          if (m_version.minor == 0) {
 540              auto connection_header{m_headers.FindFirst("Connection")};
 541              if (connection_header && ToLower(connection_header.value()) == "keep-alive") {
 542                  res.m_headers.Write("Connection", "keep-alive");
 543                  keep_alive = true;
 544                  // HTTP/1.0 connections are closed by default so EOF is sufficient
 545                  // to indicate end of the body. Adding Content-Length a special case.
 546                  if (needs_body) needs_content_length = true;
 547              }
 548          }
 549  
 550          // HTTP/1.1
 551          if (m_version.minor >= 1) {
 552              const int64_t now_seconds{TicksSinceEpoch<std::chrono::seconds>(NodeClock::now())};
 553              res.m_headers.Write("Date", FormatRFC1123DateTime(now_seconds));
 554  
 555              // HTTP/1.1 connections are kept alive by default and always require Content-Length.
 556              if (needs_body) needs_content_length = true;
 557  
 558              // Default for HTTP/1.1
 559              keep_alive = true;
 560          }
 561      }
 562  
 563      if (needs_content_length) {
 564          res.m_headers.Write("Content-Length", util::ToString(reply_body.size()));
 565      }
 566  
 567      if (needs_body && !res.m_headers.FindFirst("Content-Type")) {
 568          // Default type from libevent evhttp_new_object()
 569          res.m_headers.Write("Content-Type", "text/html; charset=ISO-8859-1");
 570      }
 571  
 572      auto connection_header{m_headers.FindFirst("Connection")};
 573      if (connection_header && ToLower(connection_header.value()) == "close") {
 574          // Might not exist already but we need to replace it, not append to it
 575          res.m_headers.RemoveAll("Connection");
 576  
 577          res.m_headers.Write("Connection", "close");
 578          keep_alive = false;
 579      }
 580  
 581      m_client->m_keep_alive = keep_alive;
 582  
 583      // Serialize the response headers
 584      const std::string headers{res.StringifyHeaders()};
 585      const auto headers_bytes{std::as_bytes(std::span{headers})};
 586  
 587      bool send_buffer_was_empty{false};
 588      // Fill the send buffer with the complete serialized response headers + body
 589      {
 590          LOCK(m_client->m_send_mutex);
 591          send_buffer_was_empty = m_client->m_send_buffer.empty();
 592          m_client->m_send_buffer.insert(m_client->m_send_buffer.end(), headers_bytes.begin(), headers_bytes.end());
 593  
 594          // We've been using std::span up until now but it is finally time to copy
 595          // data. The original data will go out of scope when WriteReply() returns.
 596          // This is analogous to the memcpy() in libevent's evbuffer_add()
 597          m_client->m_send_buffer.insert(m_client->m_send_buffer.end(), reply_body.begin(), reply_body.end());
 598  
 599          // If the buffer already held data, the I/O thread is (or soon will be)
 600          // draining it, so flag that there is more data to send. This must happen
 601          // while holding m_send_mutex and while the buffer is known non-empty:
 602          // setting m_send_ready after releasing the lock would race with the I/O
 603          // thread draining the buffer to empty and clearing m_send_ready in
 604          // between, leaving m_send_ready set on an empty buffer. The I/O loop would
 605          // then only ever poll the socket for writeability, never read the client's
 606          // next request, and wedge the connection.
 607          if (!send_buffer_was_empty) m_client->m_send_ready = true;
 608      }
 609  
 610      LogDebug(
 611          BCLog::HTTP,
 612          "HTTPResponse (status code: %d size: %lld) added to send buffer for client %s (id=%llu)",
 613          status,
 614          headers_bytes.size() + reply_body.size(),
 615          m_client->m_origin,
 616          m_client->m_id);
 617  
 618      // If the send buffer was empty before we wrote this reply, we can try an
 619      // optimistic send akin to CConnman::PushMessage() in which we
 620      // push the data directly out the socket to client right now, instead
 621      // of waiting for the next iteration of the I/O loop.
 622      if (send_buffer_was_empty) {
 623          m_client->MaybeSendBytesFromBuffer();
 624      }
 625  
 626      // Signal to the I/O loop that we are ready to handle the next request.
 627      m_client->m_req_busy = false;
 628  }
 629  
 630  CService HTTPRequest::GetPeer() const
 631  {
 632      return m_client->m_addr;
 633  }
 634  
 635  std::optional<std::string> HTTPRequest::GetQueryParameter(const std::string_view key) const
 636  {
 637      return GetQueryParameterFromUri(m_target, key);
 638  }
 639  
 640  // See libevent http.c evhttp_parse_query_impl()
 641  // and https://www.rfc-editor.org/rfc/rfc3986#section-3.4
 642  std::optional<std::string> GetQueryParameterFromUri(const std::string_view uri, const std::string_view key)
 643  {
 644      // find query in URI
 645      size_t start = uri.find('?');
 646      if (start == std::string::npos) return std::nullopt;
 647      size_t end = uri.find('#', start);
 648      if (end == std::string::npos) {
 649          end = uri.length();
 650      }
 651      const std::string_view query{uri.data() + start + 1, end - start - 1};
 652      // find requested parameter in query
 653      const std::vector<std::string_view> params{Split<std::string_view>(query, "&")};
 654      for (const std::string_view& param : params) {
 655          size_t delim = param.find('=');
 656          if (key == UrlDecode(param.substr(0, delim))) {
 657              if (delim == std::string::npos) {
 658                  return "";
 659              } else {
 660                  return std::string(UrlDecode(param.substr(delim + 1)));
 661              }
 662          }
 663      }
 664      return std::nullopt;
 665  }
 666  
 667  std::pair<bool, std::string> HTTPRequest::GetHeader(const std::string_view hdr) const
 668  {
 669      std::optional<std::string> found{m_headers.FindFirst(hdr)};
 670      return std::pair{found.has_value(), std::move(found).value_or("")};
 671  }
 672  
 673  void HTTPRequest::WriteHeader(std::string&& hdr, std::string&& value)
 674  {
 675      m_response_headers.Write(std::move(hdr), std::move(value));
 676  }
 677  
 678  util::Expected<void, std::string> HTTPServer::BindAndStartListening(const CService& to)
 679  {
 680      // Create socket for listening for incoming connections
 681      sockaddr_storage storage;
 682      auto sa = reinterpret_cast<sockaddr*>(&storage);
 683      socklen_t len{sizeof(storage)};
 684      if (!to.GetSockAddr(sa, &len)) {
 685          return util::Unexpected{strprintf("Bind address family for %s not supported", to.ToStringAddrPort())};
 686      }
 687  
 688      std::unique_ptr<Sock> sock{CreateSock(to.GetSAFamily(), SOCK_STREAM, IPPROTO_TCP)};
 689      if (!sock) {
 690          return util::Unexpected{strprintf("Cannot create %s listen socket: %s",
 691                                            to.ToStringAddrPort(),
 692                                            NetworkErrorString(WSAGetLastError()))};
 693      }
 694  
 695      // Allow binding if the port is still in TIME_WAIT state after
 696      // the program was closed and restarted.
 697      if (sock->SetSockOpt(SOL_SOCKET, SO_REUSEADDR, &SOCKET_OPTION_TRUE, sizeof(SOCKET_OPTION_TRUE)) == SOCKET_ERROR) {
 698          LogDebug(BCLog::HTTP,
 699                   "Cannot set SO_REUSEADDR on %s listen socket: %s, continuing anyway",
 700                   to.ToStringAddrPort(),
 701                   NetworkErrorString(WSAGetLastError()));
 702      }
 703  
 704      // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
 705      // and enable it by default or not. Try to enable it, if possible.
 706      if (to.IsIPv6()) {
 707  #ifdef IPV6_V6ONLY
 708          if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_V6ONLY, &SOCKET_OPTION_TRUE, sizeof(SOCKET_OPTION_TRUE)) == SOCKET_ERROR) {
 709              LogDebug(BCLog::HTTP,
 710                       "Cannot set IPV6_V6ONLY on %s listen socket: %s, continuing anyway",
 711                       to.ToStringAddrPort(),
 712                       NetworkErrorString(WSAGetLastError()));
 713          }
 714  #endif
 715  #ifdef WIN32
 716          int prot_level{PROTECTION_LEVEL_UNRESTRICTED};
 717          if (sock->SetSockOpt(IPPROTO_IPV6,
 718                               IPV6_PROTECTION_LEVEL,
 719                               &prot_level,
 720                               sizeof(prot_level)) == SOCKET_ERROR) {
 721              LogDebug(BCLog::HTTP,
 722                       "Cannot set IPV6_PROTECTION_LEVEL on %s listen socket: %s, continuing anyway",
 723                       to.ToStringAddrPort(),
 724                       NetworkErrorString(WSAGetLastError()));
 725          }
 726  #endif
 727      }
 728  
 729      if (sock->Bind(sa, len) == SOCKET_ERROR) {
 730          const int err{WSAGetLastError()};
 731          if (err == WSAEADDRINUSE) {
 732              return util::Unexpected{strprintf("Unable to bind to %s on this computer. %s is probably already running.",
 733                                                to.ToStringAddrPort(),
 734                                                CLIENT_NAME)};
 735          } else {
 736              return util::Unexpected{strprintf("Unable to bind to %s on this computer (bind returned error %s)",
 737                                                to.ToStringAddrPort(),
 738                                                NetworkErrorString(err))};
 739          }
 740      }
 741  
 742      // Listen for incoming connections
 743      if (sock->Listen(SOMAXCONN) == SOCKET_ERROR) {
 744          return util::Unexpected{strprintf("Cannot listen on %s: %s",
 745                                            to.ToStringAddrPort(),
 746                                            NetworkErrorString(WSAGetLastError()))};
 747      }
 748  
 749      m_listen.emplace_back(std::move(sock));
 750  
 751      return {};
 752  }
 753  
 754  void HTTPServer::StopListening()
 755  {
 756      m_listen.clear();
 757  }
 758  
 759  void HTTPServer::StartSocketsThreads()
 760  {
 761      m_thread_socket_handler = std::thread(&util::TraceThread,
 762                                            "http",
 763                                            [this] { ThreadSocketHandler(); });
 764  }
 765  
 766  void HTTPServer::JoinSocketsThreads()
 767  {
 768      if (m_thread_socket_handler.joinable()) {
 769          m_thread_socket_handler.join();
 770      }
 771  }
 772  
 773  std::unique_ptr<Sock> HTTPServer::AcceptConnection(const Sock& listen_sock, CService& addr)
 774  {
 775      // Make sure we only operate on our own listening sockets
 776      Assume(std::ranges::any_of(m_listen, [&](const auto& sock) { return sock.get() == &listen_sock; }));
 777  
 778      sockaddr_storage storage;
 779      socklen_t len{sizeof(storage)};
 780      auto sa = reinterpret_cast<sockaddr*>(&storage);
 781  
 782      auto sock{listen_sock.Accept(sa, &len)};
 783  
 784      if (!sock) {
 785          const int err{WSAGetLastError()};
 786          if (err != WSAEWOULDBLOCK) {
 787              LogDebug(BCLog::HTTP,
 788                       "Cannot accept new connection: %s",
 789                       NetworkErrorString(err));
 790          }
 791          return {};
 792      }
 793  
 794      // The OS handed us a valid socket but we can't determine its source address.
 795      // In the unlikely event this occurs, the invalid address will be rejected
 796      // by the downstream ClientAllowed() check.
 797      if (!addr.SetSockAddr(sa, len)) {
 798          LogDebug(BCLog::HTTP,
 799                   "Unknown socket family");
 800      }
 801  
 802      return sock;
 803  }
 804  
 805  HTTPServer::Id HTTPServer::GetNewId()
 806  {
 807      return m_next_id.fetch_add(1, std::memory_order_relaxed);
 808  }
 809  
 810  void HTTPServer::NewSockAccepted(std::unique_ptr<Sock>&& sock, const CService& addr)
 811  {
 812      if (!sock->IsSelectable()) {
 813          LogDebug(BCLog::HTTP,
 814                   "connection from %s dropped: non-selectable socket",
 815                   addr.ToStringAddrPort());
 816          return;
 817      }
 818  
 819      // According to the internet TCP_NODELAY is not carried into accepted sockets
 820      // on all platforms.  Set it again here just to be sure.
 821      if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &SOCKET_OPTION_TRUE, sizeof(SOCKET_OPTION_TRUE)) == SOCKET_ERROR) {
 822          LogDebug(BCLog::HTTP, "connection from %s: unable to set TCP_NODELAY, continuing anyway",
 823                   addr.ToStringAddrPort());
 824      }
 825  
 826      const Id id{GetNewId()};
 827  
 828      m_connected.push_back(std::make_shared<HTTPRemoteClient>(id, addr, std::move(sock)));
 829      // Report back to the main thread
 830      m_connected_size.fetch_add(1, std::memory_order_relaxed);
 831  
 832      LogDebug(BCLog::HTTP,
 833               "HTTP Connection accepted from %s (id=%llu)",
 834               addr.ToStringAddrPort(), id);
 835  }
 836  
 837  void HTTPServer::SocketHandlerConnected(const IOReadiness& io_readiness) const
 838  {
 839      for (const auto& [sock, events] : io_readiness.events_per_sock) {
 840          if (m_interrupt_net) {
 841              return;
 842          }
 843  
 844          auto it{io_readiness.httpclients_per_sock.find(sock)};
 845          if (it == io_readiness.httpclients_per_sock.end()) {
 846              continue;
 847          }
 848          const std::shared_ptr<HTTPRemoteClient>& client{it->second};
 849  
 850          bool send_ready = events.occurred & Sock::SendEvent;
 851          bool recv_ready = events.occurred & Sock::RecvEvent;
 852          bool err_ready = events.occurred & Sock::ErrorEvent;
 853  
 854          if (send_ready) {
 855              // Try to send as much data as is ready for this client.
 856              // If there's an error we can skip the receive phase for this client
 857              // because we need to disconnect.
 858              if (!client->MaybeSendBytesFromBuffer()) {
 859                  recv_ready = false;
 860              }
 861          }
 862  
 863          if (recv_ready || err_ready) {
 864              std::byte buf[0x10000]; // typical socket buffer is 8K-64K
 865  
 866              const ssize_t nrecv{WITH_LOCK(
 867                  client->m_sock_mutex,
 868                  return client->m_sock->Recv(buf, sizeof(buf), MSG_DONTWAIT);)};
 869  
 870              if (nrecv < 0) {
 871                  const int err = WSAGetLastError();
 872                  if (IOErrorIsPermanent(err)) {
 873                      LogDebug(
 874                          BCLog::HTTP,
 875                          "Permanent read error from %s (id=%llu): %s",
 876                          client->m_origin,
 877                          client->m_id,
 878                          NetworkErrorString(err));
 879                      client->m_disconnect = true;
 880                  }
 881              } else if (nrecv == 0) {
 882                  LogDebug(
 883                      BCLog::HTTP,
 884                      "Received EOF from %s (id=%llu)",
 885                      client->m_origin,
 886                      client->m_id);
 887                  client->m_disconnect = true;
 888              } else {
 889                  // Reset idle timeout
 890                  client->m_idle_since = Now<SteadySeconds>();
 891  
 892                  // Prevent disconnect until all requests are completely handled.
 893                  client->m_connection_busy = true;
 894  
 895                  // Copy data from socket buffer to client receive buffer
 896                  client->m_recv_buffer.insert(
 897                      client->m_recv_buffer.end(),
 898                      buf,
 899                      buf + nrecv);
 900              }
 901          }
 902          // Process as much received data as we can.
 903          // This executes for every client whether or not reading or writing
 904          // took place because it also (might) parse a request we have already
 905          // received and pass it to a worker thread.
 906          MaybeDispatchRequestsFromClient(client);
 907      }
 908  }
 909  
 910  void HTTPServer::SocketHandlerListening(const Sock::EventsPerSock& events_per_sock)
 911  {
 912      if (m_stop_accepting) return;
 913      for (const auto& sock : m_listen) {
 914          if (m_interrupt_net) {
 915              return;
 916          }
 917          const auto it = events_per_sock.find(sock);
 918          if (it != events_per_sock.end() && it->second.occurred & Sock::RecvEvent) {
 919              CService addr_accepted;
 920  
 921              auto sock_accepted{AcceptConnection(*sock, addr_accepted)};
 922  
 923              if (sock_accepted) {
 924                  NewSockAccepted(std::move(sock_accepted), addr_accepted);
 925              }
 926          }
 927      }
 928  }
 929  
 930  HTTPServer::IOReadiness HTTPServer::GenerateWaitSockets() const
 931  {
 932      IOReadiness io_readiness;
 933  
 934      for (const auto& sock : m_listen) {
 935          io_readiness.events_per_sock.emplace(sock, Sock::Events{Sock::RecvEvent});
 936      }
 937  
 938      for (const auto& http_client : m_connected) {
 939          // Safely copy the shared pointer to the socket
 940          std::shared_ptr<Sock> sock{WITH_LOCK(http_client->m_sock_mutex, return http_client->m_sock;)};
 941  
 942          // Check if client is ready to send data. Don't try to receive again
 943          // until the send buffer is cleared (all data sent to client).
 944          // Keep this as a separate critical section from the m_sock_mutex one above:
 945          // never hold m_sock_mutex and m_send_mutex at the same time here.
 946          // MaybeSendBytesFromBuffer() locks m_send_mutex then m_sock_mutex, so nesting
 947          // them in the opposite order here would risk a lock-order inversion deadlock.
 948          const bool send_ready{WITH_LOCK(http_client->m_send_mutex, return http_client->m_send_ready;)};
 949          Sock::Event event = (send_ready ? Sock::SendEvent : Sock::RecvEvent);
 950          io_readiness.events_per_sock.emplace(sock, Sock::Events{event});
 951          io_readiness.httpclients_per_sock.emplace(sock, http_client);
 952      }
 953  
 954      return io_readiness;
 955  }
 956  
 957  /// \anchor http
 958  void HTTPServer::ThreadSocketHandler()
 959  {
 960      while (!m_interrupt_net) {
 961          // Check for the readiness of the already connected sockets and the
 962          // listening sockets in one call ("readiness" as in poll(2) or
 963          // select(2)). If none are ready, wait for a short while and return
 964          // empty sets.
 965          auto io_readiness{GenerateWaitSockets()};
 966          if (io_readiness.events_per_sock.empty() ||
 967              // WaitMany() may as well be a static method, the context of the first Sock in the vector is not relevant.
 968              !io_readiness.events_per_sock.begin()->first->WaitMany(SELECT_TIMEOUT,
 969                                                                     io_readiness.events_per_sock)) {
 970              m_interrupt_net.sleep_for(SELECT_TIMEOUT);
 971          }
 972  
 973          // Service (send/receive) each of the already connected sockets.
 974          SocketHandlerConnected(io_readiness);
 975  
 976          // Accept new connections from listening sockets.
 977          SocketHandlerListening(io_readiness.events_per_sock);
 978  
 979          // Disconnect any clients that have been flagged.
 980          DisconnectClients();
 981      }
 982  }
 983  
 984  void HTTPServer::MaybeDispatchRequestsFromClient(const std::shared_ptr<HTTPRemoteClient>& client) const
 985  {
 986      // Try reading (potentially multiple) HTTP requests from the buffer
 987      while (!client->m_recv_buffer.empty()) {
 988          // Create a new request object and try to fill it with data from the receive buffer
 989          auto req = std::make_unique<HTTPRequest>(client);
 990          try {
 991              // Stop reading if we need more data from the client to parse a complete request
 992              if (!client->ReadRequest(*req)) break;
 993          } catch (const ContentTooLargeError& e) {
 994              LogDebug(
 995                  BCLog::HTTP,
 996                  "HTTP request body too large from client %s (id=%llu): %s",
 997                  client->m_origin,
 998                  client->m_id,
 999                  e.what());
1000  
1001              req->WriteReply(HTTP_CONTENT_TOO_LARGE);
1002              client->m_disconnect = true;
1003              return;
1004          } catch (const std::runtime_error& e) {
1005              LogDebug(
1006                  BCLog::HTTP,
1007                  "Error reading HTTP request from client %s (id=%llu): %s",
1008                  client->m_origin,
1009                  client->m_id,
1010                  e.what());
1011  
1012              // We failed to read a complete request from the buffer
1013              req->WriteReply(HTTP_BAD_REQUEST);
1014              client->m_disconnect = true;
1015              return;
1016          }
1017  
1018          // We read a complete request from the buffer into the queue
1019          LogDebug(
1020              BCLog::HTTP,
1021              "Received a %s request for %s from %s (id=%llu)",
1022              RequestMethodString(req->m_method),
1023              req->m_target,
1024              client->m_origin,
1025              client->m_id);
1026  
1027          // add request to client queue
1028          client->m_req_queue.push_back(std::move(req));
1029      }
1030  
1031      // If we are already handling a request from
1032      // this client, do nothing. We'll check again on the next I/O
1033      // loop iteration.
1034      if (client->m_req_busy) return;
1035  
1036      // Otherwise, if there is a pending request in the queue, handle it.
1037      if (!client->m_req_queue.empty()) {
1038          LOCK(m_request_dispatcher_mutex);
1039          client->m_req_busy = true;
1040          m_request_dispatcher(std::move(client->m_req_queue.front()));
1041          client->m_req_queue.pop_front();
1042      }
1043  }
1044  
1045  void HTTPServer::DisconnectClients()
1046  {
1047      const auto now{Now<SteadySeconds>()};
1048      size_t erased = std::erase_if(m_connected,
1049                                    [&](auto& client) {
1050                                          // First check for idle timeout. We reset the timer when we send and receive data,
1051                                          // but if the server is busy handling a request we should ignore the timeout until
1052                                          // the reply is sent. If we did erase the shared_ptr<HTTPRemoteClient> reference in m_connected
1053                                          // while the server is busy with a request, there would still be a reference in a worker
1054                                          // thread keeping the socket open even after "disconnecting".
1055                                          const bool is_idle{m_rpcservertimeout.count() > 0 &&
1056                                                             now - client->m_idle_since.load() > m_rpcservertimeout &&
1057                                                             !client->m_req_busy};
1058  
1059                                          // Disconnect this client due to error, end of communication, or idle timeout.
1060                                          // May drop unsent data if we are closing due to error.
1061                                          if (client->m_disconnect || is_idle) {
1062                                              if (is_idle) {
1063                                                  LogDebug(BCLog::HTTP,
1064                                                           "HTTP client idle timeout %s (id=%llu)",
1065                                                           client->m_origin,
1066                                                           client->m_id);
1067                                              }
1068                                          } else {
1069                                              // Disconnect this client because the server is shutting
1070                                              // down and we need to disconnect all clients...
1071                                              if (m_disconnect_all_clients) {
1072                                                  // ...unless we still have data for this client.
1073                                                  if (client->m_connection_busy) {
1074                                                      // There is still data for this healthy-connected client.
1075                                                      // Continue the I/O loop until all data is sent or an error is encountered.
1076                                                      return false;
1077                                                  } else {
1078                                                      // This is a healthy persistent connection (e.g. keep-alive)
1079                                                      // but it's time to say goodbye.
1080                                                      ;
1081                                                  }
1082                                              } else {
1083                                                  // No reason to disconnect.
1084                                                  return false;
1085                                              }
1086                                          }
1087                                          // No reason NOT to disconnect, log and remove.
1088                                          LogDebug(BCLog::HTTP,
1089                                                   "Disconnecting HTTP client %s (id=%llu)",
1090                                                   client->m_origin,
1091                                                   client->m_id);
1092                                          return true;
1093                                      });
1094      if (erased > 0) {
1095          // Report back to the main thread
1096          m_connected_size.fetch_sub(erased, std::memory_order_relaxed);
1097      }
1098  }
1099  
1100  void HTTPServer::ClearConnectedClients()
1101  {
1102      Assume(!m_thread_socket_handler.joinable()); // must be called after JoinSocketsThreads()
1103      if (m_connected.empty()) return;
1104      LogWarning("Force-disconnecting %d HTTP client(s) that did not disconnect gracefully", m_connected.size());
1105      m_connected_size.fetch_sub(m_connected.size(), std::memory_order_relaxed);
1106      m_connected.clear();
1107  }
1108  
1109  bool HTTPRemoteClient::ReadRequest(HTTPRequest& req)
1110  {
1111      LineReader reader(m_recv_buffer, MAX_HEADERS_SIZE);
1112  
1113      if (!req.LoadControlData(reader)) return false;
1114      if (!req.LoadHeaders(reader)) return false;
1115      if (!req.LoadBody(reader)) return false;
1116  
1117      // Remove the bytes read out of the buffer.
1118      // If one of the above calls throws an error, the caller must
1119      // catch it and disconnect the client.
1120      m_recv_buffer.erase(
1121          m_recv_buffer.begin(),
1122          m_recv_buffer.begin() + reader.Consumed());
1123  
1124      return true;
1125  }
1126  
1127  bool HTTPRemoteClient::MaybeSendBytesFromBuffer()
1128  {
1129      // Send as much data from this client's buffer as we can
1130      LOCK(m_send_mutex);
1131      if (!m_send_buffer.empty()) {
1132          // Socket flags (See kernel docs for send(2) and tcp(7) for more details).
1133          // MSG_NOSIGNAL: If the remote end of the connection is closed,
1134          //               fail with EPIPE (an error) as opposed to triggering
1135          //               SIGPIPE which terminates the process.
1136          // MSG_DONTWAIT: Makes the send operation non-blocking regardless of socket blocking mode.
1137          // MSG_MORE:     We do not set this flag here because http responses are usually
1138          //               small and we want the kernel to send them right away. Setting MSG_MORE
1139          //               would "cork" the socket to prevent sending out partial frames.
1140          int flags{MSG_NOSIGNAL | MSG_DONTWAIT};
1141  
1142          // Try to send bytes through socket
1143          ssize_t bytes_sent;
1144          {
1145              LOCK(m_sock_mutex);
1146              bytes_sent = m_sock->Send(m_send_buffer.data(),
1147                                        m_send_buffer.size(),
1148                                        flags);
1149          }
1150  
1151          if (bytes_sent < 0) {
1152              // Something went wrong
1153              const int err{WSAGetLastError()};
1154              if (!IOErrorIsPermanent(err)) {
1155                  // The error can be safely ignored, try the send again on the next I/O loop.
1156                  m_send_ready = true;
1157                  m_connection_busy = true;
1158                  return true;
1159              } else {
1160                  // Unrecoverable error, log and disconnect client.
1161                  LogDebug(
1162                      BCLog::HTTP,
1163                      "Error sending HTTP response data to client %s (id=%llu): %s",
1164                      m_origin,
1165                      m_id,
1166                      NetworkErrorString(err));
1167                  m_send_ready = false;
1168                  m_disconnect = true;
1169  
1170                  // Do not attempt to read from this client.
1171                  return false;
1172              }
1173          }
1174  
1175          // Successful send, remove sent bytes from our local buffer.
1176          Assume(static_cast<size_t>(bytes_sent) <= m_send_buffer.size());
1177          m_send_buffer.erase(m_send_buffer.begin(),
1178                              m_send_buffer.begin() + bytes_sent);
1179  
1180          LogDebug(
1181              BCLog::HTTP,
1182              "Sent %d bytes to client %s (id=%llu)",
1183              bytes_sent,
1184              m_origin,
1185              m_id);
1186  
1187          // This check is inside the if(!empty) block meaning "there was data but now its gone".
1188          // We wouldn't want to change the flags if MaybeSendBytesFromBuffer() was called
1189          // on an already-empty m_send_buffer because the connection might have just been opened.
1190          if (m_send_buffer.empty()) {
1191              m_send_ready = false;
1192              m_connection_busy = false;
1193  
1194              // Our work is done here
1195              if (!m_keep_alive) {
1196                  m_disconnect = true;
1197                  // Do not attempt to read from this client.
1198                  return false;
1199              }
1200          } else {
1201              // The send buffer isn't flushed yet, try to push more on the next loop.
1202              m_send_ready = true;
1203              m_connection_busy = true;
1204          }
1205  
1206          // Finally, reset idle timeout
1207          m_idle_since = Now<SteadySeconds>();
1208      }
1209  
1210      return true;
1211  }
1212  
1213  bool InitHTTPServer()
1214  {
1215      if (!InitHTTPAllowList()) {
1216          return false;
1217      }
1218  
1219      // Create HTTPServer
1220      g_http_server = std::make_unique<HTTPServer>(MaybeDispatchRequestToWorker);
1221  
1222      g_http_server->SetServerTimeout(std::chrono::seconds(gArgs.GetIntArg("-rpcservertimeout", DEFAULT_HTTP_SERVER_TIMEOUT)));
1223  
1224      // Bind HTTP server to specified addresses
1225      std::vector<std::pair<std::string, uint16_t>> endpoints{GetBindAddresses()};
1226      bool bind_success{false};
1227      for (const auto& [address_string, port] : endpoints) {
1228          LogInfo("Binding RPC on address %s port %i", address_string, port);
1229          const std::optional<CService> addr{Lookup(address_string, port, false)};
1230          if (addr) {
1231              if (addr->IsBindAny()) {
1232                  LogWarning("The RPC server is not safe to expose to untrusted networks such as the public internet");
1233              }
1234              auto result{g_http_server->BindAndStartListening(addr.value())};
1235              if (!result) {
1236                  LogWarning("Binding RPC on address %s failed: %s", addr->ToStringAddrPort(), result.error());
1237              } else {
1238                  bind_success = true;
1239              }
1240          } else {
1241              LogWarning("Could not bind RPC on address %s port %i: Address lookup failed.", address_string, port);
1242          }
1243      }
1244  
1245      if (!bind_success) {
1246          LogError("Unable to bind any endpoint for RPC server");
1247          return false;
1248      }
1249  
1250      LogDebug(BCLog::HTTP, "Initialized HTTP server");
1251  
1252      g_max_queue_depth = std::max(gArgs.GetArg<int>("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1);
1253      LogDebug(BCLog::HTTP, "set work queue of depth %d\n", g_max_queue_depth);
1254  
1255      return true;
1256  }
1257  
1258  void StartHTTPServer()
1259  {
1260      auto rpcThreads{std::max(gArgs.GetArg<int>("-rpcthreads", DEFAULT_HTTP_THREADS), 1)};
1261      LogInfo("Starting HTTP server with %d worker threads", rpcThreads);
1262      g_threadpool_http.Start(rpcThreads);
1263      g_http_server->StartSocketsThreads();
1264  }
1265  
1266  void InterruptHTTPServer()
1267  {
1268      LogDebug(BCLog::HTTP, "Interrupting HTTP server");
1269      if (g_http_server) {
1270          // Reject all new requests
1271          g_http_server->SetRequestHandler(RejectRequest);
1272      }
1273  
1274      // Interrupt pool after disabling requests
1275      g_threadpool_http.Interrupt();
1276  }
1277  
1278  void StopHTTPServer()
1279  {
1280      LogDebug(BCLog::HTTP, "Stopping HTTP server");
1281  
1282      LogDebug(BCLog::HTTP, "Waiting for HTTP worker threads to exit\n");
1283      g_threadpool_http.Stop();
1284  
1285      if (g_http_server) {
1286          // Must precede DisconnectAllClients(): a connection accepted after
1287          // GetConnectionsCount() returns 0 would survive into the destructor.
1288          g_http_server->StopAccepting();
1289          // Disconnect clients as their remaining responses are flushed
1290          g_http_server->DisconnectAllClients();
1291          // Wait 30 seconds for all disconnections
1292          LogDebug(BCLog::HTTP, "Waiting for HTTP clients to disconnect gracefully");
1293          const auto deadline{NodeClock::now() + 30s};
1294          while (g_http_server->GetConnectionsCount() != 0) {
1295              if (NodeClock::now() > deadline) {
1296                  LogWarning("Timeout waiting for HTTP clients to disconnect gracefully, continuing shutdown");
1297                  break;
1298              }
1299              std::this_thread::sleep_for(50ms);
1300          }
1301          // Break HTTPServer I/O loop: stop accepting connections, sending and receiving data
1302          g_http_server->InterruptNet();
1303          // Wait for HTTPServer I/O thread to exit
1304          g_http_server->JoinSocketsThreads();
1305          // Force-remove any clients that survived the graceful wait
1306          g_http_server->ClearConnectedClients();
1307          // Close all listening sockets
1308          g_http_server->StopListening();
1309      }
1310      LogDebug(BCLog::HTTP, "Stopped HTTP server");
1311  }
1312  } // namespace http_bitcoin
1313