// Copyright (c) 2015 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/core/http/quic_spdy_session.h"

#include <algorithm>
#include <cstdint>
#include <limits>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <utility>


#include "absl/base/attributes.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/http/http_constants.h"
#include "quiche/quic/core/http/http_decoder.h"
#include "quiche/quic/core/http/http_frames.h"
#include "quiche/quic/core/http/quic_headers_stream.h"
#include "quiche/quic/core/http/quic_spdy_stream.h"
#include "quiche/quic/core/http/web_transport_http3.h"
#include "quiche/quic/core/quic_error_codes.h"
#include "quiche/quic/core/quic_session.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/platform/api/quic_bug_tracker.h"
#include "quiche/quic/platform/api/quic_exported_stats.h"
#include "quiche/quic/platform/api/quic_flag_utils.h"
#include "quiche/quic/platform/api/quic_flags.h"
#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/platform/api/quic_stack_trace.h"
#include "quiche/common/platform/api/quiche_mem_slice.h"
#include "quiche/spdy/core/http2_frame_decoder_adapter.h"

using http2::Http2DecoderAdapter;
using quiche::HttpHeaderBlock;
using spdy::Http2WeightToSpdy3Priority;
using spdy::Spdy3PriorityToHttp2Weight;
using spdy::SpdyErrorCode;
using spdy::SpdyFramer;
using spdy::SpdyFramerDebugVisitorInterface;
using spdy::SpdyFramerVisitorInterface;
using spdy::SpdyFrameType;
using spdy::SpdyHeadersHandlerInterface;
using spdy::SpdyHeadersIR;
using spdy::SpdyPingId;
using spdy::SpdyPriority;
using spdy::SpdyPriorityIR;
using spdy::SpdySerializedFrame;
using spdy::SpdySettingsId;
using spdy::SpdyStreamId;

