gfe-relnote: In gQUIC, move dynamic stream accounting to LegacyStreamIdManager. Protected by gfe2_reloadable_flag_quic_stream_id_manager_handles_accounting. Making it clear that QuicSession::GetNumOpenIncomingStreams and QuicSession::GetNumOpenOutgoingStreams are only used for gQUIC. PiperOrigin-RevId: 308126943 Change-Id: Ib57ab52bf023ea83e1ada418ced8cb1dd08d186a
diff --git a/quic/core/http/quic_server_session_base_test.cc b/quic/core/http/quic_server_session_base_test.cc index 606d3eb..51b981f 100644 --- a/quic/core/http/quic_server_session_base_test.cc +++ b/quic/core/http/quic_server_session_base_test.cc
@@ -236,7 +236,7 @@ QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0, quiche::QuicheStringPiece("HT")); session_->OnStreamFrame(data1); - EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); // Send a reset (and expect the peer to send a RST in response). QuicRstStreamFrame rst1(kInvalidControlFrameId, @@ -258,13 +258,12 @@ InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0), QUIC_ERROR_PROCESSING_STREAM); - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); - + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); // Send the same two bytes of payload in a new packet. session_->OnStreamFrame(data1); // The stream should not be re-opened. - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); EXPECT_TRUE(connection_->connected()); } @@ -289,15 +288,14 @@ InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0), QUIC_ERROR_PROCESSING_STREAM); - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); - + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); // Send two bytes of payload. QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0, quiche::QuicheStringPiece("HT")); session_->OnStreamFrame(data1); // The stream should never be opened, now that the reset is received. - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); EXPECT_TRUE(connection_->connected()); } @@ -309,7 +307,7 @@ quiche::QuicheStringPiece("\2\0\0\0\0\0\0\0HT")); session_->OnStreamFrame(frame1); session_->OnStreamFrame(frame2); - EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); // Send a reset (and expect the peer to send a RST in response). QuicRstStreamFrame rst(kInvalidControlFrameId, @@ -341,7 +339,7 @@ session_->OnStreamFrame(frame3); session_->OnStreamFrame(frame4); // The stream should never be opened, now that the reset is received. - EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); EXPECT_TRUE(connection_->connected()); } @@ -361,7 +359,7 @@ EXPECT_EQ(kMaxStreamsForTest + kMaxStreamsMinimumIncrement, session_->max_open_incoming_bidirectional_streams()); } - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0); // Open the max configured number of streams, should be no problem. for (size_t i = 0; i < kMaxStreamsForTest; ++i) { @@ -407,7 +405,7 @@ const size_t kAvailableStreamLimit = session_->MaxAvailableBidirectionalStreams(); - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateStream( session_.get(), GetNthClientInitiatedBidirectionalId(0)));
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc index e09c9bc..705d45c 100644 --- a/quic/core/http/quic_spdy_session_test.cc +++ b/quic/core/http/quic_spdy_session_test.cc
@@ -221,9 +221,9 @@ TestStream* CreateIncomingStream(QuicStreamId id) override { // Enforce the limit on the number of open streams. - if (GetNumOpenIncomingStreams() + 1 > - max_open_incoming_bidirectional_streams() && - !VersionHasIetfQuicFrames(connection()->transport_version())) { + if (!VersionHasIetfQuicFrames(connection()->transport_version()) && + GetNumOpenIncomingStreams() + 1 > + max_open_incoming_bidirectional_streams()) { connection()->CloseConnection( QUIC_TOO_MANY_OPEN_STREAMS, "Too many streams!", ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); @@ -1124,7 +1124,7 @@ QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0, quiche::QuicheStringPiece("HT")); session_.OnStreamFrame(data1); - EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); if (!VersionHasIetfQuicFrames(transport_version())) { // For version99, OnStreamReset gets called because of the STOP_SENDING, @@ -1161,7 +1161,7 @@ session_.OnStopSendingFrame(stop_sending); } - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); // Connection should remain alive. EXPECT_TRUE(connection_->connected()); } @@ -1773,9 +1773,9 @@ for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += IdDelta()) { QuicStreamFrame data1(i, true, 0, quiche::QuicheStringPiece("HT")); session_.OnStreamFrame(data1); - EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); session_.StreamDraining(i, /*unidirectional=*/false); - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); } } @@ -1852,7 +1852,7 @@ return; } - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); QuicStreamId stream_id1 = GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0); // A bad stream frame with no data and no fin. @@ -1999,7 +1999,7 @@ return; } - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); // Push unidirectional stream is type 0x01. std::string frame_type1 = quiche::QuicheTextUtils::HexDecode("01"); @@ -2008,7 +2008,7 @@ session_.OnStreamFrame(QuicStreamFrame(stream_id1, /* fin = */ false, /* offset = */ 0, frame_type1)); - EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); QuicStream* stream = session_.GetOrCreateStream(stream_id1); EXPECT_EQ(1u, stream->flow_controller()->bytes_consumed()); EXPECT_EQ(1u, session_.flow_controller()->bytes_consumed()); @@ -2020,7 +2020,7 @@ session_.OnStreamFrame(QuicStreamFrame(stream_id2, /* fin = */ false, /* offset = */ 0, frame_type2)); - EXPECT_EQ(2u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); stream = session_.GetOrCreateStream(stream_id2); EXPECT_EQ(4u, stream->flow_controller()->bytes_consumed()); EXPECT_EQ(5u, session_.flow_controller()->bytes_consumed()); @@ -2031,7 +2031,7 @@ return; } - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); // Push unidirectional stream is type 0x01. std::string frame_type = quiche::QuicheTextUtils::HexDecode("01"); @@ -2049,10 +2049,10 @@ // Receiving some stream data without stream type does not open the stream. session_.OnStreamFrame(data2); - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); session_.OnStreamFrame(data1); - EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); QuicStream* stream = session_.GetOrCreateStream(stream_id); EXPECT_EQ(3u, stream->flow_controller()->highest_received_byte_offset()); } @@ -2598,7 +2598,7 @@ session_.OnStreamFrame(frame); // There are no active streams. - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); // The pending stream is still around, because it did not receive a FIN. PendingStream* pending =
diff --git a/quic/core/legacy_quic_stream_id_manager.cc b/quic/core/legacy_quic_stream_id_manager.cc index 6e8f13a..9598aff 100644 --- a/quic/core/legacy_quic_stream_id_manager.cc +++ b/quic/core/legacy_quic_stream_id_manager.cc
@@ -29,12 +29,23 @@ ? (QuicVersionUsesCryptoFrames(transport_version_) ? QuicUtils::GetInvalidStreamId(transport_version_) : QuicUtils::GetCryptoStreamId(transport_version_)) - : QuicUtils::GetInvalidStreamId(transport_version_)) {} + : QuicUtils::GetInvalidStreamId(transport_version_)), + num_open_incoming_streams_(0), + num_open_outgoing_streams_(0), + handles_accounting_( + GetQuicReloadableFlag(quic_stream_id_manager_handles_accounting)) {} LegacyQuicStreamIdManager::~LegacyQuicStreamIdManager() {} bool LegacyQuicStreamIdManager::CanOpenNextOutgoingStream( size_t current_num_open_outgoing_streams) const { + if (handles_accounting_) { + DCHECK_LE(num_open_outgoing_streams_, max_open_outgoing_streams_); + QUIC_DLOG_IF(INFO, num_open_outgoing_streams_ == max_open_outgoing_streams_) + << "Failed to create a new outgoing stream. " + << "Already " << num_open_outgoing_streams_ << " open."; + return num_open_outgoing_streams_ < max_open_outgoing_streams_; + } if (current_num_open_outgoing_streams >= max_open_outgoing_streams_) { QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " << "Already " << current_num_open_outgoing_streams @@ -46,6 +57,9 @@ bool LegacyQuicStreamIdManager::CanOpenIncomingStream( size_t current_num_open_incoming_streams) const { + if (handles_accounting_) { + return num_open_incoming_streams_ < max_open_incoming_streams_; + } // Check if the new number of open streams would cause the number of // open streams to exceed the limit. return current_num_open_incoming_streams < max_open_incoming_streams_; @@ -102,6 +116,26 @@ return id; } +void LegacyQuicStreamIdManager::ActivateStream(bool is_incoming) { + DCHECK(handles_accounting_); + if (is_incoming) { + ++num_open_incoming_streams_; + return; + } + ++num_open_outgoing_streams_; +} + +void LegacyQuicStreamIdManager::OnStreamClosed(bool is_incoming) { + DCHECK(handles_accounting_); + if (is_incoming) { + QUIC_BUG_IF(num_open_incoming_streams_ == 0); + --num_open_incoming_streams_; + return; + } + QUIC_BUG_IF(num_open_outgoing_streams_ == 0); + --num_open_outgoing_streams_; +} + bool LegacyQuicStreamIdManager::IsAvailableStream(QuicStreamId id) const { if (!IsIncomingStream(id)) { // Stream IDs under next_ougoing_stream_id_ are either open or previously
diff --git a/quic/core/legacy_quic_stream_id_manager.h b/quic/core/legacy_quic_stream_id_manager.h index 16daa64..6c1309e 100644 --- a/quic/core/legacy_quic_stream_id_manager.h +++ b/quic/core/legacy_quic_stream_id_manager.h
@@ -46,6 +46,12 @@ // underlying counter. QuicStreamId GetNextOutgoingStreamId(); + // Called when a new stream is open. + void ActivateStream(bool is_incoming); + + // Called when a stream ID is closed. + void OnStreamClosed(bool is_incoming); + // Return true if |id| is peer initiated. bool IsIncomingStream(QuicStreamId id) const; @@ -82,6 +88,15 @@ size_t GetNumAvailableStreams() const; + size_t num_open_incoming_streams() const { + return num_open_incoming_streams_; + } + size_t num_open_outgoing_streams() const { + return num_open_outgoing_streams_; + } + + bool handles_accounting() const { return handles_accounting_; } + private: friend class test::QuicSessionPeer; @@ -102,6 +117,17 @@ QuicHashSet<QuicStreamId> available_streams_; QuicStreamId largest_peer_created_stream_id_; + + // A counter for peer initiated open streams. Used when handles_accounting_ is + // true. + size_t num_open_incoming_streams_; + + // A counter for self initiated open streams. Used when handles_accounting_ is + // true. + size_t num_open_outgoing_streams_; + + // Latched value of quic_stream_id_manager_handles_accounting. + const bool handles_accounting_; }; } // namespace quic
diff --git a/quic/core/legacy_quic_stream_id_manager_test.cc b/quic/core/legacy_quic_stream_id_manager_test.cc index bd37ffe..00654b4 100644 --- a/quic/core/legacy_quic_stream_id_manager_test.cc +++ b/quic/core/legacy_quic_stream_id_manager_test.cc
@@ -78,15 +78,31 @@ ::testing::PrintToStringParamName()); TEST_P(LegacyQuicStreamIdManagerTest, CanOpenNextOutgoingStream) { + if (GetQuicReloadableFlag(quic_stream_id_manager_handles_accounting)) { + for (size_t i = 0; i < manager_.max_open_outgoing_streams() - 1; ++i) { + manager_.ActivateStream(/*is_incoming=*/false); + } + } EXPECT_TRUE(manager_.CanOpenNextOutgoingStream( manager_.max_open_outgoing_streams() - 1)); + if (GetQuicReloadableFlag(quic_stream_id_manager_handles_accounting)) { + manager_.ActivateStream(/*is_incoming=*/false); + } EXPECT_FALSE( manager_.CanOpenNextOutgoingStream(manager_.max_open_outgoing_streams())); } TEST_P(LegacyQuicStreamIdManagerTest, CanOpenIncomingStream) { + if (GetQuicReloadableFlag(quic_stream_id_manager_handles_accounting)) { + for (size_t i = 0; i < manager_.max_open_incoming_streams() - 1; ++i) { + manager_.ActivateStream(/*is_incoming=*/true); + } + } EXPECT_TRUE( manager_.CanOpenIncomingStream(manager_.max_open_incoming_streams() - 1)); + if (GetQuicReloadableFlag(quic_stream_id_manager_handles_accounting)) { + manager_.ActivateStream(/*is_incoming=*/true); + } EXPECT_FALSE( manager_.CanOpenIncomingStream(manager_.max_open_incoming_streams())); }
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc index 9172ed7..e85644d 100644 --- a/quic/core/quic_session.cc +++ b/quic/core/quic_session.cc
@@ -939,6 +939,10 @@ // Do not bother informing stream ID manager if connection is closed. v99_streamid_manager_.OnStreamClosed(stream_id); } + } else if (stream_id_manager_.handles_accounting() && had_fin_or_rst && + connection_->connected()) { + stream_id_manager_.OnStreamClosed( + /*is_incoming=*/IsIncomingStream(stream_id)); } stream->OnClose(); @@ -1023,6 +1027,11 @@ // disconnected. return; } + if (stream_id_manager_.handles_accounting() && + !VersionHasIetfQuicFrames(transport_version())) { + stream_id_manager_.OnStreamClosed( + /*is_incoming=*/IsIncomingStream(stream_id)); + } if (IsIncomingStream(stream_id)) { // Stream Id manager is only interested in peer initiated stream IDs. if (VersionHasIetfQuicFrames(transport_version())) { @@ -1037,10 +1046,9 @@ void QuicSession::ClosePendingStream(QuicStreamId stream_id) { QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; - + DCHECK(VersionHasIetfQuicFrames(transport_version())); pending_stream_map_.erase(stream_id); - if (VersionHasIetfQuicFrames(transport_version()) && - connection_->connected()) { + if (connection_->connected()) { v99_streamid_manager_.OnStreamClosed(stream_id); } } @@ -1070,6 +1078,11 @@ flow_controller_.AddBytesConsumed(offset_diff); locally_closed_streams_highest_offset_.erase(it); + if (stream_id_manager_.handles_accounting() && + !VersionHasIetfQuicFrames(transport_version())) { + stream_id_manager_.OnStreamClosed( + /*is_incoming=*/IsIncomingStream(stream_id)); + } if (IsIncomingStream(stream_id)) { --num_locally_closed_incoming_streams_highest_offset_; if (VersionHasIetfQuicFrames(transport_version())) { @@ -1586,6 +1599,12 @@ } else if (is_static) { ++num_outgoing_static_streams_; } + if (stream_id_manager_.handles_accounting() && !is_static && + !VersionHasIetfQuicFrames(transport_version())) { + // Do not inform stream ID manager of static streams. + stream_id_manager_.ActivateStream( + /*is_incoming=*/IsIncomingStream(stream_id)); + } if (VersionHasIetfQuicFrames(transport_version()) && !QuicUtils::IsBidirectionalStreamId(stream_id) && is_static) { @@ -1704,6 +1723,9 @@ QUIC_DVLOG(1) << ENDPOINT << "Stream " << stream_id << " is draining"; if (VersionHasIetfQuicFrames(transport_version())) { v99_streamid_manager_.OnStreamClosed(stream_id); + } else if (stream_id_manager_.handles_accounting()) { + stream_id_manager_.OnStreamClosed( + /*is_incoming=*/IsIncomingStream(stream_id)); } if (IsIncomingStream(stream_id)) { ++num_draining_incoming_streams_; @@ -1720,6 +1742,9 @@ } if (VersionHasIetfQuicFrames(transport_version())) { v99_streamid_manager_.OnStreamClosed(stream_id); + } else if (stream_id_manager_.handles_accounting()) { + stream_id_manager_.OnStreamClosed( + /*is_incoming=*/IsIncomingStream(stream_id)); } } if (!IsIncomingStream(stream_id)) { @@ -1853,11 +1878,19 @@ } size_t QuicSession::GetNumOpenIncomingStreams() const { + DCHECK(!VersionHasIetfQuicFrames(transport_version())); + if (stream_id_manager_.handles_accounting()) { + return stream_id_manager_.num_open_incoming_streams(); + } return num_dynamic_incoming_streams_ - num_draining_incoming_streams_ + num_locally_closed_incoming_streams_highest_offset_; } size_t QuicSession::GetNumOpenOutgoingStreams() const { + DCHECK(!VersionHasIetfQuicFrames(transport_version())); + if (stream_id_manager_.handles_accounting()) { + return stream_id_manager_.num_open_outgoing_streams(); + } DCHECK_GE(GetNumDynamicOutgoingStreams() + GetNumLocallyClosedOutgoingStreamsHighestOffset(), GetNumDrainingOutgoingStreams()); @@ -1867,6 +1900,14 @@ } size_t QuicSession::GetNumActiveStreams() const { + if (!VersionHasIetfQuicFrames(transport_version()) && + stream_id_manager_.handles_accounting()) { + // Exclude locally_closed_streams when determine whether to keep connection + // alive. + return stream_id_manager_.num_open_incoming_streams() + + stream_id_manager_.num_open_outgoing_streams() - + locally_closed_streams_highest_offset_.size(); + } return stream_map_.size() - GetNumDrainingStreams() - num_incoming_static_streams_ - num_outgoing_static_streams_; }
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h index 75e524f..85c1a5f 100644 --- a/quic/core/quic_session.h +++ b/quic/core/quic_session.h
@@ -326,10 +326,16 @@ // Returns the number of currently open peer initiated streams, excluding // static streams. + // TODO(fayang): remove this and instead use + // LegacyStreamIdManager::num_open_incoming_streams() in tests when + // deprecating quic_stream_id_manager_handles_accounting. size_t GetNumOpenIncomingStreams() const; // Returns the number of currently open self initiated streams, excluding // static streams. + // TODO(fayang): remove this and instead use + // LegacyStreamIdManager::num_open_outgoing_streams() in tests when + // deprecating quic_stream_id_manager_handles_accounting. size_t GetNumOpenOutgoingStreams() const; // Returns the number of open peer initiated static streams. @@ -764,15 +770,21 @@ UberQuicStreamIdManager v99_streamid_manager_; // A counter for peer initiated dynamic streams which are in the stream_map_. + // TODO(fayang): Remove this when deprecating + // quic_stream_id_manager_handles_accounting. size_t num_dynamic_incoming_streams_; // A counter for peer initiated streams which have sent and received FIN but // waiting for application to consume data. + // TODO(fayang): Remove this when deprecating + // quic_stream_id_manager_handles_accounting. size_t num_draining_incoming_streams_; // A counter for self initiated streams which have sent and received FIN but // waiting for application to consume data. Only used when // deprecate_draining_streams_ is true. + // TODO(fayang): Remove this when deprecating + // quic_stream_id_manager_handles_accounting. size_t num_draining_outgoing_streams_; // A counter for self initiated static streams which are in @@ -785,6 +797,8 @@ // A counter for peer initiated streams which are in the // locally_closed_streams_highest_offset_. + // TODO(fayang): Remove this when deprecating + // quic_stream_id_manager_handles_accounting. size_t num_locally_closed_incoming_streams_highest_offset_; // Received information for a connection close.
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc index 80ef0d5..36b55a1 100644 --- a/quic/core/quic_session_test.cc +++ b/quic/core/quic_session_test.cc
@@ -213,9 +213,9 @@ TestStream* CreateIncomingStream(QuicStreamId id) override { // Enforce the limit on the number of open streams. - if (GetNumOpenIncomingStreams() + 1 > - max_open_incoming_bidirectional_streams() && - !VersionHasIetfQuicFrames(connection()->transport_version())) { + if (!VersionHasIetfQuicFrames(connection()->transport_version()) && + GetNumOpenIncomingStreams() + 1 > + max_open_incoming_bidirectional_streams()) { // No need to do this test for version 99; it's done by // QuicSession::GetOrCreateStream. connection()->CloseConnection( @@ -1936,20 +1936,20 @@ session_.OnStreamFrame(data1); EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id)); EXPECT_EQ(0, session_.num_incoming_streams_created()); - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); QuicRstStreamFrame rst1(kInvalidControlFrameId, stream_id, QUIC_ERROR_PROCESSING_STREAM, 12); session_.OnRstStream(rst1); EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id)); EXPECT_EQ(0, session_.num_incoming_streams_created()); - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); QuicStreamFrame data2(stream_id, false, 0, quiche::QuicheStringPiece("HT")); session_.OnStreamFrame(data2); EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id)); EXPECT_EQ(0, session_.num_incoming_streams_created()); - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); } TEST_P(QuicSessionTestServer, OnFinPendingStreams) { @@ -1965,7 +1965,7 @@ EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id)); EXPECT_EQ(0, session_.num_incoming_streams_created()); - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); } TEST_P(QuicSessionTestServer, PendingStreamOnWindowUpdate) { @@ -2018,9 +2018,9 @@ i += QuicUtils::StreamIdDelta(connection_->transport_version())) { QuicStreamFrame data1(i, true, 0, quiche::QuicheStringPiece("HT")); session_.OnStreamFrame(data1); - EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); session_.StreamDraining(i, /*unidirectional=*/false); - EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_)); } }
diff --git a/quic/core/quic_stream_test.cc b/quic/core/quic_stream_test.cc index ed8e0e4..fdff93b 100644 --- a/quic/core/quic_stream_test.cc +++ b/quic/core/quic_stream_test.cc
@@ -754,7 +754,7 @@ EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); EXPECT_FALSE(stream_->reading_stopped()); - EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); // Outgoing data with FIN. EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) @@ -767,7 +767,7 @@ EXPECT_TRUE(stream_->write_side_closed()); EXPECT_EQ(1u, session_->GetNumDrainingStreams()); - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); } TEST_P(QuicStreamTest, SetDrainingOutgoingIncoming) { @@ -784,7 +784,7 @@ nullptr); EXPECT_TRUE(stream_->write_side_closed()); - EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); // Incoming data with FIN. QuicStreamFrame stream_frame_with_fin(stream_->id(), true, 1234, "."); @@ -795,7 +795,7 @@ EXPECT_FALSE(stream_->reading_stopped()); EXPECT_EQ(1u, session_->GetNumDrainingStreams()); - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); } TEST_P(QuicStreamTest, EarlyResponseFinHandling) {
diff --git a/quic/quic_transport/quic_transport_integration_test.cc b/quic/quic_transport/quic_transport_integration_test.cc index 355f6cc..f1912e2 100644 --- a/quic/quic_transport/quic_transport_integration_test.cc +++ b/quic/quic_transport/quic_transport_integration_test.cc
@@ -23,6 +23,7 @@ #include "net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h" #include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h" #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h" +#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" #include "net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h" #include "net/third_party/quiche/src/quic/test_tools/simulator/link.h" @@ -254,7 +255,8 @@ } ASSERT_TRUE(simulator_.RunUntilOrTimeout( [this]() { - return server_->session()->GetNumOpenIncomingStreams() == 10; + return QuicSessionPeer::GetNumOpenDynamicStreams(server_->session()) == + 10; }, kDefaultTimeout)); @@ -262,7 +264,10 @@ ASSERT_TRUE(stream->SendFin()); } ASSERT_TRUE(simulator_.RunUntilOrTimeout( - [this]() { return server_->session()->GetNumOpenIncomingStreams() == 0; }, + [this]() { + return QuicSessionPeer::GetNumOpenDynamicStreams(server_->session()) == + 0; + }, kDefaultTimeout)); } @@ -284,7 +289,10 @@ EXPECT_TRUE(stream->SendFin()); ASSERT_TRUE(simulator_.RunUntilOrTimeout( - [this]() { return server_->session()->GetNumOpenIncomingStreams() == 0; }, + [this]() { + return QuicSessionPeer::GetNumOpenDynamicStreams(server_->session()) == + 0; + }, kDefaultTimeout)); }
diff --git a/quic/test_tools/quic_session_peer.cc b/quic/test_tools/quic_session_peer.cc index c23bc88..ab28828 100644 --- a/quic/test_tools/quic_session_peer.cc +++ b/quic/test_tools/quic_session_peer.cc
@@ -233,5 +233,21 @@ session->perspective_ = perspective; } +// static +size_t QuicSessionPeer::GetNumOpenDynamicStreams(QuicSession* session) { + size_t result = 0; + for (const auto& it : session->stream_map_) { + if (!it.second->is_static()) { + ++result; + } + } + // Exclude draining streams. + result -= session->GetNumDrainingStreams(); + // Add locally closed streams. + result += session->locally_closed_streams_highest_offset_.size(); + + return result; +} + } // namespace test } // namespace quic
diff --git a/quic/test_tools/quic_session_peer.h b/quic/test_tools/quic_session_peer.h index 5a58360..ffb6a46 100644 --- a/quic/test_tools/quic_session_peer.h +++ b/quic/test_tools/quic_session_peer.h
@@ -81,6 +81,7 @@ QuicStreamId stream_id); static void set_is_configured(QuicSession* session, bool value); static void SetPerspective(QuicSession* session, Perspective perspective); + static size_t GetNumOpenDynamicStreams(QuicSession* session); }; } // namespace test
diff --git a/quic/tools/quic_simple_server_session_test.cc b/quic/tools/quic_simple_server_session_test.cc index bdcedbc..966128b 100644 --- a/quic/tools/quic_simple_server_session_test.cc +++ b/quic/tools/quic_simple_server_session_test.cc
@@ -321,7 +321,7 @@ QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0, quiche::QuicheStringPiece("HT")); session_->OnStreamFrame(data1); - EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); // Receive a reset (and send a RST in response). QuicRstStreamFrame rst1(kInvalidControlFrameId, @@ -341,13 +341,13 @@ // a one-way close. InjectStopSending(GetNthClientInitiatedBidirectionalId(0), QUIC_ERROR_PROCESSING_STREAM); - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); // Send the same two bytes of payload in a new packet. session_->OnStreamFrame(data1); // The stream should not be re-opened. - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); EXPECT_TRUE(connection_->connected()); } @@ -371,7 +371,7 @@ InjectStopSending(GetNthClientInitiatedBidirectionalId(0), QUIC_ERROR_PROCESSING_STREAM); - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); // Send two bytes of payload. QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0, @@ -379,7 +379,7 @@ session_->OnStreamFrame(data1); // The stream should never be opened, now that the reset is received. - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); EXPECT_TRUE(connection_->connected()); } @@ -391,7 +391,7 @@ quiche::QuicheStringPiece("\2\0\0\0\0\0\0\0HT")); session_->OnStreamFrame(frame1); session_->OnStreamFrame(frame2); - EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); // Send a reset (and expect the peer to send a RST in response). QuicRstStreamFrame rst(kInvalidControlFrameId, @@ -422,7 +422,7 @@ session_->OnStreamFrame(frame3); session_->OnStreamFrame(frame4); // The stream should never be opened, now that the reset is received. - EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); EXPECT_TRUE(connection_->connected()); } @@ -433,12 +433,14 @@ } // Tests that incoming stream creation fails when connection is not connected. - size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams(); + size_t initial_num_open_stream = + QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()); QuicConnectionPeer::TearDownLocalConnectionState(connection_); EXPECT_QUIC_BUG(QuicSimpleServerSessionPeer::CreateIncomingStream( session_.get(), GetNthClientInitiatedBidirectionalId(0)), "ShouldCreateIncomingStream called when disconnected"); - EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(initial_num_open_stream, + QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); } TEST_P(QuicSimpleServerSessionTest, CreateIncomingStream) { @@ -455,14 +457,16 @@ } // Tests that outgoing stream creation fails when connection is not connected. - size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams(); + size_t initial_num_open_stream = + QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()); QuicConnectionPeer::TearDownLocalConnectionState(connection_); EXPECT_QUIC_BUG( QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream( session_.get()), "ShouldCreateOutgoingUnidirectionalStream called when disconnected"); - EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(initial_num_open_stream, + QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); } TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUnencrypted) { @@ -473,12 +477,14 @@ // Tests that outgoing stream creation fails when encryption has not yet been // established. - size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams(); + size_t initial_num_open_stream = + QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()); EXPECT_QUIC_BUG( QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream( session_.get()), "Encryption not established so no outgoing stream created."); - EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(initial_num_open_stream, + QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); } TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) { @@ -491,8 +497,9 @@ QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0, quiche::QuicheStringPiece("HT")); session_->OnStreamFrame(data1); - EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); - EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); + EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()) - + /*incoming=*/1); if (!VersionUsesHttp3(transport_version())) { session_->UnregisterStreamPriority( @@ -523,20 +530,24 @@ } else { EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(i), created_stream->id()); } - EXPECT_EQ(i + 1, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(i + 1, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()) - + /*incoming=*/1); } // Continuing creating push stream would fail. EXPECT_EQ(nullptr, QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream( session_.get())); - EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(kMaxStreamsForTest, + QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()) - + /*incoming=*/1); // Create peer initiated stream should have no problem. QuicStreamFrame data2(GetNthClientInitiatedBidirectionalId(1), false, 0, quiche::QuicheStringPiece("HT")); session_->OnStreamFrame(data2); - EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()) - + /*outcoming=*/kMaxStreamsForTest); } TEST_P(QuicSimpleServerSessionTest, OnStreamFrameWithEvenStreamId) { @@ -551,7 +562,8 @@ // Tests that calling GetOrCreateStream() on an outgoing stream not promised yet // should result close connection. TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) { - const size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams(); + const size_t initial_num_open_stream = + QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()); const QuicErrorCode expected_error = VersionUsesHttp3(transport_version()) ? QUIC_HTTP_STREAM_WRONG_DIRECTION : QUIC_INVALID_STREAM_ID; @@ -560,7 +572,8 @@ EXPECT_EQ(nullptr, QuicSessionPeer::GetOrCreateStream( session_.get(), GetNthServerInitiatedUnidirectionalId(3))); - EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(initial_num_open_stream, + QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); } // In order to test the case where server push stream creation goes beyond @@ -759,7 +772,8 @@ } size_t num_resources = kMaxStreamsForTest + 5; PromisePushResources(num_resources); - EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(kMaxStreamsForTest, + QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); } // Tests that after promised stream queued up, when an opened stream is marked @@ -833,7 +847,8 @@ } // Number of open outgoing streams should still be the same, because a new // stream is opened. And the queue should be empty. - EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(kMaxStreamsForTest, + QuicSessionPeer::GetNumOpenDynamicStreams(session_.get())); } // Tests that after all resources are promised, a RST frame from client can