// Copyright 2025 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This binary contains minimal code to create an HTTP/2 server with TLS and
// TCP. It will be refactored to allow layering, with the goal of being able to
// use MASQUE over HTTP/2, and CONNECT in our MASQUE code.

#include <fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

#include "absl/cleanup/cleanup.h"
#include "absl/container/flat_hash_map.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "openssl/base.h"
#include "openssl/bio.h"
#include "openssl/hpke.h"
#include "openssl/ssl.h"
#include "openssl/x509.h"
#include "quiche/quic/core/io/quic_default_event_loop.h"
#include "quiche/quic/core/io/quic_event_loop.h"
#include "quiche/quic/core/io/socket.h"
#include "quiche/quic/core/quic_default_clock.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/masque/masque_connection_pool.h"
#include "quiche/quic/masque/masque_h2_connection.h"
#include "quiche/quic/tools/quic_url.h"
#include "quiche/binary_http/binary_http_message.h"
#include "quiche/common/http/http_header_block.h"
#include "quiche/common/platform/api/quiche_command_line_flags.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/platform/api/quiche_system_event_loop.h"
#include "quiche/common/quiche_ip_address.h"
#include "quiche/common/quiche_ip_address_family.h"
#include "quiche/common/quiche_socket_address.h"
#include "quiche/common/quiche_status_utils.h"
#include "quiche/common/quiche_text_utils.h"
#include "quiche/oblivious_http/common/oblivious_http_header_key_config.h"
#include "quiche/oblivious_http/oblivious_http_gateway.h"

DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, port, 9661,
                                "The port the MASQUE server will listen on.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, server_certificate_file, "",
                                "Path to the certificate chain.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, server_key_file, "",
                                "Path to the pkcs8 private key.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, client_root_ca_file, "",
                                "Path to the PEM file containing root CAs.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    std::string, ohttp_key, "",
    "Hex-encoded bytes of the OHTTP HPKE private key.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    std::string, gateway_path, "",
    "Enables and configures an OHTTP gateway. Sets the path at which the "
    "gateway will respond to both key requests and encapsulated requests. "
    "Example: \"/.well-known/ohttp-gateway\".");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    std::string, relay, "",
    "Enables and configures an OHTTP relay. The format is a list of (path, "
    "URL) pairs where each local path is relayed to the corresponding URL, "
    "formatted as \"path1>url1|path2>url2\". For example: "
    "\"/foo>https://foo.example:8443/|/bar>https://example.com/bar\".");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    std::string, key_proxy, "",
    "Enables and configures proxying of OHTTP key requests. The format is a "
    "list of (path, URL) pairs where each local path is proxied to the "
    "corresponding "
    "URL, formatted as \"path1>url1|path2>url2\". For example: "
    "\"/foo>https://foo.example:8443/|/bar>https://example.com/bar\".");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    bool, disable_certificate_verification, false,
    "If true, don't verify the server certificate.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(int, address_family, 0,
                                "IP address family to use. Must be 0, 4 or 6. "
                                "Defaults to 0 which means any.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, client_cert_file, "",
                                "Path to the client certificate chain.");

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    std::string, client_cert_key_file, "",
    "Path to the pkcs8 client certificate private key.");

using quiche::BinaryHttpRequest;
using quiche::BinaryHttpResponse;
using quiche::ObliviousHttpGateway;
using quiche::ObliviousHttpHeaderKeyConfig;
using quiche::ObliviousHttpKeyConfigs;
using quiche::ObliviousHttpRequest;
using quiche::ObliviousHttpResponse;

namespace quic {

namespace {

absl::string_view RemoveParameters(absl::string_view value) {
  std::vector<absl::string_view> split =
      absl::StrSplit(value, absl::MaxSplits(';', 1));
  absl::string_view without_params = split[0];
  quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&without_params);
  return without_params;
}

bool ListHeaderContainsValue(absl::string_view header,
                             absl::string_view value) {
  std::vector<absl::string_view> header_split = absl::StrSplit(header, ',');
  for (absl::string_view header_value : header_split) {
    if (RemoveParameters(header_value) == value) {
      return true;
    }
  }
  return false;
}

class MasqueOhttpGateway {
 public:
  class Visitor {
   public:
    virtual ~Visitor() = default;
    virtual void SavePendingGatewayRequest(
        MasqueH2Connection* connection, int32_t stream_id,
        MasqueConnectionPool::RequestId request_id,
        ObliviousHttpRequest::Context&& ohttp_context) = 0;
  };

  static std::unique_ptr<MasqueOhttpGateway> Create(
      const std::string& ohttp_key) {
    auto ohttp_gateway = absl::WrapUnique(new MasqueOhttpGateway());
    if (!ohttp_gateway->Setup(ohttp_key).ok()) {
      return nullptr;
    }
    return ohttp_gateway;
  }

