// 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 "quic/core/http/quic_spdy_session.h"

#include <algorithm>
#include <cstdint>
#include <limits>
#include <memory>
#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 "quic/core/http/http_constants.h"
#include "quic/core/http/http_decoder.h"
#include "quic/core/http/http_frames.h"
#include "quic/core/http/quic_headers_stream.h"
#include "quic/core/http/web_transport_http3.h"
#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_exported_stats.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_stack_trace.h"
#include "spdy/core/http2_frame_decoder_adapter.h"

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

namespace quic {

ABSL_CONST_INIT const size_t kMaxUnassociatedWebTransportStreams = 24;

namespace {

#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(const MaxPushIdFrame& /*frame*/) 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;
  }
  void OnWebTransportStreamFrameType(
      QuicByteCount /*header_length*/,
      WebTransportSessionId /*session_id*/) override {
    QUICHE_NOTREACHED();
  }
  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 absl::optional<std::string>& error_detail() const {
    return error_detail_;
  }

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

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

}  // namespace

// A SpdyFramerVisitor that passes HEADERS frames to the QuicSpdyStream, and
// closes the connection if any unexpected frames are received.
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_.compressed_header_bytes(),
        header_list_.uncompressed_header_bytes());

    if (session_->IsConnected()) {
      session_->OnHeaderList(header_list_);
    }
    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, 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) {
      CloseConnection("PUSH_PROMISE not supported.",
                      QUIC_INVALID_HEADERS_STREAM_DATA);
      return;
    }
    if (!session_->IsConnected()) {
      return;
    }
    session_->OnPushPromise(stream_id, promised_stream_id);
  }

  void OnContinuation(SpdyStreamId /*stream_id*/, 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 {
    // TODO(b/171470299): Parse and call
    // QuicSpdySession::OnPriorityUpdateForRequestStream().
  }

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

  // 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_;
  QuicHeaderList header_list_;
};

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_(
          kDefaultQpackMaxDynamicTableCapacity),
      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())),
      promised_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_(
          GetQuicReloadableFlag(quic_verify_request_headers) &&
          perspective() == Perspective::IS_SERVER &&
          VersionUsesHttp3(transport_version())) {
  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);
    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()) {
    HttpDatagramSupport local_http_datagram_support =
        LocalHttpDatagramSupport();
    if (local_http_datagram_support == HttpDatagramSupport::kDraft00 ||
        local_http_datagram_support == HttpDatagramSupport::kDraft00And04) {
      settings_.values[SETTINGS_H3_DATAGRAM_DRAFT00] = 1;
    }
    if (local_http_datagram_support == HttpDatagramSupport::kDraft04 ||
        local_http_datagram_support == HttpDatagramSupport::kDraft00And04) {
      settings_.values[SETTINGS_H3_DATAGRAM_DRAFT04] = 1;
    }
  }
  if (WillNegotiateWebTransport()) {
    settings_.values[SETTINGS_WEBTRANS_DRAFT00] = 1;
  }
  if (allow_extended_connect()) {
    QUIC_RELOADABLE_FLAG_COUNT_N(quic_verify_request_headers, 1, 3);
    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,
                                                       int urgency) {
  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, spdy::SpdyStreamPrecedence(urgency))) {
    return true;
  }

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

  buffered_stream_priorities_[stream_id] = urgency;

  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;
}

bool QuicSpdySession::OnPriorityUpdateForPushStream(QuicStreamId /*push_id*/,
                                                    int /*urgency*/) {
  // TODO(b/147306124): Implement PRIORITY_UPDATE frames for pushed streams.
  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, SpdyHeaderBlock headers, bool fin,
    const spdy::SpdyStreamPrecedence& precedence,
    QuicReferenceCountedPointer<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 id,
                                      QuicStreamId parent_stream_id, int weight,
                                      bool exclusive) {
  QUICHE_DCHECK(!VersionUsesHttp3(transport_version()));
  SpdyPriorityIR priority_frame(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(
    const PriorityUpdateFrame& priority_update) {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));

  send_control_stream_->WritePriorityUpdate(priority_update);
}

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_.value()) {
    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_.value()));
    return;
  }
  last_received_http3_goaway_id_ = id;

  if (perspective() == Perspective::IS_SERVER) {
    // TODO(b/151749109): Cancel server pushes with push ID larger than |id|.
    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;
  }

  // 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;
  }
  QuicStreamId stream_id;

  stream_id = QuicUtils::GetMaxClientInitiatedBidirectionalStreamId(
      transport_version());
  if (last_sent_http3_goaway_id_.has_value()) {
    if (last_sent_http3_goaway_id_.value() == stream_id) {
      // Do not send GOAWAY twice.
      return;
    }
    if (last_sent_http3_goaway_id_.value() < stream_id) {
      // A previous GOAWAY frame was sent with smaller stream ID.  This is not
      // possible, because the only time a GOAWAY frame with non-maximal
      // stream ID is sent is right before closing connection.
      QUIC_BUG(quic_bug_10360_3)
          << "Not sending GOAWAY frame with " << stream_id
          << " because one with " << last_sent_http3_goaway_id_.value()
          << " already sent on connection " << connection()->connection_id();
      return;
    }
  }

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

void QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
                                       QuicStreamId promised_stream_id,
                                       SpdyHeaderBlock headers) {
  if (perspective() == Perspective::IS_CLIENT) {
    QUIC_BUG(quic_bug_10360_4) << "Client shouldn't send PUSH_PROMISE";
    return;
  }

  if (VersionUsesHttp3(transport_version())) {
    QUIC_BUG(quic_bug_12477_6)
        << "Support for server push over HTTP/3 has been removed.";
    return;
  }

  SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
                                 std::move(headers));
  // PUSH_PROMISE must not be the last frame sent out, at least followed by
  // response headers.
  push_promise.set_fin(false);

  SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
  headers_stream()->WriteOrBufferData(
      absl::string_view(frame.data(), frame.size()), false, nullptr);
}

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

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(spdy::SpdyStreamPrecedence(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() { return false; }

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

bool QuicSpdySession::ShouldValidateWebTransportVersion() const { return true; }

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, spdy::SpdyHeaderBlock headers, bool fin,
    QuicStreamId parent_stream_id, int weight, bool exclusive,
    QuicReferenceCountedPointer<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();
}

void QuicSpdySession::OnPromiseHeaderList(
    QuicStreamId /*stream_id*/, QuicStreamId /*promised_stream_id*/,
    size_t /*frame_len*/, const QuicHeaderList& /*header_list*/) {
  std::string error =
      "OnPromiseHeaderList should be overridden in client code.";
  QUIC_BUG(quic_bug_10360_6) << error;
  connection()->CloseConnection(QUIC_INTERNAL_ERROR, error,
                                ConnectionCloseBehavior::SILENT_CLOSE);
}

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;
}

absl::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 absl::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;
    }
  }
  for (QuicStreamId stream_id : streams_waiting_for_settings_) {
    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;
}

absl::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 absl::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) {
  any_settings_received_ = true;

  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_DRAFT00: {
        HttpDatagramSupport local_http_datagram_support =
            LocalHttpDatagramSupport();
        if (local_http_datagram_support != HttpDatagramSupport::kDraft00 &&
            local_http_datagram_support != HttpDatagramSupport::kDraft00And04) {
          break;
        }
        QUIC_DVLOG(1) << ENDPOINT
                      << "SETTINGS_H3_DATAGRAM_DRAFT00 received with value "
                      << value;
        if (!version().UsesHttp3()) {
          break;
        }
        if (!VerifySettingIsZeroOrOne(id, value)) {
          return false;
        }
        if (value && http_datagram_support_ != HttpDatagramSupport::kDraft04) {
          // If both draft-00 and draft-04 are supported, use draft-04.
          http_datagram_support_ = HttpDatagramSupport::kDraft00;
        }
        break;
      }
      case SETTINGS_H3_DATAGRAM_DRAFT04: {
        HttpDatagramSupport local_http_datagram_support =
            LocalHttpDatagramSupport();
        if (local_http_datagram_support != HttpDatagramSupport::kDraft04 &&
            local_http_datagram_support != HttpDatagramSupport::kDraft00And04) {
          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::kDraft04;
        }
        break;
      }
      case SETTINGS_WEBTRANS_DRAFT00:
        if (!WillNegotiateWebTransport()) {
          break;
        }
        QUIC_DVLOG(1) << ENDPOINT
                      << "SETTINGS_ENABLE_WEBTRANSPORT received with value "
                      << value;
        if (!VerifySettingIsZeroOrOne(id, value)) {
          return false;
        }
        peer_supports_webtransport_ = (value == 1);
        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(value);
      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_);
  QUICHE_DCHECK_EQ(QuicUtils::GetInvalidStreamId(transport_version()),
                   promised_stream_id_);
  stream_id_ = stream_id;
  fin_ = fin;
}

