// Copyright 2019 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_client_session.h"

#include <cstdint>
#include <cstring>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "openssl/curve25519.h"
#include "quiche/quic/core/crypto/quic_crypto_client_config.h"
#include "quiche/quic/core/frames/quic_connection_close_frame.h"
#include "quiche/quic/core/http/http_frames.h"
#include "quiche/quic/core/http/quic_spdy_client_session.h"
#include "quiche/quic/core/http/quic_spdy_client_stream.h"
#include "quiche/quic/core/http/quic_spdy_stream.h"
#include "quiche/quic/core/quic_config.h"
#include "quiche/quic/core/quic_connection.h"
#include "quiche/quic/core/quic_data_reader.h"
#include "quiche/quic/core/quic_data_writer.h"
#include "quiche/quic/core/quic_error_codes.h"
#include "quiche/quic/core/quic_server_id.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/core/quic_utils.h"
#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/masque/masque_utils.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"
#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
#include "quiche/quic/tools/quic_url.h"
#include "quiche/common/capsule.h"
#include "quiche/common/http/http_header_block.h"
#include "quiche/common/platform/api/quiche_googleurl.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/platform/api/quiche_url_utils.h"
#include "quiche/common/quiche_ip_address.h"
#include "quiche/common/quiche_random.h"
#include "quiche/common/quiche_text_utils.h"