  absl::Status HandleRequest(MasqueConnectionPool* pool,
                             MasqueH2Connection* connection, int32_t stream_id,
                             const std::string& encapsulated_request) {
    if (!ohttp_gateway_.has_value()) {
      QUICHE_LOG(ERROR) << "Not ready to handle OHTTP request";
      return absl::InternalError("Not ready to handle OHTTP request");
    }
    absl::StatusOr<ObliviousHttpRequest> decrypted_request =
        ohttp_gateway_->DecryptObliviousHttpRequest(encapsulated_request);
    QUICHE_RETURN_IF_ERROR(decrypted_request.status());
    absl::StatusOr<BinaryHttpRequest> binary_request =
        BinaryHttpRequest::Create(decrypted_request->GetPlaintextData());
    QUICHE_RETURN_IF_ERROR(binary_request.status());
    const BinaryHttpRequest::ControlData& control_data =
        binary_request->control_data();

    MasqueConnectionPool::Message request;
    request.headers[":method"] = control_data.method;
    request.headers[":scheme"] = control_data.scheme;
    request.headers[":authority"] = control_data.authority;
    request.headers[":path"] = control_data.path;
    request.body = binary_request->body();
    absl::StatusOr<MasqueConnectionPool::RequestId> request_id =
        pool->SendRequest(request);
    QUICHE_RETURN_IF_ERROR(request_id.status());
    QUICHE_LOG(INFO) << "Sent decapsulated request";
    visitor_->SavePendingGatewayRequest(
        connection, stream_id, *request_id,
        std::move(*decrypted_request).ReleaseContext());
    return absl::OkStatus();
  }

  absl::StatusOr<MasqueConnectionPool::Message> HandleResponse(
      MasqueConnectionPool::Message&& response,
      ObliviousHttpRequest::Context&& ohttp_context) {
    if (!ohttp_gateway_.has_value()) {
      return absl::InternalError("Not ready to handle OHTTP response");
    }
    auto status_pair = response.headers.find(":status");
    if (status_pair == response.headers.end()) {
      return absl::InternalError("Response is missing status code");
    }
    int status_code;
    if (!absl::SimpleAtoi(status_pair->second, &status_code)) {
      return absl::InternalError(
          absl::StrCat("Failed to parse status code: ", status_pair->second));
    }
    BinaryHttpResponse binary_response(status_code);
    for (const auto& [key, value] : response.headers) {
      if (key != ":status") {
        binary_response.AddHeaderField({std::string(key), std::string(value)});
      }
    }
    binary_response.swap_body(response.body);
    absl::StatusOr<std::string> encoded_response = binary_response.Serialize();
    QUICHE_RETURN_IF_ERROR(encoded_response.status());

    absl::StatusOr<ObliviousHttpResponse> ohttp_response =
        ohttp_gateway_->CreateObliviousHttpResponse(*encoded_response,
                                                    ohttp_context);
    QUICHE_RETURN_IF_ERROR(ohttp_response.status());
    MasqueConnectionPool::Message outer_response;
    outer_response.headers[":status"] = "200";
    outer_response.headers["content-type"] = "message/ohttp-res";
    outer_response.body = ohttp_response->EncapsulateAndSerialize();
    return outer_response;
  }

  std::string concatenated_keys() const { return concatenated_keys_; }
  void set_visitor(Visitor* visitor) { visitor_ = visitor; }

 private:
  MasqueOhttpGateway() = default;

