// 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.

#include "quiche/quic/masque/masque_connection_pool.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "absl/cleanup/cleanup.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/match.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/pool.h"
#include "openssl/ssl.h"
#include "openssl/stack.h"
#include "quiche/quic/core/crypto/proof_verifier.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/core/quic_types.h"
#include "quiche/quic/masque/masque_h2_connection.h"
#include "quiche/quic/platform/api/quic_default_proof_providers.h"
#include "quiche/quic/tools/fake_proof_verifier.h"
#include "quiche/quic/tools/quic_name_lookup.h"
#include "quiche/quic/tools/quic_url.h"
#include "quiche/common/http/http_header_block.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/quiche_socket_address.h"
#include "quiche/common/quiche_status_utils.h"

#define ENDPOINT info_ << ": "

namespace quic {

namespace {

// Default DNS resolver that uses getaddrinfo().
class DefaultDnsResolver : public MasqueConnectionPool::DnsResolver {
 public:
  quiche::QuicheSocketAddress LookupAddress(
      int address_family_for_lookup, absl::string_view host,
      absl::string_view port) const override {
    return tools::LookupAddress(address_family_for_lookup, std::string(host),
                                std::string(port));
  }

  static DefaultDnsResolver* Get() {
    static DefaultDnsResolver resolver;
    return &resolver;
  }
};

class SimpleFetcher : public MasqueConnectionPool::Visitor {
 public:
  using Message = MasqueConnectionPool::Message;
  using RequestId = MasqueConnectionPool::RequestId;
  using DnsConfig = MasqueConnectionPool::DnsConfig;
  ~SimpleFetcher() override = default;

  static absl::StatusOr<Message> Fetch(const Message& request,
                                       absl::string_view info_string,
                                       const DnsConfig& dns_config,
                                       bool disable_certificate_verification,
                                       SSL_CTX* ssl_ctx) {
    SimpleFetcher fetcher;
    std::unique_ptr<QuicEventLoop> event_loop =
        GetDefaultEventLoop()->Create(QuicDefaultClock::Get());
    bssl::UniquePtr<SSL_CTX> local_ssl_ctx;
    if (ssl_ctx == nullptr) {
      QUICHE_ASSIGN_OR_RETURN(local_ssl_ctx,
                              MasqueConnectionPool::CreateSslCtx("", ""));
      ssl_ctx = local_ssl_ctx.get();
    }
    MasqueConnectionPool pool(event_loop.get(), ssl_ctx,
                              disable_certificate_verification, dns_config,
                              &fetcher, info_string);
    QUICHE_RETURN_IF_ERROR(pool.SendRequest(request).status());
    while (!fetcher.done_ && fetcher.status_.ok()) {
      event_loop->RunEventLoopOnce(quic::QuicTime::Delta::FromMilliseconds(50));
    }
    QUICHE_RETURN_IF_ERROR(fetcher.status_);
    uint16_t status_code =
        MasqueConnectionPool::GetStatusCode(fetcher.response_);
    if (status_code < 200 || status_code >= 300) {
      return absl::InternalError(
          absl::StrCat("Non-2xx status code: ", status_code));
    }
    return std::move(fetcher).response_;
  }

  static absl::StatusOr<Message> Get(absl::string_view url_string,
                                     absl::string_view info_string,
                                     const DnsConfig& dns_config,
                                     bool disable_certificate_verification,
                                     SSL_CTX* ssl_ctx) {
    Message request;
    QuicUrl url(url_string, "https");
    if (url.host().empty() && !absl::StrContains(url_string, "://")) {
      url = QuicUrl(absl::StrCat("https://", url_string));
    }
    request.headers[":method"] = "GET";
    request.headers[":scheme"] = url.scheme();
    request.headers[":authority"] = url.HostPort();
    request.headers[":path"] = url.PathParamsQuery();
    return Fetch(std::move(request), info_string, dns_config,
                 disable_certificate_verification, ssl_ctx);
  }

