Disallow sending of MAX_STREAMS and STREAM_BLOCKED frame in QuicStreamIdManager before the session is configured.
gfe-relnote: protected by gfe2_reloadable_flag_quic_enable_version_draft_25_v3
PiperOrigin-RevId: 300366362
Change-Id: I66770a7047169452f423f5b13a94083d07c6e662
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index 0d7d80e..2daef86 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -2847,98 +2847,6 @@
::testing::ValuesIn(AllSupportedVersions()),
::testing::PrintToStringParamName());
-TEST_P(QuicSessionTestClientUnconfigured, HoldMaxStreamsFrame) {
- if (!VersionHasIetfQuicFrames(transport_version())) {
- return;
- }
- QuicStreamIdManager* stream_id_manager =
- QuicSessionPeer::v99_unidirectional_stream_id_manager(&session_);
-
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- QuicStreamsBlockedFrame frame(1u, 0u, /*unidirectional=*/true);
- session_.OnStreamsBlockedFrame(frame);
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(1)
- .WillRepeatedly(Invoke(&session_, &TestSession::SaveFrame));
- session_.OnConfigNegotiated();
- EXPECT_EQ(MAX_STREAMS_FRAME, session_.save_frame().type);
- EXPECT_EQ(stream_id_manager->incoming_actual_max_streams(),
- session_.save_frame().max_streams_frame.stream_count);
- EXPECT_EQ(1u, session_.save_frame().max_streams_frame.control_frame_id);
-}
-
-TEST_P(QuicSessionTestClientUnconfigured, HoldStreamsBlockedFrameXmit) {
- if (!VersionHasIetfQuicFrames(transport_version())) {
- // Applicable only to IETF QUIC
- return;
- }
- QuicStreamIdManager* stream_id_manager =
- QuicSessionPeer::v99_unidirectional_stream_id_manager(&session_);
-
- // Set the stream limit to 0 which will cause
- // CanOpenNextOutgoingUnidirectionalStream()
- // to generated a STREAMS_BLOCKED frame.
- QuicStreamIdManagerPeer::set_outgoing_max_streams(stream_id_manager, 0);
-
- // Since the stream limit is 0 and no sreams can be created this should return
- // false and have forced a streams-blocked to be queued up, with the
- // blocked stream id == 0.
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- EXPECT_FALSE(session_.CanOpenNextOutgoingUnidirectionalStream());
-
- // We will expect two calls to SendControlFrame: The first is because
- // OnConfigNegotiated does not increase the limit, so the app still can not
- // create new streams (and therefore needs the STREAMS-BLOCKED to go out). The
- // second is because the ensuing CanOpenNext.. call will fail (this test not
- // actually increasing the limit) and that will send another STREAMS-BLOCKED.
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
- .WillRepeatedly(Invoke(&session_, &TestSession::SaveFrame));
- // Set configuration data so that when the config happens, the stream limit is
- // not increased and another STREAMS-BLOCKED will be needed..
- QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_.config(), 0);
-
- session_.OnConfigNegotiated();
-
- EXPECT_EQ(STREAMS_BLOCKED_FRAME, session_.save_frame().type);
- EXPECT_EQ(0u, session_.save_frame().streams_blocked_frame.stream_count);
- EXPECT_EQ(1u, session_.save_frame().streams_blocked_frame.control_frame_id);
-
- EXPECT_FALSE(session_.CanOpenNextOutgoingUnidirectionalStream());
- EXPECT_EQ(STREAMS_BLOCKED_FRAME, session_.save_frame().type);
- EXPECT_EQ(0u, session_.save_frame().streams_blocked_frame.stream_count);
- EXPECT_EQ(2u, session_.save_frame().streams_blocked_frame.control_frame_id);
-}
-
-TEST_P(QuicSessionTestClientUnconfigured, HoldStreamsBlockedFrameNoXmit) {
- if (!VersionHasIetfQuicFrames(transport_version())) {
- return;
- }
- QuicStreamIdManager* stream_id_manager =
- QuicSessionPeer::v99_unidirectional_stream_id_manager(&session_);
-
- // Set the stream limit to 0 which will cause
- // CanOpenNextOutgoingUnidirectionalStream()
- // to generated a STREAMS_BLOCKED frame.
- QuicStreamIdManagerPeer::set_outgoing_max_streams(stream_id_manager, 0);
-
- // Since the stream limit is 0 and no streams can be created this should
- // return false and have forced a streams-blocked to be queued up, with the
- // blocked stream id == 0.
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- EXPECT_FALSE(session_.CanOpenNextOutgoingUnidirectionalStream());
-
- // Set configuration data so that when the config happens, the stream limit is
- // increased.
- QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_.config(), 10);
-
- // STREAMS_BLOCKED frame should not be sent because streams can now be
- // created.
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- session_.OnConfigNegotiated();
- EXPECT_TRUE(session_.CanOpenNextOutgoingUnidirectionalStream());
-}
-
TEST_P(QuicSessionTestClientUnconfigured, StreamInitiallyBlockedThenUnblocked) {
if (!connection_->version().AllowsLowFlowControlLimits()) {
return;
diff --git a/quic/core/quic_stream_id_manager.cc b/quic/core/quic_stream_id_manager.cc
index 8f1b413..a2d1bad 100644
--- a/quic/core/quic_stream_id_manager.cc
+++ b/quic/core/quic_stream_id_manager.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/quic_stream_id_manager.h"
+#include <cstdint>
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
@@ -42,10 +43,7 @@
incoming_stream_count_(0),
largest_peer_created_stream_id_(
QuicUtils::GetInvalidStreamId(transport_version)),
- max_streams_window_(0),
- pending_max_streams_(false),
- pending_streams_blocked_(
- QuicUtils::GetInvalidStreamId(transport_version)) {
+ max_streams_window_(0) {
CalculateIncomingMaxStreamsWindow();
}
@@ -142,7 +140,7 @@
// MAX STREAMS frame yet. Record that we would have sent one and then
// return. A new frame will be generated once the configuration is
// received.
- pending_max_streams_ = true;
+ QUIC_BUG << "Attempt to send Max Streams Frame before config is negotiated";
return;
}
incoming_advertised_max_streams_ = incoming_actual_max_streams_;
@@ -188,15 +186,12 @@
if (outgoing_stream_count_ < outgoing_max_streams_) {
return true;
}
- // Next stream ID would exceed the limit, need to inform the peer.
-
if (!is_config_negotiated_) {
- // The config is not negotiated, so we can not send the STREAMS_BLOCKED
- // frame yet. Record that we would have sent one, and what the limit was
- // when we were blocked, and return.
- pending_streams_blocked_ = outgoing_max_streams_;
+ QUIC_BUG
+ << "Creating streams before Quic session is configured is prohibitied";
return false;
}
+ // Next stream ID would exceed the limit, need to inform the peer.
delegate_->SendStreamsBlocked(outgoing_max_streams_, unidirectional_);
QUIC_CODE_COUNT(quic_reached_outgoing_stream_id_limit);
return false;
@@ -326,23 +321,6 @@
void QuicStreamIdManager::OnConfigNegotiated() {
is_config_negotiated_ = true;
- // If a STREAMS_BLOCKED or MAX_STREAMS is pending, send it and clear
- // the pending state.
- if (pending_streams_blocked_ !=
- QuicUtils::GetInvalidStreamId(transport_version_)) {
- if (pending_streams_blocked_ >= outgoing_max_streams_) {
- // There is a pending STREAMS_BLOCKED frame and the current limit does not
- // let new streams be formed. Regenerate and send the frame.
- delegate_->SendStreamsBlocked(outgoing_max_streams_, unidirectional_);
- }
- pending_streams_blocked_ =
- QuicUtils::GetInvalidStreamId(transport_version_);
- }
- if (pending_max_streams_) {
- // Generate a MAX_STREAMS using the current stream limits.
- SendMaxStreamsFrame();
- pending_max_streams_ = false;
- }
}
} // namespace quic
diff --git a/quic/core/quic_stream_id_manager.h b/quic/core/quic_stream_id_manager.h
index 9fa26c6..15b19d3 100644
--- a/quic/core/quic_stream_id_manager.h
+++ b/quic/core/quic_stream_id_manager.h
@@ -254,13 +254,6 @@
// max_streams_window_ is set to 1/2 of the initial number of incoming streams
// that are allowed (as set in the constructor).
QuicStreamId max_streams_window_;
-
- // MAX_STREAMS and STREAMS_BLOCKED frames are not sent before the session has
- // been configured. Instead, the relevant information is stored in
- // |pending_max_streams_| and |pending_streams_blocked_| and sent when
- // OnConfigNegotiated() is invoked.
- bool pending_max_streams_;
- QuicStreamId pending_streams_blocked_;
};
} // namespace quic
diff --git a/quic/core/quic_stream_id_manager_test.cc b/quic/core/quic_stream_id_manager_test.cc
index a114295..12368e9 100644
--- a/quic/core/quic_stream_id_manager_test.cc
+++ b/quic/core/quic_stream_id_manager_test.cc
@@ -483,50 +483,24 @@
stream_id_manager_.OnStreamsBlockedFrame(frame);
}
-TEST_P(QuicStreamIdManagerTest, HoldMaxStreamsFrame) {
- // The config has not been negotiated so the MAX_STREAMS frame will not be
- // sent.
+TEST_P(QuicStreamIdManagerTest, NoMaxStreamsFrameBeforeConfigured) {
+ // The config has not been negotiated so QUIC_BUG will be triggered.
EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
QuicStreamsBlockedFrame frame(1u, 0u, IsUnidirectional());
- // Should cause change in pending_max_streams.
- stream_id_manager_.OnStreamsBlockedFrame(frame);
-
- EXPECT_CALL(delegate_, SendMaxStreams(_, IsUnidirectional()));
-
- // MAX_STREAMS will be sent now that the config has been negotiated.
- stream_id_manager_.OnConfigNegotiated();
+ // Trigger sending of MAX_STREAMS.
+ EXPECT_QUIC_BUG(
+ stream_id_manager_.OnStreamsBlockedFrame(frame),
+ "Attempt to send Max Streams Frame before config is negotiated");
}
-TEST_P(QuicStreamIdManagerTest, HoldStreamsBlockedFrameXmit) {
+TEST_P(QuicStreamIdManagerTest, NoStreamCreationBeforeConfigured) {
// We should not see a STREAMS_BLOCKED frame because we're not configured..
EXPECT_CALL(delegate_, SendStreamsBlocked(_, _)).Times(0);
- // Since the stream limit is 0 and no sreams can be created this should return
- // false and have forced a STREAMS_BLOCKED to be queued up, with the
- // blocked stream id == 0.
- EXPECT_FALSE(stream_id_manager_.CanOpenNextOutgoingStream());
-
- // Since the steam limit has not been increased when the config was negotiated
- // a STREAMS_BLOCKED frame should be sent.
- EXPECT_CALL(delegate_, SendStreamsBlocked(_, IsUnidirectional()));
- stream_id_manager_.OnConfigNegotiated();
-}
-
-TEST_P(QuicStreamIdManagerTest, HoldStreamsBlockedFrameNoXmit) {
- // We should not see a STREAMS_BLOCKED frame because we're not configured..
- EXPECT_CALL(delegate_, SendStreamsBlocked(_, IsUnidirectional())).Times(0);
-
- // Since the stream limit is 0 and no sreams can be created this should return
- // false and have forced a STREAMS_BLOCKED to be queued up, with the
- // blocked stream id == 0.
- EXPECT_FALSE(stream_id_manager_.CanOpenNextOutgoingStream());
-
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(IsUnidirectional()));
- stream_id_manager_.SetMaxOpenOutgoingStreams(10);
- // Since the stream limit has been increase which allows streams to be created
- // no STREAMS_BLOCKED should be send.
- stream_id_manager_.OnConfigNegotiated();
+ EXPECT_QUIC_BUG(
+ stream_id_manager_.CanOpenNextOutgoingStream(),
+ "Creating streams before Quic session is configured is prohibitied");
}
TEST_P(QuicStreamIdManagerTest, CheckMaxAllowedOutgoingInitialization) {
diff --git a/quic/core/uber_quic_stream_id_manager_test.cc b/quic/core/uber_quic_stream_id_manager_test.cc
index b7acc68..d7e9cc1 100644
--- a/quic/core/uber_quic_stream_id_manager_test.cc
+++ b/quic/core/uber_quic_stream_id_manager_test.cc
@@ -145,6 +145,7 @@
}
TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenOutgoingStreams) {
+ manager_.OnConfigNegotiated();
const size_t kNumMaxOutgoingStream = 123;
// Set the uni- and bi- directional limits to different values to ensure
// that they are managed separately.
@@ -171,6 +172,7 @@
manager_.GetNextOutgoingUnidirectionalStreamId();
// Both should be exhausted...
+ EXPECT_CALL(delegate_, SendStreamsBlocked(_, _)).Times(2);
EXPECT_FALSE(manager_.CanOpenNextOutgoingUnidirectionalStream());
EXPECT_FALSE(manager_.CanOpenNextOutgoingBidirectionalStream());
}
@@ -351,6 +353,7 @@
}
TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenOutgoingStreamsPlusFrame) {
+ manager_.OnConfigNegotiated();
const size_t kNumMaxOutgoingStream = 123;
// Set the uni- and bi- directional limits to different values to ensure
// that they are managed separately.
@@ -377,6 +380,7 @@
manager_.GetNextOutgoingUnidirectionalStreamId();
// Both should be exhausted...
+ EXPECT_CALL(delegate_, SendStreamsBlocked(_, _)).Times(3);
EXPECT_FALSE(manager_.CanOpenNextOutgoingUnidirectionalStream());
EXPECT_FALSE(manager_.CanOpenNextOutgoingBidirectionalStream());