namespace quic {

ABSL_CONST_INIT const size_t kMaxUnassociatedWebTransportStreams = 24;

namespace {

// Limit on HPACK encoder dynamic table size.
// Only used for Google QUIC, not IETF QUIC.
constexpr uint64_t kHpackEncoderDynamicTableSizeLimit = 16384;

constexpr QuicStreamCount kDefaultMaxWebTransportSessions = 16;

#define ENDPOINT \
  (perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")

// Class to forward ACCEPT_CH frame to QuicSpdySession,
// and ignore every other frame.
class AlpsFrameDecoder : public HttpDecoder::Visitor {
 public:
  explicit AlpsFrameDecoder(QuicSpdySession* session) : session_(session) {}
  ~AlpsFrameDecoder() override = default;

  // HttpDecoder::Visitor implementation.
  void OnError(HttpDecoder* /*decoder*/) override {}
  bool OnMaxPushIdFrame() override {
    error_detail_ = "MAX_PUSH_ID frame forbidden";
    return false;
  }
  bool OnGoAwayFrame(const GoAwayFrame& /*frame*/) override {
    error_detail_ = "GOAWAY frame forbidden";
    return false;
  }
  bool OnSettingsFrameStart(QuicByteCount /*header_length*/) override {
    return true;
  }
  bool OnSettingsFrame(const SettingsFrame& frame) override {
    if (settings_frame_received_via_alps_) {
      error_detail_ = "multiple SETTINGS frames";
      return false;
    }

    settings_frame_received_via_alps_ = true;

    error_detail_ = session_->OnSettingsFrameViaAlps(frame);
    return !error_detail_;
  }
  bool OnDataFrameStart(QuicByteCount /*header_length*/, QuicByteCount
                        /*payload_length*/) override {
    error_detail_ = "DATA frame forbidden";
    return false;
  }
  bool OnDataFramePayload(absl::string_view /*payload*/) override {
    QUICHE_NOTREACHED();
    return false;
  }
  bool OnDataFrameEnd() override {
    QUICHE_NOTREACHED();
    return false;
  }
  bool OnHeadersFrameStart(QuicByteCount /*header_length*/,
                           QuicByteCount /*payload_length*/) override {
    error_detail_ = "HEADERS frame forbidden";
    return false;
  }
  bool OnHeadersFramePayload(absl::string_view /*payload*/) override {
    QUICHE_NOTREACHED();
    return false;
  }
  bool OnHeadersFrameEnd() override {
    QUICHE_NOTREACHED();
    return false;
  }
  bool OnPriorityUpdateFrameStart(QuicByteCount /*header_length*/) override {
    error_detail_ = "PRIORITY_UPDATE frame forbidden";
    return false;
  }
  bool OnPriorityUpdateFrame(const PriorityUpdateFrame& /*frame*/) override {
    QUICHE_NOTREACHED();
    return false;
  }
  bool OnAcceptChFrameStart(QuicByteCount /*header_length*/) override {
    return true;
  }
  bool OnAcceptChFrame(const AcceptChFrame& frame) override {
    session_->OnAcceptChFrameReceivedViaAlps(frame);
    return true;
  }
  bool OnOriginFrameStart(QuicByteCount /*header_length*/) override {
    QUICHE_NOTREACHED();
    return true;
  }
  bool OnOriginFrame(const OriginFrame& /*frame*/) override { return true; }
  void OnWebTransportStreamFrameType(
      QuicByteCount /*header_length*/,
      WebTransportSessionId /*session_id*/) override {
    QUICHE_NOTREACHED();
  }
  bool OnMetadataFrameStart(QuicByteCount /*header_length*/,
                            QuicByteCount /*payload_length*/) override {
    error_detail_ = "METADATA frame forbidden";
    return false;
  }
  bool OnMetadataFramePayload(absl::string_view /*payload*/) override {
    QUICHE_NOTREACHED();
    return false;
  }
  bool OnMetadataFrameEnd() override {
    QUICHE_NOTREACHED();
    return false;
  }
  bool OnUnknownFrameStart(uint64_t /*frame_type*/,
                           QuicByteCount
                           /*header_length*/,
                           QuicByteCount /*payload_length*/) override {
    return true;
  }
  bool OnUnknownFramePayload(absl::string_view /*payload*/) override {
    return true;
  }
  bool OnUnknownFrameEnd() override { return true; }

  const std::optional<std::string>& error_detail() const {
    return error_detail_;
  }

 private:
  QuicSpdySession* const session_;
  std::optional<std::string> error_detail_;

  // True if SETTINGS frame has been received via ALPS.
  bool settings_frame_received_via_alps_ = false;
};

uint64_t GetDefaultQpackMaximumDynamicTableCapacity(Perspective perspective) {
  if (perspective == Perspective::IS_SERVER &&
      GetQuicFlag(quic_server_disable_qpack_dynamic_table)) {
    return 0;
  }

  return kDefaultQpackMaxDynamicTableCapacity;
}

// This class is only used in gQUIC.
class SizeLimitingHeaderList : public spdy::SpdyHeadersHandlerInterface {
 public:
  ~SizeLimitingHeaderList() override = default;

  void OnHeaderBlockStart() override {
    QUIC_BUG_IF(quic_bug_12518_1, current_header_list_size_ != 0)
        << "OnHeaderBlockStart called more than once!";
  }

  void OnHeader(absl::string_view name, absl::string_view value) override {
    if (current_header_list_size_ < max_header_list_size_) {
      current_header_list_size_ += name.size();
      current_header_list_size_ += value.size();
      current_header_list_size_ += kQpackEntrySizeOverhead;
      header_list_.OnHeader(name, value);
    }
  }

  void OnHeaderBlockEnd(size_t uncompressed_header_bytes,
                        size_t compressed_header_bytes) override {
    header_list_.OnHeaderBlockEnd(uncompressed_header_bytes,
                                  compressed_header_bytes);
    if (current_header_list_size_ > max_header_list_size_) {
      Clear();
    }
  }

  void set_max_header_list_size(size_t max_header_list_size) {
    max_header_list_size_ = max_header_list_size;
  }

  void Clear() {
    header_list_.Clear();
    current_header_list_size_ = 0;
  }

  const QuicHeaderList& header_list() const { return header_list_; }

 private:
  QuicHeaderList header_list_;

  // The limit on the size of the header list (defined by spec as name + value +
  // overhead for each header field). Headers over this limit will not be
  // buffered, and the list will be cleared upon OnHeaderBlockEnd().
  size_t max_header_list_size_ = std::numeric_limits<size_t>::max();

  // The total size of headers so far, including overhead.
  size_t current_header_list_size_ = 0;
};

}  // namespace

// A SpdyFramerVisitor that passes HEADERS frames to the QuicSpdyStream, and
// closes the connection if any unexpected frames are received.
// This class is only used in gQUIC.
class QuicSpdySession::SpdyFramerVisitor
    : public SpdyFramerVisitorInterface,
      public SpdyFramerDebugVisitorInterface {
 public:
  explicit SpdyFramerVisitor(QuicSpdySession* session) : session_(session) {}
  SpdyFramerVisitor(const SpdyFramerVisitor&) = delete;
  SpdyFramerVisitor& operator=(const SpdyFramerVisitor&) = delete;

  SpdyHeadersHandlerInterface* OnHeaderFrameStart(
      SpdyStreamId /* stream_id */) override {
    QUICHE_DCHECK(!VersionUsesHttp3(session_->transport_version()));
    return &header_list_;
  }

  void OnHeaderFrameEnd(SpdyStreamId /* stream_id */) override {
    QUICHE_DCHECK(!VersionUsesHttp3(session_->transport_version()));

    LogHeaderCompressionRatioHistogram(
        /* using_qpack = */ false,
        /* is_sent = */ false,
        header_list_.header_list().compressed_header_bytes(),
        header_list_.header_list().uncompressed_header_bytes());

    // Ignore pushed request headers.
    if (session_->IsConnected() && !expecting_pushed_headers_) {
      session_->OnHeaderList(header_list_.header_list());
    }
    expecting_pushed_headers_ = false;
    header_list_.Clear();
  }

  void OnStreamFrameData(SpdyStreamId /*stream_id*/, const char* /*data*/,
                         size_t /*len*/) override {
    QUICHE_DCHECK(!VersionUsesHttp3(session_->transport_version()));
    CloseConnection("SPDY DATA frame received.",
                    QUIC_INVALID_HEADERS_STREAM_DATA);
  }

  void OnStreamEnd(SpdyStreamId /*stream_id*/) override {
    // The framer invokes OnStreamEnd after processing a frame that had the fin
    // bit set.
  }

  void OnStreamPadding(SpdyStreamId /*stream_id*/, size_t /*len*/) override {
    CloseConnection("SPDY frame padding received.",
                    QUIC_INVALID_HEADERS_STREAM_DATA);
  }

  void OnError(Http2DecoderAdapter::SpdyFramerError error,
               std::string detailed_error) override {
    QuicErrorCode code;
    switch (error) {
      case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_INDEX_VARINT_ERROR:
        code = QUIC_HPACK_INDEX_VARINT_ERROR;
        break;
      case Http2DecoderAdapter::SpdyFramerError::
          SPDY_HPACK_NAME_LENGTH_VARINT_ERROR:
        code = QUIC_HPACK_NAME_LENGTH_VARINT_ERROR;
        break;
      case Http2DecoderAdapter::SpdyFramerError::
          SPDY_HPACK_VALUE_LENGTH_VARINT_ERROR:
        code = QUIC_HPACK_VALUE_LENGTH_VARINT_ERROR;
        break;
      case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_NAME_TOO_LONG:
        code = QUIC_HPACK_NAME_TOO_LONG;
        break;
      case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_VALUE_TOO_LONG:
        code = QUIC_HPACK_VALUE_TOO_LONG;
        break;
      case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_NAME_HUFFMAN_ERROR:
        code = QUIC_HPACK_NAME_HUFFMAN_ERROR;
        break;
      case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_VALUE_HUFFMAN_ERROR:
        code = QUIC_HPACK_VALUE_HUFFMAN_ERROR;
        break;
      case Http2DecoderAdapter::SpdyFramerError::
          SPDY_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE:
        code = QUIC_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE;
        break;
      case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_INVALID_INDEX:
        code = QUIC_HPACK_INVALID_INDEX;
        break;
      case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_INVALID_NAME_INDEX:
        code = QUIC_HPACK_INVALID_NAME_INDEX;
        break;
      case Http2DecoderAdapter::SpdyFramerError::
          SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED:
        code = QUIC_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED;
        break;
      case Http2DecoderAdapter::SpdyFramerError::
          SPDY_HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK:
        code = QUIC_HPACK_INITIAL_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK;
        break;
      case Http2DecoderAdapter::SpdyFramerError::
          SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING:
        code = QUIC_HPACK_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING;
        break;
      case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_TRUNCATED_BLOCK:
        code = QUIC_HPACK_TRUNCATED_BLOCK;
        break;
      case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_FRAGMENT_TOO_LONG:
        code = QUIC_HPACK_FRAGMENT_TOO_LONG;
        break;
      case Http2DecoderAdapter::SpdyFramerError::
          SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT:
        code = QUIC_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT;
        break;
      case Http2DecoderAdapter::SpdyFramerError::SPDY_DECOMPRESS_FAILURE:
        code = QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE;
        break;
      default:
        code = QUIC_INVALID_HEADERS_STREAM_DATA;
    }
    CloseConnection(
        absl::StrCat("SPDY framing error: ", detailed_error,
                     Http2DecoderAdapter::SpdyFramerErrorToString(error)),
        code);
  }

  void OnDataFrameHeader(SpdyStreamId /*stream_id*/, size_t /*length*/,
                         bool /*fin*/) override {
    QUICHE_DCHECK(!VersionUsesHttp3(session_->transport_version()));
    CloseConnection("SPDY DATA frame received.",
                    QUIC_INVALID_HEADERS_STREAM_DATA);
  }

  void OnRstStream(SpdyStreamId /*stream_id*/,
                   SpdyErrorCode /*error_code*/) override {
    CloseConnection("SPDY RST_STREAM frame received.",
                    QUIC_INVALID_HEADERS_STREAM_DATA);
  }

  void OnSetting(SpdySettingsId id, uint32_t value) override {
    QUICHE_DCHECK(!VersionUsesHttp3(session_->transport_version()));
    session_->OnSetting(id, value);
  }

  void OnSettingsEnd() override {
    QUICHE_DCHECK(!VersionUsesHttp3(session_->transport_version()));
  }

  void OnPing(SpdyPingId /*unique_id*/, bool /*is_ack*/) override {
    CloseConnection("SPDY PING frame received.",
                    QUIC_INVALID_HEADERS_STREAM_DATA);
  }

  void OnGoAway(SpdyStreamId /*last_accepted_stream_id*/,
                SpdyErrorCode /*error_code*/) override {
    CloseConnection("SPDY GOAWAY frame received.",
                    QUIC_INVALID_HEADERS_STREAM_DATA);
  }

  void OnHeaders(SpdyStreamId stream_id, size_t /*payload_length*/,
                 bool has_priority, int weight,
                 SpdyStreamId /*parent_stream_id*/, bool /*exclusive*/,
                 bool fin, bool /*end*/) override {
    if (!session_->IsConnected()) {
      return;
    }

    if (VersionUsesHttp3(session_->transport_version())) {
      CloseConnection("HEADERS frame not allowed on headers stream.",
                      QUIC_INVALID_HEADERS_STREAM_DATA);
      return;
    }

    QUIC_BUG_IF(quic_bug_12477_1,
                session_->destruction_indicator() != 123456789)
        << "QuicSpdyStream use after free. "
        << session_->destruction_indicator() << QuicStackTrace();

    SpdyPriority priority =
        has_priority ? Http2WeightToSpdy3Priority(weight) : 0;
    session_->OnHeaders(stream_id, has_priority,
                        spdy::SpdyStreamPrecedence(priority), fin);
  }

  void OnWindowUpdate(SpdyStreamId /*stream_id*/,
                      int /*delta_window_size*/) override {
    CloseConnection("SPDY WINDOW_UPDATE frame received.",
                    QUIC_INVALID_HEADERS_STREAM_DATA);
  }

  void OnPushPromise(SpdyStreamId /*stream_id*/,
                     SpdyStreamId promised_stream_id, bool /*end*/) override {
    QUICHE_DCHECK(!VersionUsesHttp3(session_->transport_version()));
    if (session_->perspective() != Perspective::IS_CLIENT) {
      // PUSH_PROMISE sent by a client is a protocol violation.
      CloseConnection("PUSH_PROMISE not supported.",
                      QUIC_INVALID_HEADERS_STREAM_DATA);
      return;
    }

    // Push streams are ignored anyway, reset the stream to save bandwidth.
    session_->MaybeSendRstStreamFrame(
        promised_stream_id,
        QuicResetStreamError::FromInternal(QUIC_REFUSED_STREAM),
        /* bytes_written = */ 0);

    QUICHE_DCHECK(!expecting_pushed_headers_);
    expecting_pushed_headers_ = true;
  }

  void OnContinuation(SpdyStreamId /*stream_id*/, size_t /*payload_size*/,
                      bool /*end*/) override {}

  void OnPriority(SpdyStreamId stream_id, SpdyStreamId /* parent_id */,
                  int weight, bool /* exclusive */) override {
    QUICHE_DCHECK(!VersionUsesHttp3(session_->transport_version()));
    if (!session_->IsConnected()) {
      return;
    }
    SpdyPriority priority = Http2WeightToSpdy3Priority(weight);
    session_->OnPriority(stream_id, spdy::SpdyStreamPrecedence(priority));
  }

  void OnPriorityUpdate(SpdyStreamId /*prioritized_stream_id*/,
                        absl::string_view /*priority_field_value*/) override {}

  bool OnUnknownFrame(SpdyStreamId /*stream_id*/,
                      uint8_t /*frame_type*/) override {
    CloseConnection("Unknown frame type received.",
                    QUIC_INVALID_HEADERS_STREAM_DATA);
    return false;
  }

  void OnUnknownFrameStart(SpdyStreamId /*stream_id*/, size_t /*length*/,
                           uint8_t /*type*/, uint8_t /*flags*/) override {}

  void OnUnknownFramePayload(SpdyStreamId /*stream_id*/,
                             absl::string_view /*payload*/) override {}

  // SpdyFramerDebugVisitorInterface implementation
  void OnSendCompressedFrame(SpdyStreamId /*stream_id*/, SpdyFrameType /*type*/,
                             size_t payload_len, size_t frame_len) override {
    if (payload_len == 0) {
      QUIC_BUG(quic_bug_10360_1) << "Zero payload length.";
      return;
    }
    int compression_pct = 100 - (100 * frame_len) / payload_len;
    QUIC_DVLOG(1) << "Net.QuicHpackCompressionPercentage: " << compression_pct;
  }

  void OnReceiveCompressedFrame(SpdyStreamId /*stream_id*/,
                                SpdyFrameType /*type*/,
                                size_t frame_len) override {
    if (session_->IsConnected()) {
      session_->OnCompressedFrameSize(frame_len);
    }
  }

  void set_max_header_list_size(size_t max_header_list_size) {
    header_list_.set_max_header_list_size(max_header_list_size);
  }

 private:
  void CloseConnection(const std::string& details, QuicErrorCode code) {
    if (session_->IsConnected()) {
      session_->CloseConnectionWithDetails(code, details);
    }
  }

  QuicSpdySession* session_;
  SizeLimitingHeaderList header_list_;

  // True if the next OnHeaderFrameEnd() call signals the end of pushed request
  // headers.
  bool expecting_pushed_headers_ = false;
};

Http3DebugVisitor::Http3DebugVisitor() {}

Http3DebugVisitor::~Http3DebugVisitor() {}

// Expected unidirectional static streams Requirement can be found at
// https://tools.ietf.org/html/draft-ietf-quic-http-22#section-6.2.
QuicSpdySession::QuicSpdySession(
    QuicConnection* connection, QuicSession::Visitor* visitor,
    const QuicConfig& config, const ParsedQuicVersionVector& supported_versions)
    : QuicSession(connection, visitor, config, supported_versions,
                  /*num_expected_unidirectional_static_streams = */
                  VersionUsesHttp3(connection->transport_version())
                      ? static_cast<QuicStreamCount>(
                            kHttp3StaticUnidirectionalStreamCount)
                      : 0u,
                  std::make_unique<DatagramObserver>(this)),
      send_control_stream_(nullptr),
      receive_control_stream_(nullptr),
      qpack_encoder_receive_stream_(nullptr),
      qpack_decoder_receive_stream_(nullptr),
      qpack_encoder_send_stream_(nullptr),
      qpack_decoder_send_stream_(nullptr),
      qpack_maximum_dynamic_table_capacity_(
          GetDefaultQpackMaximumDynamicTableCapacity(perspective())),
      qpack_maximum_blocked_streams_(kDefaultMaximumBlockedStreams),
      max_inbound_header_list_size_(kDefaultMaxUncompressedHeaderSize),
      max_outbound_header_list_size_(std::numeric_limits<size_t>::max()),
      stream_id_(
          QuicUtils::GetInvalidStreamId(connection->transport_version())),
      frame_len_(0),
      fin_(false),
      spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
      spdy_framer_visitor_(new SpdyFramerVisitor(this)),
      debug_visitor_(nullptr),
      destruction_indicator_(123456789),
      allow_extended_connect_(perspective() == Perspective::IS_SERVER &&
                              VersionUsesHttp3(transport_version())),
      force_buffer_requests_until_settings_(false) {
  h2_deframer_.set_visitor(spdy_framer_visitor_.get());
  h2_deframer_.set_debug_visitor(spdy_framer_visitor_.get());
  spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
}

QuicSpdySession::~QuicSpdySession() {
  QUIC_BUG_IF(quic_bug_12477_2, destruction_indicator_ != 123456789)
      << "QuicSpdySession use after free. " << destruction_indicator_
      << QuicStackTrace();
  destruction_indicator_ = 987654321;
}

void QuicSpdySession::Initialize() {
  QuicSession::Initialize();

  FillSettingsFrame();
  if (!VersionUsesHttp3(transport_version())) {
    if (perspective() == Perspective::IS_SERVER) {
      set_largest_peer_created_stream_id(
          QuicUtils::GetHeadersStreamId(transport_version()));
    } else {
      QuicStreamId headers_stream_id = GetNextOutgoingBidirectionalStreamId();
      QUICHE_DCHECK_EQ(headers_stream_id,
                       QuicUtils::GetHeadersStreamId(transport_version()));
    }
    auto headers_stream = std::make_unique<QuicHeadersStream>((this));
    QUICHE_DCHECK_EQ(QuicUtils::GetHeadersStreamId(transport_version()),
                     headers_stream->id());

    headers_stream_ = headers_stream.get();
    ActivateStream(std::move(headers_stream));
  } else {
    qpack_encoder_ = std::make_unique<QpackEncoder>(this, huffman_encoding_,
                                                    cookie_crumbling_);
    qpack_decoder_ =
        std::make_unique<QpackDecoder>(qpack_maximum_dynamic_table_capacity_,
                                       qpack_maximum_blocked_streams_, this);
    MaybeInitializeHttp3UnidirectionalStreams();
  }

  spdy_framer_visitor_->set_max_header_list_size(max_inbound_header_list_size_);

  // Limit HPACK buffering to 2x header list size limit.
  h2_deframer_.GetHpackDecoder().set_max_decode_buffer_size_bytes(
      2 * max_inbound_header_list_size_);
}

void QuicSpdySession::FillSettingsFrame() {
  settings_.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] =
      qpack_maximum_dynamic_table_capacity_;
  settings_.values[SETTINGS_QPACK_BLOCKED_STREAMS] =
      qpack_maximum_blocked_streams_;
  settings_.values[SETTINGS_MAX_FIELD_SECTION_SIZE] =
      max_inbound_header_list_size_;
  if (version().UsesHttp3()) {
    switch (LocalHttpDatagramSupport()) {
      case HttpDatagramSupport::kNone:
        break;
      case HttpDatagramSupport::kDraft04:
        settings_.values[SETTINGS_H3_DATAGRAM_DRAFT04] = 1;
        break;
      case HttpDatagramSupport::kRfc:
        settings_.values[SETTINGS_H3_DATAGRAM] = 1;
        break;
      case HttpDatagramSupport::kRfcAndDraft04:
        settings_.values[SETTINGS_H3_DATAGRAM] = 1;
        settings_.values[SETTINGS_H3_DATAGRAM_DRAFT04] = 1;
        break;
    }
  }
  if (WillNegotiateWebTransport()) {
    WebTransportHttp3VersionSet versions =
        LocallySupportedWebTransportVersions();
    if (versions.IsSet(WebTransportHttp3Version::kDraft02)) {
      settings_.values[SETTINGS_WEBTRANS_DRAFT00] = 1;
    }
    if (versions.IsSet(WebTransportHttp3Version::kDraft07)) {
      QUICHE_BUG_IF(
          WT_enabled_extended_connect_disabled,
          perspective() == Perspective::IS_SERVER && !allow_extended_connect())
          << "WebTransport enabled, but extended CONNECT is not";
      settings_.values[SETTINGS_WEBTRANS_MAX_SESSIONS_DRAFT07] =
          kDefaultMaxWebTransportSessions;
    }
  }
  if (allow_extended_connect()) {
    settings_.values[SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
  }
}

void QuicSpdySession::OnDecoderStreamError(QuicErrorCode error_code,
                                           absl::string_view error_message) {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));

