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