  // From MasqueConnectionPool::Visitor.
  void OnPoolResponse(MasqueConnectionPool* /*pool*/, RequestId /*request_id*/,
                      absl::StatusOr<Message>&& response,
                      bool end_stream) override {
    if (!end_stream) {
      // This should never happen because we don't stream responses.
      status_ = absl::InternalError("Unexpected non-end_stream OnPoolResponse");
      return;
    }
    if (!response.ok()) {
      status_ = response.status();
      return;
    }
    response_ = std::move(*response);
    done_ = true;
  }
  void OnPoolData(MasqueConnectionPool* /*pool*/, RequestId /*request_id*/,
                  absl::string_view /*data*/, bool /*end_stream*/) override {
    // This should never happen because we don't stream responses.
    status_ = absl::InternalError("Unexpected OnPoolData");
  }

 private:
  SimpleFetcher() = default;

  absl::Status status_ = absl::OkStatus();
  Message response_;
  bool done_ = false;
};

}  // namespace

absl::StatusOr<MasqueConnectionPool::Message> MasqueSimpleFetch(
    const MasqueConnectionPool::Message& request, absl::string_view info_string,
    const MasqueConnectionPool::DnsConfig& dns_config,
    bool disable_certificate_verification, SSL_CTX* ssl_ctx) {
  return SimpleFetcher::Fetch(request, info_string, dns_config,
                              disable_certificate_verification, ssl_ctx);
}

absl::StatusOr<MasqueConnectionPool::Message> MasqueSimpleGet(
    absl::string_view url_string, absl::string_view info_string,
    const MasqueConnectionPool::DnsConfig& dns_config,
    bool disable_certificate_verification, SSL_CTX* ssl_ctx) {
  return SimpleFetcher::Get(url_string, info_string, dns_config,
                            disable_certificate_verification, ssl_ctx);
}

// static
int16_t MasqueConnectionPool::GetStatusCode(const Message& message) {
  auto it = message.headers.find(":status");
  if (it == message.headers.end()) {
    return 0;
  }
  int16_t status_code = 0;
  if (!absl::SimpleAtoi(it->second, &status_code)) {
    return 0;
  }
  return status_code;
}

quiche::QuicheSocketAddress MasqueConnectionPool::LookupAddress(
    absl::string_view host, absl::string_view port) {
  const DnsResolver* dns_resolver = dns_config_.resolver();
  if (dns_resolver == nullptr) {
    dns_resolver = DefaultDnsResolver::Get();
  }
  dns_config_.ApplyOverrides(&host, &port);
  return dns_resolver->LookupAddress(dns_config_.address_family_for_lookup(),
                                     host, port);
}

absl::Status MasqueConnectionPool::DnsConfig::SetAddressFamily(
    int address_family) {
  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 {
    return absl::InvalidArgumentError(
        absl::StrCat("Invalid address_family ", address_family));
  }
  return absl::OkStatus();
}

absl::Status MasqueConnectionPool::DnsConfig::SetOverrides(
    const std::string& overrides) {
  if (overrides.empty()) {
    return absl::OkStatus();
  }
  std::vector<absl::string_view> overrides_split =
      absl::StrSplit(overrides, ';');
  for (absl::string_view override : overrides_split) {
    std::vector<absl::string_view> override_split =
        absl::StrSplit(override, ':');
    if (override_split.size() < 3 || override_split.size() > 4) {
      return absl::InvalidArgumentError(
          absl::StrCat("Invalid override: \"", override, "\""));
    }
    absl::string_view input_host = override_split[0];
    absl::string_view input_port = override_split[1];
    absl::string_view output_host = override_split[2];
    absl::string_view output_port =
        override_split.size() > 3 ? override_split[3] : "";
    auto [it, inserted] = overrides_.insert(
        {std::make_pair(std::string(input_host), std::string(input_port)),
         std::make_pair(std::string(output_host), std::string(output_port))});
    if (!inserted) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Duplicate override entry: \"", input_host, ":", input_port, "\""));
    }
  }
  return absl::OkStatus();
}