namespace quic {

namespace {

using ::quiche::AddressAssignCapsule;
using ::quiche::AddressRequestCapsule;
using ::quiche::RouteAdvertisementCapsule;
using ContextId = MasqueClientSession::ContextId;

constexpr MasqueClientSession::ContextId kConnectIpPayloadContextId = 0;
constexpr MasqueClientSession::ContextId kConnectEthernetPayloadContextId = 0;
}  // namespace

MasqueClientSession::MasqueClientSession(
    MasqueMode masque_mode, const std::string& uri_template,
    const QuicConfig& config, const ParsedQuicVersionVector& supported_versions,
    QuicConnection* connection, const QuicServerId& server_id,
    QuicCryptoClientConfig* crypto_config, Owner* owner)
    : QuicSpdyClientSession(config, supported_versions, connection, server_id,
                            crypto_config),
      masque_mode_(masque_mode),
      uri_template_(uri_template),
      owner_(owner) {
  QUICHE_CHECK(!QuicUrl(uri_template_).host().empty());
  // We don't currently use `masque_mode_` but will in the future. To silence
  // clang's `-Wunused-private-field` warning for this when building QUICHE for
  // Chrome, add a use of it here.
  (void)masque_mode_;
}

MasqueClientSession::MasqueClientSession(
    const QuicConfig& config, const ParsedQuicVersionVector& supported_versions,
    QuicConnection* connection, const QuicServerId& server_id,
    QuicCryptoClientConfig* crypto_config, Owner* owner)
    : QuicSpdyClientSession(config, supported_versions, connection, server_id,
                            crypto_config),
      owner_(owner) {}

void MasqueClientSession::OnDatagramAcked(QuicDatagramId datagram_id,
                                          QuicTime /*receive_timestamp*/) {
  QUIC_DVLOG(1) << "Received ack for DATAGRAM frame " << datagram_id;
}

void MasqueClientSession::OnDatagramLost(QuicDatagramId datagram_id) {
  QUIC_DVLOG(1) << "We believe DATAGRAM frame " << datagram_id << " was lost";
}

MasqueClientSession::ConnectUdpClientState*
MasqueClientSession::GetOrCreateConnectUdpClientState(
    const QuicSocketAddress& target_server_address,
    EncapsulatedClientSession* encapsulated_client_session) {
  for (ConnectUdpClientState& client_state : connect_udp_client_states_) {
    if (client_state.target_server_address() == target_server_address &&
        client_state.encapsulated_client_session() ==
            encapsulated_client_session &&
        IsBind() == client_state.is_bind()) {
      // Found existing CONNECT-UDP request.
      return &client_state;
    }
  }

  QUIC_DLOG(INFO) << "No existing state non bind state found, create one";
  // No CONNECT-UDP request found, create a new one.
  std::string target_host, target_port;

  if (IsBind()) {
    target_host = "*";
    target_port = "*";
  } else {
    auto it =
        fake_addresses_.find(target_server_address.host().ToPackedString());
    if (it != fake_addresses_.end()) {
      target_host = it->second;
    } else {
      target_host = target_server_address.host().ToString();
    }
    target_port = absl::StrCat(target_server_address.port());
  }
  QUICHE_CHECK(!target_host.empty());

  url::Parsed parsed_uri_template;
  url::ParseStandardURL(uri_template_.c_str(), uri_template_.length(),
                        &parsed_uri_template);
  if (!parsed_uri_template.path.is_nonempty()) {
    QUIC_BUG(bad URI template path)
        << connection_id() << ": Cannot parse path from URI template \""
        << uri_template_ << "\"";
    return nullptr;
  }
  std::string path = uri_template_.substr(parsed_uri_template.path.begin,
                                          parsed_uri_template.path.len);
  if (parsed_uri_template.query.is_valid()) {
    absl::StrAppend(&path, "?",
                    uri_template_.substr(parsed_uri_template.query.begin,
                                         parsed_uri_template.query.len));
  }
  absl::flat_hash_map<std::string, std::string> parameters;
  // TODO(abhisinghx): Remove this hack.
  // ExpandURITemplate, does not encode * as %2A.
  // Therefore to meet the spec, we need to do it manually.
  if (IsBind()) {
    parameters["target_host"] = "HackyStringForBind";
    parameters["target_port"] = "HackyStringForBind";
  } else {
    parameters["target_host"] = target_host;
    parameters["target_port"] = target_port;
  }

  std::string expanded_path;
  absl::flat_hash_set<std::string> vars_found;
  bool expanded =
      quiche::ExpandURITemplate(path, parameters, &expanded_path, &vars_found);
  if (!expanded || vars_found.find("target_host") == vars_found.end() ||
      vars_found.find("target_port") == vars_found.end()) {
    QUIC_DLOG(ERROR) << "Failed to expand URI template \"" << uri_template_
                     << "\" for " << target_host << " port "
                     << target_server_address.port();
    return nullptr;
  }
  if (IsBind()) {
    expanded_path =
        absl::StrReplaceAll(expanded_path, {{"HackyStringForBind", "%2A"}});
  }

  url::Component expanded_path_component(0, expanded_path.length());
  url::RawCanonOutput<1024> canonicalized_path_output;
  url::Component canonicalized_path_component;
  bool canonicalized = url::CanonicalizePath(
      expanded_path.c_str(), expanded_path_component,
      &canonicalized_path_output, &canonicalized_path_component);
  if (!canonicalized || !canonicalized_path_component.is_nonempty()) {
    QUIC_DLOG(ERROR) << "Failed to canonicalize URI template \""
                     << uri_template_ << "\" for " << target_host << " port "
                     << target_server_address.port();
    return nullptr;
  }
  std::string canonicalized_path(
      canonicalized_path_output.data() + canonicalized_path_component.begin,
      canonicalized_path_component.len);

  QuicSpdyClientStream* stream = CreateOutgoingBidirectionalStream();
  if (stream == nullptr) {
    // Stream flow control limits prevented us from opening a new stream.
    QUIC_DLOG(ERROR) << "Failed to open CONNECT-UDP stream";
    return nullptr;
  }

  QuicUrl url(uri_template_);
  std::string scheme = url.scheme();
  std::string authority = url.HostPort();

  QUIC_DLOG(INFO) << "Sending CONNECT-UDP request for " << target_host
                  << " port " << target_server_address.port() << " on stream "
                  << stream->id() << " scheme=\"" << scheme << "\" authority=\""
                  << authority << "\" path=\"" << canonicalized_path << "\"";

  // Send the request.
  quiche::HttpHeaderBlock headers;
  headers[":method"] = "CONNECT";
  headers[":protocol"] = "connect-udp";
  headers[":scheme"] = scheme;
  headers[":authority"] = authority;
  headers[":path"] = canonicalized_path;
  if (IsBind()) {
    headers["connect-udp-bind"] = "?1";
  }
  AddAdditionalHeaders(headers, url);
  QUIC_DVLOG(1) << "Sending request headers: " << headers.DebugString();
  size_t bytes_sent =
      stream->SendRequest(std::move(headers), /*body=*/"", /*fin=*/false);
  if (bytes_sent == 0) {
    QUIC_DLOG(ERROR) << "Failed to send CONNECT-UDP request";
    return nullptr;
  }

  connect_udp_client_states_.push_back(ConnectUdpClientState(
      stream, encapsulated_client_session, this, target_server_address));
  if (IsBind()) {
    QUIC_DLOG(INFO) << "Creating bind state";
    connect_udp_client_states_.back().set_is_bind(true);
  }
  return &connect_udp_client_states_.back();
}

const MasqueClientSession::ConnectIpClientState*
MasqueClientSession::GetOrCreateConnectIpClientState(
    MasqueClientSession::EncapsulatedIpSession* encapsulated_ip_session) {
  for (const ConnectIpClientState& client_state : connect_ip_client_states_) {
    if (client_state.encapsulated_ip_session() == encapsulated_ip_session) {
      // Found existing CONNECT-IP request.
      return &client_state;
    }
  }
  // No CONNECT-IP request found, create a new one.
  QuicSpdyClientStream* stream = CreateOutgoingBidirectionalStream();
  if (stream == nullptr) {
    // Stream flow control limits prevented us from opening a new stream.
    QUIC_DLOG(ERROR) << "Failed to open CONNECT-IP stream";
    return nullptr;
  }

  QuicUrl url(uri_template_);
  std::string scheme = url.scheme();
  std::string authority = url.HostPort();
  std::string path = "/.well-known/masque/ip/*/*/";

  QUIC_DLOG(INFO) << "Sending CONNECT-IP request on stream " << stream->id()
                  << " scheme=\"" << scheme << "\" authority=\"" << authority
                  << "\" path=\"" << path << "\"";

  // Send the request.
  quiche::HttpHeaderBlock headers;
  headers[":method"] = "CONNECT";
  headers[":protocol"] = "connect-ip";
  headers[":scheme"] = scheme;
  headers[":authority"] = authority;
  headers[":path"] = path;
  headers["connect-ip-version"] = "3";
  AddAdditionalHeaders(headers, url);
  QUIC_DVLOG(1) << "Sending request headers: " << headers.DebugString();
  size_t bytes_sent =
      stream->SendRequest(std::move(headers), /*body=*/"", /*fin=*/false);
  if (bytes_sent == 0) {
    QUIC_DLOG(ERROR) << "Failed to send CONNECT-IP request";
    return nullptr;
  }

  connect_ip_client_states_.push_back(
      ConnectIpClientState(stream, encapsulated_ip_session, this));
  return &connect_ip_client_states_.back();
}

const MasqueClientSession::ConnectEthernetClientState*
MasqueClientSession::GetOrCreateConnectEthernetClientState(
    MasqueClientSession::EncapsulatedEthernetSession*
        encapsulated_ethernet_session) {
  for (const ConnectEthernetClientState& client_state :
       connect_ethernet_client_states_) {
    if (client_state.encapsulated_ethernet_session() ==
        encapsulated_ethernet_session) {
      // Found existing CONNECT-ETHERNET request.
      return &client_state;
    }
  }
  // No CONNECT-ETHERNET request found, create a new one.
  QuicSpdyClientStream* stream = CreateOutgoingBidirectionalStream();
  if (stream == nullptr) {
    // Stream flow control limits prevented us from opening a new stream.
    QUIC_DLOG(ERROR) << "Failed to open CONNECT-ETHERNET stream";
    return nullptr;
  }

  QuicUrl url(uri_template_);
  std::string scheme = url.scheme();
  std::string authority = url.HostPort();
  std::string path = "/.well-known/masque/ethernet/";

  QUIC_DLOG(INFO) << "Sending CONNECT-ETHERNET request on stream "
                  << stream->id() << " scheme=\"" << scheme << "\" authority=\""
                  << authority << "\" path=\"" << path << "\"";

  // Send the request.
  quiche::HttpHeaderBlock headers;
  headers[":method"] = "CONNECT";
  headers[":protocol"] = "connect-ethernet";
  headers[":scheme"] = scheme;
  headers[":authority"] = authority;
  headers[":path"] = path;
  AddAdditionalHeaders(headers, url);
  QUIC_DVLOG(1) << "Sending request headers: " << headers.DebugString();
  size_t bytes_sent =
      stream->SendRequest(std::move(headers), /*body=*/"", /*fin=*/false);
  if (bytes_sent == 0) {
    QUIC_DLOG(ERROR) << "Failed to send CONNECT-ETHERNET request";
    return nullptr;
  }

  connect_ethernet_client_states_.push_back(
      ConnectEthernetClientState(stream, encapsulated_ethernet_session, this));
  return &connect_ethernet_client_states_.back();
}

void MasqueClientSession::SendIpPacket(
    absl::string_view packet,
    MasqueClientSession::EncapsulatedIpSession* encapsulated_ip_session) {
  const ConnectIpClientState* connect_ip =
      GetOrCreateConnectIpClientState(encapsulated_ip_session);
  if (connect_ip == nullptr) {
    QUIC_DLOG(ERROR) << "Failed to create CONNECT-IP request";
    return;
  }

  std::string http_payload;
  http_payload.resize(
      QuicDataWriter::GetVarInt62Len(kConnectIpPayloadContextId) +
      packet.size());
  QuicDataWriter writer(http_payload.size(), http_payload.data());
  if (!writer.WriteVarInt62(kConnectIpPayloadContextId)) {
    QUIC_BUG(IP context write fail) << "Failed to write CONNECT-IP context ID";
    return;
  }
  if (!writer.WriteStringPiece(packet)) {
    QUIC_BUG(IP packet write fail) << "Failed to write CONNECT-IP packet";
    return;
  }
  DatagramStatus message_status =
      SendHttp3Datagram(connect_ip->stream()->id(), http_payload);

  QUIC_DVLOG(1) << "Sent encapsulated IP packet of length " << packet.size()
                << " with stream ID " << connect_ip->stream()->id()
                << " and got message status "
                << DatagramStatusToString(message_status);
}

void MasqueClientSession::SendDnsAssignCapsule(
    const DnsAssignCapsule& capsule,
    MasqueClientSession::EncapsulatedIpSession* encapsulated_ip_session) {
  const ConnectIpClientState* connect_ip =
      GetOrCreateConnectIpClientState(encapsulated_ip_session);
  if (connect_ip == nullptr) {
    QUIC_LOG(ERROR) << "Failed to get CONNECT-IP request for DNS_ASSIGN";
    return;
  }
  WriteDnsAssignCapsule(connect_ip->stream(), capsule);
}

void MasqueClientSession::SendPref64Capsule(
    const Pref64Capsule& capsule,
    MasqueClientSession::EncapsulatedIpSession* encapsulated_ip_session) {
  const ConnectIpClientState* connect_ip =
      GetOrCreateConnectIpClientState(encapsulated_ip_session);
  if (connect_ip == nullptr) {
    QUIC_LOG(ERROR) << "Failed to get CONNECT-IP request for PREF64";
    return;
  }
  WritePref64Capsule(connect_ip->stream(), capsule);
}

void MasqueClientSession::SendEthernetFrame(
    absl::string_view frame, MasqueClientSession::EncapsulatedEthernetSession*
                                 encapsulated_ethernet_session) {
  const ConnectEthernetClientState* connect_ethernet =
      GetOrCreateConnectEthernetClientState(encapsulated_ethernet_session);
  if (connect_ethernet == nullptr) {
    QUIC_DLOG(ERROR) << "Failed to create CONNECT-ETHERNET request";
    return;
  }

  std::string http_payload;
  http_payload.resize(
      QuicDataWriter::GetVarInt62Len(kConnectEthernetPayloadContextId) +
      frame.size());
  QuicDataWriter writer(http_payload.size(), http_payload.data());
  if (!writer.WriteVarInt62(kConnectEthernetPayloadContextId)) {
    QUIC_BUG(IP context write fail)
        << "Failed to write CONNECT-ETHERNET context ID";
    return;
  }
  if (!writer.WriteStringPiece(frame)) {
    QUIC_BUG(IP packet write fail) << "Failed to write CONNECT-ETHERNET frame";
    return;
  }
  DatagramStatus message_status =
      SendHttp3Datagram(connect_ethernet->stream()->id(), http_payload);

  QUIC_DVLOG(1) << "Sent encapsulated Ethernet frame of length " << frame.size()
                << " with stream ID " << connect_ethernet->stream()->id()
                << " and got message status "
                << DatagramStatusToString(message_status);
}

void MasqueClientSession::SendConnectUdpBindPacket(
    absl::string_view packet, const QuicSocketAddress& target_server_address,
    EncapsulatedClientSession* encapsulated_client_session) {
  QUICHE_DCHECK(masque_mode_ == MasqueMode::kConnectUdpBind);
  ConnectUdpClientState* connect_udp = GetOrCreateConnectUdpClientState(
      QuicSocketAddress(), encapsulated_client_session);
  std::optional<std::string> bind_packet = connect_udp->PrepareBindPacket(
      packet, target_server_address, bind_use_uncompressed_context_);
  if (!bind_packet.has_value()) {
    QUIC_DLOG(ERROR) << "Failed to prepare bind packet";
    return;
  }
  QUIC_DVLOG(1) << "Sending bind packet: " << bind_packet.value()
                << " of length " << bind_packet.value().length() << " to "
                << target_server_address;

  SendHttp3Datagram(connect_udp->stream()->id(), bind_packet.value());
}

void MasqueClientSession::SendPacket(
    absl::string_view packet, const QuicSocketAddress& target_server_address,
    EncapsulatedClientSession* encapsulated_client_session) {
  const ConnectUdpClientState* connect_udp = GetOrCreateConnectUdpClientState(
      target_server_address, encapsulated_client_session);
  if (connect_udp == nullptr) {
    QUIC_DLOG(ERROR) << "Failed to create CONNECT-UDP request";
    return;
  }
  if (masque_mode_ == MasqueMode::kConnectUdpBind) {
    QUIC_LOG(ERROR) << "Should not be called in CONNECT-UDP Bind mode";
    return;
  }

  std::string http_payload;
  http_payload.resize(1 + packet.size());
  http_payload[0] = 0;
  memcpy(&http_payload[1], packet.data(), packet.size());
  DatagramStatus message_status =
      SendHttp3Datagram(connect_udp->stream()->id(), http_payload);

  QUIC_DVLOG(1) << "Sent packet to " << target_server_address
                << " compressed with stream ID " << connect_udp->stream()->id()
                << " and got message status "
                << DatagramStatusToString(message_status);
  QUIC_DVLOG(2) << "Contents of outgoing HTTP Datagram of length "
                << http_payload.size() << ":" << std::endl
                << quiche::QuicheTextUtils::HexDump(http_payload);
}

// Send Capsule for CONNECT-UDP Bind.
void MasqueClientSession::SendBindCapsule(
    const quiche::Capsule& capsule,
    EncapsulatedClientSession* encapsulated_client_session) {
  for (auto& state : connect_udp_client_states_) {
    if (state.is_bind() &&
        state.encapsulated_client_session() == encapsulated_client_session) {
      state.stream()->WriteCapsule(capsule);
    }
  }
}

void MasqueClientSession::CloseConnectUdpStream(
    EncapsulatedClientSession* encapsulated_client_session) {
  for (auto it = connect_udp_client_states_.begin();
       it != connect_udp_client_states_.end();) {
    if (it->encapsulated_client_session() == encapsulated_client_session) {
      QUIC_DLOG(INFO) << "Removing CONNECT-UDP state for stream ID "
                      << it->stream()->id();
      auto* stream = it->stream();
      it = connect_udp_client_states_.erase(it);
      if (!stream->write_side_closed()) {
        stream->Reset(QUIC_STREAM_CANCELLED);
      }
    } else {
      ++it;
    }
  }
}

void MasqueClientSession::CloseConnectIpStream(
    EncapsulatedIpSession* encapsulated_ip_session) {
  for (auto it = connect_ip_client_states_.begin();
       it != connect_ip_client_states_.end();) {
    if (it->encapsulated_ip_session() == encapsulated_ip_session) {
      QUIC_DLOG(INFO) << "Removing CONNECT-IP state for stream ID "
                      << it->stream()->id();
      auto* stream = it->stream();
      it = connect_ip_client_states_.erase(it);
      if (!stream->write_side_closed()) {
        stream->Reset(QUIC_STREAM_CANCELLED);
      }
    } else {
      ++it;
    }
  }
}

void MasqueClientSession::CloseConnectEthernetStream(
    EncapsulatedEthernetSession* encapsulated_ethernet_session) {
  for (auto it = connect_ethernet_client_states_.begin();
       it != connect_ethernet_client_states_.end();) {
    if (it->encapsulated_ethernet_session() == encapsulated_ethernet_session) {
      QUIC_DLOG(INFO) << "Removing CONNECT-ETHERNET state for stream ID "
                      << it->stream()->id();
      auto* stream = it->stream();
      it = connect_ethernet_client_states_.erase(it);
      if (!stream->write_side_closed()) {
        stream->Reset(QUIC_STREAM_CANCELLED);
      }
    } else {
      ++it;
    }
  }
}

void MasqueClientSession::OnConnectionClosed(
    const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) {
  QuicSpdyClientSession::OnConnectionClosed(frame, source);
  // Close all encapsulated sessions.
  for (const auto& client_state : connect_udp_client_states_) {
    client_state.encapsulated_client_session()->CloseConnection(
        QUIC_CONNECTION_CANCELLED, "Underlying MASQUE connection was closed",
        ConnectionCloseBehavior::SILENT_CLOSE);
  }
  for (const auto& client_state : connect_ip_client_states_) {
    client_state.encapsulated_ip_session()->CloseIpSession(
        "Underlying MASQUE connection was closed");
  }
}

void MasqueClientSession::OnStreamClosed(QuicStreamId stream_id) {
  if (QuicUtils::IsBidirectionalStreamId(stream_id, version()) &&
      QuicUtils::IsClientInitiatedStreamId(transport_version(), stream_id)) {
    QuicSpdyClientStream* stream =
        reinterpret_cast<QuicSpdyClientStream*>(GetActiveStream(stream_id));
    if (stream != nullptr) {
      QUIC_DLOG(INFO) << "Stream " << stream_id
                      << " closed, got response headers:"
                      << stream->response_headers().DebugString();
    }
  }
  for (auto it = connect_udp_client_states_.begin();
       it != connect_udp_client_states_.end();) {
    if (it->stream()->id() == stream_id) {
      QUIC_DLOG(INFO) << "Stream " << stream_id
                      << " was closed, removing CONNECT-UDP state";
      auto* encapsulated_client_session = it->encapsulated_client_session();
      it = connect_udp_client_states_.erase(it);
      encapsulated_client_session->CloseConnection(
          QUIC_CONNECTION_CANCELLED,
          "Underlying MASQUE CONNECT-UDP stream was closed",
          ConnectionCloseBehavior::SILENT_CLOSE);
    } else {
      ++it;
    }
  }
  for (auto it = connect_ip_client_states_.begin();
       it != connect_ip_client_states_.end();) {
    if (it->stream()->id() == stream_id) {
      QUIC_DLOG(INFO) << "Stream " << stream_id
                      << " was closed, removing CONNECT-IP state";
      auto* encapsulated_ip_session = it->encapsulated_ip_session();
      it = connect_ip_client_states_.erase(it);
      encapsulated_ip_session->CloseIpSession(
          "Underlying MASQUE CONNECT-IP stream was closed");
    } else {
      ++it;
    }
  }

  QuicSpdyClientSession::OnStreamClosed(stream_id);
}

bool MasqueClientSession::OnSettingsFrame(const SettingsFrame& frame) {
  QUIC_DLOG(INFO) << connection_id() << " Received SETTINGS: " << frame;
  if (!QuicSpdyClientSession::OnSettingsFrame(frame)) {
    QUIC_DLOG(ERROR) << "Failed to parse received settings";
    return false;
  }
  if (!SupportsH3Datagram()) {
    QUIC_DLOG(ERROR) << "Warning: MasqueClientSession without HTTP/3 Datagrams";
  }
  QUIC_DLOG(INFO) << "Using HTTP Datagram: " << http_datagram_support();
  owner_->OnSettingsReceived();
  return true;
}

MasqueClientSession::ConnectUdpClientState::ConnectUdpClientState(
    QuicSpdyClientStream* stream,
    EncapsulatedClientSession* encapsulated_client_session,
    MasqueClientSession* masque_session,
    const QuicSocketAddress& target_server_address)
    : stream_(stream),
      encapsulated_client_session_(encapsulated_client_session),
      masque_session_(masque_session),
      target_server_address_(target_server_address) {
  QUICHE_DCHECK_NE(masque_session_, nullptr);
  this->stream()->RegisterHttp3DatagramVisitor(this);
  if (masque_session->IsBind()) {
    this->stream()->RegisterConnectUdpBindVisitor(this);
  }
}

MasqueClientSession::ConnectUdpClientState::~ConnectUdpClientState() {
  if (stream() != nullptr) {
    stream()->UnregisterHttp3DatagramVisitor();
    if (masque_session_->IsBind()) {
      this->stream()->UnregisterConnectUdpBindVisitor();
    }
  }
}

MasqueClientSession::ConnectUdpClientState::ConnectUdpClientState(
    MasqueClientSession::ConnectUdpClientState&& other) {
  *this = std::move(other);
}

MasqueClientSession::ConnectUdpClientState&
MasqueClientSession::ConnectUdpClientState::operator=(
    MasqueClientSession::ConnectUdpClientState&& other) {
  stream_ = other.stream_;
  encapsulated_client_session_ = other.encapsulated_client_session_;
  masque_session_ = other.masque_session_;
  target_server_address_ = other.target_server_address_;
  other.stream_ = nullptr;
  other.is_bind_ = is_bind_;
  other.bind_context_ip_map_ = std::move(bind_context_ip_map_);
  if (stream() != nullptr) {
    stream()->ReplaceHttp3DatagramVisitor(this);
    if (masque_session_->IsBind()) {
      stream()->ReplaceConnectUdpBindVisitor(this);
    }
  }
  return *this;
}

void MasqueClientSession::ConnectUdpClientState::OnHttp3Datagram(
    QuicStreamId stream_id, absl::string_view payload) {
  QUIC_DVLOG(1) << "Received HTTP Datagram of length " << payload.size();
  QUICHE_DCHECK_EQ(stream_id, stream()->id());
  QuicDataReader reader(payload);
  if (!is_bind_) {
    ContextId context_id;
    if (!reader.ReadVarInt62(&context_id)) {
      QUIC_DLOG(ERROR) << "Failed to read context ID";
      return;
    }
    if (context_id != 0) {
      QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID "
                       << context_id;
      return;
    }
  } else {
    ContextId context_id;
    QuicSocketAddress target_address;
    if (!reader.ReadVarInt62(&context_id)) {
      QUIC_DLOG(ERROR) << "Failed to read context ID";
      return;
    }
    if (!bind_context_ip_map_.contains(context_id)) {
      // Non existent context id.
      QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with non existent context id "
                       << context_id;
      // Drop the packet.
      return;
    }
    if (bind_context_ip_map_[context_id] == quiche::QuicheSocketAddress()) {
      // Uncompressed Context.
      // Parse IP and port.
      uint8_t ip_version;
      if (!reader.ReadUInt8(&ip_version)) {
        QUIC_DLOG(ERROR) << "Failed to read IP version";
        return;
      }
      auto address_size = ip_version == 4
                              ? quiche::QuicheIpAddress::kIPv4AddressSize
                              : quiche::QuicheIpAddress::kIPv6AddressSize;
      absl::string_view ip_address_bytes;
      if (!reader.ReadStringPiece(&ip_address_bytes, address_size)) {
        QUIC_DLOG(ERROR) << "Failed to read IP address";
        return;
      }
      quiche::QuicheIpAddress ip_address;
      if (!ip_address.FromPackedString(ip_address_bytes.data(), address_size)) {
        QUIC_DLOG(ERROR) << "Failed to parse IP address";
        return;
      }
      uint16_t port;
      if (!reader.ReadUInt16(&port)) {
        QUIC_DLOG(ERROR) << "Failed to read port";
        return;
      }
      target_address = QuicSocketAddress(ip_address, port);
    } else {
      target_address = bind_context_ip_map_[context_id];
    }
  }

  absl::string_view http_payload = reader.ReadRemainingPayload();
  encapsulated_client_session_->ProcessPacket(http_payload,
                                              target_server_address_);
  QUIC_DVLOG(1) << "Sent " << http_payload.size()
                << " bytes to connection for stream ID " << stream_id;
}

ContextId MasqueClientSession::ConnectUdpClientState::CreateCompressedContext(
    const QuicSocketAddress& target_address) {
  bind_context_ip_map_[next_available_context_id_] = target_address;
  quiche::Capsule capsule = quiche::Capsule::CompressionAssign();
  capsule.compression_assign_capsule().context_id = next_available_context_id_;
  capsule.compression_assign_capsule().ip_address_port = target_address;

  masque_session_->SendBindCapsule(capsule, encapsulated_client_session_);
  // TODO(abhisinghx): Verify Acks Before using it
  return AllocateContextId();
}

ContextId
MasqueClientSession::ConnectUdpClientState::CreateUncompressedContext() {
  bind_context_ip_map_[next_available_context_id_] =
      quiche::QuicheSocketAddress();
  quiche::Capsule capsule = quiche::Capsule::CompressionAssign();
  capsule.compression_assign_capsule().context_id = next_available_context_id_;
  capsule.compression_assign_capsule().ip_address_port =
      quiche::QuicheSocketAddress();
  QUIC_DLOG(INFO) << "Requesting open context " << next_available_context_id_;
  masque_session_->SendBindCapsule(capsule, encapsulated_client_session_);
  // TODO(abhisinghx): Verify capsule ack before using it.
  // It is fine to pre-emptively send UDP packets.
  return AllocateContextId();
}

ContextId MasqueClientSession::ConnectUdpClientState::AllocateContextId() {
  next_available_context_id_ += 2;
  return next_available_context_id_ - 2;
}

void MasqueClientSession::ConnectUdpClientState::CloseContext(
    ContextId context_id) {
  bind_context_ip_map_.erase(context_id);
  quiche::Capsule capsule = quiche::Capsule::CompressionClose();
  capsule.compression_close_capsule().context_id = context_id;
  QUIC_DLOG(INFO) << "Closing context " << context_id;
  masque_session_->SendBindCapsule(capsule, encapsulated_client_session_);
}

bool MasqueClientSession::ConnectUdpClientState::OnCompressionAssignCapsule(
    const quiche::CompressionAssignCapsule& capsule) {
  if (!is_bind_) {
    QUIC_DLOG(ERROR) << "Received CompressionAssignCapsule "
                     << capsule.ToString() << " when bind is not set";
    return false;
  }
  QUIC_DLOG(INFO) << "CompressionAssignCapsule received: "
                  << capsule.ToString();
  if (!bind_context_ip_map_.contains(capsule.context_id)) {
    // Server is asking to create a new context.
    if (capsule.ip_address_port == quiche::QuicheSocketAddress()) {
      // Server is not allowed to create open context.
      QUIC_DLOG(ERROR) << "Server is not allowed to create open context";
      return false;
    } else {
      // Compressed context requested by server.
      if (capsule.context_id % 2 == 0) {
        // Even contexts are client-allocated.
        QUIC_DLOG(ERROR) << "Server is not allowed to create even contexts";
        return false;
      }
      bind_context_ip_map_[capsule.context_id] = capsule.ip_address_port;
      // Send acknowledgement.

      quiche::Capsule to_send = quiche::Capsule::CompressionAssign();
      to_send.compression_assign_capsule() = capsule;
      masque_session_->SendBindCapsule(to_send, encapsulated_client_session_);
      return true;
    }
  } else if (bind_context_ip_map_[capsule.context_id] !=
             capsule.ip_address_port) {
    // Context already exists but the target address is different.
    QUIC_DLOG(ERROR) << "Context already exists with different target address "
                     << bind_context_ip_map_[capsule.context_id] << " and "
                     << capsule.ip_address_port;
    return false;
  } else {
    // This is an ack of client's request, ignore it.
    QUIC_DLOG(INFO) << "Ignoring ack of client's request";
    return true;
  }
}

bool MasqueClientSession::ConnectUdpClientState::OnCompressionCloseCapsule(
    const quiche::CompressionCloseCapsule& capsule) {
  if (!is_bind_) {
    QUIC_DLOG(ERROR) << "Received CompressionCloseCapsule "
                     << capsule.ToString() << " when bind is not set";
    return false;
  }
  QUIC_DLOG(INFO) << "CompressionCloseCapsule received: " << capsule.ToString();
  // If we have this context id in the map, we can close it and send ack.
  if (bind_context_ip_map_.contains(capsule.context_id)) {
    CloseContext(capsule.context_id);
  }
  return true;
}

std::optional<ContextId>
MasqueClientSession::ConnectUdpClientState::GetContextForAddress(
    const QuicSocketAddress& target_server_address) {
  std::optional<ContextId> uncompressed_context_id;
  for (const auto& [context_id, address] : bind_context_ip_map_) {
    if (address == target_server_address) {
      return context_id;
    }
    if (address == quiche::QuicheSocketAddress()) {
      uncompressed_context_id = context_id;
    }
  }
  return uncompressed_context_id;
}

std::optional<std::string>
MasqueClientSession::ConnectUdpClientState::PrepareBindPacket(
    absl::string_view packet, const QuicSocketAddress& target_address,
    bool use_uncompressed_context) {
  std::string payload_out;
  // Find existing or open context for this address.
  std::optional<ContextId> context_id_opt =
      GetContextForAddress(target_address);
  ContextId context_id;
  if (!context_id_opt.has_value()) {
    // No context exists for this address, create a new compressed context.
    context_id = use_uncompressed_context
                     ? CreateUncompressedContext()
                     : CreateCompressedContext(target_address);
  } else {
    context_id = context_id_opt.value();
  }
  size_t total_size =
      quiche::QuicheDataWriter::GetVarInt62Len(context_id) + packet.size();
  if (bind_context_ip_map_[context_id] == target_address) {
    // No need to append target info, compress it.
    payload_out.resize(total_size);
    QuicDataWriter writer(total_size, payload_out.data());
    if (!writer.WriteVarInt62(context_id)) {
      QUIC_DLOG(ERROR) << "Failed to write compressed bind packet context id "
                       << context_id;
      return std::nullopt;
    }
    if (!writer.WriteStringPiece(packet)) {
      QUIC_DLOG(ERROR)
          << "Failed to write compressed bind packet payload for context id "
          << context_id;
      return std::nullopt;
    }
  } else {
    // Append target info.
    total_size += (sizeof(uint8_t)  // Ip version.
                   + target_address.host().ToPackedString().size()  // Ip addr.
                   + sizeof(uint16_t));                             // Port.
    payload_out.resize(total_size);
    QuicDataWriter writer(total_size, payload_out.data());
    if (!writer.WriteVarInt62(context_id) ||
        !writer.WriteUInt8(
            target_address.host().AddressFamilyToInt() == AF_INET ? 4 : 6) ||
        !writer.WriteStringPiece(target_address.host().ToPackedString()) ||
        !writer.WriteUInt16(target_address.port()) ||
        !writer.WriteStringPiece(packet)) {
      QUIC_DLOG(ERROR)
          << "Failed to write uncompressed bind packet for context id "
          << context_id;
      return std::nullopt;
    }
  }
  return payload_out;
}

MasqueClientSession::ConnectIpClientState::ConnectIpClientState(
    QuicSpdyClientStream* stream,
    EncapsulatedIpSession* encapsulated_ip_session,
    MasqueClientSession* masque_session)
    : stream_(stream),
      encapsulated_ip_session_(encapsulated_ip_session),
      masque_session_(masque_session) {
  QUICHE_DCHECK_NE(masque_session_, nullptr);
  this->stream()->RegisterHttp3DatagramVisitor(this);
  this->stream()->RegisterConnectIpVisitor(this);
}

MasqueClientSession::ConnectIpClientState::~ConnectIpClientState() {
  if (stream() != nullptr) {
    stream()->UnregisterHttp3DatagramVisitor();
    stream()->UnregisterConnectIpVisitor();
  }
}

MasqueClientSession::ConnectIpClientState::ConnectIpClientState(
    MasqueClientSession::ConnectIpClientState&& other) {
  *this = std::move(other);
}

MasqueClientSession::ConnectIpClientState&
MasqueClientSession::ConnectIpClientState::operator=(
    MasqueClientSession::ConnectIpClientState&& other) {
  stream_ = other.stream_;
  encapsulated_ip_session_ = other.encapsulated_ip_session_;
  masque_session_ = other.masque_session_;
  other.stream_ = nullptr;
  if (stream() != nullptr) {
    stream()->ReplaceHttp3DatagramVisitor(this);
    stream()->ReplaceConnectIpVisitor(this);
  }
  return *this;
}

void MasqueClientSession::ConnectIpClientState::OnHttp3Datagram(
    QuicStreamId stream_id, absl::string_view payload) {
  QUICHE_DCHECK_EQ(stream_id, stream()->id());
  QuicDataReader reader(payload);
  ContextId context_id;
  if (!reader.ReadVarInt62(&context_id)) {
    QUIC_DLOG(ERROR) << "Failed to read context ID";
    return;
  }
  if (context_id != kConnectIpPayloadContextId) {
    QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID "
                     << context_id;
    return;
  }
  absl::string_view http_payload = reader.ReadRemainingPayload();
  encapsulated_ip_session_->ProcessIpPacket(http_payload);
  QUIC_DVLOG(1) << "Sent " << http_payload.size()
                << " IP bytes to connection for stream ID " << stream_id;
}

void MasqueClientSession::ConnectIpClientState::OnUnknownCapsule(
    QuicStreamId /*stream_id*/, const quiche::UnknownCapsule& capsule) {
  if (capsule.type == kDnsAssignCapsuleType) {
    DnsAssignCapsule dns_assign_capsule;
    if (ParseDnsAssignCapsulePayload(capsule.payload, &dns_assign_capsule)) {
      encapsulated_ip_session_->OnDnsAssignCapsule(dns_assign_capsule);
    } else {
      QUIC_LOG(ERROR) << "Failed to parse DNS_ASSIGN capsule";
    }
  } else if (capsule.type == kPref64CapsuleType) {
    Pref64Capsule pref64_capsule;
    if (ParsePref64CapsulePayload(capsule.payload, &pref64_capsule)) {
      encapsulated_ip_session_->OnPref64Capsule(pref64_capsule);
    } else {
      QUIC_LOG(ERROR) << "Failed to parse PREF64 capsule";
    }
  }
}

bool MasqueClientSession::ConnectIpClientState::OnAddressAssignCapsule(
    const AddressAssignCapsule& capsule) {
  return encapsulated_ip_session_->OnAddressAssignCapsule(capsule);
}

bool MasqueClientSession::ConnectIpClientState::OnAddressRequestCapsule(
    const AddressRequestCapsule& capsule) {
  return encapsulated_ip_session_->OnAddressRequestCapsule(capsule);
}

bool MasqueClientSession::ConnectIpClientState::OnRouteAdvertisementCapsule(
    const RouteAdvertisementCapsule& capsule) {
  return encapsulated_ip_session_->OnRouteAdvertisementCapsule(capsule);
}

void MasqueClientSession::ConnectIpClientState::OnHeadersWritten() {}

// ConnectEthernetClientState

MasqueClientSession::ConnectEthernetClientState::ConnectEthernetClientState(
    QuicSpdyClientStream* stream,
    EncapsulatedEthernetSession* encapsulated_ethernet_session,
    MasqueClientSession* masque_session)
    : stream_(stream),
      encapsulated_ethernet_session_(encapsulated_ethernet_session),
      masque_session_(masque_session) {
  QUICHE_DCHECK_NE(masque_session_, nullptr);
  this->stream()->RegisterHttp3DatagramVisitor(this);
}

MasqueClientSession::ConnectEthernetClientState::~ConnectEthernetClientState() {
  if (stream() != nullptr) {
    stream()->UnregisterHttp3DatagramVisitor();
  }
}

MasqueClientSession::ConnectEthernetClientState::ConnectEthernetClientState(
    MasqueClientSession::ConnectEthernetClientState&& other) {
  *this = std::move(other);
}

MasqueClientSession::ConnectEthernetClientState&
MasqueClientSession::ConnectEthernetClientState::operator=(
    MasqueClientSession::ConnectEthernetClientState&& other) {
  stream_ = other.stream_;
  encapsulated_ethernet_session_ = other.encapsulated_ethernet_session_;
  masque_session_ = other.masque_session_;
  other.stream_ = nullptr;
  if (stream() != nullptr) {
    stream()->ReplaceHttp3DatagramVisitor(this);
  }
  return *this;
}

void MasqueClientSession::ConnectEthernetClientState::OnHttp3Datagram(
    QuicStreamId stream_id, absl::string_view payload) {
  QUICHE_DCHECK_EQ(stream_id, stream()->id());
  QuicDataReader reader(payload);
  ContextId context_id;
  if (!reader.ReadVarInt62(&context_id)) {
    QUIC_DLOG(ERROR) << "Failed to read context ID";
    return;
  }
  if (context_id != kConnectEthernetPayloadContextId) {
    QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID "
                     << context_id;
    return;
  }
  absl::string_view http_payload = reader.ReadRemainingPayload();
  encapsulated_ethernet_session_->ProcessEthernetFrame(http_payload);
  QUIC_DVLOG(1) << "Sent " << http_payload.size()
                << " ETHERNET bytes to connection for stream ID " << stream_id;
}

// End ConnectEthernetClientState

quiche::QuicheIpAddress MasqueClientSession::GetFakeAddress(
    absl::string_view hostname) {
  QUICHE_CHECK(!hostname.empty());
  quiche::QuicheIpAddress address;
  uint8_t address_bytes[16] = {0xFD};
  quiche::QuicheRandom::GetInstance()->RandBytes(&address_bytes[1],
                                                 sizeof(address_bytes) - 1);
  address.FromPackedString(reinterpret_cast<const char*>(address_bytes),
                           sizeof(address_bytes));
  std::string address_bytes_string(reinterpret_cast<const char*>(address_bytes),
                                   sizeof(address_bytes));
  fake_addresses_[address_bytes_string] = std::string(hostname);
  return address;
}

void MasqueClientSession::RemoveFakeAddress(
    const quiche::QuicheIpAddress& fake_address) {
  fake_addresses_.erase(fake_address.ToPackedString());
}

void MasqueClientSession::EnableConcealedAuth(absl::string_view key_id,
                                              absl::string_view private_key,
                                              absl::string_view public_key) {
  QUICHE_CHECK(!key_id.empty());
  QUICHE_CHECK_EQ(private_key.size(),
                  static_cast<size_t>(ED25519_PRIVATE_KEY_LEN));
  QUICHE_CHECK_EQ(public_key.size(),
                  static_cast<size_t>(ED25519_PUBLIC_KEY_LEN));
  concealed_auth_key_id_ = key_id;
  concealed_auth_private_key_ = private_key;
  concealed_auth_public_key_ = public_key;
}

QuicSpdyClientStream* MasqueClientSession::SendGetRequest(
    absl::string_view path) {
  QuicSpdyClientStream* stream = CreateOutgoingBidirectionalStream();
  if (stream == nullptr) {
    // Stream flow control limits prevented us from opening a new stream.
    QUIC_DLOG(ERROR) << "Failed to open GET stream";
    return nullptr;
  }

  QuicUrl url(uri_template_);
  std::string scheme = url.scheme();
  std::string authority = url.HostPort();

  QUIC_DLOG(INFO) << "Sending GET request on stream " << stream->id()
                  << " scheme=\"" << scheme << "\" authority=\"" << authority
                  << "\" path=\"" << path << "\"";

  // Send the request.
  quiche::HttpHeaderBlock headers;
  headers[":method"] = "GET";
  headers[":scheme"] = scheme;
  headers[":authority"] = authority;
  headers[":path"] = path;
  AddAdditionalHeaders(headers, url);
  QUIC_DVLOG(1) << "Sending request headers: " << headers.DebugString();
  // Setting the stream visitor is required to enable reading of the response
  // body from the stream.
  stream->set_visitor(this);
  size_t bytes_sent =
      stream->SendRequest(std::move(headers), /*body=*/"", /*fin=*/true);
  if (bytes_sent == 0) {
    QUIC_DLOG(ERROR) << "Failed to send GET request";
    return nullptr;
  }
  return stream;
}

void MasqueClientSession::OnClose(QuicSpdyStream* stream) {
  QUIC_DVLOG(1) << "Closing stream " << stream->id();
}

std::optional<std::string> MasqueClientSession::ComputeConcealedAuthHeader(
    const QuicUrl& url) {
  if (concealed_auth_private_key_.empty()) {
    return std::nullopt;
  }
  std::string scheme = url.scheme();
  std::string host = url.host();
  uint16_t port = url.port();
  std::string realm = "";
  std::string key_exporter_output;
  std::string key_exporter_context = ComputeConcealedAuthContext(
      kEd25519SignatureScheme, concealed_auth_key_id_,
      concealed_auth_public_key_, scheme, host, port, realm);
  QUIC_DVLOG(1) << "key_exporter_context: "
                << absl::WebSafeBase64Escape(key_exporter_context);
  QUICHE_DCHECK(!key_exporter_context.empty());
  if (!GetMutableCryptoStream()->ExportKeyingMaterial(
          kConcealedAuthLabel, key_exporter_context, kConcealedAuthExporterSize,
          &key_exporter_output)) {
    QUIC_LOG(FATAL) << "Concealed auth TLS exporter failed";
    return std::nullopt;
  }
  QUICHE_CHECK_EQ(key_exporter_output.size(), kConcealedAuthExporterSize);
  std::string signature_input =
      key_exporter_output.substr(0, kConcealedAuthSignatureInputSize);
  QUIC_DVLOG(1) << "signature_input: "
                << absl::WebSafeBase64Escape(signature_input);
  std::string verification = key_exporter_output.substr(
      kConcealedAuthSignatureInputSize, kConcealedAuthVerificationSize);
  std::string data_covered_by_signature =
      ConcealedAuthDataCoveredBySignature(signature_input);
  QUIC_DVLOG(1) << "data_covered_by_signature: "
                << absl::WebSafeBase64Escape(data_covered_by_signature);
  uint8_t signature[ED25519_SIGNATURE_LEN];
  if (ED25519_sign(
          signature,
          reinterpret_cast<const uint8_t*>(data_covered_by_signature.data()),
          data_covered_by_signature.size(),
          reinterpret_cast<const uint8_t*>(
              concealed_auth_private_key_.data())) != 1) {
    QUIC_LOG(FATAL) << "Concealed auth signature failed";
    return std::nullopt;
  }
  return absl::StrCat(
      "Concealed k=", absl::WebSafeBase64Escape(concealed_auth_key_id_),
      ", a=", absl::WebSafeBase64Escape(concealed_auth_public_key_), ", p=",
      absl::WebSafeBase64Escape(absl::string_view(
          reinterpret_cast<const char*>(signature), sizeof(signature))),
      ", s=", kEd25519SignatureScheme,
      ", v=", absl::WebSafeBase64Escape(verification));
}

void MasqueClientSession::AddAdditionalHeaders(quiche::HttpHeaderBlock& headers,
                                               const QuicUrl& url) {
  std::optional<std::string> concealed_auth_header =
      ComputeConcealedAuthHeader(url);
  if (concealed_auth_header.has_value()) {
    headers["authorization"] = *concealed_auth_header;
  }
  if (additional_headers_.empty()) {
    return;
  }
  for (absl::string_view sp : absl::StrSplit(additional_headers_, ';')) {
    quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&sp);
    if (sp.empty()) {
      continue;
    }
    std::vector<absl::string_view> kv =
        absl::StrSplit(sp, absl::MaxSplits(':', 1));
    quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]);
    quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]);
    headers[kv[0]] = kv[1];
  }
}

}  // namespace quic
