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