void MasqueConnectionPool::DnsConfig::ApplyOverrides(
    absl::string_view* host, absl::string_view* port) const {
  for (const auto& [input, output] : overrides_) {
    if ((input.first == *host || input.first.empty()) &&
        (input.second == *port || input.second.empty())) {
      *host = output.first;
      if (!output.second.empty()) {
        *port = output.second;
      }
      return;
    }
  }
}

MasqueConnectionPool::MasqueConnectionPool(
    QuicEventLoop* event_loop, SSL_CTX* ssl_ctx,
    bool disable_certificate_verification, const DnsConfig& dns_config,
    Visitor* visitor, absl::string_view info_string)
    : event_loop_(event_loop),
      tls_ssl_ctx_(ssl_ctx),
      disable_certificate_verification_(disable_certificate_verification),
      dns_config_(dns_config),
      visitor_(visitor),
      info_(info_string) {}

void MasqueConnectionPool::OnConnectionReady(MasqueH2Connection* connection) {
  SendPendingRequests(connection);
}

void MasqueConnectionPool::OnConnectionFinished(MasqueH2Connection* connection,
                                                absl::Status error) {
  FailPendingRequests(
      connection,
      error.ok() ? absl::InternalError(
                       "Connection finished before receiving complete response")
                 : error);
}

void MasqueConnectionPool::OnRequest(MasqueH2Connection* /*connection*/,
                                     int32_t /*stream_id*/,
                                     const quiche::HttpHeaderBlock& /*headers*/,
                                     const std::string& /*body*/) {
  QUICHE_LOG(FATAL) << ENDPOINT << "Client cannot receive requests";
}

void MasqueConnectionPool::OnResponse(MasqueH2Connection* connection,
                                      int32_t stream_id,
                                      const quiche::HttpHeaderBlock& headers,
                                      const std::string& body,
                                      bool end_stream) {
  bool found = false;
  for (auto it = pending_requests_.begin(); it != pending_requests_.end();) {
    RequestId request_id = it->first;
    PendingRequest& pending_request = *it->second;
    if (pending_request.connection == connection &&
        pending_request.stream_id == stream_id) {
      Message response;
      response.headers = headers.Clone();
      response.body = body;
      response.draining = connection->draining();
      if (end_stream) {
        pending_request.response_done = true;
      }
      if (end_stream && pending_request.end_stream_pending) {
        pending_requests_.erase(it);
      }
      visitor_->OnPoolResponse(this, request_id, std::move(response),
                               end_stream);
      found = true;
      break;
    }
    ++it;
  }
  if (!found) {
    QUICHE_LOG(ERROR) << ENDPOINT
                      << "Received unexpected response for unknown request: "
                      << headers.DebugString();
  }
}

void MasqueConnectionPool::OnDataForStream(MasqueH2Connection* connection,
                                           int32_t stream_id,
                                           absl::string_view data,
                                           bool end_stream) {
  for (auto it = pending_requests_.begin(); it != pending_requests_.end();
       ++it) {
    RequestId request_id = it->first;
    PendingRequest& pending_request = *it->second;
    if (pending_request.connection == connection &&
        pending_request.stream_id == stream_id) {
      if (end_stream) {
        pending_request.response_done = true;
      }
      if (end_stream && pending_request.end_stream_pending) {
        pending_requests_.erase(it);
      }
      visitor_->OnPoolData(this, request_id, data, end_stream);
      break;
    }
  }
}

void MasqueConnectionPool::OnStreamFailure(MasqueH2Connection* connection,
                                           int32_t stream_id,
                                           absl::Status error) {
  for (auto it = pending_requests_.begin(); it != pending_requests_.end();) {
    RequestId request_id = it->first;
    PendingRequest& pending_request = *it->second;
    if (pending_request.connection == connection &&
        pending_request.stream_id == stream_id) {
      pending_requests_.erase(it++);
      visitor_->OnPoolResponse(this, request_id, error, /*end_stream=*/true);
      break;
    }
    ++it;
  }
}