  CloseConnectionWithDetails(
      error_code, absl::StrCat("Decoder stream error: ", error_message));
}

void QuicSpdySession::OnEncoderStreamError(QuicErrorCode error_code,
                                           absl::string_view error_message) {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));

  CloseConnectionWithDetails(
      error_code, absl::StrCat("Encoder stream error: ", error_message));
}

void QuicSpdySession::OnStreamHeadersPriority(
    QuicStreamId stream_id, const spdy::SpdyStreamPrecedence& precedence) {
  QuicSpdyStream* stream = GetOrCreateSpdyDataStream(stream_id);
  if (!stream) {
    // It's quite possible to receive headers after a stream has been reset.
    return;
  }
  stream->OnStreamHeadersPriority(precedence);
}

void QuicSpdySession::OnStreamHeaderList(QuicStreamId stream_id, bool fin,
                                         size_t frame_len,
                                         const QuicHeaderList& header_list) {
  if (IsStaticStream(stream_id)) {
    connection()->CloseConnection(
        QUIC_INVALID_HEADERS_STREAM_DATA, "stream is static",
        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return;
  }
  QuicSpdyStream* stream = GetOrCreateSpdyDataStream(stream_id);
  if (stream == nullptr) {
    // The stream no longer exists, but trailing headers may contain the final
    // byte offset necessary for flow control and open stream accounting.
    size_t final_byte_offset = 0;
    for (const auto& header : header_list) {
      const std::string& header_key = header.first;
      const std::string& header_value = header.second;
      if (header_key == kFinalOffsetHeaderKey) {
        if (!absl::SimpleAtoi(header_value, &final_byte_offset)) {
          connection()->CloseConnection(
              QUIC_INVALID_HEADERS_STREAM_DATA,
              "Trailers are malformed (no final offset)",
              ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
          return;
        }
        QUIC_DVLOG(1) << ENDPOINT
                      << "Received final byte offset in trailers for stream "
                      << stream_id << ", which no longer exists.";
        OnFinalByteOffsetReceived(stream_id, final_byte_offset);
      }
    }

    // It's quite possible to receive headers after a stream has been reset.
    return;
  }
  stream->OnStreamHeaderList(fin, frame_len, header_list);
}

void QuicSpdySession::OnPriorityFrame(
    QuicStreamId stream_id, const spdy::SpdyStreamPrecedence& precedence) {
  QuicSpdyStream* stream = GetOrCreateSpdyDataStream(stream_id);
  if (!stream) {
    // It's quite possible to receive a PRIORITY frame after a stream has been
    // reset.
    return;
  }
  stream->OnPriorityFrame(precedence);
}

bool QuicSpdySession::OnPriorityUpdateForRequestStream(
    QuicStreamId stream_id, HttpStreamPriority priority) {
  if (perspective() == Perspective::IS_CLIENT ||
      !QuicUtils::IsBidirectionalStreamId(stream_id, version()) ||
      !QuicUtils::IsClientInitiatedStreamId(transport_version(), stream_id)) {
    return true;
  }

  QuicStreamCount advertised_max_incoming_bidirectional_streams =
      GetAdvertisedMaxIncomingBidirectionalStreams();
  if (advertised_max_incoming_bidirectional_streams == 0 ||
      stream_id > QuicUtils::GetFirstBidirectionalStreamId(
                      transport_version(), Perspective::IS_CLIENT) +
                      QuicUtils::StreamIdDelta(transport_version()) *
                          (advertised_max_incoming_bidirectional_streams - 1)) {
    connection()->CloseConnection(
        QUIC_INVALID_STREAM_ID,
        "PRIORITY_UPDATE frame received for invalid stream.",
        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }

  if (MaybeSetStreamPriority(stream_id, QuicStreamPriority(priority))) {
    return true;
  }

  if (IsClosedStream(stream_id)) {
    return true;
  }

  buffered_stream_priorities_[stream_id] = priority;

  if (buffered_stream_priorities_.size() >
      10 * max_open_incoming_bidirectional_streams()) {
    // This should never happen, because |buffered_stream_priorities_| should
    // only contain entries for streams that are allowed to be open by the peer
    // but have not been opened yet.
    std::string error_message =
        absl::StrCat("Too many stream priority values buffered: ",
                     buffered_stream_priorities_.size(),
                     ", which should not exceed the incoming stream limit of ",
                     max_open_incoming_bidirectional_streams());
    QUIC_BUG(quic_bug_10360_2) << error_message;
    connection()->CloseConnection(
        QUIC_INTERNAL_ERROR, error_message,
        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }

  return true;
}

size_t QuicSpdySession::ProcessHeaderData(const struct iovec& iov) {
  QUIC_BUG_IF(quic_bug_12477_4, destruction_indicator_ != 123456789)
      << "QuicSpdyStream use after free. " << destruction_indicator_
      << QuicStackTrace();
  return h2_deframer_.ProcessInput(static_cast<char*>(iov.iov_base),
                                   iov.iov_len);
}

size_t QuicSpdySession::WriteHeadersOnHeadersStream(
    QuicStreamId id, HttpHeaderBlock headers, bool fin,
    const spdy::SpdyStreamPrecedence& precedence,
    quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
        ack_listener) {
  QUICHE_DCHECK(!VersionUsesHttp3(transport_version()));

  return WriteHeadersOnHeadersStreamImpl(
      id, std::move(headers), fin,
      /* parent_stream_id = */ 0,
      Spdy3PriorityToHttp2Weight(precedence.spdy3_priority()),
      /* exclusive = */ false, std::move(ack_listener));
}

size_t QuicSpdySession::WritePriority(QuicStreamId stream_id,
                                      QuicStreamId parent_stream_id, int weight,
                                      bool exclusive) {
  QUICHE_DCHECK(!VersionUsesHttp3(transport_version()));
  SpdyPriorityIR priority_frame(stream_id, parent_stream_id, weight, exclusive);
  SpdySerializedFrame frame(spdy_framer_.SerializeFrame(priority_frame));
  headers_stream()->WriteOrBufferData(
      absl::string_view(frame.data(), frame.size()), false, nullptr);
  return frame.size();
}

void QuicSpdySession::WriteHttp3PriorityUpdate(QuicStreamId stream_id,
                                               HttpStreamPriority priority) {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));

  send_control_stream_->WritePriorityUpdate(stream_id, priority);
}

void QuicSpdySession::OnHttp3GoAway(uint64_t id) {
  QUIC_BUG_IF(quic_bug_12477_5, !version().UsesHttp3())
      << "HTTP/3 GOAWAY received on version " << version();

  if (last_received_http3_goaway_id_.has_value() &&
      id > *last_received_http3_goaway_id_) {
    CloseConnectionWithDetails(
        QUIC_HTTP_GOAWAY_ID_LARGER_THAN_PREVIOUS,
        absl::StrCat("GOAWAY received with ID ", id,
                     " greater than previously received ID ",
                     *last_received_http3_goaway_id_));
    return;
  }
  last_received_http3_goaway_id_ = id;

  if (perspective() == Perspective::IS_SERVER) {
    return;
  }

  // QuicStreamId is uint32_t.  Casting to this narrower type is well-defined
  // and preserves the lower 32 bits.  Both IsBidirectionalStreamId() and
  // IsIncomingStream() give correct results, because their return value is
  // determined by the least significant two bits.
  QuicStreamId stream_id = static_cast<QuicStreamId>(id);
  if (!QuicUtils::IsBidirectionalStreamId(stream_id, version()) ||
      IsIncomingStream(stream_id)) {
    CloseConnectionWithDetails(QUIC_HTTP_GOAWAY_INVALID_STREAM_ID,
                               "GOAWAY with invalid stream ID");
    return;
  }

  if (SupportsWebTransport()) {
    PerformActionOnActiveStreams([](QuicStream* stream) {
      if (!QuicUtils::IsBidirectionalStreamId(stream->id(),
                                              stream->version()) ||
          !QuicUtils::IsClientInitiatedStreamId(
              stream->version().transport_version, stream->id())) {
        return true;
      }
      QuicSpdyStream* spdy_stream = static_cast<QuicSpdyStream*>(stream);
      WebTransportHttp3* web_transport = spdy_stream->web_transport();
      if (web_transport == nullptr) {
        return true;
      }
      web_transport->OnGoAwayReceived();
      return true;
    });
  }

  // TODO(b/161252736): Cancel client requests with ID larger than |id|.
  // If |id| is larger than numeric_limits<QuicStreamId>::max(), then use
  // max() instead of downcast value.
}

bool QuicSpdySession::OnStreamsBlockedFrame(
    const QuicStreamsBlockedFrame& frame) {
  if (!QuicSession::OnStreamsBlockedFrame(frame)) {
    return false;
  }

  // The peer asked for stream space more than this implementation has. Send
  // goaway.
  if (perspective() == Perspective::IS_SERVER &&
      frame.stream_count >= QuicUtils::GetMaxStreamCount()) {
    QUICHE_DCHECK_EQ(frame.stream_count, QuicUtils::GetMaxStreamCount());
    SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "stream count too large");
  }
  return true;
}

void QuicSpdySession::SendHttp3GoAway(QuicErrorCode error_code,
                                      const std::string& reason) {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
  if (!IsEncryptionEstablished()) {
    QUIC_CODE_COUNT(quic_h3_goaway_before_encryption_established);
    connection()->CloseConnection(
        error_code, reason,
        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return;
  }
  ietf_streamid_manager().StopIncreasingIncomingMaxStreams();

  QuicStreamId stream_id =
      QuicUtils::GetMaxClientInitiatedBidirectionalStreamId(
          transport_version());
  if (last_sent_http3_goaway_id_.has_value() &&
      *last_sent_http3_goaway_id_ <= stream_id) {
    // Do not send GOAWAY frame with a higher id, because it is forbidden.
    // Do not send one with same stream id as before, since frames on the
    // control stream are guaranteed to be processed in order.
    return;
  }

  send_control_stream_->SendGoAway(stream_id);
  last_sent_http3_goaway_id_ = stream_id;
}

void QuicSpdySession::SendInitialData() {
  if (!VersionUsesHttp3(transport_version())) {
    return;
  }
  QuicConnection::ScopedPacketFlusher flusher(connection());
  send_control_stream_->MaybeSendSettingsFrame();
  SendInitialDataAfterSettings();
}

bool QuicSpdySession::CheckStreamWriteBlocked(QuicStream* stream) const {
  if (qpack_decoder_send_stream_ != nullptr &&
      stream->id() == qpack_decoder_send_stream_->id()) {
    // Decoder data is always bundled opportunistically.
    return true;
  }
  return QuicSession::CheckStreamWriteBlocked(stream);
}

QpackEncoder* QuicSpdySession::qpack_encoder() {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));

  return qpack_encoder_.get();
}