  absl::Status Setup(const std::string& ohttp_key) {
    hpke_key_.reset(EVP_HPKE_KEY_new());
    if (!ohttp_key.empty()) {
      if (!absl::HexStringToBytes(ohttp_key, &hpke_private_key_)) {
        return absl::InvalidArgumentError(
            "OHTTP key is not a valid hex string");
      }
      if (EVP_HPKE_KEY_init(
              hpke_key_.get(), kem_,
              reinterpret_cast<const uint8_t*>(hpke_private_key_.data()),
              hpke_private_key_.size()) != 1) {
        return absl::InternalError("Failed to ingest HPKE key");
      }
    } else {
      if (EVP_HPKE_KEY_generate(hpke_key_.get(), kem_) != 1) {
        return absl::InternalError("Failed to generate new HPKE key");
      }
      size_t private_key_len = EVP_HPKE_KEM_private_key_len(kem_);
      hpke_private_key_ = std::string(private_key_len, '0');
      if (EVP_HPKE_KEY_private_key(
              hpke_key_.get(),
              reinterpret_cast<uint8_t*>(hpke_private_key_.data()),
              &private_key_len, private_key_len) != 1 ||
          private_key_len != hpke_private_key_.size()) {
        return absl::InternalError("Failed to extract new HPKE private key");
      }
      QUICHE_LOG(INFO) << "Generated new HPKE private key: "
                       << absl::BytesToHexString(hpke_private_key_);
    }
    size_t public_key_len = EVP_HPKE_KEM_public_key_len(kem_);
    hpke_public_key_ = std::string(public_key_len, '0');
    if (EVP_HPKE_KEY_public_key(
            hpke_key_.get(),
            reinterpret_cast<uint8_t*>(hpke_public_key_.data()),
            &public_key_len, public_key_len) != 1 ||
        public_key_len != hpke_public_key_.size()) {
      return absl::InternalError("Failed to extract new HPKE public key");
    }
    static constexpr uint8_t kOhttpKeyId = 0x01;
    static constexpr uint16_t kOhttpKemId = EVP_HPKE_DHKEM_X25519_HKDF_SHA256;
    static constexpr uint16_t kOhttpKdfId = EVP_HPKE_HKDF_SHA256;
    static constexpr uint16_t kOhttpAeadId = EVP_HPKE_AES_128_GCM;
    absl::StatusOr<ObliviousHttpHeaderKeyConfig> ohttp_header_key_config =
        ObliviousHttpHeaderKeyConfig::Create(kOhttpKeyId, kOhttpKemId,
                                             kOhttpKdfId, kOhttpAeadId);
    QUICHE_RETURN_IF_ERROR(ohttp_header_key_config.status());
    QUICHE_LOG(INFO) << "Using OHTTP header key config: "
                     << ohttp_header_key_config->DebugString();
    absl::StatusOr<ObliviousHttpKeyConfigs> ohttp_key_configs =
        ObliviousHttpKeyConfigs::Create(*ohttp_header_key_config,
                                        hpke_public_key_);
    QUICHE_RETURN_IF_ERROR(ohttp_key_configs.status());
    QUICHE_LOG(INFO) << "Using OHTTP key configs: " << std::endl
                     << ohttp_key_configs->DebugString();
    absl::StatusOr<std::string> concatenated_keys =
        ohttp_key_configs->GenerateConcatenatedKeys();
    QUICHE_RETURN_IF_ERROR(concatenated_keys.status());
    concatenated_keys_ = *concatenated_keys;
    absl::StatusOr<ObliviousHttpGateway> ohttp_gateway =
        ObliviousHttpGateway::Create(hpke_private_key_,
                                     *ohttp_header_key_config);
    QUICHE_RETURN_IF_ERROR(ohttp_gateway.status());
    ohttp_gateway_.emplace(std::move(*ohttp_gateway));
    return absl::OkStatus();
  }

  Visitor* visitor_ = nullptr;
  std::string hpke_private_key_;
  std::string hpke_public_key_;
  const EVP_HPKE_KEM* kem_ = EVP_hpke_x25519_hkdf_sha256();
  bssl::UniquePtr<EVP_HPKE_KEY> hpke_key_;
  std::string concatenated_keys_;
  std::optional<ObliviousHttpGateway> ohttp_gateway_;
};

static int SelectAlpnCallback(SSL* /*ssl*/, const uint8_t** out,
                              uint8_t* out_len, const uint8_t* in,
                              unsigned in_len, void* /*arg*/) {
  unsigned i = 0;
  while (i < in_len) {
    uint8_t alpn_length = in[i];
    if (i + alpn_length > in_len) {
      // Client sent a malformed ALPN extension.
      break;
    }
    if (alpn_length == 2 && in[i + 1] == 'h' && in[i + 2] == '2') {
      // Found "h2".
      *out = in + i + 1;
      *out_len = alpn_length;
      return SSL_TLSEXT_ERR_OK;
    }
    i += alpn_length + 1;
  }
  *out = nullptr;
  *out_len = 0;
  return SSL_TLSEXT_ERR_ALERT_FATAL;
}

class MasqueH2SocketConnection : public QuicSocketEventListener {
 public:
  explicit MasqueH2SocketConnection(SocketFd connected_socket,
                                    QuicEventLoop* event_loop, SSL_CTX* ctx,
                                    bool is_server,
                                    MasqueH2Connection::Visitor* visitor)
      : socket_(connected_socket),
        event_loop_(event_loop),
        connection_(CreateSsl(ctx), is_server, visitor) {
    if (!event_loop_->RegisterSocket(socket_, kSocketEventReadable, this)) {
      QUICHE_LOG(FATAL)
          << "Failed to register connection socket with the event loop";
    }
  }

  ~MasqueH2SocketConnection() {
    if (socket_ != kInvalidSocketFd) {
      if (!event_loop_->UnregisterSocket(socket_)) {
        QUICHE_LOG(ERROR) << "Failed to unregister socket";
      }
      close(socket_);
      socket_ = kInvalidSocketFd;
    }
  }

  bool Start() {
    connection_.OnTransportReadable();
    return !connection_.aborted();
  }

