Have separate uni- and bi-directional stream limits for IETF QUIC
IETF QUIC supports unidirectional and bidirectional streams, each
of which can have a different stream limit. The stream limit is first
negotiated using the transport parameters. This change connects the
transport parameters to the stream-id-manager so that the former
can configure both the types of streams.
gfe-relnote: N/A all for version99 code.
PiperOrigin-RevId: 248325885
Change-Id: I4675c147dfda856b73337aac87a4290958599a18
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index 8f418c0..95bb6d4 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -69,7 +69,8 @@
kInitialStreamFlowControlWindowForTest);
session()->config()->SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
- session()->config()->ToHandshakeMessage(&msg);
+ session()->config()->ToHandshakeMessage(
+ &msg, session()->connection()->transport_version());
const QuicErrorCode error =
session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
@@ -707,31 +708,86 @@
TEST_P(QuicSessionTestServer, ManyAvailableBidirectionalStreams) {
// When max_open_streams_ is 200, should be able to create 200 streams
// out-of-order, that is, creating the one with the largest stream ID first.
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
+ if (transport_version() == QUIC_VERSION_99) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 200);
+ // Smaller limit on unidirectional streams to help detect crossed wires.
+ QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(&session_, 50);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
+ }
+ // Create a stream at the start of the range.
QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
- // Create one stream.
EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
- EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
// Create the largest stream ID of a threatened total of 200 streams.
// GetNth... starts at 0, so for 200 streams, get the 199th.
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
GetNthClientInitiatedBidirectionalId(199)));
+
+ if (transport_version() == QUIC_VERSION_99) {
+ // If IETF QUIC, check to make sure that creating bidirectional
+ // streams does not mess up the unidirectional streams.
+ stream_id = GetNthClientInitiatedUnidirectionalId(0);
+ EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
+ // Now try to get the last possible unidirectional stream.
+ EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
+ GetNthClientInitiatedUnidirectionalId(49)));
+ // and this should fail because it exceeds the unidirectional limit
+ // (but not the bi-)
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Stream id 798 would exceed stream count limit 50",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET
+
+ ))
+ .Times(1);
+ EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(
+ GetNthClientInitiatedUnidirectionalId(199)));
+ }
}
TEST_P(QuicSessionTestServer, ManyAvailableUnidirectionalStreams) {
// When max_open_streams_ is 200, should be able to create 200 streams
// out-of-order, that is, creating the one with the largest stream ID first.
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
- QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalId(0);
+ if (transport_version() == QUIC_VERSION_99) {
+ QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(&session_, 200);
+ // Smaller limit on unidirectional streams to help detect crossed wires.
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 50);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
+ }
// Create one stream.
+ QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalId(0);
EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
- EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
// Create the largest stream ID of a threatened total of 200 streams.
// GetNth... starts at 0, so for 200 streams, get the 199th.
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
GetNthClientInitiatedUnidirectionalId(199)));
+ if (transport_version() == QUIC_VERSION_99) {
+ // If IETF QUIC, check to make sure that creating unidirectional
+ // streams does not mess up the bidirectional streams.
+ stream_id = GetNthClientInitiatedBidirectionalId(0);
+ EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
+ // Now try to get the last possible bidirectional stream.
+ EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
+ GetNthClientInitiatedBidirectionalId(49)));
+ // and this should fail because it exceeds the bnidirectional limit
+ // (but not the uni-)
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Stream id 800 would exceed stream count limit 51",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET
+
+ ))
+ .Times(1);
+ EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(
+ GetNthClientInitiatedBidirectionalId(199)));
+ }
}
TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
@@ -1304,7 +1360,7 @@
QuicStreamOffset offset = crypto_stream->stream_bytes_written();
QuicConfig config;
CryptoHandshakeMessage crypto_message;
- config.ToHandshakeMessage(&crypto_message);
+ config.ToHandshakeMessage(&crypto_message, transport_version());
crypto_stream->SendHandshakeMessage(crypto_message);
char buf[1000];
QuicDataWriter writer(1000, buf, NETWORK_BYTE_ORDER);
@@ -1528,7 +1584,12 @@
// with a FIN or RST then we send an RST to refuse streams. For V99 the
// connection is closed.
const QuicStreamId kMaxStreams = 5;
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ if (transport_version() == QUIC_VERSION_99) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
+ kMaxStreams);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ }
const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
const QuicStreamId kFinalStreamId =
GetNthClientInitiatedBidirectionalId(kMaxStreams);
@@ -1653,7 +1714,12 @@
}
EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
const QuicStreamId kMaxStreams = 5;
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ if (transport_version() == QUIC_VERSION_99) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
+ kMaxStreams);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ }
// Create kMaxStreams + 1 data streams, and mark them draining.
const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);