QpackDecoder* QuicSpdySession::qpack_decoder() {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));

  return qpack_decoder_.get();
}

void QuicSpdySession::OnStreamCreated(QuicSpdyStream* stream) {
  auto it = buffered_stream_priorities_.find(stream->id());
  if (it == buffered_stream_priorities_.end()) {
    return;
  }

  stream->SetPriority(QuicStreamPriority(it->second));
  buffered_stream_priorities_.erase(it);
}

QuicSpdyStream* QuicSpdySession::GetOrCreateSpdyDataStream(
    const QuicStreamId stream_id) {
  QuicStream* stream = GetOrCreateStream(stream_id);
  if (stream && stream->is_static()) {
    QUIC_BUG(quic_bug_10360_5)
        << "GetOrCreateSpdyDataStream returns static stream " << stream_id
        << " in version " << transport_version() << "\n"
        << QuicStackTrace();
    connection()->CloseConnection(
        QUIC_INVALID_STREAM_ID,
        absl::StrCat("stream ", stream_id, " is static"),
        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return nullptr;
  }
  return static_cast<QuicSpdyStream*>(stream);
}

void QuicSpdySession::OnNewEncryptionKeyAvailable(
    EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter) {
  QuicSession::OnNewEncryptionKeyAvailable(level, std::move(encrypter));
  if (IsEncryptionEstablished()) {
    // Send H3 SETTINGs once encryption is established.
    SendInitialData();
  }
}

bool QuicSpdySession::ShouldNegotiateWebTransport() const {
  return LocallySupportedWebTransportVersions().Any();
}

WebTransportHttp3VersionSet
QuicSpdySession::LocallySupportedWebTransportVersions() const {
  return WebTransportHttp3VersionSet();
}

bool QuicSpdySession::WillNegotiateWebTransport() {
  return LocalHttpDatagramSupport() != HttpDatagramSupport::kNone &&
         version().UsesHttp3() && ShouldNegotiateWebTransport();
}

// True if there are open HTTP requests.
bool QuicSpdySession::ShouldKeepConnectionAlive() const {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()) ||
                0u == pending_streams_size());
  return GetNumActiveStreams() + pending_streams_size() > 0;
}

bool QuicSpdySession::UsesPendingStreamForFrame(QuicFrameType type,
                                                QuicStreamId stream_id) const {
  // Pending streams can only be used to handle unidirectional stream with
  // STREAM & RESET_STREAM frames in IETF QUIC.
  return VersionUsesHttp3(transport_version()) &&
         (type == STREAM_FRAME || type == RST_STREAM_FRAME) &&
         QuicUtils::GetStreamType(stream_id, perspective(),
                                  IsIncomingStream(stream_id),
                                  version()) == READ_UNIDIRECTIONAL;
}

size_t QuicSpdySession::WriteHeadersOnHeadersStreamImpl(
    QuicStreamId id, quiche::HttpHeaderBlock headers, bool fin,
    QuicStreamId parent_stream_id, int weight, bool exclusive,
    quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
        ack_listener) {
  QUICHE_DCHECK(!VersionUsesHttp3(transport_version()));

  const QuicByteCount uncompressed_size = headers.TotalBytesUsed();
  SpdyHeadersIR headers_frame(id, std::move(headers));
  headers_frame.set_fin(fin);
  if (perspective() == Perspective::IS_CLIENT) {
    headers_frame.set_has_priority(true);
    headers_frame.set_parent_stream_id(parent_stream_id);
    headers_frame.set_weight(weight);
    headers_frame.set_exclusive(exclusive);
  }
  SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
  headers_stream()->WriteOrBufferData(
      absl::string_view(frame.data(), frame.size()), false,
      std::move(ack_listener));

  // Calculate compressed header block size without framing overhead.
  QuicByteCount compressed_size = frame.size();
  compressed_size -= spdy::kFrameHeaderSize;
  if (perspective() == Perspective::IS_CLIENT) {
    // Exclusive bit and Stream Dependency are four bytes, weight is one more.
    compressed_size -= 5;
  }

  LogHeaderCompressionRatioHistogram(
      /* using_qpack = */ false,
      /* is_sent = */ true, compressed_size, uncompressed_size);

  return frame.size();
}