  // From QuicSocketEventListener.
  void OnSocketEvent(QuicEventLoop* event_loop, SocketFd fd,
                     QuicSocketEventMask events) {
    auto cleanup = absl::MakeCleanup([this, event_loop, fd]() {
      if (!event_loop->SupportsEdgeTriggered() && !connection_.aborted()) {
        if (!event_loop->RearmSocket(
                fd, kSocketEventReadable | kSocketEventWritable)) {
          QUICHE_LOG(FATAL) << "Failed to re-arm socket " << fd;
        }
      }
    });
    if (fd != socket_ || ((events & kSocketEventReadable) == 0)) {
      return;
    }
    connection_.OnTransportReadable();
  }

  MasqueH2Connection* connection() { return &connection_; }

 private:
  SSL* CreateSsl(SSL_CTX* ctx) {
    ssl_.reset(SSL_new(ctx));
    SSL_set_accept_state(ssl_.get());
    BIO* bio = BIO_new_socket(socket_, BIO_CLOSE);
    SSL_set_bio(ssl_.get(), bio, bio);
    // `SSL_set_bio` causes `ssl_` to take ownership of `bio`.
    return ssl_.get();
  }

  SocketFd socket_;
  bssl::UniquePtr<SSL> ssl_;
  QuicEventLoop* event_loop_;  // Unowned.
  MasqueH2Connection connection_;
};

class MasqueTcpServer : public QuicSocketEventListener,
                        public MasqueH2Connection::Visitor,
                        public MasqueConnectionPool::Visitor,
                        public MasqueOhttpGateway::Visitor {
 public:
  using RequestId = MasqueConnectionPool::RequestId;
  using Message = MasqueConnectionPool::Message;

  explicit MasqueTcpServer(SSL_CTX* client_ssl_ctx,
                           bool disable_certificate_verification,
                           int address_family_for_lookup)
      : event_loop_(GetDefaultEventLoop()->Create(QuicDefaultClock::Get())),
        connection_pool_(event_loop_.get(), client_ssl_ctx,
                         disable_certificate_verification,
                         address_family_for_lookup, this) {}

  MasqueTcpServer(const MasqueTcpServer&) = delete;
  MasqueTcpServer(MasqueTcpServer&&) = delete;
  MasqueTcpServer& operator=(const MasqueTcpServer&) = delete;
  MasqueTcpServer& operator=(MasqueTcpServer&&) = delete;

  ~MasqueTcpServer() {
    if (server_socket_ != kInvalidSocketFd) {
      if (!event_loop_->UnregisterSocket(server_socket_)) {
        QUICHE_LOG(ERROR) << "Failed to unregister socket";
      }
      close(server_socket_);
      server_socket_ = kInvalidSocketFd;
    }
  }

  bool SetupSslCtx(const std::string& server_certificate_file,
                   const std::string& server_key_file,
                   const std::string& client_root_ca_file) {
    ctx_.reset(SSL_CTX_new(TLS_method()));

    if (!SSL_CTX_use_PrivateKey_file(ctx_.get(), server_key_file.c_str(),
                                     SSL_FILETYPE_PEM)) {
      QUICHE_LOG(ERROR) << "Failed to load private key: " << server_key_file;
      return false;
    }
    if (!SSL_CTX_use_certificate_chain_file(ctx_.get(),
                                            server_certificate_file.c_str())) {
      QUICHE_LOG(ERROR) << "Failed to load cert chain: "
                        << server_certificate_file;
      return false;
    }
    if (!client_root_ca_file.empty()) {
      X509_STORE* store = SSL_CTX_get_cert_store(ctx_.get());
      if (store == nullptr) {
        QUICHE_LOG(ERROR) << "Failed to get certificate store";
        return false;
      }
      if (X509_STORE_load_locations(store, client_root_ca_file.c_str(),
                                    /*dir=*/nullptr) != 1) {
        QUICHE_LOG(ERROR) << "Failed to load client root CA file: "
                          << client_root_ca_file;
        return false;
      }
      SSL_CTX_set_verify(ctx_.get(),
                         SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                         /*callback=*/nullptr);
    }

    SSL_CTX_set_alpn_select_cb(ctx_.get(), &SelectAlpnCallback, this);

    SSL_CTX_set_min_proto_version(ctx_.get(), TLS1_2_VERSION);
    SSL_CTX_set_max_proto_version(ctx_.get(), TLS1_3_VERSION);

    return true;
  }

  bool SetupSocket(uint16_t server_port) {
    if (server_socket_ != kInvalidSocketFd) {
      QUICHE_LOG(ERROR) << "Socket already set up";
      return false;
    }

    absl::StatusOr<SocketFd> create_result = socket_api::CreateSocket(
        quiche::IpAddressFamily::IP_V6, socket_api::SocketProtocol::kTcp,
        /*blocking=*/false);
    if (!create_result.ok() || create_result.value() == kInvalidSocketFd) {
      QUICHE_LOG(ERROR) << "Failed to create socket: "
                        << create_result.status();
      return false;
    }
    server_socket_ = create_result.value();

    const int enable = 1;
    if (setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR,
                   (const char*)&enable, sizeof(enable)) < 0) {
      QUICHE_LOG(ERROR) << "Failed to set SO_REUSEADDR on socket";
      return false;
    }

    absl::Status bind_result = socket_api::Bind(
        server_socket_, quiche::QuicheSocketAddress(
                            quiche::QuicheIpAddress::Any6(), server_port));
    if (!bind_result.ok()) {
      QUICHE_LOG(ERROR) << "Failed to bind socket: " << bind_result;
      return false;
    }

    absl::Status listen_result = socket_api::Listen(server_socket_, SOMAXCONN);
    if (!listen_result.ok()) {
      QUICHE_LOG(ERROR) << "Failed to listen on socket: " << listen_result;
      return false;
    }

    if (!event_loop_->RegisterSocket(server_socket_, kSocketEventReadable,
                                     this)) {
      QUICHE_LOG(ERROR) << "Failed to register socket with the event loop";
      return false;
    }

    QUICHE_LOG(INFO) << "Started listening on port " << server_port;
    return true;
  }

  void Run() {
    while (true) {
      event_loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(50));
    }
  }

  void OnSocketEvent(QuicEventLoop* event_loop, SocketFd fd,
                     QuicSocketEventMask events) override {
    if (fd != server_socket_ || ((events & kSocketEventReadable) == 0)) {
      return;
    }
    AcceptConnection();
    if (!event_loop->SupportsEdgeTriggered()) {
      if (!event_loop->RearmSocket(server_socket_, kSocketEventReadable)) {
        QUICHE_LOG(FATAL) << "Failed to re-arm socket " << server_socket_;
      }
    }
  }

  // From MasqueH2Connection::Visitor.
  void OnConnectionReady(MasqueH2Connection* /*connection*/) override {}
  void OnConnectionFinished(MasqueH2Connection* connection) override {
    connections_.erase(
        std::remove_if(connections_.begin(), connections_.end(),
                       [connection](const auto& socket_connection) {
                         return socket_connection->connection() == connection;
                       }),
        connections_.end());
  }

  absl::Status HandleOhttpGatewayRequest(
      MasqueH2Connection* connection, int32_t stream_id,
      const std::string& encapsulated_request) {
    return masque_ohttp_gateway_->HandleRequest(
        &connection_pool_, connection, stream_id, encapsulated_request);
  }

  absl::Status HandleOhttpRelayRequest(MasqueH2Connection* connection,
                                       int32_t stream_id,
                                       const std::string& encapsulated_request,
                                       const QuicUrl& relay_gateway_url) {
    Message request;
    request.headers[":method"] = "POST";
    request.headers[":scheme"] = relay_gateway_url.scheme();
    request.headers[":authority"] = relay_gateway_url.HostPort();
    request.headers[":path"] = relay_gateway_url.PathParamsQuery();
    request.headers["content-type"] = "message/ohttp-req";
    request.body = encapsulated_request;
    absl::StatusOr<RequestId> request_id =
        connection_pool_.SendRequest(request);
    QUICHE_RETURN_IF_ERROR(request_id.status());
    QUICHE_LOG(INFO) << "Sent relayed request";
    PendingRequest pending_request;
    pending_request.connection = connection;
    pending_request.stream_id = stream_id;
    pending_requests_.insert({*request_id, std::move(pending_request)});
    return absl::OkStatus();
  }

  absl::Status HandleOhttpKeyProxyRequest(MasqueH2Connection* connection,
                                          int32_t stream_id,
                                          const QuicUrl& key_proxy_url) {
    Message request;
    request.headers[":method"] = "GET";
    request.headers[":scheme"] = key_proxy_url.scheme();
    request.headers[":authority"] = key_proxy_url.HostPort();
    request.headers[":path"] = key_proxy_url.PathParamsQuery();
    request.headers["accept"] = "application/ohttp-keys";
    absl::StatusOr<RequestId> request_id =
        connection_pool_.SendRequest(request);
    QUICHE_RETURN_IF_ERROR(request_id.status());
    QUICHE_LOG(INFO) << "Sent relayed request";
    PendingRequest pending_request;
    pending_request.connection = connection;
    pending_request.stream_id = stream_id;
    pending_requests_.insert({*request_id, std::move(pending_request)});
    return absl::OkStatus();
  }

  void OnRequest(MasqueH2Connection* connection, int32_t stream_id,
                 const quiche::HttpHeaderBlock& headers,
                 const std::string& body) override {
    quiche::HttpHeaderBlock response_headers;
    std::string response_body;
    auto path_pair = headers.find(":path");
    auto method_pair = headers.find(":method");
    if (path_pair == headers.end() || method_pair == headers.end()) {
      // This should never happen because the h2 adapter should have rejected
      // the request, but handle it gracefully just in case.
      response_headers[":status"] = "400";
      response_body = "Request missing pseudo-headers";
      connection->SendResponse(stream_id, response_headers, response_body);
      return;
    }
    std::vector<absl::string_view> path_parts =
        absl::StrSplit(path_pair->second, absl::MaxSplits('?', 1));
    absl::string_view path = path_parts[0];
    absl::string_view content_type;
    auto content_type_pair = headers.find("content-type");
    if (content_type_pair != headers.end()) {
      content_type = RemoveParameters(content_type_pair->second);
    }
    auto accept_pair = headers.find("accept");
    if (!gateway_path_.empty() && path == gateway_path_ &&
        masque_ohttp_gateway_ && method_pair->second == "GET" &&
        (accept_pair == headers.end() ||
         ListHeaderContainsValue(accept_pair->second,
                                 "application/ohttp-keys"))) {
      response_headers[":status"] = "200";
      response_headers["content-type"] = "application/ohttp-keys";
      response_body = masque_ohttp_gateway_->concatenated_keys();
    } else if (auto key_proxy_pair = key_proxy_urls_.find(path);
               key_proxy_pair != key_proxy_urls_.end() &&
               method_pair->second == "GET" &&
               (accept_pair == headers.end() ||
                ListHeaderContainsValue(accept_pair->second,
                                        "application/ohttp-keys")) &&
               body.empty()) {
      absl::Status status = HandleOhttpKeyProxyRequest(connection, stream_id,
                                                       key_proxy_pair->second);
      if (status.ok()) {
        return;
      } else {
        QUICHE_LOG(ERROR) << "Failed to handle OHTTP key proxy request for "
                          << path << ": " << status;
        response_headers[":status"] = "500";
        response_body = status.message();
      }
    } else if (auto relay_pair = relay_gateway_urls_.find(path);
               relay_pair != relay_gateway_urls_.end() &&
               method_pair->second == "POST" &&
               content_type == "message/ohttp-req") {
      absl::Status status = HandleOhttpRelayRequest(connection, stream_id, body,
                                                    relay_pair->second);
      if (status.ok()) {
        return;
      } else {
        QUICHE_LOG(ERROR) << "Failed to handle OHTTP relay request for " << path
                          << ": " << status;
        response_headers[":status"] = "500";
        response_body = status.message();
      }
    } else if (!gateway_path_.empty() && path == gateway_path_ &&
               method_pair->second == "POST" &&
               content_type == "message/ohttp-req") {
      absl::Status status =
          HandleOhttpGatewayRequest(connection, stream_id, body);
      if (status.ok()) {
        return;
      } else {
        response_headers[":status"] = "500";
        QUICHE_LOG(ERROR) << "Failed to handle OHTTP gateway request: "
                          << status;
        response_body = status.message();
      }
    } else if (method_pair->second == "GET" && path == "/") {
      response_headers[":status"] = "200";
      response_body = "<h1>This is a response body</h1>";
    } else {
      response_headers[":status"] = "404";
      response_body = "Path not found";
    }
    connection->SendResponse(stream_id, response_headers, response_body);
  }

  void OnResponse(MasqueH2Connection* /*connection*/, int32_t /*stream_id*/,
                  const quiche::HttpHeaderBlock& /*headers*/,
                  const std::string& /*body*/) override {
    QUICHE_LOG(FATAL) << "Server cannot receive responses";
  }

  // From MasqueConnectionPool::Visitor.
  void OnPoolResponse(MasqueConnectionPool* /*pool*/, RequestId request_id,
                      absl::StatusOr<Message>&& response) override {
    auto it = pending_requests_.find(request_id);
    if (it == pending_requests_.end()) {
      QUICHE_LOG(ERROR) << "Received unexpected response for unknown request "
                        << request_id;
      return;
    }
    PendingRequest pending_request = std::move(it->second);
    pending_requests_.erase(it);
    quiche::HttpHeaderBlock response_headers;
    std::string response_body;
    if (response.ok()) {
      if (pending_request.ohttp_context.has_value()) {
        absl::StatusOr<MasqueConnectionPool::Message> gateway_response =
            masque_ohttp_gateway_->HandleResponse(
                std::move(*response),
                std::move(*pending_request.ohttp_context));
        if (!gateway_response.ok()) {
          response_headers[":status"] = "500";
          response_body = absl::StrCat("Failed to handle gateway response: ",
                                       gateway_response.status().message());
          QUICHE_LOG(ERROR) << response_body;
        } else {
          response_headers = std::move(gateway_response->headers);
          response_body = std::move(gateway_response->body);
          QUICHE_LOG(INFO) << "Sending OHTTP response";
        }
      } else {
        QUICHE_LOG(INFO) << "Forwarding relayed response to stream ID "
                         << pending_request.stream_id;
        response_headers = std::move(response->headers);
        response_body = std::move(response->body);
      }
    } else {
      QUICHE_LOG(ERROR) << "Received relayed error response: "
                        << response.status();
      response_headers[":status"] = "500";
      response_body =
          absl::StrCat("Relayed request failed: ", response.status().message());
    }
    pending_request.connection->SendResponse(pending_request.stream_id,
                                             response_headers, response_body);
    pending_request.connection->AttemptToSend();
  }

  bool SetupGateway(const std::string& gateway_path,
                    MasqueOhttpGateway* gateway) {
    if (gateway_path.empty() != (gateway == nullptr)) {
      QUICHE_LOG(ERROR) << "Invalid gateway configuration";
      return false;
    }
    gateway_path_ = gateway_path;
    masque_ohttp_gateway_ = gateway;
    if (masque_ohttp_gateway_) {
      masque_ohttp_gateway_->set_visitor(this);
    }
    return true;
  }

  bool SetupRelay(const std::string& relay) {
    if (relay.empty()) {
      return true;
    }
    std::vector<absl::string_view> relay_split = absl::StrSplit(relay, '|');
    for (absl::string_view relay_param : relay_split) {
      std::vector<absl::string_view> relay_param_split =
          absl::StrSplit(relay_param, '>');
      if (relay_param_split.size() != 2) {
        QUICHE_LOG(ERROR) << "Invalid relay parameter: \"" << relay_param
                          << "\". It should be in the format of \"path>url\"";
        return false;
      }
      absl::string_view path = relay_param_split[0];
      absl::string_view gateway_url = relay_param_split[1];
      auto [it, inserted] = relay_gateway_urls_.insert(
          {std::string(path), QuicUrl(gateway_url, "https")});
      if (!inserted) {
        QUICHE_LOG(ERROR) << "Duplicate relay path: \"" << path << "\"";
        return false;
      }
    }
    return true;
  }

  bool SetupKeyProxy(const std::string& key_proxy) {
    if (key_proxy.empty()) {
      return true;
    }
    std::vector<absl::string_view> key_proxy_split =
        absl::StrSplit(key_proxy, '|');
    for (absl::string_view key_proxy_param : key_proxy_split) {
      std::vector<absl::string_view> key_proxy_param_split =
          absl::StrSplit(key_proxy_param, '>');
      if (key_proxy_param_split.size() != 2) {
        QUICHE_LOG(ERROR) << "Invalid key proxy parameter: \""
                          << key_proxy_param
                          << "\". It should be in the format of \"path>url\"";
        return false;
      }
      absl::string_view path = key_proxy_param_split[0];
      absl::string_view key_proxy_url = key_proxy_param_split[1];
      auto [it, inserted] = key_proxy_urls_.insert(
          {std::string(path), QuicUrl(key_proxy_url, "https")});
      if (!inserted) {
        QUICHE_LOG(ERROR) << "Duplicate relay path: \"" << path << "\"";
        return false;
      }
      QUICHE_LOG(INFO) << "Added key proxy for " << path << ": "
                       << key_proxy_url;
    }
    return true;
  }

  void SavePendingGatewayRequest(
      MasqueH2Connection* connection, int32_t stream_id,
      MasqueConnectionPool::RequestId request_id,
      ObliviousHttpRequest::Context&& ohttp_context) override {
    PendingRequest pending_request;
    pending_request.connection = connection;
    pending_request.stream_id = stream_id;
    pending_request.ohttp_context = std::move(ohttp_context);
    pending_requests_.insert({request_id, std::move(pending_request)});
  }

 private:
  struct PendingRequest {
    MasqueH2Connection* connection = nullptr;  // Not owned.
    int32_t stream_id = -1;
    std::optional<ObliviousHttpRequest::Context> ohttp_context;
  };

  void AcceptConnection() {
    absl::StatusOr<socket_api::AcceptResult> accept_result =
        socket_api::Accept(server_socket_, /*blocking=*/false);
    if (!accept_result.ok()) {
      QUICHE_LOG(ERROR) << "Failed to accept connection: "
                        << accept_result.status();
      return;
    }
    QUICHE_LOG(INFO) << "Accepted TCP connection from "
                     << accept_result.value().peer_address;

    // `connection` takes ownership of the socket.
    auto connection = std::make_unique<MasqueH2SocketConnection>(
        accept_result.value().fd, event_loop_.get(), ctx_.get(),
        /*is_server=*/true, this);
    if (!connection->Start()) {
      QUICHE_LOG(ERROR) << "Failed to start connection handler from "
                        << accept_result.value().peer_address;
      return;
    }
    QUICHE_LOG(INFO) << "Started connection from "
                     << accept_result.value().peer_address;
    connections_.push_back(std::move(connection));
  }

  std::unique_ptr<QuicEventLoop> event_loop_;
  bssl::UniquePtr<SSL_CTX> ctx_;
  std::string gateway_path_;
  MasqueOhttpGateway* masque_ohttp_gateway_;  // Unowned.
  SocketFd server_socket_ = kInvalidSocketFd;
  std::vector<std::unique_ptr<MasqueH2SocketConnection>> connections_;
  // Maps from local paths to remote gateway URLs.
  absl::flat_hash_map<std::string, QuicUrl> relay_gateway_urls_;
  // Maps from local paths to remote key fetch URLs.
  absl::flat_hash_map<std::string, QuicUrl> key_proxy_urls_;
  MasqueConnectionPool connection_pool_;
  absl::flat_hash_map<RequestId, PendingRequest> pending_requests_;
};