void QuicSpdySession::OnPushPromise(SpdyStreamId stream_id,
                                    SpdyStreamId promised_stream_id) {
  QUICHE_DCHECK_EQ(QuicUtils::GetInvalidStreamId(transport_version()),
                   stream_id_);
  QUICHE_DCHECK_EQ(QuicUtils::GetInvalidStreamId(transport_version()),
                   promised_stream_id_);
  stream_id_ = stream_id;
  promised_stream_id_ = promised_stream_id;
}

// 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();
  // This code path is only executed for push promise in IETF QUIC.
  if (VersionUsesHttp3(transport_version())) {
    QUICHE_DCHECK(promised_stream_id_ !=
                  QuicUtils::GetInvalidStreamId(transport_version()));
  }
  if (promised_stream_id_ ==
      QuicUtils::GetInvalidStreamId(transport_version())) {
    OnStreamHeaderList(stream_id_, fin_, frame_len_, header_list);
  } else {
    OnPromiseHeaderList(stream_id_, promised_stream_id_, frame_len_,
                        header_list);
  }
  // Reset state for the next frame.
  promised_stream_id_ = QuicUtils::GetInvalidStreamId(transport_version());
  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::ProcessPendingStream(PendingStream* pending) {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
  QUICHE_DCHECK(connection()->connected());
  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_.value() <= stream_id) {
    // A previous GOAWAY frame was sent with smaller stream ID.  This is not
    // possible, because this is the only method sending a GOAWAY frame with
    // non-maximal stream ID, and this must only be called once, right
    // before closing connection.
    QUIC_BUG(QuicGoawayFrameAlreadySent)
        << "Not sending GOAWAY frame with " << stream_id << " because one with "
        << last_sent_http3_goaway_id_.value() << " already sent on connection "
        << connection()->connection_id();

    // MUST not send GOAWAY with identifier larger than previously sent.
    // Do not bother sending one with same identifier as before, since GOAWAY
    // 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::OnCanCreateNewOutgoingStream(bool unidirectional) {
  if (unidirectional && VersionUsesHttp3(transport_version())) {
    MaybeInitializeHttp3UnidirectionalStreams();
  }
}

bool QuicSpdySession::OnMaxPushIdFrame(PushId max_push_id) {
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
  QUICHE_DCHECK_EQ(Perspective::IS_SERVER, perspective());

  if (max_push_id_.has_value()) {
    QUIC_DVLOG(1) << "Setting max_push_id to:  " << max_push_id
                  << " from: " << max_push_id_.value();
  } else {
    QUIC_DVLOG(1) << "Setting max_push_id to:  " << max_push_id
                  << " from unset";
  }
  absl::optional<PushId> old_max_push_id = max_push_id_;
  max_push_id_ = max_push_id;

  if (!old_max_push_id.has_value() || max_push_id > old_max_push_id.value()) {
    OnCanCreateNewOutgoingStream(true);
    return true;
  }

  // Equal value is not considered an error.
  if (max_push_id < old_max_push_id.value()) {
    CloseConnectionWithDetails(
        QUIC_HTTP_INVALID_MAX_PUSH_ID,
        absl::StrCat("MAX_PUSH_ID received with value ", max_push_id,
                     " which is smaller that previously received value ",
                     old_max_push_id.value()));
    return false;
  }

  return true;
}

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();
}

