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/crypto/crypto_handshake_message.cc b/quic/core/crypto/crypto_handshake_message.cc
index 1bbed74..579bb37 100644
--- a/quic/core/crypto/crypto_handshake_message.cc
+++ b/quic/core/crypto/crypto_handshake_message.cc
@@ -274,7 +274,8 @@
case kCFCW:
case kSFCW:
case kIRTT:
- case kMIDS:
+ case kMIUS:
+ case kMIBS:
case kSCLS:
case kTCID:
// uint32_t value
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index a3abb33..e8c8d84 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -218,7 +218,8 @@
const QuicTag kCLOP = TAG('C', 'L', 'O', 'P'); // Client connection options
const QuicTag kICSL = TAG('I', 'C', 'S', 'L'); // Idle network timeout
const QuicTag kSCLS = TAG('S', 'C', 'L', 'S'); // Silently close on timeout
-const QuicTag kMIDS = TAG('M', 'I', 'D', 'S'); // Max incoming dynamic streams
+const QuicTag kMIBS = TAG('M', 'I', 'D', 'S'); // Max incoming bidi streams
+const QuicTag kMIUS = TAG('M', 'I', 'U', 'S'); // Max incoming unidi streams
const QuicTag kIRTT = TAG('I', 'R', 'T', 'T'); // Estimated initial RTT in us.
const QuicTag kSNI = TAG('S', 'N', 'I', '\0'); // Server name
// indication
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 2675428..209bc81 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -1389,7 +1389,7 @@
// Set a limit on maximum number of incoming dynamic streams.
// Make sure the limit is respected.
const uint32_t kServerMaxIncomingDynamicStreams = 1;
- server_config_.SetMaxIncomingDynamicStreamsToSend(
+ server_config_.SetMaxIncomingBidirectionalStreamsToSend(
kServerMaxIncomingDynamicStreams);
ASSERT_TRUE(Initialize());
if (GetParam().negotiated_version.transport_version == QUIC_VERSION_99) {
@@ -1430,10 +1430,15 @@
// Each endpoint can set max incoming dynamic streams independently.
const uint32_t kClientMaxIncomingDynamicStreams = 2;
const uint32_t kServerMaxIncomingDynamicStreams = 1;
- client_config_.SetMaxIncomingDynamicStreamsToSend(
+ client_config_.SetMaxIncomingBidirectionalStreamsToSend(
kClientMaxIncomingDynamicStreams);
- server_config_.SetMaxIncomingDynamicStreamsToSend(
+ server_config_.SetMaxIncomingBidirectionalStreamsToSend(
kServerMaxIncomingDynamicStreams);
+ client_config_.SetMaxIncomingUnidirectionalStreamsToSend(
+ kClientMaxIncomingDynamicStreams);
+ server_config_.SetMaxIncomingUnidirectionalStreamsToSend(
+ kServerMaxIncomingDynamicStreams);
+
ASSERT_TRUE(Initialize());
EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
@@ -2739,8 +2744,10 @@
const size_t kNumMaxStreams = 10;
EndToEndTestServerPush() : EndToEndTest() {
- client_config_.SetMaxIncomingDynamicStreamsToSend(kNumMaxStreams);
- server_config_.SetMaxIncomingDynamicStreamsToSend(kNumMaxStreams);
+ client_config_.SetMaxIncomingBidirectionalStreamsToSend(kNumMaxStreams);
+ server_config_.SetMaxIncomingBidirectionalStreamsToSend(kNumMaxStreams);
+ client_config_.SetMaxIncomingUnidirectionalStreamsToSend(kNumMaxStreams);
+ server_config_.SetMaxIncomingUnidirectionalStreamsToSend(kNumMaxStreams);
support_server_push_ = true;
}
diff --git a/quic/core/http/quic_server_session_base_test.cc b/quic/core/http/quic_server_session_base_test.cc
index 0527f0b..b532601 100644
--- a/quic/core/http/quic_server_session_base_test.cc
+++ b/quic/core/http/quic_server_session_base_test.cc
@@ -131,9 +131,12 @@
TlsServerHandshaker::CreateSslCtx()),
compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
- config_.SetMaxIncomingDynamicStreamsToSend(kMaxStreamsForTest);
- QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(&config_,
- kMaxStreamsForTest);
+ config_.SetMaxIncomingBidirectionalStreamsToSend(kMaxStreamsForTest);
+ config_.SetMaxIncomingUnidirectionalStreamsToSend(kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
+ &config_, kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
+ &config_, kMaxStreamsForTest);
config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindowForTest);
config_.SetInitialSessionFlowControlWindowToSend(
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc
index 8460c7d..599f939 100644
--- a/quic/core/http/quic_spdy_client_session_test.cc
+++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -153,7 +153,15 @@
QuicCryptoClientStream* stream = static_cast<QuicCryptoClientStream*>(
session_->GetMutableCryptoStream());
QuicConfig config = DefaultQuicConfig();
- config.SetMaxIncomingDynamicStreamsToSend(server_max_incoming_streams);
+ if (connection_->transport_version() == QUIC_VERSION_99) {
+ config.SetMaxIncomingUnidirectionalStreamsToSend(
+ server_max_incoming_streams);
+ config.SetMaxIncomingBidirectionalStreamsToSend(
+ server_max_incoming_streams);
+ } else {
+ config.SetMaxIncomingBidirectionalStreamsToSend(
+ server_max_incoming_streams);
+ }
crypto_test_utils::HandshakeWithFakeServer(
&config, &helper_, &alarm_factory_, connection_, stream);
}
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index 26ec153..c7ce057 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -69,7 +69,7 @@
kInitialStreamFlowControlWindowForTest);
session()->config()->SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
- session()->config()->ToHandshakeMessage(&msg);
+ session()->config()->ToHandshakeMessage(&msg, transport_version());
const QuicErrorCode error =
session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
@@ -565,7 +565,11 @@
TEST_P(QuicSpdySessionTestServer, ManyAvailableStreams) {
// 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 (IsVersion99()) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 200);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
+ }
QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
// Create one stream.
session_.GetOrCreateDynamicStream(stream_id);
@@ -1179,7 +1183,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);
@@ -1500,7 +1504,12 @@
// with a FIN or RST then we send an RST to refuse streams for versions other
// than version 99. In version 99 the connection gets closed.
const QuicStreamId kMaxStreams = 5;
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ if (IsVersion99()) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
+ kMaxStreams);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ }
// GetNth assumes that both the crypto and header streams have been
// open, but the stream id manager, using GetFirstBidirectional... only
// assumes that the crypto stream is open. This means that GetNth...(0)
@@ -1573,7 +1582,12 @@
}
EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
const QuicStreamId kMaxStreams = 5;
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ if (IsVersion99()) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
+ kMaxStreams);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ }
// Create kMaxStreams + 1 data streams, and mark them draining.
const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
diff --git a/quic/core/quic_config.cc b/quic/core/quic_config.cc
index 4880c6d..0914809 100644
--- a/quic/core/quic_config.cc
+++ b/quic/core/quic_config.cc
@@ -404,7 +404,7 @@
client_connection_options_(kCLOP, PRESENCE_OPTIONAL),
idle_network_timeout_seconds_(kICSL, PRESENCE_REQUIRED),
silent_close_(kSCLS, PRESENCE_OPTIONAL),
- max_incoming_dynamic_streams_(kMIDS, PRESENCE_REQUIRED),
+ max_incoming_bidirectional_streams_(kMIBS, PRESENCE_REQUIRED),
bytes_for_connection_id_(kTCID, PRESENCE_OPTIONAL),
initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
@@ -412,7 +412,8 @@
connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL),
alternate_server_address_(kASAD, PRESENCE_OPTIONAL),
support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL),
- stateless_reset_token_(kSRST, PRESENCE_OPTIONAL) {
+ stateless_reset_token_(kSRST, PRESENCE_OPTIONAL),
+ max_incoming_unidirectional_streams_(kMIUS, PRESENCE_OPTIONAL) {
SetDefaults();
}
@@ -505,21 +506,38 @@
return silent_close_.GetUint32() > 0;
}
-void QuicConfig::SetMaxIncomingDynamicStreamsToSend(
- uint32_t max_incoming_dynamic_streams) {
- max_incoming_dynamic_streams_.SetSendValue(max_incoming_dynamic_streams);
+void QuicConfig::SetMaxIncomingBidirectionalStreamsToSend(
+ uint32_t max_streams) {
+ max_incoming_bidirectional_streams_.SetSendValue(max_streams);
}
-uint32_t QuicConfig::GetMaxIncomingDynamicStreamsToSend() {
- return max_incoming_dynamic_streams_.GetSendValue();
+uint32_t QuicConfig::GetMaxIncomingBidirectionalStreamsToSend() {
+ return max_incoming_bidirectional_streams_.GetSendValue();
}
-bool QuicConfig::HasReceivedMaxIncomingDynamicStreams() {
- return max_incoming_dynamic_streams_.HasReceivedValue();
+bool QuicConfig::HasReceivedMaxIncomingBidirectionalStreams() {
+ return max_incoming_bidirectional_streams_.HasReceivedValue();
}
-uint32_t QuicConfig::ReceivedMaxIncomingDynamicStreams() {
- return max_incoming_dynamic_streams_.GetReceivedValue();
+uint32_t QuicConfig::ReceivedMaxIncomingBidirectionalStreams() {
+ return max_incoming_bidirectional_streams_.GetReceivedValue();
+}
+
+void QuicConfig::SetMaxIncomingUnidirectionalStreamsToSend(
+ uint32_t max_streams) {
+ max_incoming_unidirectional_streams_.SetSendValue(max_streams);
+}
+
+uint32_t QuicConfig::GetMaxIncomingUnidirectionalStreamsToSend() {
+ return max_incoming_unidirectional_streams_.GetSendValue();
+}
+
+bool QuicConfig::HasReceivedMaxIncomingUnidirectionalStreams() {
+ return max_incoming_unidirectional_streams_.HasReceivedValue();
+}
+
+uint32_t QuicConfig::ReceivedMaxIncomingUnidirectionalStreams() {
+ return max_incoming_unidirectional_streams_.GetReceivedValue();
}
bool QuicConfig::HasSetBytesForConnectionIdToSend() const {
@@ -664,7 +682,8 @@
idle_network_timeout_seconds_.set(kMaximumIdleTimeoutSecs,
kDefaultIdleTimeoutSecs);
silent_close_.set(1, 0);
- SetMaxIncomingDynamicStreamsToSend(kDefaultMaxStreamsPerConnection);
+ SetMaxIncomingBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
+ SetMaxIncomingUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
max_time_before_crypto_handshake_ =
QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs);
max_idle_time_before_crypto_handshake_ =
@@ -676,10 +695,18 @@
SetSupportMaxHeaderListSize();
}
-void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
+void QuicConfig::ToHandshakeMessage(
+ CryptoHandshakeMessage* out,
+ QuicTransportVersion transport_version) const {
idle_network_timeout_seconds_.ToHandshakeMessage(out);
silent_close_.ToHandshakeMessage(out);
- max_incoming_dynamic_streams_.ToHandshakeMessage(out);
+ // Do not need a version check here, max...bi... will encode
+ // as "MIDS" -- the max initial dynamic streams tag -- if
+ // doing some version other than IETF QUIC/V99.
+ max_incoming_bidirectional_streams_.ToHandshakeMessage(out);
+ if (transport_version == QUIC_VERSION_99) {
+ max_incoming_unidirectional_streams_.ToHandshakeMessage(out);
+ }
bytes_for_connection_id_.ToHandshakeMessage(out);
initial_round_trip_time_us_.ToHandshakeMessage(out);
initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
@@ -707,7 +734,11 @@
silent_close_.ProcessPeerHello(peer_hello, hello_type, error_details);
}
if (error == QUIC_NO_ERROR) {
- error = max_incoming_dynamic_streams_.ProcessPeerHello(
+ error = max_incoming_bidirectional_streams_.ProcessPeerHello(
+ peer_hello, hello_type, error_details);
+ }
+ if (error == QUIC_NO_ERROR) {
+ error = max_incoming_unidirectional_streams_.ProcessPeerHello(
peer_hello, hello_type, error_details);
}
if (error == QUIC_NO_ERROR) {
@@ -771,9 +802,9 @@
params->initial_max_stream_data_uni.set_value(
initial_stream_flow_control_window_bytes_.GetSendValue());
params->initial_max_streams_bidi.set_value(
- max_incoming_dynamic_streams_.GetSendValue());
+ max_incoming_bidirectional_streams_.GetSendValue());
params->initial_max_streams_uni.set_value(
- max_incoming_dynamic_streams_.GetSendValue());
+ max_incoming_unidirectional_streams_.GetSendValue());
params->max_ack_delay.set_value(kDefaultDelayedAckTimeMs);
params->disable_migration =
connection_migration_disabled_.HasSendValue() &&
@@ -846,10 +877,12 @@
initial_session_flow_control_window_bytes_.SetReceivedValue(
std::min<uint64_t>(params.initial_max_data.value(),
std::numeric_limits<uint32_t>::max()));
-
- max_incoming_dynamic_streams_.SetReceivedValue(
+ max_incoming_bidirectional_streams_.SetReceivedValue(
std::min<uint64_t>(params.initial_max_streams_bidi.value(),
std::numeric_limits<uint32_t>::max()));
+ max_incoming_unidirectional_streams_.SetReceivedValue(
+ std::min<uint64_t>(params.initial_max_streams_uni.value(),
+ std::numeric_limits<uint32_t>::max()));
initial_stream_flow_control_window_bytes_.SetReceivedValue(
std::min<uint64_t>(params.initial_max_stream_data_bidi_local.value(),
diff --git a/quic/core/quic_config.h b/quic/core/quic_config.h
index 8ad161d..ae15b6a 100644
--- a/quic/core/quic_config.h
+++ b/quic/core/quic_config.h
@@ -305,14 +305,24 @@
bool SilentClose() const;
- void SetMaxIncomingDynamicStreamsToSend(
- uint32_t max_incoming_dynamic_streams);
+ // Configuration for the Google QUIC and IETF QUIC stream ID managers. Note
+ // that the naming is a bit weird; it is from the perspective of the node
+ // generating (sending) the configuration and, thus, The "incoming" counts are
+ // the number of streams that the node sending the configuration is willing to
+ // accept and therefore the number that the node receiving the confguration
+ // can create .. the number of outbound streams that may be intiated..
+ // There are two sets, one for unidirectional streams and one for
+ // bidirectional. The bidirectional set also covers Google-QUICs
+ // dynamic stream count (which are bidirectional streams).
+ void SetMaxIncomingBidirectionalStreamsToSend(uint32_t max_streams);
+ uint32_t GetMaxIncomingBidirectionalStreamsToSend();
+ bool HasReceivedMaxIncomingBidirectionalStreams();
+ uint32_t ReceivedMaxIncomingBidirectionalStreams();
- uint32_t GetMaxIncomingDynamicStreamsToSend();
-
- bool HasReceivedMaxIncomingDynamicStreams();
-
- uint32_t ReceivedMaxIncomingDynamicStreams();
+ void SetMaxIncomingUnidirectionalStreamsToSend(uint32_t max_streams);
+ uint32_t GetMaxIncomingUnidirectionalStreamsToSend();
+ bool HasReceivedMaxIncomingUnidirectionalStreams();
+ uint32_t ReceivedMaxIncomingUnidirectionalStreams();
void set_max_time_before_crypto_handshake(
QuicTime::Delta max_time_before_crypto_handshake) {
@@ -412,7 +422,8 @@
// ToHandshakeMessage serialises the settings in this object as a series of
// tags /value pairs and adds them to |out|.
- void ToHandshakeMessage(CryptoHandshakeMessage* out) const;
+ void ToHandshakeMessage(CryptoHandshakeMessage* out,
+ QuicTransportVersion transport_version) const;
// Calls ProcessPeerHello on each negotiable parameter. On failure returns
// the corresponding QuicErrorCode and sets detailed error in |error_details|.
@@ -456,8 +467,10 @@
QuicNegotiableUint32 idle_network_timeout_seconds_;
// Whether to use silent close. Defaults to 0 (false) and is otherwise true.
QuicNegotiableUint32 silent_close_;
- // Maximum number of incoming dynamic streams that the connection can support.
- QuicFixedUint32 max_incoming_dynamic_streams_;
+ // Maximum number of incoming dynamic streams that a Google QUIC connection
+ // can support or the maximum number of incoming bidirectional streams that
+ // an IETF QUIC connection can support.
+ QuicFixedUint32 max_incoming_bidirectional_streams_;
// The number of bytes required for the connection ID.
QuicFixedUint32 bytes_for_connection_id_;
// Initial round trip time estimate in microseconds.
@@ -484,6 +497,10 @@
// be created. This allows for CHLOs that are larger than a single
// packet to be processed.
QuicTagVector create_session_tag_indicators_;
+
+ // Maximum number of incoming unidirectional streams that the connection can
+ // support.
+ QuicFixedUint32 max_incoming_unidirectional_streams_;
};
} // namespace quic
diff --git a/quic/core/quic_config_test.cc b/quic/core/quic_config_test.cc
index c18c520..84e89c1 100644
--- a/quic/core/quic_config_test.cc
+++ b/quic/core/quic_config_test.cc
@@ -21,12 +21,17 @@
namespace test {
namespace {
-class QuicConfigTest : public QuicTest {
+class QuicConfigTest : public QuicTestWithParam<QuicTransportVersion> {
protected:
QuicConfig config_;
};
-TEST_F(QuicConfigTest, ToHandshakeMessage) {
+// Run all tests with all versions of QUIC.
+INSTANTIATE_TEST_SUITE_P(QuicConfigTests,
+ QuicConfigTest,
+ ::testing::ValuesIn(AllSupportedTransportVersions()));
+
+TEST_P(QuicConfigTest, ToHandshakeMessage) {
config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindowForTest);
config_.SetInitialSessionFlowControlWindowToSend(
@@ -34,7 +39,7 @@
config_.SetIdleNetworkTimeout(QuicTime::Delta::FromSeconds(5),
QuicTime::Delta::FromSeconds(2));
CryptoHandshakeMessage msg;
- config_.ToHandshakeMessage(&msg);
+ config_.ToHandshakeMessage(&msg, GetParam());
uint32_t value;
QuicErrorCode error = msg.GetUint32(kICSL, &value);
@@ -50,7 +55,7 @@
EXPECT_EQ(kInitialSessionFlowControlWindowForTest, value);
}
-TEST_F(QuicConfigTest, ProcessClientHello) {
+TEST_P(QuicConfigTest, ProcessClientHello) {
QuicConfig client_config;
QuicTagVector cgst;
cgst.push_back(kQBIC);
@@ -66,7 +71,7 @@
copt.push_back(kTBBR);
client_config.SetConnectionOptionsToSend(copt);
CryptoHandshakeMessage msg;
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
QuicTagVector initial_received_options;
@@ -96,7 +101,7 @@
2 * kInitialSessionFlowControlWindowForTest);
}
-TEST_F(QuicConfigTest, ProcessServerHello) {
+TEST_P(QuicConfigTest, ProcessServerHello) {
QuicIpAddress host;
host.FromString("127.0.3.1");
const QuicSocketAddress kTestServerAddress = QuicSocketAddress(host, 1234);
@@ -115,7 +120,7 @@
server_config.SetAlternateServerAddressToSend(kTestServerAddress);
server_config.SetStatelessResetTokenToSend(kTestResetToken);
CryptoHandshakeMessage msg;
- server_config.ToHandshakeMessage(&msg);
+ server_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, SERVER, &error_details);
@@ -134,13 +139,13 @@
EXPECT_EQ(kTestResetToken, config_.ReceivedStatelessResetToken());
}
-TEST_F(QuicConfigTest, MissingOptionalValuesInCHLO) {
+TEST_P(QuicConfigTest, MissingOptionalValuesInCHLO) {
CryptoHandshakeMessage msg;
msg.SetValue(kICSL, 1);
// Set all REQUIRED tags.
msg.SetValue(kICSL, 1);
- msg.SetValue(kMIDS, 1);
+ msg.SetValue(kMIBS, 1);
// No error, as rest are optional.
std::string error_details;
@@ -150,12 +155,12 @@
EXPECT_TRUE(config_.negotiated());
}
-TEST_F(QuicConfigTest, MissingOptionalValuesInSHLO) {
+TEST_P(QuicConfigTest, MissingOptionalValuesInSHLO) {
CryptoHandshakeMessage msg;
// Set all REQUIRED tags.
msg.SetValue(kICSL, 1);
- msg.SetValue(kMIDS, 1);
+ msg.SetValue(kMIBS, 1);
// No error, as rest are optional.
std::string error_details;
@@ -165,7 +170,7 @@
EXPECT_TRUE(config_.negotiated());
}
-TEST_F(QuicConfigTest, MissingValueInCHLO) {
+TEST_P(QuicConfigTest, MissingValueInCHLO) {
// Server receives CHLO with missing kICSL.
CryptoHandshakeMessage msg;
std::string error_details;
@@ -174,7 +179,7 @@
EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND, error);
}
-TEST_F(QuicConfigTest, MissingValueInSHLO) {
+TEST_P(QuicConfigTest, MissingValueInSHLO) {
// Client receives SHLO with missing kICSL.
CryptoHandshakeMessage msg;
std::string error_details;
@@ -183,21 +188,21 @@
EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND, error);
}
-TEST_F(QuicConfigTest, OutOfBoundSHLO) {
+TEST_P(QuicConfigTest, OutOfBoundSHLO) {
QuicConfig server_config;
server_config.SetIdleNetworkTimeout(
QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs),
QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs));
CryptoHandshakeMessage msg;
- server_config.ToHandshakeMessage(&msg);
+ server_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, SERVER, &error_details);
EXPECT_EQ(QUIC_INVALID_NEGOTIATED_VALUE, error);
}
-TEST_F(QuicConfigTest, InvalidFlowControlWindow) {
+TEST_P(QuicConfigTest, InvalidFlowControlWindow) {
// QuicConfig should not accept an invalid flow control window to send to the
// peer: the receive window must be at least the default of 16 Kb.
QuicConfig config;
@@ -210,7 +215,7 @@
config.GetInitialStreamFlowControlWindowToSend());
}
-TEST_F(QuicConfigTest, HasClientSentConnectionOption) {
+TEST_P(QuicConfigTest, HasClientSentConnectionOption) {
QuicConfig client_config;
QuicTagVector copt;
copt.push_back(kTBBR);
@@ -219,7 +224,7 @@
kTBBR, Perspective::IS_CLIENT));
CryptoHandshakeMessage msg;
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
const QuicErrorCode error =
@@ -233,14 +238,14 @@
config_.HasClientSentConnectionOption(kTBBR, Perspective::IS_SERVER));
}
-TEST_F(QuicConfigTest, DontSendClientConnectionOptions) {
+TEST_P(QuicConfigTest, DontSendClientConnectionOptions) {
QuicConfig client_config;
QuicTagVector copt;
copt.push_back(kTBBR);
client_config.SetClientConnectionOptions(copt);
CryptoHandshakeMessage msg;
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
const QuicErrorCode error =
@@ -251,7 +256,7 @@
EXPECT_FALSE(config_.HasReceivedConnectionOptions());
}
-TEST_F(QuicConfigTest, HasClientRequestedIndependentOption) {
+TEST_P(QuicConfigTest, HasClientRequestedIndependentOption) {
QuicConfig client_config;
QuicTagVector client_opt;
client_opt.push_back(kRENO);
@@ -267,7 +272,7 @@
kTBBR, Perspective::IS_CLIENT));
CryptoHandshakeMessage msg;
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
const QuicErrorCode error =
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 0bae7d5..d80b55f 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -4988,7 +4988,7 @@
client_config.SetIdleNetworkTimeout(
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs),
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs));
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, connection_.transport_version());
const QuicErrorCode error =
config.ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
@@ -5055,7 +5055,7 @@
client_config.SetIdleNetworkTimeout(
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs),
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs));
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, connection_.transport_version());
const QuicErrorCode error =
config.ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
@@ -5111,7 +5111,7 @@
client_config.SetIdleNetworkTimeout(
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs),
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs));
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, connection_.transport_version());
const QuicErrorCode error =
config.ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
diff --git a/quic/core/quic_crypto_client_handshaker.cc b/quic/core/quic_crypto_client_handshaker.cc
index 57d8c28..b0c26be 100644
--- a/quic/core/quic_crypto_client_handshaker.cc
+++ b/quic/core/quic_crypto_client_handshaker.cc
@@ -263,7 +263,7 @@
DCHECK(session()->config() != nullptr);
// Send all the options, regardless of whether we're sending an
// inchoate or subsequent hello.
- session()->config()->ToHandshakeMessage(&out);
+ session()->config()->ToHandshakeMessage(&out, session()->transport_version());
if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
crypto_config_->FillInchoateClientHello(
diff --git a/quic/core/quic_crypto_server_handshaker.cc b/quic/core/quic_crypto_server_handshaker.cc
index 9e46d6d..025e391 100644
--- a/quic/core/quic_crypto_server_handshaker.cc
+++ b/quic/core/quic_crypto_server_handshaker.cc
@@ -208,7 +208,7 @@
session()->OnConfigNegotiated();
- config->ToHandshakeMessage(reply.get());
+ config->ToHandshakeMessage(reply.get(), session()->transport_version());
// Receiving a full CHLO implies the client is prepared to decrypt with
// the new server write key. We can start to encrypt with the new server
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 0545fa6..d56689f 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -55,10 +55,13 @@
config_(config),
stream_id_manager_(this,
kDefaultMaxStreamsPerConnection,
- config_.GetMaxIncomingDynamicStreamsToSend()),
- v99_streamid_manager_(this,
- kDefaultMaxStreamsPerConnection,
- config_.GetMaxIncomingDynamicStreamsToSend()),
+ config_.GetMaxIncomingBidirectionalStreamsToSend()),
+ v99_streamid_manager_(
+ this,
+ kDefaultMaxStreamsPerConnection,
+ kDefaultMaxStreamsPerConnection,
+ config_.GetMaxIncomingBidirectionalStreamsToSend(),
+ config_.GetMaxIncomingUnidirectionalStreamsToSend()),
num_dynamic_incoming_streams_(0),
num_draining_incoming_streams_(0),
num_outgoing_static_streams_(0),
@@ -973,23 +976,33 @@
void QuicSession::OnConfigNegotiated() {
connection_->SetFromConfig(config_);
- uint32_t max_streams = 0;
- if (config_.HasReceivedMaxIncomingDynamicStreams()) {
- max_streams = config_.ReceivedMaxIncomingDynamicStreams();
- }
- QUIC_DVLOG(1) << "Setting max_open_outgoing_streams_ to " << max_streams;
if (connection_->transport_version() == QUIC_VERSION_99) {
- // TODO: When transport negotiation knows about bi- and uni- directional
- // streams, this should be modified to indicate which one to the manager.
- // Currently, BOTH are set to the same value.
- // TODO(fkastenholz): AdjustMax is cognizant of the number of static streams
- // and sets the maximum to be max_streams + number_of_statics. This should
- // eventually be removed from IETF QUIC. -- Replace the call with
- // ConfigureMaxOpen...
- v99_streamid_manager_.AdjustMaxOpenOutgoingStreams(max_streams);
+ uint32_t max_streams = 0;
+ if (config_.HasReceivedMaxIncomingBidirectionalStreams()) {
+ max_streams = config_.ReceivedMaxIncomingBidirectionalStreams();
+ }
+ QUIC_DVLOG(1) << "Setting Bidirectional outgoing_max_streams_ to "
+ << max_streams;
+ v99_streamid_manager_.AdjustMaxOpenOutgoingBidirectionalStreams(
+ max_streams);
+
+ max_streams = 0;
+ if (config_.HasReceivedMaxIncomingUnidirectionalStreams()) {
+ max_streams = config_.ReceivedMaxIncomingUnidirectionalStreams();
+ }
+ QUIC_DVLOG(1) << "Setting Unidirectional outgoing_max_streams_ to "
+ << max_streams;
+ v99_streamid_manager_.AdjustMaxOpenOutgoingUnidirectionalStreams(
+ max_streams);
} else {
+ uint32_t max_streams = 0;
+ if (config_.HasReceivedMaxIncomingBidirectionalStreams()) {
+ max_streams = config_.ReceivedMaxIncomingBidirectionalStreams();
+ }
+ QUIC_DVLOG(1) << "Setting max_open_outgoing_streams_ to " << max_streams;
stream_id_manager_.set_max_open_outgoing_streams(max_streams);
}
+
if (perspective() == Perspective::IS_SERVER) {
if (config_.HasReceivedConnectionOptions()) {
// The following variations change the initial receive flow control
@@ -1014,17 +1027,19 @@
config_.SetStatelessResetTokenToSend(GetStatelessResetToken());
}
- // A small number of additional incoming streams beyond the limit should be
- // allowed. This helps avoid early connection termination when FIN/RSTs for
- // old streams are lost or arrive out of order.
- // Use a minimum number of additional streams, or a percentage increase,
- // whichever is larger.
- uint32_t max_incoming_streams_to_send =
- config_.GetMaxIncomingDynamicStreamsToSend();
if (connection_->transport_version() == QUIC_VERSION_99) {
- v99_streamid_manager_.SetMaxOpenIncomingStreams(
- max_incoming_streams_to_send);
+ v99_streamid_manager_.SetMaxOpenIncomingBidirectionalStreams(
+ config_.GetMaxIncomingBidirectionalStreamsToSend());
+ v99_streamid_manager_.SetMaxOpenIncomingUnidirectionalStreams(
+ config_.GetMaxIncomingUnidirectionalStreamsToSend());
} else {
+ // A small number of additional incoming streams beyond the limit should be
+ // allowed. This helps avoid early connection termination when FIN/RSTs for
+ // old streams are lost or arrive out of order.
+ // Use a minimum number of additional streams, or a percentage increase,
+ // whichever is larger.
+ uint32_t max_incoming_streams_to_send =
+ config_.GetMaxIncomingBidirectionalStreamsToSend();
uint32_t max_incoming_streams =
std::max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement,
static_cast<uint32_t>(max_incoming_streams_to_send *
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index f16477c..7da8ec3 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -419,6 +419,10 @@
static void RecordConnectionCloseAtServer(QuicErrorCode error,
ConnectionCloseSource source);
+ inline QuicTransportVersion transport_version() const {
+ return connection_->transport_version();
+ }
+
protected:
using StaticStreamMap = QuicSmallMap<QuicStreamId, QuicStream*, 2>;
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);
diff --git a/quic/core/quic_stream_id_manager.cc b/quic/core/quic_stream_id_manager.cc
index f68401a..94a8487 100644
--- a/quic/core/quic_stream_id_manager.cc
+++ b/quic/core/quic_stream_id_manager.cc
@@ -130,12 +130,13 @@
outgoing_max_streams_ = std::min(
static_cast<QuicStreamCount>(max_open_streams),
QuicUtils::GetMaxStreamCount(unidirectional_, session_->perspective()));
-
return true;
}
void QuicStreamIdManager::SetMaxOpenOutgoingStreams(size_t max_open_streams) {
QUIC_BUG_IF(!using_default_max_streams_);
+ // TODO(fkastenholz): when static streams are removed from I-Quic, this
+ // should be revised to invoke ConfigureMaxOpen...
AdjustMaxOpenOutgoingStreams(max_open_streams);
}
@@ -143,8 +144,8 @@
// including static streams. If the new stream limit wraps, will peg
// the limit at the implementation max.
// TODO(fkastenholz): AdjustMax is cognizant of the number of static streams and
-// sets the maximum to be max_streams + number_of_statics. This should
-// eventually be removed from IETF QUIC.
+// sets the maximum to be max_streams + number_of_statics. This should be
+// removed from IETF QUIC when static streams are gone.
void QuicStreamIdManager::AdjustMaxOpenOutgoingStreams(
size_t max_open_streams) {
if ((outgoing_static_stream_count_ + max_open_streams) < max_open_streams) {
diff --git a/quic/core/uber_quic_stream_id_manager.cc b/quic/core/uber_quic_stream_id_manager.cc
index e2261a0..75f7c6a 100644
--- a/quic/core/uber_quic_stream_id_manager.cc
+++ b/quic/core/uber_quic_stream_id_manager.cc
@@ -11,17 +11,19 @@
UberQuicStreamIdManager::UberQuicStreamIdManager(
QuicSession* session,
- QuicStreamCount max_open_outgoing_streams,
- QuicStreamCount max_open_incoming_streams)
+ QuicStreamCount max_open_outgoing_bidirectional_streams,
+ QuicStreamCount max_open_outgoing_unidirectional_streams,
+ QuicStreamCount max_open_incoming_bidirectional_streams,
+ QuicStreamCount max_open_incoming_unidirectional_streams)
: bidirectional_stream_id_manager_(session,
/*unidirectional=*/false,
- max_open_outgoing_streams,
- max_open_incoming_streams),
- unidirectional_stream_id_manager_(session,
- /*unidirectional=*/true,
- max_open_outgoing_streams,
- max_open_incoming_streams) {}
-
+ max_open_outgoing_bidirectional_streams,
+ max_open_incoming_bidirectional_streams),
+ unidirectional_stream_id_manager_(
+ session,
+ /*unidirectional=*/true,
+ max_open_outgoing_unidirectional_streams,
+ max_open_incoming_unidirectional_streams) {}
void UberQuicStreamIdManager::RegisterStaticStream(QuicStreamId id) {
if (QuicUtils::IsBidirectionalStreamId(id)) {
bidirectional_stream_id_manager_.RegisterStaticStream(id);
@@ -30,35 +32,42 @@
unidirectional_stream_id_manager_.RegisterStaticStream(id);
}
-void UberQuicStreamIdManager::ConfigureMaxOpenOutgoingStreams(
+void UberQuicStreamIdManager::AdjustMaxOpenOutgoingUnidirectionalStreams(
size_t max_streams) {
- // TODO(fkastenholz): When transport configuration negotiation knows uni- vs
- // bi- directionality, this method needs modifying to select the correct
- // manager to configure.
- bidirectional_stream_id_manager_.ConfigureMaxOpenOutgoingStreams(max_streams);
- unidirectional_stream_id_manager_.ConfigureMaxOpenOutgoingStreams(
- max_streams);
+ unidirectional_stream_id_manager_.AdjustMaxOpenOutgoingStreams(max_streams);
+}
+void UberQuicStreamIdManager::AdjustMaxOpenOutgoingBidirectionalStreams(
+ size_t max_streams) {
+ bidirectional_stream_id_manager_.AdjustMaxOpenOutgoingStreams(max_streams);
}
-void UberQuicStreamIdManager::AdjustMaxOpenOutgoingStreams(size_t max_streams) {
- // TODO(fkastenholz): When transport configuration negotiation knows uni- vs
- // bi- directionality, this method needs modifying to select the correct
- // manager to configure.
- bidirectional_stream_id_manager_.AdjustMaxOpenOutgoingStreams(max_streams);
- unidirectional_stream_id_manager_.AdjustMaxOpenOutgoingStreams(max_streams);
+void UberQuicStreamIdManager::ConfigureMaxOpenOutgoingBidirectionalStreams(
+ size_t max_streams) {
+ bidirectional_stream_id_manager_.ConfigureMaxOpenOutgoingStreams(max_streams);
+}
+void UberQuicStreamIdManager::ConfigureMaxOpenOutgoingUnidirectionalStreams(
+ size_t max_streams) {
+ unidirectional_stream_id_manager_.ConfigureMaxOpenOutgoingStreams(
+ max_streams);
}
// TODO(fkastenholz): SetMax is cognizant of the number of static streams and
// sets the maximum to be max_streams + number_of_statics. This should
// eventually be removed from IETF QUIC.
-void UberQuicStreamIdManager::SetMaxOpenOutgoingStreams(
+void UberQuicStreamIdManager::SetMaxOpenOutgoingBidirectionalStreams(
size_t max_open_streams) {
bidirectional_stream_id_manager_.SetMaxOpenOutgoingStreams(max_open_streams);
+}
+void UberQuicStreamIdManager::SetMaxOpenOutgoingUnidirectionalStreams(
+ size_t max_open_streams) {
unidirectional_stream_id_manager_.SetMaxOpenOutgoingStreams(max_open_streams);
}
-void UberQuicStreamIdManager::SetMaxOpenIncomingStreams(
+void UberQuicStreamIdManager::SetMaxOpenIncomingBidirectionalStreams(
size_t max_open_streams) {
bidirectional_stream_id_manager_.SetMaxOpenIncomingStreams(max_open_streams);
+}
+void UberQuicStreamIdManager::SetMaxOpenIncomingUnidirectionalStreams(
+ size_t max_open_streams) {
unidirectional_stream_id_manager_.SetMaxOpenIncomingStreams(max_open_streams);
}
diff --git a/quic/core/uber_quic_stream_id_manager.h b/quic/core/uber_quic_stream_id_manager.h
index 41fa12b..288f0c0 100644
--- a/quic/core/uber_quic_stream_id_manager.h
+++ b/quic/core/uber_quic_stream_id_manager.h
@@ -20,9 +20,12 @@
// unidirectional stream IDs, respectively.
class QUIC_EXPORT_PRIVATE UberQuicStreamIdManager {
public:
- UberQuicStreamIdManager(QuicSession* session,
- QuicStreamCount max_open_outgoing_streams,
- QuicStreamCount max_open_incoming_streams);
+ UberQuicStreamIdManager(
+ QuicSession* session,
+ QuicStreamCount max_open_outgoing_bidirectional_streams,
+ QuicStreamCount max_open_outgoing_unidirectional_streams,
+ QuicStreamCount max_open_incoming_bidirectional_streams,
+ QuicStreamCount max_open_incoming_unidirectional_streams);
// Called when a stream with |stream_id| is registered as a static stream.
void RegisterStaticStream(QuicStreamId id);
@@ -30,21 +33,26 @@
// Sets the maximum outgoing stream count as a result of doing the transport
// configuration negotiation. Forces the limit to max_streams, regardless of
// static streams.
- void ConfigureMaxOpenOutgoingStreams(size_t max_streams);
+ void ConfigureMaxOpenOutgoingBidirectionalStreams(size_t max_streams);
+ void ConfigureMaxOpenOutgoingUnidirectionalStreams(size_t max_streams);
// Sets the limits to max_open_streams + number of static streams
// in existence. SetMaxOpenOutgoingStreams will QUIC_BUG if it is called
- // after getting the first MAX_STREAMS frame.
+ // after getting the first MAX_STREAMS frame or the transport configuration
+ // was done.
// TODO(fkastenholz): SetMax is cognizant of the number of static streams and
// sets the maximum to be max_streams + number_of_statics. This should
// eventually be removed from IETF QUIC.
- void SetMaxOpenOutgoingStreams(size_t max_open_streams);
- void SetMaxOpenIncomingStreams(size_t max_open_streams);
+ void SetMaxOpenOutgoingBidirectionalStreams(size_t max_open_streams);
+ void SetMaxOpenOutgoingUnidirectionalStreams(size_t max_open_streams);
+ void SetMaxOpenIncomingBidirectionalStreams(size_t max_open_streams);
+ void SetMaxOpenIncomingUnidirectionalStreams(size_t max_open_streams);
// Sets the outgoing stream count to the number of static streams + max
// outgoing streams. Unlike SetMaxOpenOutgoingStreams, this method will
// not QUIC_BUG if called after getting the first MAX_STREAMS frame.
- void AdjustMaxOpenOutgoingStreams(size_t max_streams);
+ void AdjustMaxOpenOutgoingBidirectionalStreams(size_t max_streams);
+ void AdjustMaxOpenOutgoingUnidirectionalStreams(size_t max_streams);
// Returns true if next outgoing bidirectional stream ID can be allocated.
bool CanOpenNextOutgoingBidirectionalStream();
@@ -58,7 +66,7 @@
// Returns the next outgoing unidirectional stream id.
QuicStreamId GetNextOutgoingUnidirectionalStreamId();
- // Returns true if allow to open the incoming |id|.
+ // Returns true if the incoming |id| is within the limit.
bool MaybeIncreaseLargestPeerStreamId(QuicStreamId id);
// Called when |id| is released.
diff --git a/quic/core/uber_quic_stream_id_manager_test.cc b/quic/core/uber_quic_stream_id_manager_test.cc
index ed08d8f..b9420bf 100644
--- a/quic/core/uber_quic_stream_id_manager_test.cc
+++ b/quic/core/uber_quic_stream_id_manager_test.cc
@@ -60,6 +60,28 @@
kV99StreamIdIncrement * n;
}
+ // TODO(fkastenholz): Existing tests can use these helper functions.
+ QuicStreamId GetNthPeerInitiatedBidirectionalStreamId(int n) {
+ return ((GetParam() == Perspective::IS_SERVER)
+ ? GetNthClientInitiatedBidirectionalId(n)
+ : GetNthServerInitiatedBidirectionalId(n));
+ }
+ QuicStreamId GetNthPeerInitiatedUnidirectionalStreamId(int n) {
+ return ((GetParam() == Perspective::IS_SERVER)
+ ? GetNthClientInitiatedUnidirectionalId(n)
+ : GetNthServerInitiatedUnidirectionalId(n));
+ }
+ QuicStreamId GetNthSelfInitiatedBidirectionalStreamId(int n) {
+ return ((GetParam() == Perspective::IS_CLIENT)
+ ? GetNthClientInitiatedBidirectionalId(n)
+ : GetNthServerInitiatedBidirectionalId(n));
+ }
+ QuicStreamId GetNthSelfInitiatedUnidirectionalStreamId(int n) {
+ return ((GetParam() == Perspective::IS_CLIENT)
+ ? GetNthClientInitiatedUnidirectionalId(n)
+ : GetNthServerInitiatedUnidirectionalId(n));
+ }
+
QuicStreamId StreamCountToId(QuicStreamCount stream_count,
Perspective perspective,
bool bidirectional) {
@@ -129,17 +151,39 @@
TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenOutgoingStreams) {
const size_t kNumMaxOutgoingStream = 123;
- manager_->SetMaxOpenOutgoingStreams(kNumMaxOutgoingStream);
+ // Set the uni- and bi- directional limits to different values to ensure
+ // that they are managed separately.
+ manager_->SetMaxOpenOutgoingBidirectionalStreams(kNumMaxOutgoingStream);
+ manager_->SetMaxOpenOutgoingUnidirectionalStreams(kNumMaxOutgoingStream + 1);
EXPECT_EQ(kNumMaxOutgoingStream,
manager_->max_allowed_outgoing_bidirectional_streams());
- EXPECT_EQ(kNumMaxOutgoingStream,
+ EXPECT_EQ(kNumMaxOutgoingStream + 1,
manager_->max_allowed_outgoing_unidirectional_streams());
+ // Check that, for each directionality, we can open the correct number of
+ // streams.
+ int i = kNumMaxOutgoingStream;
+ while (i) {
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingBidirectionalStream());
+ manager_->GetNextOutgoingBidirectionalStreamId();
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ manager_->GetNextOutgoingUnidirectionalStreamId();
+ i--;
+ }
+ // One more unidirectional
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ manager_->GetNextOutgoingUnidirectionalStreamId();
+
+ // Both should be exhausted...
+ EXPECT_FALSE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ EXPECT_FALSE(manager_->CanOpenNextOutgoingBidirectionalStream());
}
TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenIncomingStreams) {
const size_t kNumMaxIncomingStreams = 456;
- manager_->SetMaxOpenIncomingStreams(kNumMaxIncomingStreams);
- EXPECT_EQ(kNumMaxIncomingStreams,
+ manager_->SetMaxOpenIncomingUnidirectionalStreams(kNumMaxIncomingStreams);
+ // Do +1 for bidirectional to ensure that uni- and bi- get properly set.
+ manager_->SetMaxOpenIncomingBidirectionalStreams(kNumMaxIncomingStreams + 1);
+ EXPECT_EQ(kNumMaxIncomingStreams + 1,
manager_->GetMaxAllowdIncomingBidirectionalStreams());
EXPECT_EQ(kNumMaxIncomingStreams,
manager_->GetMaxAllowdIncomingUnidirectionalStreams());
@@ -147,6 +191,24 @@
manager_->advertised_max_allowed_incoming_bidirectional_streams());
EXPECT_EQ(manager_->actual_max_allowed_incoming_unidirectional_streams(),
manager_->advertised_max_allowed_incoming_unidirectional_streams());
+ // Make sure that we can create kNumMaxIncomingStreams incoming unidirectional
+ // streams and kNumMaxIncomingStreams+1 incoming bidirectional streams.
+ size_t i;
+ for (i = 0; i < kNumMaxIncomingStreams; i++) {
+ EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedUnidirectionalStreamId(i)));
+ EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedBidirectionalStreamId(i)));
+ }
+ // Should be able to open the next bidirectional stream
+ EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedBidirectionalStreamId(i)));
+
+ // We should have exhausted the counts, the next streams should fail
+ EXPECT_FALSE(manager_->MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedUnidirectionalStreamId(i)));
+ EXPECT_FALSE(manager_->MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedBidirectionalStreamId(i + 1)));
}
TEST_P(UberQuicStreamIdManagerTest, GetNextOutgoingStreamId) {
@@ -339,6 +401,44 @@
}
}
+TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenOutgoingStreamsPlusFrame) {
+ const size_t kNumMaxOutgoingStream = 123;
+ // Set the uni- and bi- directional limits to different values to ensure
+ // that they are managed separately.
+ manager_->SetMaxOpenOutgoingBidirectionalStreams(kNumMaxOutgoingStream);
+ manager_->SetMaxOpenOutgoingUnidirectionalStreams(kNumMaxOutgoingStream + 1);
+ EXPECT_EQ(kNumMaxOutgoingStream,
+ manager_->max_allowed_outgoing_bidirectional_streams());
+ EXPECT_EQ(kNumMaxOutgoingStream + 1,
+ manager_->max_allowed_outgoing_unidirectional_streams());
+ // Check that, for each directionality, we can open the correct number of
+ // streams.
+ int i = kNumMaxOutgoingStream;
+ while (i) {
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingBidirectionalStream());
+ manager_->GetNextOutgoingBidirectionalStreamId();
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ manager_->GetNextOutgoingUnidirectionalStreamId();
+ i--;
+ }
+ // One more unidirectional
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ manager_->GetNextOutgoingUnidirectionalStreamId();
+
+ // Both should be exhausted...
+ EXPECT_FALSE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ EXPECT_FALSE(manager_->CanOpenNextOutgoingBidirectionalStream());
+
+ // Now cons a MAX STREAMS frame for unidirectional streams to raise
+ // the limit.
+ QuicMaxStreamsFrame frame(1, kNumMaxOutgoingStream + 10,
+ /*unidirectional=*/true);
+ manager_->OnMaxStreamsFrame(frame);
+ // We now should be able to get another uni- stream, but not a bi.
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ EXPECT_FALSE(manager_->CanOpenNextOutgoingBidirectionalStream());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/quartc/quartc_factory.cc b/quic/quartc/quartc_factory.cc
index cb457ff..5b83a46 100644
--- a/quic/quartc/quartc_factory.cc
+++ b/quic/quartc/quartc_factory.cc
@@ -190,7 +190,7 @@
// incomplete streams, but targets 1 second for recovery. Increasing the
// number of open streams gives sufficient headroom to recover before QUIC
// refuses new streams.
- quic_config.SetMaxIncomingDynamicStreamsToSend(1000);
+ quic_config.SetMaxIncomingBidirectionalStreamsToSend(1000);
return quic_config;
}
diff --git a/quic/test_tools/quic_config_peer.cc b/quic/test_tools/quic_config_peer.cc
index f5a5b31..f9ce04f 100644
--- a/quic/test_tools/quic_config_peer.cc
+++ b/quic/test_tools/quic_config_peer.cc
@@ -45,10 +45,16 @@
}
// static
-void QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(
+void QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
QuicConfig* config,
uint32_t max_streams) {
- config->max_incoming_dynamic_streams_.SetReceivedValue(max_streams);
+ config->max_incoming_bidirectional_streams_.SetReceivedValue(max_streams);
+}
+// static
+void QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
+ QuicConfig* config,
+ uint32_t max_streams) {
+ config->max_incoming_unidirectional_streams_.SetReceivedValue(max_streams);
}
// static
diff --git a/quic/test_tools/quic_config_peer.h b/quic/test_tools/quic_config_peer.h
index 8869d27..7faee7e 100644
--- a/quic/test_tools/quic_config_peer.h
+++ b/quic/test_tools/quic_config_peer.h
@@ -33,8 +33,10 @@
static void SetReceivedDisableConnectionMigration(QuicConfig* config);
- static void SetReceivedMaxIncomingDynamicStreams(QuicConfig* config,
- uint32_t max_streams);
+ static void SetReceivedMaxIncomingBidirectionalStreams(QuicConfig* config,
+ uint32_t max_streams);
+ static void SetReceivedMaxIncomingUnidirectionalStreams(QuicConfig* config,
+ uint32_t max_streams);
static void SetConnectionOptionsToSend(QuicConfig* config,
const QuicTagVector& options);
diff --git a/quic/test_tools/quic_session_peer.cc b/quic/test_tools/quic_session_peer.cc
index 176e22a..0683fd7 100644
--- a/quic/test_tools/quic_session_peer.cc
+++ b/quic/test_tools/quic_session_peer.cc
@@ -39,23 +39,73 @@
void QuicSessionPeer::SetMaxOpenIncomingStreams(QuicSession* session,
uint32_t max_streams) {
if (session->connection()->transport_version() == QUIC_VERSION_99) {
- session->v99_streamid_manager_.SetMaxOpenIncomingStreams(max_streams);
+ QUIC_BUG << "SetmaxOpenIncomingStreams deprecated for IETF QUIC/V99";
+ session->v99_streamid_manager_.SetMaxOpenIncomingUnidirectionalStreams(
+ max_streams);
+ session->v99_streamid_manager_.SetMaxOpenIncomingBidirectionalStreams(
+ max_streams);
return;
}
session->stream_id_manager_.set_max_open_incoming_streams(max_streams);
}
// static
+void QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(
+ QuicSession* session,
+ uint32_t max_streams) {
+ DCHECK_EQ(QUIC_VERSION_99, session->connection()->transport_version())
+ << "SetmaxOpenIncomingBidirectionalStreams not supported for Google "
+ "QUIC/not-V99";
+ session->v99_streamid_manager_.SetMaxOpenIncomingBidirectionalStreams(
+ max_streams);
+}
+// static
+void QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(
+ QuicSession* session,
+ uint32_t max_streams) {
+ DCHECK_EQ(QUIC_VERSION_99, session->connection()->transport_version())
+ << "SetmaxOpenIncomingUnidirectionalStreams not supported for Google "
+ "QUIC/not-V99";
+ session->v99_streamid_manager_.SetMaxOpenIncomingUnidirectionalStreams(
+ max_streams);
+}
+
+// static
void QuicSessionPeer::SetMaxOpenOutgoingStreams(QuicSession* session,
uint32_t max_streams) {
if (session->connection()->transport_version() == QUIC_VERSION_99) {
- session->v99_streamid_manager_.SetMaxOpenOutgoingStreams(max_streams);
+ QUIC_BUG << "SetmaxOpenOutgoingStreams deprecated for IETF QUIC/V99";
+ session->v99_streamid_manager_.SetMaxOpenOutgoingUnidirectionalStreams(
+ max_streams);
+ session->v99_streamid_manager_.SetMaxOpenOutgoingBidirectionalStreams(
+ max_streams);
return;
}
session->stream_id_manager_.set_max_open_outgoing_streams(max_streams);
}
// static
+void QuicSessionPeer::SetMaxOpenOutgoingBidirectionalStreams(
+ QuicSession* session,
+ uint32_t max_streams) {
+ DCHECK_EQ(QUIC_VERSION_99, session->connection()->transport_version())
+ << "SetmaxOpenOutgoingBidirectionalStreams not supported for Google "
+ "QUIC/not-V99";
+ session->v99_streamid_manager_.SetMaxOpenOutgoingBidirectionalStreams(
+ max_streams);
+}
+// static
+void QuicSessionPeer::SetMaxOpenOutgoingUnidirectionalStreams(
+ QuicSession* session,
+ uint32_t max_streams) {
+ DCHECK_EQ(QUIC_VERSION_99, session->connection()->transport_version())
+ << "SetmaxOpenOutgoingUnidirectionalStreams not supported for Google "
+ "QUIC/not-V99";
+ session->v99_streamid_manager_.SetMaxOpenOutgoingUnidirectionalStreams(
+ max_streams);
+}
+
+// static
QuicCryptoStream* QuicSessionPeer::GetMutableCryptoStream(
QuicSession* session) {
return session->GetMutableCryptoStream();
diff --git a/quic/test_tools/quic_session_peer.h b/quic/test_tools/quic_session_peer.h
index 30e358f..994a36c 100644
--- a/quic/test_tools/quic_session_peer.h
+++ b/quic/test_tools/quic_session_peer.h
@@ -32,10 +32,24 @@
QuicSession* session);
static void SetNextOutgoingBidirectionalStreamId(QuicSession* session,
QuicStreamId id);
+ // Following is only for Google-QUIC, will QUIC_BUG if called for IETF
+ // QUIC.
static void SetMaxOpenIncomingStreams(QuicSession* session,
uint32_t max_streams);
+ // Following two are only for IETF-QUIC, will QUIC_BUG if called for Google
+ // QUIC.
+ static void SetMaxOpenIncomingBidirectionalStreams(QuicSession* session,
+ uint32_t max_streams);
+ static void SetMaxOpenIncomingUnidirectionalStreams(QuicSession* session,
+ uint32_t max_streams);
+
static void SetMaxOpenOutgoingStreams(QuicSession* session,
uint32_t max_streams);
+ static void SetMaxOpenOutgoingBidirectionalStreams(QuicSession* session,
+ uint32_t max_streams);
+ static void SetMaxOpenOutgoingUnidirectionalStreams(QuicSession* session,
+ uint32_t max_streams);
+
static QuicCryptoStream* GetMutableCryptoStream(QuicSession* session);
static QuicWriteBlockedList* GetWriteBlockedStreams(QuicSession* session);
static QuicStream* GetOrCreateDynamicStream(QuicSession* session,
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc
index d74e0ba..00cd34a 100644
--- a/quic/test_tools/quic_test_utils.cc
+++ b/quic/test_tools/quic_test_utils.cc
@@ -1051,7 +1051,7 @@
kInitialStreamFlowControlWindowForTest);
config.SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
- QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(
+ QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
&config, kDefaultMaxStreamsPerConnection);
// Default enable NSTP.
// This is unnecessary for versions > 44
diff --git a/quic/test_tools/simulator/quic_endpoint.cc b/quic/test_tools/simulator/quic_endpoint.cc
index 61d253f..043eae9 100644
--- a/quic/test_tools/simulator/quic_endpoint.cc
+++ b/quic/test_tools/simulator/quic_endpoint.cc
@@ -113,7 +113,7 @@
CryptoHandshakeMessage peer_hello;
peer_hello.SetValue(kICSL,
static_cast<uint32_t>(kMaximumIdleTimeoutSecs - 1));
- peer_hello.SetValue(kMIDS,
+ peer_hello.SetValue(kMIBS,
static_cast<uint32_t>(kDefaultMaxStreamsPerConnection));
QuicConfig config;
QuicErrorCode error_code = config.ProcessPeerHello(
diff --git a/quic/tools/quic_simple_server_session_test.cc b/quic/tools/quic_simple_server_session_test.cc
index 330862a..577ff26 100644
--- a/quic/tools/quic_simple_server_session_test.cc
+++ b/quic/tools/quic_simple_server_session_test.cc
@@ -200,9 +200,13 @@
TlsServerHandshaker::CreateSslCtx()),
compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
- config_.SetMaxIncomingDynamicStreamsToSend(kMaxStreamsForTest);
- QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(&config_,
- kMaxStreamsForTest);
+ config_.SetMaxIncomingBidirectionalStreamsToSend(kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
+ &config_, kMaxStreamsForTest);
+ config_.SetMaxIncomingUnidirectionalStreamsToSend(kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
+ &config_, kMaxStreamsForTest);
+
config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindowForTest);
config_.SetInitialSessionFlowControlWindowToSend(
diff --git a/quic/tools/quic_simple_server_stream_test.cc b/quic/tools/quic_simple_server_stream_test.cc
index 7572a75..8aaaf6b 100644
--- a/quic/tools/quic_simple_server_stream_test.cc
+++ b/quic/tools/quic_simple_server_stream_test.cc
@@ -100,8 +100,15 @@
crypto_config,
compressed_certs_cache,
quic_simple_server_backend) {
- QuicSessionPeer::SetMaxOpenIncomingStreams(this, kMaxStreamsForTest);
- QuicSessionPeer::SetMaxOpenOutgoingStreams(this, kMaxStreamsForTest);
+ if (connection->transport_version() == QUIC_VERSION_99) {
+ QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(
+ this, kMaxStreamsForTest);
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(
+ this, kMaxStreamsForTest);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(this, kMaxStreamsForTest);
+ QuicSessionPeer::SetMaxOpenOutgoingStreams(this, kMaxStreamsForTest);
+ }
ON_CALL(*this, WritevData(_, _, _, _, _))
.WillByDefault(Invoke(MockQuicSession::ConsumeData));
}