Add a new StopIncreasingIncomingMaxStreams() method to QuicStreamIdManager which prevents the incoming max streams limit from being increased. PiperOrigin-RevId: 571114450
diff --git a/quiche/quic/core/quic_stream_id_manager.cc b/quiche/quic/core/quic_stream_id_manager.cc index 1443211..91e8e9d 100644 --- a/quiche/quic/core/quic_stream_id_manager.cc +++ b/quiche/quic/core/quic_stream_id_manager.cc
@@ -37,7 +37,8 @@ incoming_initial_max_open_streams_(max_allowed_incoming_streams), incoming_stream_count_(0), largest_peer_created_stream_id_( - QuicUtils::GetInvalidStreamId(version.transport_version)) {} + QuicUtils::GetInvalidStreamId(version.transport_version)), + stop_increasing_incoming_max_streams_(false) {} QuicStreamIdManager::~QuicStreamIdManager() {} @@ -129,9 +130,11 @@ // supports. Nothing can be done here. return; } - // One stream closed, and another one can be opened. - incoming_actual_max_streams_++; - MaybeSendMaxStreamsFrame(); + if (!stop_increasing_incoming_max_streams_) { + // One stream closed, and another one can be opened. + incoming_actual_max_streams_++; + MaybeSendMaxStreamsFrame(); + } } QuicStreamId QuicStreamIdManager::GetNextOutgoingStreamId() {
diff --git a/quiche/quic/core/quic_stream_id_manager.h b/quiche/quic/core/quic_stream_id_manager.h index 45c7666..922c09a 100644 --- a/quiche/quic/core/quic_stream_id_manager.h +++ b/quiche/quic/core/quic_stream_id_manager.h
@@ -91,6 +91,11 @@ // Returns true if |id| is still available. bool IsAvailableStream(QuicStreamId id) const; + // Once called, the incoming max streams limit will never be increased. + void StopIncreasingIncomingMaxStreams() { + stop_increasing_incoming_max_streams_ = true; + } + QuicStreamCount incoming_initial_max_open_streams() const { return incoming_initial_max_open_streams_; } @@ -178,6 +183,9 @@ absl::flat_hash_set<QuicStreamId> available_streams_; QuicStreamId largest_peer_created_stream_id_; + + // If true, then the stream limit will never be increased. + bool stop_increasing_incoming_max_streams_; }; } // namespace quic
diff --git a/quiche/quic/core/quic_stream_id_manager_test.cc b/quiche/quic/core/quic_stream_id_manager_test.cc index 5b13112..d1e8137 100644 --- a/quiche/quic/core/quic_stream_id_manager_test.cc +++ b/quiche/quic/core/quic_stream_id_manager_test.cc
@@ -377,6 +377,44 @@ stream_id_manager_.OnStreamClosed(stream_id); } +TEST_P(QuicStreamIdManagerTest, MaxStreamsWindowStopsIncreasing) { + // Verify that the incoming stream limit does not increase after + // StopIncreasingIncomingMaxStreams() is called, even when streams ar closed. + + QuicStreamId stream_count = + stream_id_manager_.incoming_initial_max_open_streams(); + // Open up to the stream limit. + QuicStreamId stream_id = GetNthIncomingStreamId(0); + for (QuicStreamCount i = 0; i < stream_count; ++i) { + EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id, + nullptr)); + + stream_id += QuicUtils::StreamIdDelta(transport_version()); + } + + // Prevent max streams from increasing. + stream_id_manager_.StopIncreasingIncomingMaxStreams(); + + // Since the limit does not increase, a MAX_STREAMS frame will not be sent. + EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0); + + // Now close them. + stream_id = GetNthIncomingStreamId(0); + QuicStreamCount expected_actual_max = + stream_id_manager_.incoming_actual_max_streams(); + QuicStreamCount expected_advertised_max_streams = + stream_id_manager_.incoming_advertised_max_streams(); + for (QuicStreamCount i = 0; i < stream_count; ++i) { + stream_id_manager_.OnStreamClosed(stream_id); + stream_id += QuicUtils::StreamIdDelta(transport_version()); + // Limits should not change. + EXPECT_EQ(expected_actual_max, + stream_id_manager_.incoming_actual_max_streams()); + EXPECT_EQ(expected_advertised_max_streams, + stream_id_manager_.incoming_advertised_max_streams()); + } +} + TEST_P(QuicStreamIdManagerTest, StreamsBlockedEdgeConditions) { QuicStreamsBlockedFrame frame; frame.unidirectional = IsUnidirectional();