int RunMasqueTcpServer(int argc, char* argv[]) {
  const char* usage = "Usage: masque_server [options]";
  std::vector<std::string> non_option_args =
      quiche::QuicheParseCommandLineFlags(usage, argc, argv);
  if (!non_option_args.empty()) {
    quiche::QuichePrintCommandLineFlagHelp(usage);
    return 1;
  }

  std::string server_certificate_file =
      quiche::GetQuicheCommandLineFlag(FLAGS_server_certificate_file);
  if (server_certificate_file.empty()) {
    QUICHE_LOG(ERROR) << "--server_certificate_file cannot be empty";
    return 1;
  }
  std::string server_key_file =
      quiche::GetQuicheCommandLineFlag(FLAGS_server_key_file);
  if (server_key_file.empty()) {
    QUICHE_LOG(ERROR) << "--server_key_file cannot be empty";
    return 1;
  }
  std::string client_root_ca_file =
      quiche::GetQuicheCommandLineFlag(FLAGS_client_root_ca_file);

  quiche::QuicheSystemEventLoop system_event_loop("masque_tcp_server");

  std::unique_ptr<MasqueOhttpGateway> masque_ohttp_gateway;
  std::string gateway_path =
      quiche::GetQuicheCommandLineFlag(FLAGS_gateway_path);
  if (!gateway_path.empty()) {
    masque_ohttp_gateway = MasqueOhttpGateway::Create(
        quiche::GetQuicheCommandLineFlag(FLAGS_ohttp_key));
    if (!masque_ohttp_gateway) {
      QUICHE_LOG(ERROR) << "Failed to create OHTTP gateway";
      return 1;
    }
  }

  const bool disable_certificate_verification =
      quiche::GetQuicheCommandLineFlag(FLAGS_disable_certificate_verification);
  const std::string client_cert_file =
      quiche::GetQuicheCommandLineFlag(FLAGS_client_cert_file);
  const std::string client_cert_key_file =
      quiche::GetQuicheCommandLineFlag(FLAGS_client_cert_key_file);
  absl::StatusOr<bssl::UniquePtr<SSL_CTX>> client_ssl_ctx =
      MasqueConnectionPool::CreateSslCtx(client_cert_file,
                                         client_cert_key_file);
  if (!client_ssl_ctx.ok()) {
    QUICHE_LOG(ERROR) << "Failed to create client SSL context: "
                      << client_ssl_ctx.status();
    return 1;
  }
  const int address_family =
      quiche::GetQuicheCommandLineFlag(FLAGS_address_family);
  int address_family_for_lookup;
  if (address_family == 0) {
    address_family_for_lookup = AF_UNSPEC;
  } else if (address_family == 4) {
    address_family_for_lookup = AF_INET;
  } else if (address_family == 6) {
    address_family_for_lookup = AF_INET6;
  } else {
    QUICHE_LOG(ERROR) << "Invalid address_family " << address_family;
    return 1;
  }

  MasqueTcpServer server(client_ssl_ctx->get(),
                         disable_certificate_verification,
                         address_family_for_lookup);

  if (!server.SetupGateway(gateway_path, masque_ohttp_gateway.get())) {
    QUICHE_LOG(ERROR) << "Invalid gateway configuration";
    return 1;
  }
  if (!server.SetupRelay(quiche::GetQuicheCommandLineFlag(FLAGS_relay))) {
    QUICHE_LOG(ERROR) << "Invalid --relay input";
    return 1;
  }
  if (!server.SetupKeyProxy(
          quiche::GetQuicheCommandLineFlag(FLAGS_key_proxy))) {
    QUICHE_LOG(ERROR) << "Invalid --key_proxy input";
    return 1;
  }
  if (!server.SetupSslCtx(server_certificate_file, server_key_file,
                          client_root_ca_file)) {
    QUICHE_LOG(ERROR) << "Failed to setup SSL context";
    return 1;
  }
  if (!server.SetupSocket(quiche::GetQuicheCommandLineFlag(FLAGS_port))) {
    QUICHE_LOG(ERROR) << "Failed to setup socket";
    return 1;
  }
  server.Run();

  return 0;
}

}  // namespace
}  // namespace quic

int main(int argc, char* argv[]) {
  return quic::RunMasqueTcpServer(argc, argv);
}