bool QuicSpdySession::ResumeApplicationState(ApplicationState* cached_state) {
  QUICHE_DCHECK_EQ(perspective(), Perspective::IS_CLIENT);
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));

  SettingsFrame out;
  if (!HttpDecoder::DecodeSettings(
          reinterpret_cast<char*>(cached_state->data()), cached_state->size(),
          &out)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnSettingsFrameResumed(out);
  }
  QUICHE_DCHECK(streams_waiting_for_settings_.empty());
  for (const auto& setting : out.values) {
    OnSetting(setting.first, setting.second);
  }
  return true;
}

std::optional<std::string> QuicSpdySession::OnAlpsData(const uint8_t* alps_data,
                                                       size_t alps_length) {
  AlpsFrameDecoder alps_frame_decoder(this);
  HttpDecoder decoder(&alps_frame_decoder);
  decoder.ProcessInput(reinterpret_cast<const char*>(alps_data), alps_length);
  if (alps_frame_decoder.error_detail()) {
    return alps_frame_decoder.error_detail();
  }

  if (decoder.error() != QUIC_NO_ERROR) {
    return decoder.error_detail();
  }

  if (!decoder.AtFrameBoundary()) {
    return "incomplete HTTP/3 frame";
  }

  return std::nullopt;
}

void QuicSpdySession::OnAcceptChFrameReceivedViaAlps(
    const AcceptChFrame& frame) {
  if (debug_visitor_) {
    debug_visitor_->OnAcceptChFrameReceivedViaAlps(frame);
  }
}

bool QuicSpdySession::OnSettingsFrame(const SettingsFrame& frame) {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnSettingsFrameReceived(frame);
  }
  for (const auto& setting : frame.values) {
    if (!OnSetting(setting.first, setting.second)) {
      return false;
    }
  }

  if (!ValidateWebTransportSettingsConsistency()) {
    return false;
  }

  // This is the last point in the connection when we can receive new SETTINGS
  // values (ALPS and settings from the session ticket come before, and only one
  // SETTINGS frame per connection is allowed).  Notify all the streams that are
  // blocking on having the definitive settings list.
  QUICHE_DCHECK(!settings_received_);
  settings_received_ = true;
  for (QuicStreamId stream_id : streams_waiting_for_settings_) {
    QUICHE_RELOADABLE_FLAG_COUNT_N(quic_block_until_settings_received_copt, 4,
                                   4);
    QUICHE_DCHECK(ShouldBufferRequestsUntilSettings());
    QuicSpdyStream* stream = GetOrCreateSpdyDataStream(stream_id);
    if (stream == nullptr) {
      // The stream may no longer exist, since it is possible for a stream to
      // get reset while waiting for the SETTINGS frame.
      continue;
    }
    stream->OnDataAvailable();
  }
  streams_waiting_for_settings_.clear();

  return true;
}

bool QuicSpdySession::ValidateWebTransportSettingsConsistency() {
  // Only apply the following checks to draft-07 or later.
  std::optional<WebTransportHttp3Version> version =
      NegotiatedWebTransportVersion();
  if (!version.has_value() || *version == WebTransportHttp3Version::kDraft02) {
    return true;
  }

  if (!allow_extended_connect_) {
    CloseConnectionWithDetails(
        QUIC_HTTP_INVALID_SETTING_VALUE,
        "Negotiated use of WebTransport over HTTP/3 (draft-07 or later), but "
        "failed to negotiate extended CONNECT");
    return false;
  }

  if (http_datagram_support_ == HttpDatagramSupport::kDraft04) {
    CloseConnectionWithDetails(
        QUIC_HTTP_INVALID_SETTING_VALUE,
        "WebTransport over HTTP/3 version draft-07 and beyond requires the "
        "RFC version of HTTP datagrams");
    return false;
  }

  if (http_datagram_support_ != HttpDatagramSupport::kRfc) {
    CloseConnectionWithDetails(
        QUIC_HTTP_INVALID_SETTING_VALUE,
        "WebTransport over HTTP/3 requires HTTP datagrams support");
    return false;
  }

  return true;
}

std::optional<std::string> QuicSpdySession::OnSettingsFrameViaAlps(
    const SettingsFrame& frame) {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnSettingsFrameReceivedViaAlps(frame);
  }
  for (const auto& setting : frame.values) {
    if (!OnSetting(setting.first, setting.second)) {
      // Do not bother adding the setting identifier or value to the error
      // message, because OnSetting() already closed the connection, therefore
      // the error message will be ignored.
      return "error parsing setting";
    }
  }
  return std::nullopt;
}

bool QuicSpdySession::VerifySettingIsZeroOrOne(uint64_t id, uint64_t value) {
  if (value == 0 || value == 1) {
    return true;
  }
  std::string error_details = absl::StrCat(
      "Received ",
      H3SettingsToString(static_cast<Http3AndQpackSettingsIdentifiers>(id)),
      " with invalid value ", value);
  QUIC_PEER_BUG(bad received setting) << ENDPOINT << error_details;
  CloseConnectionWithDetails(QUIC_HTTP_INVALID_SETTING_VALUE, error_details);
  return false;
}

bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
  if (VersionUsesHttp3(transport_version())) {
    // SETTINGS frame received on the control stream.
    switch (id) {
      case SETTINGS_QPACK_MAX_TABLE_CAPACITY: {
        QUIC_DVLOG(1)
            << ENDPOINT
            << "SETTINGS_QPACK_MAX_TABLE_CAPACITY received with value "
            << value;
        // Communicate |value| to encoder, because it is used for encoding
        // Required Insert Count.
        if (!qpack_encoder_->SetMaximumDynamicTableCapacity(value)) {
          CloseConnectionWithDetails(
              was_zero_rtt_rejected()
                  ? QUIC_HTTP_ZERO_RTT_REJECTION_SETTINGS_MISMATCH
                  : QUIC_HTTP_ZERO_RTT_RESUMPTION_SETTINGS_MISMATCH,
              absl::StrCat(was_zero_rtt_rejected()
                               ? "Server rejected 0-RTT, aborting because "
                               : "",
                           "Server sent an SETTINGS_QPACK_MAX_TABLE_CAPACITY: ",
                           value, " while current value is: ",
                           qpack_encoder_->MaximumDynamicTableCapacity()));
          return false;
        }
        // However, limit the dynamic table capacity to
        // |qpack_maximum_dynamic_table_capacity_|.
        qpack_encoder_->SetDynamicTableCapacity(
            std::min(value, qpack_maximum_dynamic_table_capacity_));
        break;
      }
      case SETTINGS_MAX_FIELD_SECTION_SIZE:
        QUIC_DVLOG(1) << ENDPOINT
                      << "SETTINGS_MAX_FIELD_SECTION_SIZE received with value "
                      << value;
        if (max_outbound_header_list_size_ !=
                std::numeric_limits<size_t>::max() &&
            max_outbound_header_list_size_ > value) {
          CloseConnectionWithDetails(
              was_zero_rtt_rejected()
                  ? QUIC_HTTP_ZERO_RTT_REJECTION_SETTINGS_MISMATCH
                  : QUIC_HTTP_ZERO_RTT_RESUMPTION_SETTINGS_MISMATCH,
              absl::StrCat(was_zero_rtt_rejected()
                               ? "Server rejected 0-RTT, aborting because "
                               : "",
                           "Server sent an SETTINGS_MAX_FIELD_SECTION_SIZE: ",
                           value, " which reduces current value: ",
                           max_outbound_header_list_size_));
          return false;
        }
        max_outbound_header_list_size_ = value;
        break;
      case SETTINGS_QPACK_BLOCKED_STREAMS: {
        QUIC_DVLOG(1) << ENDPOINT
                      << "SETTINGS_QPACK_BLOCKED_STREAMS received with value "
                      << value;
        if (!qpack_encoder_->SetMaximumBlockedStreams(value)) {
          CloseConnectionWithDetails(
              was_zero_rtt_rejected()
                  ? QUIC_HTTP_ZERO_RTT_REJECTION_SETTINGS_MISMATCH
                  : QUIC_HTTP_ZERO_RTT_RESUMPTION_SETTINGS_MISMATCH,
              absl::StrCat(was_zero_rtt_rejected()
                               ? "Server rejected 0-RTT, aborting because "
                               : "",
                           "Server sent an SETTINGS_QPACK_BLOCKED_STREAMS: ",
                           value, " which reduces current value: ",
                           qpack_encoder_->maximum_blocked_streams()));
          return false;
        }
        break;
      }
      case SETTINGS_ENABLE_CONNECT_PROTOCOL: {
        QUIC_DVLOG(1) << ENDPOINT
                      << "SETTINGS_ENABLE_CONNECT_PROTOCOL received with value "
                      << value;
        if (!VerifySettingIsZeroOrOne(id, value)) {
          return false;
        }
        if (perspective() == Perspective::IS_CLIENT) {
          allow_extended_connect_ = value != 0;
        }
        break;
      }
      case spdy::SETTINGS_ENABLE_PUSH:
        ABSL_FALLTHROUGH_INTENDED;
      case spdy::SETTINGS_MAX_CONCURRENT_STREAMS:
        ABSL_FALLTHROUGH_INTENDED;
      case spdy::SETTINGS_INITIAL_WINDOW_SIZE:
        ABSL_FALLTHROUGH_INTENDED;
      case spdy::SETTINGS_MAX_FRAME_SIZE:
        CloseConnectionWithDetails(
            QUIC_HTTP_RECEIVE_SPDY_SETTING,
            absl::StrCat("received HTTP/2 specific setting in HTTP/3 session: ",
                         id));
        return false;
      case SETTINGS_H3_DATAGRAM_DRAFT04: {
        HttpDatagramSupport local_http_datagram_support =
            LocalHttpDatagramSupport();
        if (local_http_datagram_support != HttpDatagramSupport::kDraft04 &&
            local_http_datagram_support !=
                HttpDatagramSupport::kRfcAndDraft04) {
          break;
        }
        QUIC_DVLOG(1) << ENDPOINT
                      << "SETTINGS_H3_DATAGRAM_DRAFT04 received with value "
                      << value;
        if (!version().UsesHttp3()) {
          break;
        }
        if (!VerifySettingIsZeroOrOne(id, value)) {
          return false;
        }
        if (value && http_datagram_support_ != HttpDatagramSupport::kRfc) {
          // If both RFC 9297 and draft-04 are supported, we use the RFC. This
          // is implemented by ignoring SETTINGS_H3_DATAGRAM_DRAFT04 when we've
          // already parsed SETTINGS_H3_DATAGRAM.
          http_datagram_support_ = HttpDatagramSupport::kDraft04;
        }
        break;
      }
      case SETTINGS_H3_DATAGRAM: {
        HttpDatagramSupport local_http_datagram_support =
            LocalHttpDatagramSupport();
        if (local_http_datagram_support != HttpDatagramSupport::kRfc &&
            local_http_datagram_support !=
                HttpDatagramSupport::kRfcAndDraft04) {
          break;
        }
        QUIC_DVLOG(1) << ENDPOINT << "SETTINGS_H3_DATAGRAM received with value "
                      << value;
        if (!version().UsesHttp3()) {
          break;
        }
        if (!VerifySettingIsZeroOrOne(id, value)) {
          return false;
        }
        if (value) {
          http_datagram_support_ = HttpDatagramSupport::kRfc;
        }
        break;
      }
      case SETTINGS_WEBTRANS_DRAFT00:
        if (!WillNegotiateWebTransport()) {
          break;
        }
        QUIC_DVLOG(1) << ENDPOINT
                      << "SETTINGS_ENABLE_WEBTRANSPORT(02) received with value "
                      << value;
        if (!VerifySettingIsZeroOrOne(id, value)) {
          return false;
        }
        if (value == 1) {
          peer_web_transport_versions_.Set(WebTransportHttp3Version::kDraft02);
          if (perspective() == Perspective::IS_CLIENT) {
            allow_extended_connect_ = true;
          }
        }
        break;
      case SETTINGS_WEBTRANS_MAX_SESSIONS_DRAFT07:
        if (!WillNegotiateWebTransport()) {
          break;
        }
        QUIC_DVLOG(1)
            << ENDPOINT
            << "SETTINGS_WEBTRANS_MAX_SESSIONS_DRAFT07 received with value "
            << value;
        if (value > 0) {
          peer_web_transport_versions_.Set(WebTransportHttp3Version::kDraft07);
          if (perspective() == Perspective::IS_CLIENT) {
            max_webtransport_sessions_[WebTransportHttp3Version::kDraft07] =
                value;
          }
        }
        break;
      default:
        QUIC_DVLOG(1) << ENDPOINT << "Unknown setting identifier " << id
                      << " received with value " << value;
        // Ignore unknown settings.
        break;
    }
    return true;
  }

  // SETTINGS frame received on the headers stream.
  switch (id) {
    case spdy::SETTINGS_HEADER_TABLE_SIZE:
      QUIC_DVLOG(1) << ENDPOINT
                    << "SETTINGS_HEADER_TABLE_SIZE received with value "
                    << value;
      spdy_framer_.UpdateHeaderEncoderTableSize(
          std::min<uint64_t>(value, kHpackEncoderDynamicTableSizeLimit));
      break;
    case spdy::SETTINGS_ENABLE_PUSH:
      if (perspective() == Perspective::IS_SERVER) {
        // See rfc7540, Section 6.5.2.
        if (value > 1) {
          QUIC_DLOG(ERROR) << ENDPOINT << "Invalid value " << value
                           << " received for SETTINGS_ENABLE_PUSH.";
          if (IsConnected()) {
            CloseConnectionWithDetails(
                QUIC_INVALID_HEADERS_STREAM_DATA,
                absl::StrCat("Invalid value for SETTINGS_ENABLE_PUSH: ",
                             value));
          }
          return true;
        }
        QUIC_DVLOG(1) << ENDPOINT << "SETTINGS_ENABLE_PUSH received with value "
                      << value << ", ignoring.";
        break;
      } else {
        QUIC_DLOG(ERROR)
            << ENDPOINT
            << "Invalid SETTINGS_ENABLE_PUSH received by client with value "
            << value;
        if (IsConnected()) {
          CloseConnectionWithDetails(
              QUIC_INVALID_HEADERS_STREAM_DATA,
              absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
        }
      }
      break;
    case spdy::SETTINGS_MAX_HEADER_LIST_SIZE:
      QUIC_DVLOG(1) << ENDPOINT
                    << "SETTINGS_MAX_HEADER_LIST_SIZE received with value "
                    << value;
      max_outbound_header_list_size_ = value;
      break;
    default:
      QUIC_DLOG(ERROR) << ENDPOINT << "Unknown setting identifier " << id
                       << " received with value " << value;
      if (IsConnected()) {
        CloseConnectionWithDetails(
            QUIC_INVALID_HEADERS_STREAM_DATA,
            absl::StrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
      }
  }
  return true;
}

bool QuicSpdySession::ShouldReleaseHeadersStreamSequencerBuffer() {
  return false;
}

void QuicSpdySession::OnHeaders(SpdyStreamId stream_id, bool has_priority,
                                const spdy::SpdyStreamPrecedence& precedence,
                                bool fin) {
  if (has_priority) {
    if (perspective() == Perspective::IS_CLIENT) {
      CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
                                 "Server must not send priorities.");
      return;
    }
    OnStreamHeadersPriority(stream_id, precedence);
  } else {
    if (perspective() == Perspective::IS_SERVER) {
      CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
                                 "Client must send priorities.");
      return;
    }
  }
  QUICHE_DCHECK_EQ(QuicUtils::GetInvalidStreamId(transport_version()),
                   stream_id_);
  stream_id_ = stream_id;
  fin_ = fin;
}

// TODO (wangyix): Why is SpdyStreamId used instead of QuicStreamId?
// This occurs in many places in this file.
void QuicSpdySession::OnPriority(SpdyStreamId stream_id,
                                 const spdy::SpdyStreamPrecedence& precedence) {
  if (perspective() == Perspective::IS_CLIENT) {
    CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
                               "Server must not send PRIORITY frames.");
    return;
  }
  OnPriorityFrame(stream_id, precedence);
}

void QuicSpdySession::OnHeaderList(const QuicHeaderList& header_list) {
  QUIC_DVLOG(1) << ENDPOINT << "Received header list for stream " << stream_id_
                << ": " << header_list.DebugString();
  QUICHE_DCHECK(!VersionUsesHttp3(transport_version()));

  OnStreamHeaderList(stream_id_, fin_, frame_len_, header_list);

  // Reset state for the next frame.
  stream_id_ = QuicUtils::GetInvalidStreamId(transport_version());
  fin_ = false;
  frame_len_ = 0;
}

void QuicSpdySession::OnCompressedFrameSize(size_t frame_len) {
  frame_len_ += frame_len;
}