bool QuicSpdySession::CanCreatePushStreamWithId(PushId /* push_id */) {
  // TODO(b/171463363): Remove this method.
  QUICHE_DCHECK(VersionUsesHttp3(transport_version()));

  return false;
}

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(
    QuicDatagramStreamId stream_id,
    absl::optional<QuicDatagramContextId> context_id,
    absl::string_view payload) {
  if (!SupportsH3Datagram()) {
    QUIC_BUG(send http datagram too early)
        << "Refusing to send HTTP Datagram before SETTINGS received";
    return MESSAGE_STATUS_INTERNAL_ERROR;
  }
  uint64_t stream_id_to_write = stream_id;
  if (http_datagram_support_ != HttpDatagramSupport::kDraft00) {
    // Stream ID is sent divided by four as per the specification.
    stream_id_to_write /= kHttpDatagramStreamIdDivisor;
  }
  size_t slice_length =
      QuicDataWriter::GetVarInt62Len(stream_id_to_write) + payload.length();
  if (context_id.has_value()) {
    slice_length += QuicDataWriter::GetVarInt62Len(context_id.value());
  }
  QuicBuffer 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 (context_id.has_value()) {
    if (!writer.WriteVarInt62(context_id.value())) {
      QUIC_BUG(h3 datagram context ID write fail)
          << "Failed to write HTTP/3 datagram context 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;
  }

  QuicMemSlice 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::RegisterHttp3DatagramFlowId(QuicDatagramStreamId flow_id,
                                                  QuicStreamId stream_id) {
  h3_datagram_flow_id_to_stream_id_map_[flow_id] = stream_id;
}

void QuicSpdySession::UnregisterHttp3DatagramFlowId(
    QuicDatagramStreamId flow_id) {
  h3_datagram_flow_id_to_stream_id_map_.erase(flow_id);
}

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;
  }
  if (http_datagram_support_ != HttpDatagramSupport::kDraft00) {
    // Stream ID is sent divided by four as per the specification.
    stream_id64 *= kHttpDatagramStreamIdDivisor;
  }
  if (perspective() == Perspective::IS_SERVER &&
      http_datagram_support_ == HttpDatagramSupport::kDraft00) {
    auto it = h3_datagram_flow_id_to_stream_id_map_.find(stream_id64);
    if (it == h3_datagram_flow_id_to_stream_id_map_.end()) {
      QUIC_DLOG(INFO) << "Received unknown HTTP/3 datagram flow ID "
                      << stream_id64;
      return;
    }
    stream_id64 = it->second;
  }
  if (stream_id64 > std::numeric_limits<QuicStreamId>::max()) {
    // TODO(b/181256914) make this a connection close once we deprecate
    // draft-ietf-masque-h3-datagram-00 in favor of later drafts.
    QUIC_DLOG(ERROR) << "Received unexpectedly high HTTP/3 datagram stream ID "
                     << stream_id64;
    return;
  }
  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 unknown HTTP/3 datagram flow IDs for a short
    // period of time in case they were reordered.
    return;
  }
  stream->OnDatagramReceived(&reader);
}

bool QuicSpdySession::SupportsWebTransport() {
  return WillNegotiateWebTransport() && SupportsH3Datagram() &&
         peer_supports_webtransport_ &&
         (!GetQuicReloadableFlag(quic_verify_request_headers) ||
          allow_extended_connect_);
}

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;
  }

  return any_settings_received_;
}

void QuicSpdySession::OnStreamWaitingForClientSettings(QuicStreamId id) {
  QUICHE_DCHECK(ShouldBufferRequestsUntilSettings());
  QUICHE_DCHECK(QuicUtils::IsBidirectionalStreamId(id, version()));
  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(
    absl::optional<MessageStatus> /*status*/) {
  // TODO(b/184598230): make this work with multiple datagram flows.
}

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

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

std::string HttpDatagramSupportToString(
    HttpDatagramSupport http_datagram_support) {
  switch (http_datagram_support) {
    case HttpDatagramSupport::kNone:
      return "None";
    case HttpDatagramSupport::kDraft00:
      return "Draft00";
    case HttpDatagramSupport::kDraft04:
      return "Draft04";
    case HttpDatagramSupport::kDraft00And04:
      return "Draft00And04";
  }
  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,
              !GetQuicReloadableFlag(quic_verify_request_headers) ||
                  !VersionUsesHttp3(transport_version()))
      << "Try to enable/disable extended CONNECT in Google QUIC";
  QUIC_BUG_IF(extended connect on client,
              !GetQuicReloadableFlag(quic_verify_request_headers) ||
                  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;
}

#undef ENDPOINT  // undef for jumbo builds

}  // namespace quic