absl::StatusOr<MasqueConnectionPool::RequestId>
MasqueConnectionPool::SendRequest(const Message& request, bool mtls,
                                  bool end_stream, bool stream_response) {
  auto authority = request.headers.find(":authority");
  if (authority == request.headers.end()) {
    return absl::InvalidArgumentError("Request missing :authority header");
  }
  QUICHE_ASSIGN_OR_RETURN(
      ConnectionState * connection,
      GetOrCreateConnectionState(std::string(authority->second), mtls));
  auto pending_request = std::make_unique<PendingRequest>();
  if (connection->connection() != nullptr &&
      !connection->connection()->aborted()) {
    QUICHE_LOG(INFO) << ENDPOINT << "Reusing existing connection "
                     << connection->connection()->info() << " to "
                     << authority->second;
    pending_request->connection = connection->connection();
    pending_request->stream_id = connection->connection()->SendRequest(
        request.headers, request.body, end_stream, stream_response);
    if (pending_request->stream_id < 0) {
      return absl::InternalError(
          absl::StrCat("Failed to send request to ", authority->second));
    }
    connection->connection()->AttemptToSend();
  } else {
    QUICHE_LOG(INFO) << ENDPOINT << "No existing connection to "
                     << authority->second;
  }
  RequestId request_id = ++next_request_id_;
  pending_request->request.headers = request.headers.Clone();
  pending_request->request.body = request.body;
  pending_request->stream_response = stream_response;
  pending_request->end_stream_pending = end_stream;
  pending_requests_.insert({request_id, std::move(pending_request)});
  return request_id;
}

absl::Status MasqueConnectionPool::SendBodyChunk(RequestId request_id,
                                                 const std::string& body,
                                                 bool end_stream) {
  auto it = pending_requests_.find(request_id);
  if (it == pending_requests_.end()) {
    return absl::InternalError(
        absl::StrCat("SendBodyChunk called for unknown request ", request_id));
  }
  PendingRequest& pending_request = *it->second;
  if (pending_request.connection == nullptr || pending_request.stream_id < 0) {
    // Connection not ready yet, append to pending body chunks.
    pending_request.pending_data += body;
    pending_request.end_stream_pending = end_stream;
    return absl::OkStatus();
  }
  if (pending_request.end_stream_pending) {
    return absl::FailedPreconditionError(absl::StrCat(
        "SendBodyChunk called when end_stream already pending ", request_id));
  }
  pending_request.end_stream_pending = end_stream;
  pending_request.connection->SendBodyChunk(pending_request.stream_id, body,
                                            end_stream);
  pending_request.connection->AttemptToSend();

  if (end_stream && pending_request.response_done) {
    pending_requests_.erase(it);
  }
  return absl::OkStatus();
}

absl::StatusOr<MasqueConnectionPool::ConnectionState*>
MasqueConnectionPool::GetOrCreateConnectionState(const std::string& authority,
                                                 bool mtls) {
  std::string entry = absl::StrCat((mtls ? "m" : ""), "tls:", authority);
  auto connection_state_it = connections_.find(entry);
  if (connection_state_it != connections_.end()) {
    return connection_state_it->second.get();
  }
  auto connection_state = std::make_unique<ConnectionState>(this);
  connection_state->set_mtls(mtls);
  QUICHE_RETURN_IF_ERROR(connection_state->SetupSocket(
      authority, disable_certificate_verification_));
  return connections_.insert({entry, std::move(connection_state)})
      .first->second.get();
}

void MasqueConnectionPool::AttachConnectionToPendingRequests(
    const std::string& authority, MasqueH2Connection* connection) {
  for (auto it = pending_requests_.begin(); it != pending_requests_.end();
       ++it) {
    PendingRequest& pending_request = *it->second;
    auto authority_header = pending_request.request.headers.find(":authority");
    if (authority_header == pending_request.request.headers.end()) {
      QUICHE_LOG(ERROR) << ENDPOINT << "Request missing :authority header";
      continue;
    }
    if (authority_header->second != authority) {
      continue;
    }
    QUICHE_LOG(INFO) << ENDPOINT << "Attaching connection "
                     << connection->info() << " to pending request for "
                     << authority;
    pending_request.connection = connection;
  }
}

