Allow creation of HTTP/3 static stream after MAX_STREAM frame is received.

outgoing_max_streams_ is not incremented after MAX_STREAM frame to reflect the intention that after max stream settings, outgoing_max_streams_ becomes the real max stream count, including static streams.

gfe-relnote: v99 only, not protected.
PiperOrigin-RevId: 263140936
Change-Id: I187fcaf6874f1e8386edb497ba92b7a7b563bfea
diff --git a/quic/core/quic_stream_id_manager.cc b/quic/core/quic_stream_id_manager.cc
index f384776..8865a1d 100644
--- a/quic/core/quic_stream_id_manager.cc
+++ b/quic/core/quic_stream_id_manager.cc
@@ -276,10 +276,6 @@
     return true;
   }
 
-  QUIC_BUG_IF(!using_default_max_streams_)
-      << "Attempted to allocate static stream (id " << stream_id
-      << ") after receiving a MAX_STREAMS frame";
-
   // If we have reached the limit on stream creation, do not create
   // the static stream; return false.
   if (outgoing_max_streams_ >=
@@ -291,7 +287,9 @@
   // outgoing_max_streams_ was inialized to a "maximum request/response" count
   // and only becomes a maximum stream count when we receive the first
   // MAX_STREAMS.
-  outgoing_max_streams_++;
+  if (using_default_max_streams_) {
+    outgoing_max_streams_++;
+  }
   outgoing_static_stream_count_++;
   return true;
 }
diff --git a/quic/core/quic_stream_id_manager_test.cc b/quic/core/quic_stream_id_manager_test.cc
index 30ff954..bd41e45 100644
--- a/quic/core/quic_stream_id_manager_test.cc
+++ b/quic/core/quic_stream_id_manager_test.cc
@@ -867,6 +867,30 @@
   EXPECT_EQ(max_stream_count, stream_id_manager_->outgoing_max_streams());
 }
 
+// Check that static streams can be created before and after MAX_STREAM frame is
+// received.
+TEST_P(QuicStreamIdManagerTestServer, RegisterStaticStreams) {
+  EXPECT_EQ(0u, stream_id_manager_->outgoing_static_stream_count());
+  QuicStreamCount previous_max = stream_id_manager_->outgoing_max_streams();
+  stream_id_manager_->RegisterStaticStream(
+      stream_id_manager_->GetNextOutgoingStreamId(),
+      /*stream_already_counted = */ false);
+  EXPECT_EQ(1u, stream_id_manager_->outgoing_static_stream_count());
+  EXPECT_EQ(previous_max + 1, stream_id_manager_->outgoing_max_streams());
+
+  QuicMaxStreamsFrame frame;
+  frame.unidirectional = IsUnidi();
+  frame.stream_count = 20;
+  EXPECT_TRUE(stream_id_manager_->OnMaxStreamsFrame(frame));
+  EXPECT_EQ(20u, stream_id_manager_->outgoing_max_streams());
+
+  stream_id_manager_->RegisterStaticStream(
+      stream_id_manager_->GetNextOutgoingStreamId(),
+      /*stream_already_counted = */ false);
+  EXPECT_EQ(2u, stream_id_manager_->outgoing_static_stream_count());
+  EXPECT_EQ(20u, stream_id_manager_->outgoing_max_streams());
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic