Merge changes Ie13868e5,Ie2c1e0ca,Ib91037bf,Ibf204b14,I0b1079c4, ...
* changes:
Replace a DCHECK with a parse failure in connection ID parsing
Move drop_response_body from QuicClient to QuicSpdyClientBase to share with chromium
Extract the FakeProofVerifier from quic_client_bin.cc to facilitate sharing with Chromium.
Add QuicFramer Probe methods
Remove .impl() method from QuicSocketAddress and QuicIpAddress.
Change QuartcClientEndpoint to handle client-side version negotiation.
In quic_client_bin.cc, print the "Request (succeeded|failed)" messages in stdout instead of stderr.
Have separate uni- and bi-directional stream limits for IETF QUIC
Fix a use-after-free in quic_client.
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_framer.cc b/quic/core/quic_framer.cc
index 9633053..b686068 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -2699,8 +2699,13 @@
if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
if (header->source_connection_id_included == CONNECTION_ID_PRESENT) {
+ DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
+ DCHECK_EQ(IETF_QUIC_LONG_HEADER_PACKET, header->form);
+ if (!header->destination_connection_id.IsEmpty()) {
+ set_detailed_error("Client connection ID not supported yet.");
+ return false;
+ }
// Set destination connection ID to source connection ID.
- DCHECK_EQ(EmptyQuicConnectionId(), header->destination_connection_id);
header->destination_connection_id = header->source_connection_id;
} else if (header->destination_connection_id_included ==
CONNECTION_ID_ABSENT) {
@@ -6104,5 +6109,162 @@
return QUIC_NO_ERROR;
}
+// static
+bool QuicFramer::WriteClientVersionNegotiationProbePacket(
+ char* packet_bytes,
+ QuicByteCount packet_length,
+ const char* destination_connection_id_bytes,
+ uint8_t destination_connection_id_length) {
+ if (packet_bytes == nullptr) {
+ QUIC_BUG << "Invalid packet_bytes";
+ return false;
+ }
+ if (packet_length < kMinPacketSizeForVersionNegotiation ||
+ packet_length > 65535) {
+ QUIC_BUG << "Invalid packet_length";
+ return false;
+ }
+ if (destination_connection_id_length > kQuicMaxConnectionIdLength ||
+ (destination_connection_id_length > 0 &&
+ destination_connection_id_length < 4)) {
+ QUIC_BUG << "Invalid connection_id_length";
+ return false;
+ }
+ // clang-format off
+ static const unsigned char packet_start_bytes[] = {
+ // IETF long header with fixed bit set, type initial, all-0 encrypted bits.
+ 0xc0,
+ // Version, part of the IETF space reserved for negotiation.
+ // This intentionally differs from QuicVersionReservedForNegotiation()
+ // to allow differentiating them over the wire.
+ 0xca, 0xba, 0xda, 0xba,
+ };
+ // clang-format on
+ static_assert(sizeof(packet_start_bytes) == 5, "bad packet_start_bytes size");
+ QuicDataWriter writer(packet_length, packet_bytes);
+ if (!writer.WriteBytes(packet_start_bytes, sizeof(packet_start_bytes))) {
+ QUIC_BUG << "Failed to write packet start";
+ return false;
+ }
+
+ QuicConnectionId destination_connection_id(destination_connection_id_bytes,
+ destination_connection_id_length);
+ if (!AppendIetfConnectionIds(/*version_flag=*/true, destination_connection_id,
+ EmptyQuicConnectionId(), &writer)) {
+ QUIC_BUG << "Failed to write connection IDs";
+ return false;
+ }
+ // Add 8 bytes of zeroes followed by 8 bytes of ones to ensure that this does
+ // not parse with any known version. The zeroes make sure that packet numbers,
+ // retry token lengths and payload lengths are parsed as zero, and if the
+ // zeroes are treated as padding frames, 0xff is known to not parse as a
+ // valid frame type.
+ if (!writer.WriteUInt64(0) ||
+ !writer.WriteUInt64(std::numeric_limits<uint64_t>::max())) {
+ QUIC_BUG << "Failed to write 18 bytes";
+ return false;
+ }
+ // Make sure the polite greeting below is padded to a 16-byte boundary to
+ // make it easier to read in tcpdump.
+ while (writer.length() % 16 != 0) {
+ if (!writer.WriteUInt8(0)) {
+ QUIC_BUG << "Failed to write padding byte";
+ return false;
+ }
+ }
+ // Add a polite greeting in case a human sees this in tcpdump.
+ static const char polite_greeting[] =
+ "This packet only exists to trigger IETF QUIC version negotiation. "
+ "Please respond with a Version Negotiation packet indicating what "
+ "versions you support. Thank you and have a nice day.";
+ if (!writer.WriteBytes(polite_greeting, sizeof(polite_greeting))) {
+ QUIC_BUG << "Failed to write polite greeting";
+ return false;
+ }
+ // Fill the rest of the packet with zeroes.
+ writer.WritePadding();
+ DCHECK_EQ(0u, writer.remaining());
+ return true;
+}
+
+// static
+bool QuicFramer::ParseServerVersionNegotiationProbeResponse(
+ const char* packet_bytes,
+ QuicByteCount packet_length,
+ char* source_connection_id_bytes,
+ uint8_t* source_connection_id_length_out,
+ std::string* detailed_error) {
+ if (detailed_error == nullptr) {
+ QUIC_BUG << "Invalid error_details";
+ return false;
+ }
+ *detailed_error = "";
+ if (packet_bytes == nullptr) {
+ *detailed_error = "Invalid packet_bytes";
+ return false;
+ }
+ if (packet_length < 6) {
+ *detailed_error = "Invalid packet_length";
+ return false;
+ }
+ if (source_connection_id_bytes == nullptr) {
+ *detailed_error = "Invalid source_connection_id_bytes";
+ return false;
+ }
+ if (source_connection_id_length_out == nullptr) {
+ *detailed_error = "Invalid source_connection_id_length_out";
+ return false;
+ }
+ QuicDataReader reader(packet_bytes, packet_length);
+ uint8_t type_byte = 0;
+ if (!reader.ReadUInt8(&type_byte)) {
+ *detailed_error = "Failed to read type byte";
+ return false;
+ }
+ if ((type_byte & 0x80) == 0) {
+ *detailed_error = "Packet does not have long header";
+ return false;
+ }
+ uint32_t version = 0;
+ if (!reader.ReadUInt32(&version)) {
+ *detailed_error = "Failed to read version";
+ return false;
+ }
+ if (version != 0) {
+ *detailed_error = "Packet is not a version negotiation packet";
+ return false;
+ }
+ uint8_t expected_connection_id_length = 0,
+ destination_connection_id_length = 0, source_connection_id_length = 0;
+ if (!ProcessAndValidateIetfConnectionIdLength(
+ &reader, UnsupportedQuicVersion(),
+ /*should_update_expected_connection_id_length=*/true,
+ &expected_connection_id_length, &destination_connection_id_length,
+ &source_connection_id_length, detailed_error)) {
+ return false;
+ }
+ if (destination_connection_id_length != 0) {
+ *detailed_error = "Received unexpected destination connection ID length";
+ return false;
+ }
+ QuicConnectionId destination_connection_id, source_connection_id;
+ if (!reader.ReadConnectionId(&destination_connection_id,
+ destination_connection_id_length)) {
+ *detailed_error = "Failed to read destination connection ID";
+ return false;
+ }
+ if (!reader.ReadConnectionId(&source_connection_id,
+ source_connection_id_length)) {
+ *detailed_error = "Failed to read source connection ID";
+ return false;
+ }
+
+ memcpy(source_connection_id_bytes, source_connection_id.data(),
+ source_connection_id_length);
+ *source_connection_id_length_out = source_connection_id_length;
+
+ return true;
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h
index bded585..ab0e8d7 100644
--- a/quic/core/quic_framer.h
+++ b/quic/core/quic_framer.h
@@ -588,6 +588,38 @@
void EnableMultiplePacketNumberSpacesSupport();
+ // Writes an array of bytes that, if sent as a UDP datagram, will trigger
+ // IETF QUIC Version Negotiation on servers. The bytes will be written to
+ // |packet_bytes|, which must point to |packet_length| bytes of memory.
+ // |packet_length| must be in the range [1200, 65535].
+ // |destination_connection_id_bytes| will be sent as the destination
+ // connection ID, and must point to |destination_connection_id_length| bytes
+ // of memory. |destination_connection_id_length| must be either 0 or in the
+ // range [4,18]. When targeting Google servers, it is recommended to use a
+ // |destination_connection_id_length| of 8.
+ static bool WriteClientVersionNegotiationProbePacket(
+ char* packet_bytes,
+ QuicByteCount packet_length,
+ const char* destination_connection_id_bytes,
+ uint8_t destination_connection_id_length);
+
+ // Parses a packet which a QUIC server sent in response to a packet sent by
+ // WriteClientVersionNegotiationProbePacket. |packet_bytes| must point to
+ // |packet_length| bytes in memory which represent the response.
+ // |packet_length| must be greater or equal to 6. This method will fill in
+ // |source_connection_id_bytes| which must point to at least 18 bytes in
+ // memory. |source_connection_id_length_out| will contain the length of the
+ // received source connection ID, which on success will match the contents of
+ // the destination connection ID passed in to
+ // WriteClientVersionNegotiationProbePacket. In the case of a failure,
+ // |detailed_error| will be filled in with an explanation of what failed.
+ static bool ParseServerVersionNegotiationProbeResponse(
+ const char* packet_bytes,
+ QuicByteCount packet_length,
+ char* source_connection_id_bytes,
+ uint8_t* source_connection_id_length_out,
+ std::string* detailed_error);
+
private:
friend class test::QuicFramerPeer;
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc
index e83fd1b..347df84 100644
--- a/quic/core/quic_framer_test.cc
+++ b/quic/core/quic_framer_test.cc
@@ -13603,6 +13603,147 @@
CheckFramingBoundaries(packet, QUIC_INVALID_PACKET_HEADER);
}
+TEST_P(QuicFramerTest, WriteClientVersionNegotiationProbePacket) {
+ // clang-format off
+ static const char expected_packet[1200] = {
+ // IETF long header with fixed bit set, type initial, all-0 encrypted bits.
+ 0xc0,
+ // Version, part of the IETF space reserved for negotiation.
+ 0xca, 0xba, 0xda, 0xba,
+ // Destination connection ID length 8, source connection ID length 0.
+ 0x50,
+ // 8-byte destination connection ID.
+ 0x56, 0x4e, 0x20, 0x70, 0x6c, 0x7a, 0x20, 0x21,
+ // 8 bytes of zeroes followed by 8 bytes of ones to ensure that this does
+ // not parse with any known version.
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ // 2 bytes of zeroes to pad to 16 byte boundary.
+ 0x00, 0x00,
+ // A polite greeting in case a human sees this in tcpdump.
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x61, 0x63,
+ 0x6b, 0x65, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79,
+ 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x72, 0x69, 0x67, 0x67,
+ 0x65, 0x72, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20,
+ 0x51, 0x55, 0x49, 0x43, 0x20, 0x76, 0x65, 0x72,
+ 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x65, 0x67,
+ 0x6f, 0x74, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2e, 0x20, 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65,
+ 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20,
+ 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20,
+ 0x4e, 0x65, 0x67, 0x6f, 0x74, 0x69, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b,
+ 0x65, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x68,
+ 0x61, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20,
+ 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x2e,
+ 0x20, 0x54, 0x68, 0x61, 0x6e, 0x6b, 0x20, 0x79,
+ 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x6e, 0x69,
+ 0x63, 0x65, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x00,
+ };
+ // clang-format on
+ char packet[1200];
+ char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
+ 0x6c, 0x7a, 0x20, 0x21};
+ EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
+ packet, sizeof(packet), destination_connection_id_bytes,
+ sizeof(destination_connection_id_bytes)));
+ test::CompareCharArraysWithHexError("constructed packet", expected_packet,
+ sizeof(expected_packet), packet,
+ sizeof(packet));
+ QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
+ sizeof(packet), false);
+ // Make sure we fail to parse this packet for the version under test.
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+ if (framer_.transport_version() <= QUIC_VERSION_43) {
+ // We can only parse the connection ID with an IETF parser.
+ return;
+ }
+ ASSERT_TRUE(visitor_.header_.get());
+ QuicConnectionId probe_payload_connection_id(
+ reinterpret_cast<const char*>(destination_connection_id_bytes),
+ sizeof(destination_connection_id_bytes));
+ EXPECT_EQ(probe_payload_connection_id,
+ visitor_.header_.get()->destination_connection_id);
+}
+
+TEST_P(QuicFramerTest, ParseServerVersionNegotiationProbeResponse) {
+ // clang-format off
+ const char packet[] = {
+ // IETF long header with fixed bit set, type initial, all-0 encrypted bits.
+ 0xc0,
+ // Version of 0, indicating version negotiation.
+ 0x00, 0x00, 0x00, 0x00,
+ // Destination connection ID length 0, source connection ID length 8.
+ 0x05,
+ // 8-byte source connection ID.
+ 0x56, 0x4e, 0x20, 0x70, 0x6c, 0x7a, 0x20, 0x21,
+ // A few supported versions.
+ 0xaa, 0xaa, 0xaa, 0xaa,
+ QUIC_VERSION_BYTES,
+ };
+ // clang-format on
+ char probe_payload_bytes[] = {0x56, 0x4e, 0x20, 0x70, 0x6c, 0x7a, 0x20, 0x21};
+ char parsed_probe_payload_bytes[kQuicMaxConnectionIdLength] = {};
+ uint8_t parsed_probe_payload_length = 0;
+ std::string parse_detailed_error = "";
+ EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
+ reinterpret_cast<const char*>(packet), sizeof(packet),
+ reinterpret_cast<char*>(parsed_probe_payload_bytes),
+ &parsed_probe_payload_length, &parse_detailed_error));
+ EXPECT_EQ("", parse_detailed_error);
+ test::CompareCharArraysWithHexError(
+ "parsed probe", probe_payload_bytes, sizeof(probe_payload_bytes),
+ parsed_probe_payload_bytes, parsed_probe_payload_length);
+}
+
+TEST_P(QuicFramerTest, ClientConnectionIdNotSupportedYet) {
+ if (GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ // This check is currently only performed when this flag is disabled.
+ return;
+ }
+ if (framer_.transport_version() <= QUIC_VERSION_43) {
+ // This test requires an IETF long header.
+ return;
+ }
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
+ const unsigned char type_byte =
+ framer_.transport_version() == QUIC_VERSION_44 ? 0xFC : 0xD3;
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (long header with packet type ZERO_RTT_PROTECTED and
+ // 4-byte packet number)
+ type_byte,
+ // version
+ QUIC_VERSION_BYTES,
+ // destination connection ID length
+ 0x50,
+ // destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // long header packet length
+ 0x05,
+ // packet number
+ 0x12, 0x34, 0x56, 0x00,
+ // padding frame
+ 0x00,
+ };
+ // clang-format on
+ EXPECT_FALSE(framer_.ProcessPacket(
+ QuicEncryptedPacket(AsChars(packet), QUIC_ARRAYSIZE(packet), false)));
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
+ framer_.transport_version())) {
+ EXPECT_EQ("Invalid ConnectionId length.", framer_.detailed_error());
+ } else {
+ EXPECT_EQ("Client connection ID not supported yet.",
+ framer_.detailed_error());
+ }
+}
+
} // namespace
} // namespace test
} // namespace quic
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/platform/api/quic_ip_address.h b/quic/platform/api/quic_ip_address.h
index 856efbe..6d507b4 100644
--- a/quic/platform/api/quic_ip_address.h
+++ b/quic/platform/api/quic_ip_address.h
@@ -76,8 +76,6 @@
in_addr GetIPv4() const;
in6_addr GetIPv6() const;
- const QuicIpAddressImpl& impl() const { return impl_; }
-
private:
QuicIpAddressImpl impl_;
};
diff --git a/quic/platform/api/quic_socket_address.cc b/quic/platform/api/quic_socket_address.cc
index dacd6ac..e0bb35c 100644
--- a/quic/platform/api/quic_socket_address.cc
+++ b/quic/platform/api/quic_socket_address.cc
@@ -9,7 +9,7 @@
namespace quic {
QuicSocketAddress::QuicSocketAddress(QuicIpAddress address, uint16_t port)
- : impl_(address.impl(), port) {}
+ : impl_(address, port) {}
QuicSocketAddress::QuicSocketAddress(const struct sockaddr_storage& saddr)
: impl_(saddr) {}
diff --git a/quic/platform/api/quic_socket_address.h b/quic/platform/api/quic_socket_address.h
index 57689a7..85e61d5 100644
--- a/quic/platform/api/quic_socket_address.h
+++ b/quic/platform/api/quic_socket_address.h
@@ -39,7 +39,6 @@
QuicIpAddress host() const;
uint16_t port() const;
sockaddr_storage generic_address() const;
- const QuicSocketAddressImpl& impl() const { return impl_; }
private:
QuicSocketAddressImpl impl_;
diff --git a/quic/quartc/quartc_endpoint.cc b/quic/quartc/quartc_endpoint.cc
index fe87ca1..7676c59 100644
--- a/quic/quartc/quartc_endpoint.cc
+++ b/quic/quartc/quartc_endpoint.cc
@@ -67,17 +67,72 @@
void QuartcClientEndpoint::Connect(QuartcPacketTransport* packet_transport) {
packet_transport_ = packet_transport;
+ // For the first attempt to connect, use any version that the client supports.
+ current_versions_ = version_manager_->GetSupportedVersions();
create_session_alarm_->Set(clock_->Now());
}
void QuartcClientEndpoint::OnCreateSessionAlarm() {
session_ = CreateQuartcClientSession(
config_, clock_, alarm_factory_, connection_helper_.get(),
- version_manager_->GetSupportedVersions(), serialized_server_config_,
- packet_transport_);
+ current_versions_, serialized_server_config_, packet_transport_);
+ session_->SetDelegate(this);
delegate_->OnSessionCreated(session_.get());
}
+void QuartcClientEndpoint::OnCryptoHandshakeComplete() {
+ delegate_->OnCryptoHandshakeComplete();
+}
+
+void QuartcClientEndpoint::OnConnectionWritable() {
+ delegate_->OnConnectionWritable();
+}
+
+void QuartcClientEndpoint::OnIncomingStream(QuartcStream* stream) {
+ delegate_->OnIncomingStream(stream);
+}
+
+void QuartcClientEndpoint::OnCongestionControlChange(
+ QuicBandwidth bandwidth_estimate,
+ QuicBandwidth pacing_rate,
+ QuicTime::Delta latest_rtt) {
+ delegate_->OnCongestionControlChange(bandwidth_estimate, pacing_rate,
+ latest_rtt);
+}
+
+void QuartcClientEndpoint::OnConnectionClosed(QuicErrorCode error_code,
+ const std::string& error_details,
+ ConnectionCloseSource source) {
+ // First, see if we can restart the session with a mutually-supported version.
+ if (error_code == QUIC_INVALID_VERSION && session_ &&
+ session_->connection() &&
+ !session_->connection()->server_supported_versions().empty()) {
+ for (const auto& client_version :
+ version_manager_->GetSupportedVersions()) {
+ if (QuicContainsValue(session_->connection()->server_supported_versions(),
+ client_version)) {
+ // Found a mutually-supported version. Reconnect using that version.
+ current_versions_.clear();
+ current_versions_.push_back(client_version);
+ create_session_alarm_->Set(clock_->Now());
+ return;
+ }
+ }
+ }
+
+ // Permanent version negotiation errors are forwarded to the |delegate_|,
+ // along with all other errors.
+ delegate_->OnConnectionClosed(error_code, error_details, source);
+}
+
+void QuartcClientEndpoint::OnMessageReceived(QuicStringPiece message) {
+ delegate_->OnMessageReceived(message);
+}
+
+void QuartcClientEndpoint::OnMessageSent(int64_t datagram_id) {
+ delegate_->OnMessageSent(datagram_id);
+}
+
QuartcServerEndpoint::QuartcServerEndpoint(
QuicAlarmFactory* alarm_factory,
const QuicClock* clock,
@@ -115,6 +170,7 @@
}
void QuartcServerEndpoint::OnSessionCreated(QuartcSession* session) {
+ session->SetDelegate(delegate_);
delegate_->OnSessionCreated(session);
}
diff --git a/quic/quartc/quartc_endpoint.h b/quic/quartc/quartc_endpoint.h
index 1169403..6c7644c 100644
--- a/quic/quartc/quartc_endpoint.h
+++ b/quic/quartc/quartc_endpoint.h
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h"
@@ -29,22 +30,23 @@
// Endpoint (client or server) in a peer-to-peer Quartc connection.
class QuartcEndpoint {
public:
- class Delegate {
+ class Delegate : public QuartcSession::Delegate {
public:
virtual ~Delegate() = default;
// Called when an endpoint creates a new session, before any packets are
// processed or sent. The callee should perform any additional
- // configuration required, such as setting a session delegate, before
+ // configuration required, such as setting up congestion control, before
// returning. |session| is owned by the endpoint, but remains safe to use
- // until another call to |OnSessionCreated| occurs, at which point previous
- // session is destroyed.
+ // until another call to |OnSessionCreated| or |OnConnectionClosed| occurs,
+ // at which point previous session may be destroyed.
+ //
+ // Callees must not change the |session|'s delegate. The Endpoint itself
+ // manages the delegate and will forward calls.
+ //
+ // New calls to |OnSessionCreated| will only occur prior to
+ // |OnConnectionWritable|, during initial connection negotiation.
virtual void OnSessionCreated(QuartcSession* session) = 0;
-
- // Called if the endpoint fails to establish a session after a call to
- // Connect. (The most likely cause is a network idle timeout.)
- virtual void OnConnectError(QuicErrorCode error,
- const std::string& error_details) = 0;
};
virtual ~QuartcEndpoint() = default;
@@ -58,7 +60,8 @@
// Implementation of QuartcEndpoint which immediately (but asynchronously)
// creates a session by scheduling a QuicAlarm. Only suitable for use with the
// client perspective.
-class QuartcClientEndpoint : public QuartcEndpoint {
+class QuartcClientEndpoint : public QuartcEndpoint,
+ public QuartcSession::Delegate {
public:
// |alarm_factory|, |clock|, and |delegate| are owned by the caller and must
// outlive the endpoint.
@@ -66,13 +69,26 @@
QuicAlarmFactory* alarm_factory,
const QuicClock* clock,
QuicRandom* random,
- Delegate* delegate,
+ QuartcEndpoint::Delegate* delegate,
const QuartcSessionConfig& config,
QuicStringPiece serialized_server_config,
std::unique_ptr<QuicVersionManager> version_manager = nullptr);
void Connect(QuartcPacketTransport* packet_transport) override;
+ // QuartcSession::Delegate overrides.
+ void OnCryptoHandshakeComplete() override;
+ void OnConnectionWritable() override;
+ void OnIncomingStream(QuartcStream* stream) override;
+ void OnCongestionControlChange(QuicBandwidth bandwidth_estimate,
+ QuicBandwidth pacing_rate,
+ QuicTime::Delta latest_rtt) override;
+ void OnConnectionClosed(QuicErrorCode error_code,
+ const std::string& error_details,
+ ConnectionCloseSource source) override;
+ void OnMessageReceived(QuicStringPiece message) override;
+ void OnMessageSent(int64_t datagram_id) override;
+
private:
friend class CreateSessionDelegate;
class CreateSessionDelegate : public QuicAlarm::Delegate {
@@ -104,6 +120,18 @@
// Version manager. May be injected to control version negotiation in tests.
std::unique_ptr<QuicVersionManager> version_manager_;
+ // Versions to be used when the next session is created. The session will
+ // choose one of these versions for its connection attempt.
+ //
+ // If the connection does not succeed, the client session MAY try again using
+ // another version from this list, or it MAY simply fail with a
+ // QUIC_INVALID_VERSION error. The latter occurs when it is not possible to
+ // upgrade a connection in-place (for example, if the way stream ids are
+ // allocated changes between versions). This failure mode is handled by
+ // narrowing |current_versions_| to one of that is mutually-supported and
+ // reconnecting (with a new session).
+ ParsedQuicVersionVector current_versions_;
+
// Alarm for creating sessions asynchronously. The alarm is set when
// Connect() is called. When it fires, the endpoint creates a session and
// calls the delegate.
diff --git a/quic/quartc/quartc_endpoint_test.cc b/quic/quartc/quartc_endpoint_test.cc
index 567ccdd..5f8c25d 100644
--- a/quic/quartc/quartc_endpoint_test.cc
+++ b/quic/quartc/quartc_endpoint_test.cc
@@ -30,18 +30,16 @@
&server_transport_,
QuicBandwidth::FromKBitsPerSecond(10000),
QuicTime::Delta::FromMilliseconds(1)),
- server_session_delegate_(&server_stream_delegate_,
- simulator_.GetClock()),
- server_endpoint_delegate_(&server_session_delegate_),
+ server_endpoint_delegate_(&server_stream_delegate_,
+ simulator_.GetClock()),
server_endpoint_(QuicMakeUnique<QuartcServerEndpoint>(
simulator_.GetAlarmFactory(),
simulator_.GetClock(),
simulator_.GetRandomGenerator(),
&server_endpoint_delegate_,
QuartcSessionConfig())),
- client_session_delegate_(&client_stream_delegate_,
- simulator_.GetClock()),
- client_endpoint_delegate_(&client_session_delegate_),
+ client_endpoint_delegate_(&client_stream_delegate_,
+ simulator_.GetClock()),
client_endpoint_(QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(),
simulator_.GetClock(),
@@ -57,13 +55,11 @@
simulator::SymmetricLink client_server_link_;
FakeQuartcStreamDelegate server_stream_delegate_;
- FakeQuartcSessionDelegate server_session_delegate_;
FakeQuartcEndpointDelegate server_endpoint_delegate_;
std::unique_ptr<QuartcServerEndpoint> server_endpoint_;
FakeQuartcStreamDelegate client_stream_delegate_;
- FakeQuartcSessionDelegate client_session_delegate_;
FakeQuartcEndpointDelegate client_endpoint_delegate_;
std::unique_ptr<QuartcClientEndpoint> client_endpoint_;
@@ -215,5 +211,57 @@
EXPECT_EQ(client_endpoint_delegate_.session()->error(), QUIC_INVALID_VERSION);
}
+// Tests that the client endpoint can create a new session in order to continue
+// version negotiation.
+TEST_F(QuartcEndpointTest,
+ QUIC_TEST_DISABLED_IN_CHROME(CreatesNewSessionWhenRequired)) {
+ // Setting this flag to true requires the client to create a new session when
+ // version negotiation fails.
+ SetQuicReloadableFlag(quic_no_client_conn_ver_negotiation, true);
+
+ // Note: for this test, we need support for two versions. Which two shouldn't
+ // matter, but they must be enabled so that the version manager doesn't filter
+ // them out.
+ SetQuicReloadableFlag(quic_enable_version_46, true);
+
+ // Reset the client endpoint to prefer version 46 but also be capable of
+ // speaking version 43.
+ ParsedQuicVersionVector client_versions;
+ client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46});
+ client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
+ client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
+ simulator_.GetAlarmFactory(), simulator_.GetClock(),
+ simulator_.GetRandomGenerator(), &client_endpoint_delegate_,
+ QuartcSessionConfig(),
+ /*serialized_server_config=*/"",
+ QuicMakeUnique<QuicVersionManager>(client_versions));
+
+ // Reset the server endpoint to only speak version 43.
+ ParsedQuicVersionVector server_versions;
+ server_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
+ server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
+ simulator_.GetAlarmFactory(), simulator_.GetClock(),
+ simulator_.GetRandomGenerator(), &server_endpoint_delegate_,
+ QuartcSessionConfig(),
+ QuicMakeUnique<QuicVersionManager>(server_versions));
+
+ // The endpoints should be able to establish a connection using version 46.
+ server_endpoint_->Connect(&server_transport_);
+ client_endpoint_->Connect(&client_transport_);
+
+ ASSERT_TRUE(simulator_.RunUntil([this] {
+ return client_endpoint_delegate_.session() != nullptr &&
+ client_endpoint_delegate_.session()->IsEncryptionEstablished() &&
+ server_endpoint_delegate_.session() != nullptr &&
+ server_endpoint_delegate_.session()->IsEncryptionEstablished();
+ }));
+ EXPECT_EQ(client_endpoint_delegate_.session()->connection()->version(),
+ server_versions[0]);
+ EXPECT_EQ(server_endpoint_delegate_.session()->connection()->version(),
+ server_versions[0]);
+
+ EXPECT_EQ(2, client_endpoint_delegate_.num_sessions_created());
+}
+
} // namespace
} // namespace quic
diff --git a/quic/quartc/quartc_factory.cc b/quic/quartc/quartc_factory.cc
index 93bb03f..06871a2 100644
--- a/quic/quartc/quartc_factory.cc
+++ b/quic/quartc/quartc_factory.cc
@@ -71,16 +71,6 @@
SetQuicFlag(FLAGS_quic_buffered_data_threshold,
std::numeric_limits<int>::max());
- // TODO(b/117157454): Perform version negotiation for Quartc outside of
- // QuicSession/QuicConnection. Currently default of
- // quic_restart_flag_quic_no_server_conn_ver_negotiation2 is false,
- // but we fail blueprint test that sets all QUIC flags to true.
- //
- // Forcing flag to false to pass blueprint tests, but eventually we'll have
- // to implement negotiation outside of QuicConnection.
- SetQuicRestartFlag(quic_no_server_conn_ver_negotiation2, false);
- SetQuicReloadableFlag(quic_no_client_conn_ver_negotiation, false);
-
// Enable and request QUIC to include receive timestamps in ACK frames.
SetQuicReloadableFlag(quic_send_timestamps, true);
@@ -190,7 +180,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/quartc/quartc_fakes.h b/quic/quartc/quartc_fakes.h
index 7048a5e..13b65b1 100644
--- a/quic/quartc/quartc_fakes.h
+++ b/quic/quartc/quartc_fakes.h
@@ -18,37 +18,17 @@
class FakeQuartcEndpointDelegate : public QuartcEndpoint::Delegate {
public:
- explicit FakeQuartcEndpointDelegate(QuartcSession::Delegate* session_delegate)
- : session_delegate_(session_delegate) {}
+ explicit FakeQuartcEndpointDelegate(QuartcStream::Delegate* stream_delegate,
+ const QuicClock* clock)
+ : stream_delegate_(stream_delegate), clock_(clock) {}
void OnSessionCreated(QuartcSession* session) override {
- CHECK_EQ(session_, nullptr);
CHECK_NE(session, nullptr);
session_ = session;
- session_->SetDelegate(session_delegate_);
session_->StartCryptoHandshake();
+ ++num_sessions_created_;
}
- void OnConnectError(QuicErrorCode error,
- const std::string& error_details) override {
- QUIC_LOG(FATAL)
- << "Unexpected error during QuartcEndpoint::Connect(); error=" << error
- << ", error_details=" << error_details;
- }
-
- QuartcSession* session() { return session_; }
-
- private:
- QuartcSession::Delegate* session_delegate_;
- QuartcSession* session_ = nullptr;
-};
-
-class FakeQuartcSessionDelegate : public QuartcSession::Delegate {
- public:
- explicit FakeQuartcSessionDelegate(QuartcStream::Delegate* stream_delegate,
- const QuicClock* clock)
- : stream_delegate_(stream_delegate), clock_(clock) {}
-
void OnConnectionWritable() override {
QUIC_LOG(INFO) << "Connection writable!";
if (!writable_time_.IsInitialized()) {
@@ -87,6 +67,10 @@
QuicBandwidth pacing_rate,
QuicTime::Delta latest_rtt) override {}
+ QuartcSession* session() { return session_; }
+
+ int num_sessions_created() const { return num_sessions_created_; }
+
QuartcStream* last_incoming_stream() const { return last_incoming_stream_; }
// Returns all received messages.
@@ -104,6 +88,12 @@
QuicTime crypto_handshake_time() const { return crypto_handshake_time_; }
private:
+ // Current session.
+ QuartcSession* session_ = nullptr;
+
+ // Number of new sessions created by the endpoint.
+ int num_sessions_created_ = 0;
+
QuartcStream* last_incoming_stream_;
std::vector<std::string> incoming_messages_;
std::vector<int64_t> sent_datagram_ids_;
diff --git a/quic/quartc/quartc_session_test.cc b/quic/quartc/quartc_session_test.cc
index e150e03..87174dc 100644
--- a/quic/quartc/quartc_session_test.cc
+++ b/quic/quartc/quartc_session_test.cc
@@ -61,29 +61,25 @@
QuicBandwidth::FromKBitsPerSecond(10 * 1000), kPropagationDelay);
client_stream_delegate_ = QuicMakeUnique<FakeQuartcStreamDelegate>();
- client_session_delegate_ = QuicMakeUnique<FakeQuartcSessionDelegate>(
+ client_session_delegate_ = QuicMakeUnique<FakeQuartcEndpointDelegate>(
client_stream_delegate_.get(), simulator_.GetClock());
- client_endpoint_delegate_ = QuicMakeUnique<FakeQuartcEndpointDelegate>(
- client_session_delegate_.get());
server_stream_delegate_ = QuicMakeUnique<FakeQuartcStreamDelegate>();
- server_session_delegate_ = QuicMakeUnique<FakeQuartcSessionDelegate>(
+ server_session_delegate_ = QuicMakeUnique<FakeQuartcEndpointDelegate>(
server_stream_delegate_.get(), simulator_.GetClock());
- server_endpoint_delegate_ = QuicMakeUnique<FakeQuartcEndpointDelegate>(
- server_session_delegate_.get());
// No 0-rtt setup, because server config is empty.
// CannotCreateDataStreamBeforeHandshake depends on 1-rtt setup.
if (create_client_endpoint) {
client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- simulator_.GetRandomGenerator(), client_endpoint_delegate_.get(),
+ simulator_.GetRandomGenerator(), client_session_delegate_.get(),
quic::QuartcSessionConfig(),
/*serialized_server_config=*/"");
}
server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- simulator_.GetRandomGenerator(), server_endpoint_delegate_.get(),
+ simulator_.GetRandomGenerator(), server_session_delegate_.get(),
quic::QuartcSessionConfig());
}
@@ -99,12 +95,12 @@
client_endpoint_->Connect(client_transport_.get());
CHECK(simulator_.RunUntil([this] {
- return client_endpoint_delegate_->session() != nullptr &&
- server_endpoint_delegate_->session() != nullptr;
+ return client_session_delegate_->session() != nullptr &&
+ server_session_delegate_->session() != nullptr;
}));
- client_peer_ = client_endpoint_delegate_->session();
- server_peer_ = server_endpoint_delegate_->session();
+ client_peer_ = client_session_delegate_->session();
+ server_peer_ = server_session_delegate_->session();
}
// Runs all tasks scheduled in the next 200 ms.
@@ -214,11 +210,11 @@
QuartcSession* const peer_sending =
direction_from_server ? server_peer_ : client_peer_;
- FakeQuartcSessionDelegate* const delegate_receiving =
+ FakeQuartcEndpointDelegate* const delegate_receiving =
direction_from_server ? client_session_delegate_.get()
: server_session_delegate_.get();
- FakeQuartcSessionDelegate* const delegate_sending =
+ FakeQuartcEndpointDelegate* const delegate_sending =
direction_from_server ? server_session_delegate_.get()
: client_session_delegate_.get();
@@ -299,11 +295,9 @@
std::unique_ptr<simulator::SymmetricLink> client_server_link_;
std::unique_ptr<FakeQuartcStreamDelegate> client_stream_delegate_;
- std::unique_ptr<FakeQuartcSessionDelegate> client_session_delegate_;
- std::unique_ptr<FakeQuartcEndpointDelegate> client_endpoint_delegate_;
+ std::unique_ptr<FakeQuartcEndpointDelegate> client_session_delegate_;
std::unique_ptr<FakeQuartcStreamDelegate> server_stream_delegate_;
- std::unique_ptr<FakeQuartcSessionDelegate> server_session_delegate_;
- std::unique_ptr<FakeQuartcEndpointDelegate> server_endpoint_delegate_;
+ std::unique_ptr<FakeQuartcEndpointDelegate> server_session_delegate_;
std::unique_ptr<QuartcClientEndpoint> client_endpoint_;
std::unique_ptr<QuartcServerEndpoint> server_endpoint_;
@@ -537,7 +531,7 @@
client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- simulator_.GetRandomGenerator(), client_endpoint_delegate_.get(),
+ simulator_.GetRandomGenerator(), client_session_delegate_.get(),
QuartcSessionConfig(),
// This is the key line here. It passes through the server config
// from the server to the client.
@@ -549,8 +543,8 @@
// client session should be created, but server won't be created yet.
simulator_.RunFor(QuicTime::Delta::FromMilliseconds(1));
- client_peer_ = client_endpoint_delegate_->session();
- server_peer_ = server_endpoint_delegate_->session();
+ client_peer_ = client_session_delegate_->session();
+ server_peer_ = server_session_delegate_->session();
ASSERT_NE(client_peer_, nullptr);
ASSERT_EQ(server_peer_, nullptr);
diff --git a/quic/quartc/test/quartc_peer.cc b/quic/quartc/test/quartc_peer.cc
index 6857858..761349e 100644
--- a/quic/quartc/test/quartc_peer.cc
+++ b/quic/quartc/test/quartc_peer.cc
@@ -46,7 +46,6 @@
void QuartcPeer::OnSessionCreated(QuartcSession* session) {
session_ = session;
- session_->SetDelegate(this);
session_->StartCryptoHandshake();
QuicByteCount largest_message_payload =
@@ -65,13 +64,6 @@
}
}
-void QuartcPeer::OnConnectError(QuicErrorCode error,
- const std::string& error_details) {
- QUIC_LOG(WARNING) << "Connect failed, error=" << error
- << ", details=" << error_details;
- SetEnabled(false);
-}
-
void QuartcPeer::OnCryptoHandshakeComplete() {
SetEnabled(true);
}
diff --git a/quic/quartc/test/quartc_peer.h b/quic/quartc/test/quartc_peer.h
index 65d85fa..b96f488 100644
--- a/quic/quartc/test/quartc_peer.h
+++ b/quic/quartc/test/quartc_peer.h
@@ -39,7 +39,6 @@
// datagram frames. It also adjusts the bitrate of each source to fit within
// the bandwidth available to the session.
class QuartcPeer : public QuartcEndpoint::Delegate,
- public QuartcSession::Delegate,
public QuartcDataSource::Delegate {
public:
// Creates a QuartcPeer that sends data from a set of sources described by
@@ -73,8 +72,6 @@
// QuartcEndpoint::Delegate overrides.
void OnSessionCreated(QuartcSession* session) override;
- void OnConnectError(QuicErrorCode error,
- const std::string& error_details) override;
// QuartcSession::Delegate overrides.
void OnCryptoHandshakeComplete() override;
diff --git a/quic/quartc/test/quic_trace_interceptor.cc b/quic/quartc/test/quic_trace_interceptor.cc
index c2fa6ec..741c542 100644
--- a/quic/quartc/test/quic_trace_interceptor.cc
+++ b/quic/quartc/test/quic_trace_interceptor.cc
@@ -33,9 +33,38 @@
delegate_->OnSessionCreated(session);
}
-void QuicTraceInterceptor::OnConnectError(QuicErrorCode error,
- const std::string& details) {
- delegate_->OnConnectError(error, details);
+void QuicTraceInterceptor::OnCryptoHandshakeComplete() {
+ delegate_->OnCryptoHandshakeComplete();
+}
+
+void QuicTraceInterceptor::OnConnectionWritable() {
+ delegate_->OnConnectionWritable();
+}
+
+void QuicTraceInterceptor::OnIncomingStream(QuartcStream* stream) {
+ delegate_->OnIncomingStream(stream);
+}
+
+void QuicTraceInterceptor::OnCongestionControlChange(
+ QuicBandwidth bandwidth_estimate,
+ QuicBandwidth pacing_rate,
+ QuicTime::Delta latest_rtt) {
+ delegate_->OnCongestionControlChange(bandwidth_estimate, pacing_rate,
+ latest_rtt);
+}
+
+void QuicTraceInterceptor::OnConnectionClosed(QuicErrorCode error_code,
+ const std::string& error_details,
+ ConnectionCloseSource source) {
+ delegate_->OnConnectionClosed(error_code, error_details, source);
+}
+
+void QuicTraceInterceptor::OnMessageReceived(QuicStringPiece message) {
+ delegate_->OnMessageReceived(message);
+}
+
+void QuicTraceInterceptor::OnMessageSent(int64_t datagram_id) {
+ delegate_->OnMessageSent(datagram_id);
}
void QuicTraceInterceptor::SetDelegate(QuartcEndpoint::Delegate* delegate) {
diff --git a/quic/quartc/test/quic_trace_interceptor.h b/quic/quartc/test/quic_trace_interceptor.h
index bb731b1..ee79d1e 100644
--- a/quic/quartc/test/quic_trace_interceptor.h
+++ b/quic/quartc/test/quic_trace_interceptor.h
@@ -28,7 +28,17 @@
// QuartcEndpointIntercept overrides.
void OnSessionCreated(QuartcSession* session) override;
- void OnConnectError(QuicErrorCode error, const std::string& details) override;
+ void OnCryptoHandshakeComplete() override;
+ void OnConnectionWritable() override;
+ void OnIncomingStream(QuartcStream* stream) override;
+ void OnCongestionControlChange(QuicBandwidth bandwidth_estimate,
+ QuicBandwidth pacing_rate,
+ QuicTime::Delta latest_rtt) override;
+ void OnConnectionClosed(QuicErrorCode error_code,
+ const std::string& error_details,
+ ConnectionCloseSource source) override;
+ void OnMessageReceived(QuicStringPiece message) override;
+ void OnMessageSent(int64_t datagram_id) override;
void SetDelegate(QuartcEndpoint::Delegate* delegate) override;
private:
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/fake_proof_verifier.h b/quic/tools/fake_proof_verifier.h
new file mode 100644
index 0000000..ffeb6e9
--- /dev/null
+++ b/quic/tools/fake_proof_verifier.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TOOLS_FAKE_PROOF_VERIFIER_H_
+#define QUICHE_QUIC_TOOLS_FAKE_PROOF_VERIFIER_H_
+
+#include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h"
+
+namespace quic {
+
+// ProofVerifier implementation which always returns success.
+class FakeProofVerifier : public ProofVerifier {
+ public:
+ ~FakeProofVerifier() override {}
+ QuicAsyncStatus VerifyProof(
+ const std::string& /*hostname*/,
+ const uint16_t /*port*/,
+ const std::string& /*server_config*/,
+ QuicTransportVersion /*quic_version*/,
+ QuicStringPiece /*chlo_hash*/,
+ const std::vector<std::string>& /*certs*/,
+ const std::string& /*cert_sct*/,
+ const std::string& /*signature*/,
+ const ProofVerifyContext* /*context*/,
+ std::string* /*error_details*/,
+ std::unique_ptr<ProofVerifyDetails>* /*details*/,
+ std::unique_ptr<ProofVerifierCallback> /*callback*/) override {
+ return QUIC_SUCCESS;
+ }
+ QuicAsyncStatus VerifyCertChain(
+ const std::string& /*hostname*/,
+ const std::vector<std::string>& /*certs*/,
+ const std::string& /*ocsp_response*/,
+ const std::string& /*cert_sct*/,
+ const ProofVerifyContext* /*context*/,
+ std::string* /*error_details*/,
+ std::unique_ptr<ProofVerifyDetails>* /*details*/,
+ std::unique_ptr<ProofVerifierCallback> /*callback*/) override {
+ return QUIC_SUCCESS;
+ }
+ std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
+ return nullptr;
+ }
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TOOLS_FAKE_PROOF_VERIFIER_H_
diff --git a/quic/tools/quic_client.cc b/quic/tools/quic_client.cc
index b736c71..e7fe6b4 100644
--- a/quic/tools/quic_client.cc
+++ b/quic/tools/quic_client.cc
@@ -85,7 +85,7 @@
QuicConnection* connection) {
return QuicMakeUnique<QuicSimpleClientSession>(
*config(), supported_versions, connection, server_id(), crypto_config(),
- push_promise_index(), drop_response_body_);
+ push_promise_index(), drop_response_body());
}
QuicClientEpollNetworkHelper* QuicClient::epoll_network_helper() {
diff --git a/quic/tools/quic_client.h b/quic/tools/quic_client.h
index b84c597..0e708ec 100644
--- a/quic/tools/quic_client.h
+++ b/quic/tools/quic_client.h
@@ -67,13 +67,8 @@
QuicClientEpollNetworkHelper* epoll_network_helper();
const QuicClientEpollNetworkHelper* epoll_network_helper() const;
- void set_drop_response_body(bool drop_response_body) {
- drop_response_body_ = drop_response_body;
- }
-
private:
friend class test::QuicClientPeer;
- bool drop_response_body_ = false;
};
} // namespace quic
diff --git a/quic/tools/quic_client_bin.cc b/quic/tools/quic_client_bin.cc
index ff711a5..1ec47a9 100644
--- a/quic/tools/quic_client_bin.cc
+++ b/quic/tools/quic_client_bin.cc
@@ -60,6 +60,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/tools/fake_proof_verifier.h"
#include "net/third_party/quiche/src/quic/tools/quic_client.h"
#include "net/third_party/quiche/src/quic/tools/quic_url.h"
@@ -70,40 +71,6 @@
using quic::QuicTextUtils;
using quic::QuicUrl;
-class FakeProofVerifier : public quic::ProofVerifier {
- public:
- ~FakeProofVerifier() override {}
- quic::QuicAsyncStatus VerifyProof(
- const std::string& /*hostname*/,
- const uint16_t /*port*/,
- const std::string& /*server_config*/,
- quic::QuicTransportVersion /*quic_version*/,
- quic::QuicStringPiece /*chlo_hash*/,
- const std::vector<std::string>& /*certs*/,
- const std::string& /*cert_sct*/,
- const std::string& /*signature*/,
- const quic::ProofVerifyContext* /*context*/,
- std::string* /*error_details*/,
- std::unique_ptr<quic::ProofVerifyDetails>* /*details*/,
- std::unique_ptr<quic::ProofVerifierCallback> /*callback*/) override {
- return quic::QUIC_SUCCESS;
- }
- quic::QuicAsyncStatus VerifyCertChain(
- const std::string& /*hostname*/,
- const std::vector<std::string>& /*certs*/,
- const std::string& /*ocsp_response*/,
- const std::string& /*cert_sct*/,
- const quic::ProofVerifyContext* /*context*/,
- std::string* /*error_details*/,
- std::unique_ptr<quic::ProofVerifyDetails>* /*details*/,
- std::unique_ptr<quic::ProofVerifierCallback> /*callback*/) override {
- return quic::QUIC_SUCCESS;
- }
- std::unique_ptr<quic::ProofVerifyContext> CreateDefaultContext() override {
- return nullptr;
- }
-};
-
QuicSocketAddress LookupAddress(std::string host, std::string port) {
addrinfo hint;
memset(&hint, 0, sizeof(hint));
@@ -285,7 +252,7 @@
const int32_t num_requests(GetQuicFlag(FLAGS_num_requests));
std::unique_ptr<quic::ProofVerifier> proof_verifier;
if (GetQuicFlag(FLAGS_disable_certificate_verification)) {
- proof_verifier = quic::QuicMakeUnique<FakeProofVerifier>();
+ proof_verifier = quic::QuicMakeUnique<quic::FakeProofVerifier>();
} else {
proof_verifier = quic::CreateDefaultProofVerifier();
}
@@ -331,8 +298,8 @@
header_block[":path"] = url.PathParamsQuery();
// Append any additional headers supplied on the command line.
- for (QuicStringPiece sp :
- QuicTextUtils::Split(GetQuicFlag(FLAGS_headers), ';')) {
+ const std::string headers = GetQuicFlag(FLAGS_headers);
+ for (QuicStringPiece sp : QuicTextUtils::Split(headers, ';')) {
QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&sp);
if (sp.empty()) {
continue;
@@ -394,18 +361,18 @@
size_t response_code = client.latest_response_code();
if (response_code >= 200 && response_code < 300) {
- std::cerr << "Request succeeded (" << response_code << ")." << std::endl;
+ std::cout << "Request succeeded (" << response_code << ")." << std::endl;
} else if (response_code >= 300 && response_code < 400) {
if (GetQuicFlag(FLAGS_redirect_is_success)) {
- std::cerr << "Request succeeded (redirect " << response_code << ")."
+ std::cout << "Request succeeded (redirect " << response_code << ")."
<< std::endl;
} else {
- std::cerr << "Request failed (redirect " << response_code << ")."
+ std::cout << "Request failed (redirect " << response_code << ")."
<< std::endl;
return 1;
}
} else {
- std::cerr << "Request failed (" << response_code << ")." << std::endl;
+ std::cout << "Request failed (" << response_code << ")." << std::endl;
return 1;
}
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));
}
diff --git a/quic/tools/quic_spdy_client_base.h b/quic/tools/quic_spdy_client_base.h
index 03a981e..0bc4f23 100644
--- a/quic/tools/quic_spdy_client_base.h
+++ b/quic/tools/quic_spdy_client_base.h
@@ -135,6 +135,11 @@
response_listener_ = std::move(listener);
}
+ void set_drop_response_body(bool drop_response_body) {
+ drop_response_body_ = drop_response_body;
+ }
+ bool drop_response_body() const { return drop_response_body_; }
+
protected:
int GetNumSentClientHellosFromSession() override;
int GetNumReceivedServerConfigUpdatesFromSession() override;
@@ -209,6 +214,8 @@
std::vector<std::unique_ptr<QuicDataToResend>> data_to_resend_on_connect_;
std::unique_ptr<ClientQuicDataToResend> push_promise_data_to_resend_;
+
+ bool drop_response_body_ = false;
};
} // namespace quic