When quic_limit_sending_max_streams is enabled and MAX_STREAMS
frame is ack'd, delay sending a new MAX_STREAMS frame if the
connection is currently processing a packet.

Protected by quic_reloadable_flag_quic_limit_sending_max_streams.

PiperOrigin-RevId: 574987377
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index b9ab89f..74588ea 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -74,7 +74,7 @@
 // If true, dispatcher sends error code QUIC_HANDSHAKE_FAILED_PACKETS_BUFFERED_TOO_LONG when handshake fails due to packets buffered for too long.
 QUIC_FLAG(quic_reloadable_flag_quic_new_error_code_when_packets_buffered_too_long, true)
 // If true, do not send MAX_STREAM frames if there are already 2 outstanding.
-QUIC_FLAG(quic_reloadable_flag_quic_limit_sending_max_streams, false)
+QUIC_FLAG(quic_reloadable_flag_quic_limit_sending_max_streams2, false)
 // If true, enable server retransmittable on wire PING.
 QUIC_FLAG(quic_reloadable_flag_quic_enable_server_on_wire_ping, true)
 // If true, flush ACK frame in QuicConnection::MaybeBundleOpportunistically.
diff --git a/quiche/quic/core/quic_session.cc b/quiche/quic/core/quic_session.cc
index 4daff51..1ec3c57 100644
--- a/quiche/quic/core/quic_session.cc
+++ b/quiche/quic/core/quic_session.cc
@@ -111,7 +111,7 @@
       was_zero_rtt_rejected_(false),
       liveness_testing_in_progress_(false),
       limit_sending_max_streams_(
-          GetQuicReloadableFlag(quic_limit_sending_max_streams)) {
+          GetQuicReloadableFlag(quic_limit_sending_max_streams2)) {
   closed_streams_clean_up_alarm_ =
       absl::WrapUnique<QuicAlarm>(connection_->alarm_factory()->CreateAlarm(
           new ClosedStreamsCleanUpDelegate(this)));
@@ -880,6 +880,12 @@
     // Suppress the write before encryption gets established.
     return false;
   }
+  if (limit_sending_max_streams_ &&
+      connection_->framer().is_processing_packet()) {
+    QUIC_RELOADABLE_FLAG_COUNT_N(quic_limit_sending_max_streams2, 3, 3);
+    // The frame will be sent when OnCanWrite() is called.
+    return false;
+  }
   SetTransmissionType(type);
   QuicConnection::ScopedEncryptionLevelContext context(
       connection(), GetEncryptionLevelToSendApplicationData());
@@ -984,7 +990,7 @@
   if (!limit_sending_max_streams_) {
     return true;
   }
-  QUIC_RELOADABLE_FLAG_COUNT_N(quic_limit_sending_max_streams, 1, 2);
+  QUIC_RELOADABLE_FLAG_COUNT_N(quic_limit_sending_max_streams2, 1, 3);
   return control_frame_manager_.NumBufferedMaxStreams() < 2;
 }
 
@@ -2289,7 +2295,7 @@
       // Since there is a 2 frame limit on the number of outstanding max_streams
       // frames, when an outstanding max_streams frame is ack'd that frees up
       // room to potntially send another.
-      QUIC_RELOADABLE_FLAG_COUNT_N(quic_limit_sending_max_streams, 2, 2);
+      QUIC_RELOADABLE_FLAG_COUNT_N(quic_limit_sending_max_streams2, 2, 3);
       ietf_streamid_manager_.MaybeSendMaxStreamsFrame();
     }
     return acked;
diff --git a/quiche/quic/core/quic_session_test.cc b/quiche/quic/core/quic_session_test.cc
index d1553e8..e7e304d 100644
--- a/quiche/quic/core/quic_session_test.cc
+++ b/quiche/quic/core/quic_session_test.cc
@@ -1284,7 +1284,7 @@
 
 TEST_P(QuicSessionTestServer, LimitMaxStreams) {
   if (!VersionHasIetfQuicFrames(transport_version()) ||
-      !GetQuicReloadableFlag(quic_limit_sending_max_streams)) {
+      !GetQuicReloadableFlag(quic_limit_sending_max_streams2)) {
     return;
   }
   CompleteHandshake();