Prevent IETF QUIC Frame transmission prior to config A number of IETF QUIC fames, including MAX_STREAMS and STREAMS_BLOCKED, should not be sent prior to having the session configured. gfe-relnote: N/A IETF QUIC, protected via V99 flag. PiperOrigin-RevId: 269611696 Change-Id: Ibed580f9bff8f716f3f78481022b5c929f5634ef
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc index 310081c..8ea04f8 100644 --- a/quic/core/http/quic_spdy_session_test.cc +++ b/quic/core/http/quic_spdy_session_test.cc
@@ -1645,6 +1645,9 @@ // it) does not count against the open quota (because it is closed from the // protocol point of view). if (VersionHasIetfQuicFrames(transport_version())) { + // Simulate receiving a config. so that MAX_STREAMS/etc frames may + // be transmitted + QuicSessionPeer::set_is_configured(&session_, true); // Version 99 will result in a MAX_STREAMS frame as streams are consumed // (via the OnStreamFrame call) and then released (via // StreamDraining). Eventually this node will believe that the peer is
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc index 9ede3f8..23873d0 100644 --- a/quic/core/quic_session.cc +++ b/quic/core/quic_session.cc
@@ -1044,6 +1044,13 @@ config_.ReceivedInitialSessionFlowControlWindowBytes()); } is_configured_ = true; + + // Inform stream ID manager so that it can reevaluate any deferred + // STREAMS_BLOCKED or MAX_STREAMS frames against the config and either send + // the frames or discard them. + if (VersionHasIetfQuicFrames(connection_->transport_version())) { + v99_streamid_manager_.OnConfigNegotiated(); + } } void QuicSession::AdjustInitialFlowControlWindows(size_t stream_window) {
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc index 004af59..60178fe 100644 --- a/quic/core/quic_session_test.cc +++ b/quic/core/quic_session_test.cc
@@ -32,6 +32,7 @@ #include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h" +#include "net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" @@ -155,7 +156,6 @@ } ~TestSession() override { - EXPECT_TRUE(is_configured()); delete connection(); } @@ -284,14 +284,14 @@ return consumed; } + const QuicFrame& save_frame() { return save_frame_; } + bool SaveFrame(const QuicFrame& frame) { save_frame_ = frame; DeleteFrame(&const_cast<QuicFrame&>(frame)); return true; } - const QuicFrame& save_frame() { return save_frame_; } - QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) { DCHECK(writev_consumes_all_data_); return WritevData(stream, stream->id(), bytes, 0, FIN); @@ -308,6 +308,7 @@ } using QuicSession::ActivateStream; + using QuicSession::CanOpenNextOutgoingUnidirectionalStream; using QuicSession::closed_streams; using QuicSession::zombie_streams; @@ -322,13 +323,14 @@ class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> { protected: - explicit QuicSessionTestBase(Perspective perspective) + QuicSessionTestBase(Perspective perspective, bool configure_session) : connection_( new StrictMock<MockQuicConnection>(&helper_, &alarm_factory_, perspective, SupportedVersions(GetParam()))), - session_(connection_, &session_visitor_) { + session_(connection_, &session_visitor_), + configure_session_(configure_session) { session_.config()->SetInitialStreamFlowControlWindowToSend( kInitialStreamFlowControlWindowForTest); session_.config()->SetInitialSessionFlowControlWindowToSend( @@ -341,12 +343,20 @@ QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow( session_.config(), kMinimumFlowControlSendWindow); connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); - session_.OnConfigNegotiated(); + if (configure_session) { + session_.OnConfigNegotiated(); + } TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream(); EXPECT_CALL(*crypto_stream, HasPendingRetransmission()) .Times(testing::AnyNumber()); } + ~QuicSessionTestBase() { + if (configure_session_) { + EXPECT_TRUE(session_.is_configured()); + } + } + void CheckClosedStreams() { QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId( connection_->transport_version(), Perspective::IS_CLIENT); @@ -440,6 +450,7 @@ StrictMock<MockQuicConnection>* connection_; TestSession session_; std::set<QuicStreamId> closed_streams_; + bool configure_session_; }; class QuicSessionTestServer : public QuicSessionTestBase { @@ -479,7 +490,7 @@ protected: QuicSessionTestServer() - : QuicSessionTestBase(Perspective::IS_SERVER), + : QuicSessionTestBase(Perspective::IS_SERVER, /*configure_session=*/true), path_frame_buffer1_({0, 1, 2, 3, 4, 5, 6, 7}), path_frame_buffer2_({8, 9, 10, 11, 12, 13, 14, 15}), client_framer_(SupportedVersions(GetParam()), @@ -1943,7 +1954,9 @@ class QuicSessionTestClient : public QuicSessionTestBase { protected: - QuicSessionTestClient() : QuicSessionTestBase(Perspective::IS_CLIENT) {} + QuicSessionTestClient() + : QuicSessionTestBase(Perspective::IS_CLIENT, + /*configure_session=*/true) {} }; INSTANTIATE_TEST_SUITE_P(Tests, @@ -2553,6 +2566,7 @@ // Applicable only to IETF QUIC return; } + QuicStreamId bidirectional_stream_id = StreamCountToId( QuicSessionPeer::v99_streamid_manager(&session_) ->advertised_max_allowed_incoming_bidirectional_streams() + @@ -2729,6 +2743,113 @@ } } +// A client test class that can be used when the automatic configuration is not +// desired. +class QuicSessionTestClientUnconfigured : public QuicSessionTestBase { + protected: + QuicSessionTestClientUnconfigured() + : QuicSessionTestBase(Perspective::IS_CLIENT, + /*configure_session=*/false) {} +}; + +INSTANTIATE_TEST_SUITE_P(Tests, + QuicSessionTestClientUnconfigured, + ::testing::ValuesIn(AllSupportedVersions())); + +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::SetReceivedMaxIncomingUnidirectionalStreams(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::SetReceivedMaxIncomingUnidirectionalStreams(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()); +} + } // namespace } // namespace test } // namespace quic
diff --git a/quic/core/quic_stream_id_manager.cc b/quic/core/quic_stream_id_manager.cc index c400d77..9d94157 100644 --- a/quic/core/quic_stream_id_manager.cc +++ b/quic/core/quic_stream_id_manager.cc
@@ -39,7 +39,10 @@ incoming_stream_count_(0), largest_peer_created_stream_id_( QuicUtils::GetInvalidStreamId(transport_version())), - max_streams_window_(0) { + max_streams_window_(0), + pending_max_streams_(false), + pending_streams_blocked_( + QuicUtils::GetInvalidStreamId(transport_version())) { CalculateIncomingMaxStreamsWindow(); } @@ -50,20 +53,11 @@ // Ensure that the frame has the correct directionality. DCHECK_EQ(frame.unidirectional, unidirectional_); QUIC_CODE_COUNT_N(quic_max_streams_received, 2, 2); - const QuicStreamCount current_outgoing_max_streams = outgoing_max_streams_; // Set the limit to be exactly the stream count in the frame. - if (!SetMaxOpenOutgoingStreams(frame.stream_count)) { - return false; - } - // If we were at the previous limit and this MAX_STREAMS frame - // increased the limit, inform the application that new streams are - // available. - if (outgoing_stream_count_ == current_outgoing_max_streams && - current_outgoing_max_streams < outgoing_max_streams_) { - session_->OnCanCreateNewOutgoingStream(unidirectional_); - } - return true; + // Also informs the higher layers that they can create more + // streams if the limit is increased. + return SetMaxOpenOutgoingStreams(frame.stream_count); } // The peer sends a streams blocked frame when it can not open any more @@ -140,6 +134,11 @@ outgoing_max_streams_ = std::min<size_t>( max_open_streams, QuicUtils::GetMaxStreamCount(unidirectional_, session_->perspective())); + + // Inform the higher layers that the stream limit has increased and that + // new streams may be created. + session_->OnCanCreateNewOutgoingStream(unidirectional_); + return true; } @@ -171,6 +170,13 @@ } void QuicStreamIdManager::SendMaxStreamsFrame() { + if (!session_->is_configured()) { + // Session not configured, so we can not send the MAX STREAMS frame yet. + // Remember that we would have sent one and then return. A new frame will + // be generated once the configuration is received. + pending_max_streams_ = true; + return; + } incoming_advertised_max_streams_ = incoming_actual_max_streams_; session_->SendMaxStreams(incoming_advertised_max_streams_, unidirectional_); } @@ -213,6 +219,15 @@ return true; } // Next stream ID would exceed the limit, need to inform the peer. + + if (!session_->is_configured()) { + // Session not configured, so we can not send the STREAMS_BLOCKED frame yet. + // Remember that we would have sent one, and what the limit was when we were + // blocked, and return. + pending_streams_blocked_ = outgoing_max_streams_; + return false; + } + session_->SendStreamsBlocked(outgoing_max_streams_, unidirectional_); QUIC_CODE_COUNT(quic_reached_outgoing_stream_id_limit); return false; @@ -342,4 +357,25 @@ } } +void QuicStreamIdManager::OnConfigNegotiated() { + QuicConnection::ScopedPacketFlusher flusher(session_->connection()); + // 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. + session_->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 baba5ac..51524ba 100644 --- a/quic/core/quic_stream_id_manager.h +++ b/quic/core/quic_stream_id_manager.h
@@ -149,6 +149,10 @@ QuicTransportVersion transport_version() const; + // Called when session has been configured. Causes the Stream ID manager to + // send out any pending MAX_STREAMS and STREAMS_BLOCKED frames. + void OnConfigNegotiated(); + private: friend class test::QuicSessionPeer; friend class test::QuicStreamIdManagerPeer; @@ -226,6 +230,13 @@ // 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 06eb141..67f20f4 100644 --- a/quic/core/quic_stream_id_manager_test.cc +++ b/quic/core/quic_stream_id_manager_test.cc
@@ -56,6 +56,9 @@ public: TestQuicSession(QuicConnection* connection) : MockQuicSession(connection, /*create_mock_crypto_stream=*/true) { + // Initialize to an invalid frame type to detect cases where the frame type + // is not set subsequently. + save_frame_.type = static_cast<QuicFrameType>(-1); Initialize(); } @@ -277,6 +280,10 @@ QuicStreamCount stream_count = stream_id_manager_->incoming_initial_max_open_streams() - 1; QuicStreamsBlockedFrame frame(0, stream_count, /*unidirectional=*/false); + + // Simulate being configured so that the MAX_STREAMS is transmitted. + session_->OnConfigNegotiated(); + session_->OnStreamsBlockedFrame(frame); // We should see a MAX_STREAMS frame. @@ -395,6 +402,9 @@ // Get the current maximum allowed incoming stream count. QuicStreamCount advertised_stream_count = stream_id_manager_->incoming_advertised_max_streams(); + // Simulate receiving a config to allow frame transmission + session_->OnConfigNegotiated(); + QuicStreamsBlockedFrame frame; frame.unidirectional = IsUnidi(); @@ -457,6 +467,15 @@ // Number of streams we can open and the first one we should get when // opening... size_t number_of_streams = kDefaultMaxStreamsPerConnection; + + // Set up config to allow the default stream limit and then + // simulate receiving a config to allow frame transmission + QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams( + session_->config(), kDefaultMaxStreamsPerConnection); + QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams( + session_->config(), kDefaultMaxStreamsPerConnection); + session_->OnConfigNegotiated(); + QuicStreamId stream_id = IsUnidi() ? session_->next_outgoing_unidirectional_stream_id() : session_->next_outgoing_bidirectional_stream_id(); @@ -510,6 +529,9 @@ // Test the MAX STREAMS Window functionality. TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerServerMaxStreams) { + // Simulate completed config to allow frame transmission + session_->OnConfigNegotiated(); + // Test that a MAX_STREAMS frame is generated when the peer has less than // |max_streams_window_| streams left that it can initiate. @@ -585,6 +607,9 @@ // Check that edge conditions of the stream count in a STREAMS_BLOCKED frame // are. properly handled. TEST_P(QuicStreamIdManagerTestClient, StreamsBlockedEdgeConditions) { + // Simulate completed config to allow frame transmission + session_->OnConfigNegotiated(); + QuicStreamsBlockedFrame frame; frame.unidirectional = IsUnidi(); @@ -607,6 +632,28 @@ EXPECT_EQ(123u, session_->save_frame().max_streams_frame.stream_count); } +TEST_P(QuicStreamIdManagerTestClient, HoldMaxStreamsFrame) { + if (!VersionHasIetfQuicFrames(transport_version())) { + return; + } + + // The session has not been configured so frame transmission will not be + // allowed. + EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0); + + QuicStreamsBlockedFrame frame( + 1u, 0u, QuicStreamIdManagerPeer::get_unidirectional(stream_id_manager_)); + // Should cause change in pending_max_streams. + stream_id_manager_->OnStreamsBlockedFrame(frame); + // Will do OnConfig. We should see a control frame pop out now. + EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1); + + // Now allow frame transmission -- which happens when the QuicSession + // receives the configuration and calls + // QuicStreamIdManager::OnConfigNegotiated() + session_->OnConfigNegotiated(); +} + // Following tests all are server-specific. They depend, in some way, on // server-specific attributes, such as the initial stream ID. @@ -616,6 +663,64 @@ : QuicStreamIdManagerTestBase(Perspective::IS_SERVER) {} }; +TEST_P(QuicStreamIdManagerTestClient, HoldStreamsBlockedFrameXmit) { + if (!VersionHasIetfQuicFrames(transport_version())) { + return; + } + + // set outgoing limit to 0, will cause the CanOpenNext... to fail + // leading to a STREAMS_BLOCKED. + QuicStreamIdManagerPeer::set_outgoing_max_streams(stream_id_manager_, 0); + + // We should not see a STREAMS-BLOCKED frame because we're not configured.. + EXPECT_CALL(*connection_, SendControlFrame(_)).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()); + + // Simulate receipt of the configuration; This case does not update the + // outgoing stream limit, so the on-config should result in a streams-blocked + // being sent. + EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1); + QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams( + session_->config(), 0); + QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(session_->config(), + 0); + session_->OnConfigNegotiated(); +} + +TEST_P(QuicStreamIdManagerTestClient, HoldStreamsBlockedFrameNoXmit) { + if (!VersionHasIetfQuicFrames(transport_version())) { + return; + } + // Set outgoing limit to 0, will cause the CanOpenNext... to fail + // leading to a STREAMS_BLOCKED. + QuicStreamIdManagerPeer::set_outgoing_max_streams(stream_id_manager_, 0); + + // We should not see a STREAMS-BLOCKED frame because we're not configured.. + EXPECT_CALL(*connection_, SendControlFrame(_)).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 config gives some streams to create, we should not see + // a STREAMS-BLOCKED frame. + EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0); + + // Do the configuration. The stream limits are increased, allowing this + // node to create more streams, so we should not see the pending + // STREAMS-BLOCKED frame get transmitted. + QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams( + session_->config(), 10); + QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(session_->config(), + 10); + session_->OnConfigNegotiated(); +} + INSTANTIATE_TEST_SUITE_P(Tests, QuicStreamIdManagerTestServer, testing::Bool()); // This test checks that the initialization for the maximum allowed outgoing @@ -677,6 +782,13 @@ // Tast that an attempt to create an outgoing stream does not exceed the limit // and that it generates an appropriate STREAMS_BLOCKED frame. TEST_P(QuicStreamIdManagerTestServer, NewStreamDoesNotExceedLimit) { + // Configure with some number of streams, and allow frame transmission + QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams( + session_->config(), 100); + QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(session_->config(), + 100); + session_->OnConfigNegotiated(); + size_t stream_count = stream_id_manager_->outgoing_max_streams(); EXPECT_NE(0u, stream_count); TestQuicStream* stream;
diff --git a/quic/core/uber_quic_stream_id_manager.h b/quic/core/uber_quic_stream_id_manager.h index 61eaf62..4db221a 100644 --- a/quic/core/uber_quic_stream_id_manager.h +++ b/quic/core/uber_quic_stream_id_manager.h
@@ -83,6 +83,11 @@ QuicStreamCount advertised_max_allowed_incoming_unidirectional_streams() const; + void OnConfigNegotiated() { + bidirectional_stream_id_manager_.OnConfigNegotiated(); + unidirectional_stream_id_manager_.OnConfigNegotiated(); + } + private: friend class test::QuicSessionPeer; friend class test::UberQuicStreamIdManagerPeer;
diff --git a/quic/core/uber_quic_stream_id_manager_test.cc b/quic/core/uber_quic_stream_id_manager_test.cc index 6d4990e..3362139 100644 --- a/quic/core/uber_quic_stream_id_manager_test.cc +++ b/quic/core/uber_quic_stream_id_manager_test.cc
@@ -313,6 +313,8 @@ } TEST_P(UberQuicStreamIdManagerTest, OnStreamsBlockedFrame) { + // Allow MAX_STREAMS frame transmission + QuicSessionPeer::set_is_configured(session_.get(), true); // Set up to capture calls to SendControlFrame - when a STREAMS_BLOCKED // frame is received, it will result in a a new MAX_STREAMS frame being // sent (if new streams can be made available).
diff --git a/quic/test_tools/quic_session_peer.cc b/quic/test_tools/quic_session_peer.cc index 22ccb28..001f1ca 100644 --- a/quic/test_tools/quic_session_peer.cc +++ b/quic/test_tools/quic_session_peer.cc
@@ -241,5 +241,10 @@ return it == session->pending_stream_map_.end() ? nullptr : it->second.get(); } +// static +void QuicSessionPeer::set_is_configured(QuicSession* session, bool value) { + session->is_configured_ = value; +} + } // namespace test } // namespace quic
diff --git a/quic/test_tools/quic_session_peer.h b/quic/test_tools/quic_session_peer.h index 79338fc..eed3bdd 100644 --- a/quic/test_tools/quic_session_peer.h +++ b/quic/test_tools/quic_session_peer.h
@@ -86,6 +86,7 @@ bool close_write_side_only); static PendingStream* GetPendingStream(QuicSession* session, QuicStreamId stream_id); + static void set_is_configured(QuicSession* session, bool value); }; } // namespace test
diff --git a/quic/test_tools/quic_stream_id_manager_peer.cc b/quic/test_tools/quic_stream_id_manager_peer.cc index 3ce5f1f..6c08ece 100644 --- a/quic/test_tools/quic_stream_id_manager_peer.cc +++ b/quic/test_tools/quic_stream_id_manager_peer.cc
@@ -20,10 +20,23 @@ } // static +void QuicStreamIdManagerPeer::set_outgoing_max_streams( + QuicStreamIdManager* stream_id_manager, + QuicStreamCount count) { + stream_id_manager->outgoing_max_streams_ = count; +} + +// static QuicStreamId QuicStreamIdManagerPeer::GetFirstIncomingStreamId( QuicStreamIdManager* stream_id_manager) { return stream_id_manager->GetFirstIncomingStreamId(); } +// static +bool QuicStreamIdManagerPeer::get_unidirectional( + QuicStreamIdManager* stream_id_manager) { + return stream_id_manager->unidirectional_; +} + } // namespace test } // namespace quic
diff --git a/quic/test_tools/quic_stream_id_manager_peer.h b/quic/test_tools/quic_stream_id_manager_peer.h index cc78aee..4c97512 100644 --- a/quic/test_tools/quic_stream_id_manager_peer.h +++ b/quic/test_tools/quic_stream_id_manager_peer.h
@@ -22,9 +22,13 @@ static void set_incoming_actual_max_streams( QuicStreamIdManager* stream_id_manager, QuicStreamCount count); + static void set_outgoing_max_streams(QuicStreamIdManager* stream_id_manager, + QuicStreamCount count); static QuicStreamId GetFirstIncomingStreamId( QuicStreamIdManager* stream_id_manager); + + static bool get_unidirectional(QuicStreamIdManager* stream_id_manager); }; } // namespace test
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h index 8ba9615..ba5e1cd 100644 --- a/quic/test_tools/quic_test_utils.h +++ b/quic/test_tools/quic_test_utils.h
@@ -632,6 +632,12 @@ MOCK_CONST_METHOD0(IsCryptoHandshakeConfirmed, bool()); MOCK_CONST_METHOD0(ShouldKeepConnectionAlive, bool()); MOCK_METHOD2(SendStopSending, void(uint16_t code, QuicStreamId stream_id)); +#ifdef undefined + MOCK_METHOD2(SendMaxStreams, + void(QuicStreamCount stream_count, bool unidirectional)); + MOCK_METHOD2(SendStreamsBlocked, + void(QuicStreamCount stream_count, bool unidirectional)); +#endif MOCK_METHOD1(OnCryptoHandshakeEvent, void(QuicSession::CryptoHandshakeEvent)); MOCK_CONST_METHOD0(GetAlpnsToOffer, std::vector<std::string>()); MOCK_CONST_METHOD1(SelectAlpn,