Make GfeQboneServerSession buffer STREAM_FRAME (with pending stream) and drop MESSAGE_FRAME before LOAS authentication completes. Other stream related frames on the server side: STREAM_RESET_FRAME -> connection close STOP_SENDING_FRAME -> connection close WINDOW_UPDATE_FRAME is handled by pending stream before LOAS authentication completes. Other stream related frames on the client side: STREAM_RESET_FRAME -> connection close STOP_SENDING_FRAME -> connection close WINDOW_UPDATE_FRAME received before LOAS authentication -> connection close Protected by FLAGS_qbone_server_support_h3_loas. PiperOrigin-RevId: 421072604
diff --git a/quic/qbone/qbone_control_stream.cc b/quic/qbone/qbone_control_stream.cc index 7303b06..61a9afe 100644 --- a/quic/qbone/qbone_control_stream.cc +++ b/quic/qbone/qbone_control_stream.cc
@@ -6,6 +6,7 @@ #include <cstdint> #include <limits> + #include "absl/strings/string_view.h" #include "quic/core/quic_session.h" #include "quic/platform/api/quic_bug_tracker.h" @@ -25,6 +26,14 @@ BIDIRECTIONAL), pending_message_size_(0) {} +QboneControlStreamBase::QboneControlStreamBase(quic::PendingStream* pending, + QuicSession* session) + : QuicStream(pending, session, /*is_static=*/true), + pending_message_size_(0) { + QUICHE_DCHECK_EQ(pending->id(), QboneConstants::GetControlStreamId( + session->transport_version())); +} + void QboneControlStreamBase::OnDataAvailable() { sequencer()->Read(&buffer_); while (true) {
diff --git a/quic/qbone/qbone_control_stream.h b/quic/qbone/qbone_control_stream.h index d0c2b1a..c38697d 100644 --- a/quic/qbone/qbone_control_stream.h +++ b/quic/qbone/qbone_control_stream.h
@@ -16,6 +16,7 @@ class QUIC_EXPORT_PRIVATE QboneControlStreamBase : public QuicStream { public: explicit QboneControlStreamBase(QuicSession* session); + QboneControlStreamBase(quic::PendingStream* pending, QuicSession* session); void OnDataAvailable() override; @@ -46,6 +47,9 @@ QboneControlStream(QuicSession* session, Handler* handler) : QboneControlStreamBase(session), handler_(handler) {} + QboneControlStream(quic::PendingStream* pending, QuicSession* session, + Handler* handler) + : QboneControlStreamBase(pending, session), handler_(handler) {} bool SendRequest(const Outgoing& request) { return SendMessage(request); }
diff --git a/quic/qbone/qbone_server_session.cc b/quic/qbone/qbone_server_session.cc index 2ddb8e4..1fc0842 100644 --- a/quic/qbone/qbone_server_session.cc +++ b/quic/qbone/qbone_server_session.cc
@@ -72,6 +72,17 @@ ActivateStream(std::move(control_stream)); } +QuicStream* QboneServerSession::CreateControlStreamFromPendingStream( + PendingStream* pending) { + QUICHE_DCHECK(control_stream_ == nullptr); + // Register the reserved control stream. + auto control_stream = + std::make_unique<QboneServerControlStream>(pending, this, handler_); + control_stream_ = control_stream.get(); + ActivateStream(std::move(control_stream)); + return control_stream_; +} + void QboneServerSession::Initialize() { QboneSessionBase::Initialize(); if (!GetQuicFlag(FLAGS_qbone_server_defer_control_stream_creation)) {
diff --git a/quic/qbone/qbone_server_session.h b/quic/qbone/qbone_server_session.h index f398f06..d206e4d 100644 --- a/quic/qbone/qbone_server_session.h +++ b/quic/qbone/qbone_server_session.h
@@ -76,9 +76,13 @@ // QboneSessionBase interface implementation. std::unique_ptr<QuicCryptoStream> CreateCryptoStream() override; - // Instantiate QboneServerControlStream. + // Instantiates QboneServerControlStream. void CreateControlStream(); + // Instantiates QboneServerControlStream from the pending stream and returns a + // pointer to it. + QuicStream* CreateControlStreamFromPendingStream(PendingStream* pending); + // The packet processor. QbonePacketProcessor processor_;