void MasqueConnectionPool::SendPendingRequests(MasqueH2Connection* connection) {
  for (auto it = pending_requests_.begin(); it != pending_requests_.end();) {
    RequestId request_id = it->first;
    PendingRequest& pending_request = *it->second;
    if (pending_request.connection != connection) {
      ++it;
      continue;
    }
    bool is_request_complete = pending_request.pending_data.empty() &&
                               pending_request.end_stream_pending;
    QUICHE_LOG(INFO) << ENDPOINT << "Sending pending request ID " << request_id;
    int32_t stream_id = connection->SendRequest(
        pending_request.request.headers, pending_request.request.body,
        is_request_complete, pending_request.stream_response);
    if (stream_id < 0) {
      QUICHE_LOG(ERROR) << ENDPOINT << "Failed to send request ID "
                        << request_id << " on connection "
                        << connection->info();
      visitor_->OnPoolResponse(this, request_id,
                               absl::InternalError("Failed to send request"),
                               /*end_stream=*/true);
      pending_requests_.erase(it++);
      continue;
    }

    if (!pending_request.pending_data.empty()) {
      connection->AttemptToSend();
    }

    if (!is_request_complete) {
      connection->SendBodyChunk(stream_id, pending_request.pending_data,
                                pending_request.end_stream_pending);
    }
    pending_request.pending_data.clear();

    pending_request.stream_id = stream_id;
    ++it;
  }
}

void MasqueConnectionPool::FailPendingRequests(MasqueH2Connection* connection,
                                               const absl::Status& error) {
  for (auto it = pending_requests_.begin(); it != pending_requests_.end();) {
    RequestId request_id = it->first;
    PendingRequest& pending_request = *it->second;
    if (pending_request.connection != connection) {
      ++it;
      continue;
    }
    visitor_->OnPoolResponse(this, request_id, error, /*end_stream=*/true);
    pending_requests_.erase(it++);
  }
}

MasqueConnectionPool::ConnectionState::ConnectionState(
    MasqueConnectionPool* connection_pool)
    : connection_pool_(connection_pool), info_(connection_pool->info()) {}

MasqueConnectionPool::ConnectionState::~ConnectionState() {
  if (socket_ != kInvalidSocketFd) {
    QUICHE_LOG(INFO) << ENDPOINT << "Closing socket fd " << socket_ << " for "
                     << authority_;
    if (!connection_pool_->event_loop()->UnregisterSocket(socket_)) {
      QUICHE_LOG(ERROR) << ENDPOINT << "Failed to unregister socket";
    }
    if (!socket_api::Close(socket_).ok()) {
      QUICHE_LOG(ERROR) << ENDPOINT << "Error while closing socket";
    }
    socket_ = kInvalidSocketFd;
  }
}