void QuicSpdySession::CloseConnectionWithDetails(QuicErrorCode error,
                                                 const std::string& details) {
  connection()->CloseConnection(
      error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}

bool QuicSpdySession::HasActiveRequestStreams() const {
  return GetNumActiveStreams() + num_draining_streams() > 0;
}

QuicStream* QuicSpdySession::ProcessReadUnidirectionalPendingStream(
    PendingStream* pending) {
  struct iovec iov;
  if (!pending->sequencer()->GetReadableRegion(&iov)) {
    // The first byte hasn't been received yet.
    return nullptr;
  }

  QuicDataReader reader(static_cast<char*>(iov.iov_base), iov.iov_len);
  uint8_t stream_type_length = reader.PeekVarInt62Length();
  uint64_t stream_type = 0;
  if (!reader.ReadVarInt62(&stream_type)) {
    if (pending->sequencer()->NumBytesBuffered() ==
        pending->sequencer()->close_offset()) {
      // Stream received FIN but there are not enough bytes for stream type.
      // Mark all bytes consumed in order to close stream.
      pending->MarkConsumed(pending->sequencer()->close_offset());
    }
    return nullptr;
  }
  pending->MarkConsumed(stream_type_length);

  switch (stream_type) {
    case kControlStream: {  // HTTP/3 control stream.
      if (receive_control_stream_) {
        CloseConnectionOnDuplicateHttp3UnidirectionalStreams("Control");
        return nullptr;
      }
      auto receive_stream =
          std::make_unique<QuicReceiveControlStream>(pending, this);
      receive_control_stream_ = receive_stream.get();
      ActivateStream(std::move(receive_stream));
      QUIC_DVLOG(1) << ENDPOINT << "Receive Control stream is created";
      if (debug_visitor_ != nullptr) {
        debug_visitor_->OnPeerControlStreamCreated(
            receive_control_stream_->id());
      }
      return receive_control_stream_;
    }
    case kServerPushStream: {  // Push Stream.
      CloseConnectionWithDetails(QUIC_HTTP_RECEIVE_SERVER_PUSH,
                                 "Received server push stream");
      return nullptr;
    }
    case kQpackEncoderStream: {  // QPACK encoder stream.
      if (qpack_encoder_receive_stream_) {
        CloseConnectionOnDuplicateHttp3UnidirectionalStreams("QPACK encoder");
        return nullptr;
      }
      auto encoder_receive = std::make_unique<QpackReceiveStream>(
          pending, this, qpack_decoder_->encoder_stream_receiver());
      qpack_encoder_receive_stream_ = encoder_receive.get();
      ActivateStream(std::move(encoder_receive));
      QUIC_DVLOG(1) << ENDPOINT << "Receive QPACK Encoder stream is created";
      if (debug_visitor_ != nullptr) {
        debug_visitor_->OnPeerQpackEncoderStreamCreated(
            qpack_encoder_receive_stream_->id());
      }
      return qpack_encoder_receive_stream_;
    }
    case kQpackDecoderStream: {  // QPACK decoder stream.
      if (qpack_decoder_receive_stream_) {
        CloseConnectionOnDuplicateHttp3UnidirectionalStreams("QPACK decoder");
        return nullptr;
      }
      auto decoder_receive = std::make_unique<QpackReceiveStream>(
          pending, this, qpack_encoder_->decoder_stream_receiver());
      qpack_decoder_receive_stream_ = decoder_receive.get();
      ActivateStream(std::move(decoder_receive));
      QUIC_DVLOG(1) << ENDPOINT << "Receive QPACK Decoder stream is created";
      if (debug_visitor_ != nullptr) {
        debug_visitor_->OnPeerQpackDecoderStreamCreated(
            qpack_decoder_receive_stream_->id());
      }
      return qpack_decoder_receive_stream_;
    }
    case kWebTransportUnidirectionalStream: {
      // Note that this checks whether WebTransport is enabled on the receiver
      // side, as we may receive WebTransport streams before peer's SETTINGS are
      // received.
      // TODO(b/184156476): consider whether this means we should drop buffered
      // streams if we don't receive indication of WebTransport support.
      if (!WillNegotiateWebTransport()) {
        // Treat as unknown stream type.
        break;
      }
      QUIC_DVLOG(1) << ENDPOINT << "Created an incoming WebTransport stream "
                    << pending->id();
      auto stream_owned =
          std::make_unique<WebTransportHttp3UnidirectionalStream>(pending,
                                                                  this);
      WebTransportHttp3UnidirectionalStream* stream = stream_owned.get();
      ActivateStream(std::move(stream_owned));
      return stream;
    }
    default:
      break;
  }
  MaybeSendStopSendingFrame(
      pending->id(),
      QuicResetStreamError::FromInternal(QUIC_STREAM_STREAM_CREATION_ERROR));
  pending->StopReading();
  return nullptr;
}

void QuicSpdySession::MaybeInitializeHttp3UnidirectionalStreams() {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
  if (!send_control_stream_ && CanOpenNextOutgoingUnidirectionalStream()) {
    auto send_control = std::make_unique<QuicSendControlStream>(
        GetNextOutgoingUnidirectionalStreamId(), this, settings_);
    send_control_stream_ = send_control.get();
    ActivateStream(std::move(send_control));
    if (debug_visitor_) {
      debug_visitor_->OnControlStreamCreated(send_control_stream_->id());
    }
  }

  if (!qpack_decoder_send_stream_ &&
      CanOpenNextOutgoingUnidirectionalStream()) {
    auto decoder_send = std::make_unique<QpackSendStream>(
        GetNextOutgoingUnidirectionalStreamId(), this, kQpackDecoderStream);
    qpack_decoder_send_stream_ = decoder_send.get();
    ActivateStream(std::move(decoder_send));
    qpack_decoder_->set_qpack_stream_sender_delegate(
        qpack_decoder_send_stream_);
    if (debug_visitor_) {
      debug_visitor_->OnQpackDecoderStreamCreated(
          qpack_decoder_send_stream_->id());
    }
  }

  if (!qpack_encoder_send_stream_ &&
      CanOpenNextOutgoingUnidirectionalStream()) {
    auto encoder_send = std::make_unique<QpackSendStream>(
        GetNextOutgoingUnidirectionalStreamId(), this, kQpackEncoderStream);
    qpack_encoder_send_stream_ = encoder_send.get();
    ActivateStream(std::move(encoder_send));
    qpack_encoder_->set_qpack_stream_sender_delegate(
        qpack_encoder_send_stream_);
    if (debug_visitor_) {
      debug_visitor_->OnQpackEncoderStreamCreated(
          qpack_encoder_send_stream_->id());
    }
  }
}

void QuicSpdySession::BeforeConnectionCloseSent() {
  if (!VersionUsesHttp3(transport_version()) || !IsEncryptionEstablished()) {
    return;
  }

  QUICHE_DCHECK_EQ(perspective(), Perspective::IS_SERVER);

  QuicStreamId stream_id =
      GetLargestPeerCreatedStreamId(/*unidirectional = */ false);

  if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
    // No client-initiated bidirectional streams received yet.
    // Send 0 to let client know that all requests can be retried.
    stream_id = 0;
  } else {
    // Tell client that streams starting with the next after the largest
    // received one can be retried.
    stream_id += QuicUtils::StreamIdDelta(transport_version());
  }
  if (last_sent_http3_goaway_id_.has_value() &&
      *last_sent_http3_goaway_id_ <= stream_id) {
    // Do not send GOAWAY frame with a higher id, because it is forbidden.
    // Do not send one with same stream id as before, since frames on the
    // control stream are guaranteed to be processed in order.
    return;
  }

  send_control_stream_->SendGoAway(stream_id);
  last_sent_http3_goaway_id_ = stream_id;
}

void QuicSpdySession::MaybeBundleOpportunistically() {
  if (qpack_decoder_ != nullptr) {
    qpack_decoder_->FlushDecoderStream();
  }
}

void QuicSpdySession::OnCanCreateNewOutgoingStream(bool unidirectional) {
  if (unidirectional && VersionUsesHttp3(transport_version())) {
    MaybeInitializeHttp3UnidirectionalStreams();
  }
}

bool QuicSpdySession::goaway_received() const {
  return VersionUsesHttp3(transport_version())
             ? last_received_http3_goaway_id_.has_value()
             : transport_goaway_received();
}

bool QuicSpdySession::goaway_sent() const {
  return VersionUsesHttp3(transport_version())
             ? last_sent_http3_goaway_id_.has_value()
             : transport_goaway_sent();
}

void QuicSpdySession::CloseConnectionOnDuplicateHttp3UnidirectionalStreams(
    absl::string_view type) {
  QUIC_PEER_BUG(quic_peer_bug_10360_9) << absl::StrCat(
      "Received a duplicate ", type, " stream: Closing connection.");
  CloseConnectionWithDetails(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM,
                             absl::StrCat(type, " stream is received twice."));
}

// static
void QuicSpdySession::LogHeaderCompressionRatioHistogram(
    bool using_qpack, bool is_sent, QuicByteCount compressed,
    QuicByteCount uncompressed) {
  if (compressed <= 0 || uncompressed <= 0) {
    return;
  }

  int ratio = 100 * (compressed) / (uncompressed);
  if (ratio < 1) {
    ratio = 1;
  } else if (ratio > 200) {
    ratio = 200;
  }

  // Note that when using histogram macros in Chromium, the histogram name must
  // be the same across calls for any given call site.
  if (using_qpack) {
    if (is_sent) {
      QUIC_HISTOGRAM_COUNTS("QuicSession.HeaderCompressionRatioQpackSent",
                            ratio, 1, 200, 200,
                            "Header compression ratio as percentage for sent "
                            "headers using QPACK.");
    } else {
      QUIC_HISTOGRAM_COUNTS("QuicSession.HeaderCompressionRatioQpackReceived",
                            ratio, 1, 200, 200,
                            "Header compression ratio as percentage for "
                            "received headers using QPACK.");
    }
  } else {
    if (is_sent) {
      QUIC_HISTOGRAM_COUNTS("QuicSession.HeaderCompressionRatioHpackSent",
                            ratio, 1, 200, 200,
                            "Header compression ratio as percentage for sent "
                            "headers using HPACK.");
    } else {
      QUIC_HISTOGRAM_COUNTS("QuicSession.HeaderCompressionRatioHpackReceived",
                            ratio, 1, 200, 200,
                            "Header compression ratio as percentage for "
                            "received headers using HPACK.");
    }
  }
}

MessageStatus QuicSpdySession::SendHttp3Datagram(QuicStreamId stream_id,
                                                 absl::string_view payload) {
  if (!SupportsH3Datagram()) {
    if (LocalHttpDatagramSupport() == HttpDatagramSupport::kNone) {
      QUIC_BUG(http datagram disabled locally)
          << "Cannot send HTTP Datagram when disabled locally";
      return MESSAGE_STATUS_UNSUPPORTED;
    } else if (!settings_received_) {
      QUIC_DLOG(INFO)
          << "Refusing to send HTTP Datagram before SETTINGS received";
      return MESSAGE_STATUS_SETTINGS_NOT_RECEIVED;
    } else {
      QUIC_DLOG(INFO) << "Refusing to send HTTP Datagram without peer support";
      return MESSAGE_STATUS_UNSUPPORTED;
    }
  }
  // Stream ID is sent divided by four as per the specification.
  uint64_t stream_id_to_write = stream_id / kHttpDatagramStreamIdDivisor;
  size_t slice_length =
      QuicDataWriter::GetVarInt62Len(stream_id_to_write) + payload.length();
  quiche::QuicheBuffer buffer(
      connection()->helper()->GetStreamSendBufferAllocator(), slice_length);
  QuicDataWriter writer(slice_length, buffer.data());
  if (!writer.WriteVarInt62(stream_id_to_write)) {
    QUIC_BUG(h3 datagram stream ID write fail)
        << "Failed to write HTTP/3 datagram stream ID";
    return MESSAGE_STATUS_INTERNAL_ERROR;
  }
  if (!writer.WriteBytes(payload.data(), payload.length())) {
    QUIC_BUG(h3 datagram payload write fail)
        << "Failed to write HTTP/3 datagram payload";
    return MESSAGE_STATUS_INTERNAL_ERROR;
  }

  quiche::QuicheMemSlice slice(std::move(buffer));
  return datagram_queue()->SendOrQueueDatagram(std::move(slice));
}