absl::Status MasqueConnectionPool::ConnectionState::SetupSocket(
    const std::string& authority, bool disable_certificate_verification) {
  authority_ = authority;
  std::vector<std::string> authority_split =
      absl::StrSplit(authority_, absl::MaxSplits(':', 1));
  std::string port;
  if (authority_split.size() == 2) {
    host_ = authority_split[0];
    port = authority_split[1];
  } else {
    host_ = authority_split[0];
    port = "443";
  }
  quiche::QuicheSocketAddress socket_address =
      connection_pool_->LookupAddress(host_, port);
  if (!socket_address.IsInitialized()) {
    return absl::InvalidArgumentError(
        absl::StrCat("Failed to resolve address for \"", authority_, "\""));
  }
  absl::StatusOr<SocketFd> create_result = socket_api::CreateSocket(
      socket_address.host().address_family(), socket_api::SocketProtocol::kTcp,
      /*blocking=*/false);
  if (!create_result.ok() || create_result.value() == kInvalidSocketFd) {
    return absl::InternalError(absl::StrCat("Failed to create socket: ",
                                            create_result.status().message()));
  }
  socket_ = create_result.value();
  QUICHE_LOG(INFO) << ENDPOINT << "Socket fd " << socket_
                   << " starting connect to " << socket_address << " for "
                   << authority_;
  // Ignore result because asynchronous connect is expected to fail.
  (void)socket_api::Connect(socket_, socket_address);
  if (!connection_pool_->event_loop()->RegisterSocket(
          socket_, kSocketEventReadable | kSocketEventWritable, this)) {
    return absl::InternalError("Failed to register socket with the event loop");
  }

  if (disable_certificate_verification) {
    proof_verifier_ = std::make_unique<FakeProofVerifier>();
  } else {
    proof_verifier_ = CreateDefaultProofVerifier(host_);
    if (!proof_verifier_) {
      QUICHE_LOG(FATAL) << ENDPOINT
                        << "The default proof verifier is not supported. Pass "
                           "in --disable_certificate_verification.";
    }
  }
  return absl::OkStatus();
}

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

  if (fd != socket_) {
    return;
  }
  if (connection_ && ((events & kSocketEventReadable) != 0)) {
    connection_->OnTransportReadable();
  }
  if ((events & kSocketEventWritable) != 0) {
    if (!ssl_) {
      ssl_.reset((SSL_new(connection_pool_->GetSslCtx(mtls_))));
      SSL_set_connect_state(ssl_.get());

      if (SSL_set_app_data(ssl_.get(), this) != 1) {
        QUICHE_LOG(FATAL) << ENDPOINT << "SSL_set_app_data failed";
      }
      SSL_set_custom_verify(ssl_.get(), SSL_VERIFY_PEER, &VerifyCallback);

      if (SSL_set_tlsext_host_name(ssl_.get(), host_.c_str()) != 1) {
        QUICHE_LOG(FATAL) << ENDPOINT << "SSL_set_tlsext_host_name failed";
      }

      static constexpr uint8_t kAlpnProtocols[] = {
          // clang-format off
          0x02, 'h', '2',  // h2
          // clang-format on
      };
      if (SSL_set_alpn_protos(ssl_.get(), kAlpnProtocols,
                              sizeof(kAlpnProtocols)) != 0) {
        QUICHE_LOG(FATAL) << ENDPOINT << "SSL_set_alpn_protos failed";
      }
      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`.
      connection_ = std::make_unique<MasqueH2Connection>(
          ssl_.get(), /*is_server=*/false, connection_pool_,
          connection_pool_->info());
      info_ = connection_->info();
      connection_pool_->AttachConnectionToPendingRequests(authority_,
                                                          connection_.get());
      connection_->OnTransportReadable();
    }
    connection_->AttemptToSend();
  }
}

// static
enum ssl_verify_result_t MasqueConnectionPool::ConnectionState::VerifyCallback(
    SSL* ssl, uint8_t* out_alert) {
  return static_cast<MasqueConnectionPool::ConnectionState*>(
             SSL_get_app_data(ssl))
      ->VerifyCertificate(ssl, out_alert);
}

enum ssl_verify_result_t
MasqueConnectionPool::ConnectionState::VerifyCertificate(SSL* ssl,
                                                         uint8_t* out_alert) {
  const STACK_OF(CRYPTO_BUFFER)* cert_chain = SSL_get0_peer_certificates(ssl);
  if (cert_chain == nullptr) {
    QUICHE_LOG(ERROR) << ENDPOINT << "No certificate chain";
    *out_alert = SSL_AD_INTERNAL_ERROR;
    return ssl_verify_invalid;
  }
  std::vector<absl::string_view> certs;
  for (CRYPTO_BUFFER* cert : cert_chain) {
    certs.push_back(absl::string_view(
        reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert)),
        CRYPTO_BUFFER_len(cert)));
  }
  const uint8_t* ocsp_response_raw;
  size_t ocsp_response_len;
  SSL_get0_ocsp_response(ssl, &ocsp_response_raw, &ocsp_response_len);
  std::string ocsp_response(reinterpret_cast<const char*>(ocsp_response_raw),
                            ocsp_response_len);
  const uint8_t* sct_list_raw;
  size_t sct_list_len;
  SSL_get0_signed_cert_timestamp_list(ssl, &sct_list_raw, &sct_list_len);
  std::string cert_sct(reinterpret_cast<const char*>(sct_list_raw),
                       sct_list_len);
  std::string error_details;
  std::unique_ptr<ProofVerifyDetails> details;
  QuicAsyncStatus verify_status = proof_verifier_->VerifyCertChain(
      host_, /*port=*/443, certs, ocsp_response, cert_sct,
      /*context=*/nullptr, &error_details, &details, out_alert,
      /*callback=*/nullptr);
  if (verify_status != QUIC_SUCCESS) {
    // TODO(dschinazi) properly handle QUIC_PENDING.
    QUICHE_LOG(ERROR) << ENDPOINT << "Failed to verify certificate"
                      << (verify_status == QUIC_PENDING ? " (pending)" : "")
                      << ": " << error_details;
    return ssl_verify_invalid;
  }
  QUICHE_LOG(INFO) << ENDPOINT << "Successfully verified certificate";
  return ssl_verify_ok;
}

// static
absl::StatusOr<bssl::UniquePtr<SSL_CTX>> MasqueConnectionPool::CreateSslCtx(
    const std::string& client_cert_file,
    const std::string& client_cert_key_file) {
  if (client_cert_file.empty() != client_cert_key_file.empty()) {
    return absl::InvalidArgumentError(
        "Both private key and certificate chain are required when using client "
        "certificates");
  }
  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));

  if (!client_cert_key_file.empty() &&
      !SSL_CTX_use_PrivateKey_file(ctx.get(), client_cert_key_file.c_str(),
                                   SSL_FILETYPE_PEM)) {
    QUICHE_LOG(ERROR) << "Failed to load client certificate private key: "
                      << client_cert_key_file;
    return absl::InternalError(
        absl::StrCat("Failed to load client certificate private key: ",
                     client_cert_key_file));
  }
  if (!client_cert_file.empty() && !SSL_CTX_use_certificate_chain_file(
                                       ctx.get(), client_cert_file.c_str())) {
    QUICHE_LOG(ERROR) << "Failed to load client certificate chain: "
                      << client_cert_file;
    return absl::InternalError(absl::StrCat(
        "Failed to load client certificate chain: ", client_cert_file));
  }

  SSL_CTX_set_min_proto_version(ctx.get(), TLS1_2_VERSION);
  SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_VERSION);
  SSL_CTX_set_mode(ctx.get(), SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

  return ctx;
}

// static
absl::StatusOr<bssl::UniquePtr<SSL_CTX>>
MasqueConnectionPool::CreateSslCtxFromData(
    const std::string& client_cert_pem_data,
    const std::string& client_cert_key_data) {
  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
  // Load public cert.
  BIO* cert_bio = BIO_new_mem_buf(client_cert_pem_data.c_str(), -1);
  QUICHE_CHECK(cert_bio);
  X509* cert = PEM_read_bio_X509(cert_bio, nullptr, nullptr, nullptr);
  QUICHE_CHECK(cert);
  BIO_free(cert_bio);
  int rv = SSL_CTX_use_certificate(ctx.get(), cert);
  QUICHE_CHECK_EQ(rv, 1);
  X509_free(cert);

  // Load private key.
  BIO* key_bio = BIO_new_mem_buf(client_cert_key_data.c_str(), -1);
  QUICHE_CHECK(key_bio);
  EVP_PKEY* private_key =
      PEM_read_bio_PrivateKey(key_bio, nullptr, nullptr, nullptr);
  QUICHE_CHECK(private_key);
  BIO_free(key_bio);
  rv = SSL_CTX_use_PrivateKey(ctx.get(), private_key);
  QUICHE_CHECK_EQ(rv, 1);
  EVP_PKEY_free(private_key);

  SSL_CTX_set_min_proto_version(ctx.get(), TLS1_2_VERSION);
  SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_VERSION);
  SSL_CTX_set_mode(ctx.get(), SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

  return ctx;
}

}  // namespace quic

#undef ENDPOINT