void QuicSpdySession::SetMaxDatagramTimeInQueueForStreamId(
    QuicStreamId /*stream_id*/, QuicTime::Delta max_time_in_queue) {
  // TODO(b/184598230): implement this in a way that works for multiple sessions
  // on a same connection.
  datagram_queue()->SetMaxTimeInQueue(max_time_in_queue);
}

void QuicSpdySession::OnMessageReceived(absl::string_view message) {
  QuicSession::OnMessageReceived(message);
  if (!SupportsH3Datagram()) {
    QUIC_DLOG(INFO) << "Ignoring unexpected received HTTP/3 datagram";
    return;
  }
  QuicDataReader reader(message);
  uint64_t stream_id64;
  if (!reader.ReadVarInt62(&stream_id64)) {
    QUIC_DLOG(ERROR) << "Failed to parse stream ID in received HTTP/3 datagram";
    return;
  }
  // Stream ID is sent divided by four as per the specification.
  if (stream_id64 >
      std::numeric_limits<QuicStreamId>::max() / kHttpDatagramStreamIdDivisor) {
    CloseConnectionWithDetails(
        QUIC_HTTP_FRAME_ERROR,
        absl::StrCat("Received HTTP Datagram with invalid quarter stream ID ",
                     stream_id64));
    return;
  }
  stream_id64 *= kHttpDatagramStreamIdDivisor;
  QuicStreamId stream_id = static_cast<QuicStreamId>(stream_id64);
  QuicSpdyStream* stream =
      static_cast<QuicSpdyStream*>(GetActiveStream(stream_id));
  if (stream == nullptr) {
    QUIC_DLOG(INFO) << "Received HTTP/3 datagram for unknown stream ID "
                    << stream_id;
    // TODO(b/181256914) buffer HTTP/3 datagrams with unknown stream IDs for a
    // short period of time in case they were reordered.
    return;
  }
  stream->OnDatagramReceived(&reader);
}

bool QuicSpdySession::SupportsWebTransport() {
  return WillNegotiateWebTransport() && SupportsH3Datagram() &&
         NegotiatedWebTransportVersion().has_value() && allow_extended_connect_;
}

std::optional<WebTransportHttp3Version>
QuicSpdySession::SupportedWebTransportVersion() {
  if (!SupportsWebTransport()) {
    return std::nullopt;
  }
  return NegotiatedWebTransportVersion();
}

bool QuicSpdySession::SupportsH3Datagram() const {
  return http_datagram_support_ != HttpDatagramSupport::kNone;
}

WebTransportHttp3* QuicSpdySession::GetWebTransportSession(
    WebTransportSessionId id) {
  if (!SupportsWebTransport()) {
    return nullptr;
  }
  if (!IsValidWebTransportSessionId(id, version())) {
    return nullptr;
  }
  QuicSpdyStream* connect_stream = GetOrCreateSpdyDataStream(id);
  if (connect_stream == nullptr) {
    return nullptr;
  }
  return connect_stream->web_transport();
}

bool QuicSpdySession::ShouldProcessIncomingRequests() {
  if (!ShouldBufferRequestsUntilSettings()) {
    return true;
  }

  QUICHE_RELOADABLE_FLAG_COUNT_N(quic_block_until_settings_received_copt, 2, 4);
  return settings_received_;
}

void QuicSpdySession::OnStreamWaitingForClientSettings(QuicStreamId id) {
  QUICHE_DCHECK(ShouldBufferRequestsUntilSettings());
  QUICHE_DCHECK(QuicUtils::IsBidirectionalStreamId(id, version()));
  QUICHE_RELOADABLE_FLAG_COUNT_N(quic_block_until_settings_received_copt, 3, 4);
  streams_waiting_for_settings_.insert(id);
}

void QuicSpdySession::AssociateIncomingWebTransportStreamWithSession(
    WebTransportSessionId session_id, QuicStreamId stream_id) {
  if (QuicUtils::IsOutgoingStreamId(version(), stream_id, perspective())) {
    QUIC_BUG(AssociateIncomingWebTransportStreamWithSession got outgoing stream)
        << ENDPOINT
        << "AssociateIncomingWebTransportStreamWithSession() got an outgoing "
           "stream ID: "
        << stream_id;
    return;
  }
  WebTransportHttp3* session = GetWebTransportSession(session_id);
  if (session != nullptr) {
    QUIC_DVLOG(1) << ENDPOINT
                  << "Successfully associated incoming WebTransport stream "
                  << stream_id << " with session ID " << session_id;

    session->AssociateStream(stream_id);
    return;
  }
  // Evict the oldest streams until we are under the limit.
  while (buffered_streams_.size() >= kMaxUnassociatedWebTransportStreams) {
    QUIC_DVLOG(1) << ENDPOINT << "Removing stream "
                  << buffered_streams_.front().stream_id
                  << " from buffered streams as the queue is full.";
    ResetStream(buffered_streams_.front().stream_id,
                QUIC_STREAM_WEBTRANSPORT_BUFFERED_STREAMS_LIMIT_EXCEEDED);
    buffered_streams_.pop_front();
  }
  QUIC_DVLOG(1) << ENDPOINT << "Received a WebTransport stream " << stream_id
                << " for session ID " << session_id
                << " but cannot associate it; buffering instead.";
  buffered_streams_.push_back(
      BufferedWebTransportStream{session_id, stream_id});
}

void QuicSpdySession::ProcessBufferedWebTransportStreamsForSession(
    WebTransportHttp3* session) {
  const WebTransportSessionId session_id = session->id();
  QUIC_DVLOG(1) << "Processing buffered WebTransport streams for "
                << session_id;
  auto it = buffered_streams_.begin();
  while (it != buffered_streams_.end()) {
    if (it->session_id == session_id) {
      QUIC_DVLOG(1) << "Unbuffered and associated WebTransport stream "
                    << it->stream_id << " with session " << it->session_id;
      session->AssociateStream(it->stream_id);
      it = buffered_streams_.erase(it);
    } else {
      it++;
    }
  }
}

WebTransportHttp3UnidirectionalStream*
QuicSpdySession::CreateOutgoingUnidirectionalWebTransportStream(
    WebTransportHttp3* session) {
  if (!CanOpenNextOutgoingUnidirectionalStream()) {
    return nullptr;
  }

  QuicStreamId stream_id = GetNextOutgoingUnidirectionalStreamId();
  auto stream_owned = std::make_unique<WebTransportHttp3UnidirectionalStream>(
      stream_id, this, session->id());
  WebTransportHttp3UnidirectionalStream* stream = stream_owned.get();
  ActivateStream(std::move(stream_owned));
  stream->WritePreamble();
  session->AssociateStream(stream_id);
  return stream;
}

QuicSpdyStream* QuicSpdySession::CreateOutgoingBidirectionalWebTransportStream(
    WebTransportHttp3* session) {
  QuicSpdyStream* stream = CreateOutgoingBidirectionalStream();
  if (stream == nullptr) {
    return nullptr;
  }
  QuicStreamId stream_id = stream->id();
  stream->ConvertToWebTransportDataStream(session->id());
  if (stream->web_transport_stream() == nullptr) {
    // An error in ConvertToWebTransportDataStream() would result in
    // CONNECTION_CLOSE, thus we don't need to do anything here.
    return nullptr;
  }
  session->AssociateStream(stream_id);
  return stream;
}

void QuicSpdySession::OnDatagramProcessed(
    std::optional<MessageStatus> /*status*/) {
  // TODO(b/184598230): make this work with multiple datagram flows.
}

void QuicSpdySession::DatagramObserver::OnDatagramProcessed(
    std::optional<MessageStatus> status) {
  session_->OnDatagramProcessed(status);
}

HttpDatagramSupport QuicSpdySession::LocalHttpDatagramSupport() {
  return HttpDatagramSupport::kRfc;
}

std::string HttpDatagramSupportToString(
    HttpDatagramSupport http_datagram_support) {
  switch (http_datagram_support) {
    case HttpDatagramSupport::kNone:
      return "None";
    case HttpDatagramSupport::kDraft04:
      return "Draft04";
    case HttpDatagramSupport::kRfc:
      return "Rfc";
    case HttpDatagramSupport::kRfcAndDraft04:
      return "RfcAndDraft04";
  }
  return absl::StrCat("Unknown(", static_cast<int>(http_datagram_support), ")");
}

std::ostream& operator<<(std::ostream& os,
                         const HttpDatagramSupport& http_datagram_support) {
  os << HttpDatagramSupportToString(http_datagram_support);
  return os;
}

// Must not be called after Initialize().
void QuicSpdySession::set_allow_extended_connect(bool allow_extended_connect) {
  QUIC_BUG_IF(extended connect wrong version,
              !VersionUsesHttp3(transport_version()))
      << "Try to enable/disable extended CONNECT in Google QUIC";
  QUIC_BUG_IF(extended connect on client,
              perspective() == Perspective::IS_CLIENT)
      << "Enabling/disabling extended CONNECT on the client side has no effect";
  if (ShouldNegotiateWebTransport()) {
    QUIC_BUG_IF(disable extended connect, !allow_extended_connect)
        << "Disabling extended CONNECT with web transport enabled has no "
           "effect.";
    return;
  }
  allow_extended_connect_ = allow_extended_connect;
}

void QuicSpdySession::OnConfigNegotiated() {
  QuicSession::OnConfigNegotiated();

  if (GetQuicReloadableFlag(quic_block_until_settings_received_copt) &&
      perspective() == Perspective::IS_SERVER &&
      config()->HasClientSentConnectionOption(kBSUS, Perspective::IS_SERVER)) {
    QUICHE_RELOADABLE_FLAG_COUNT_N(quic_block_until_settings_received_copt, 1,
                                   4);
    force_buffer_requests_until_settings_ = true;
  }
}

#undef ENDPOINT  // undef for jumbo builds

}  // namespace quic
