summaryrefslogtreecommitdiff
path: root/chromium/net/quic
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/quic')
-rw-r--r--chromium/net/quic/OWNERS2
-rw-r--r--chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc157
-rw-r--r--chromium/net/quic/crypto/proof_verifier_chromium.cc10
-rw-r--r--chromium/net/quic/crypto/proof_verifier_chromium.h6
-rw-r--r--chromium/net/quic/crypto/proof_verifier_chromium_test.cc216
-rw-r--r--chromium/net/quic/crypto_test_utils_chromium.cc4
-rw-r--r--chromium/net/quic/mock_crypto_client_stream.cc121
-rw-r--r--chromium/net/quic/mock_quic_data.cc1
-rw-r--r--chromium/net/quic/network_connection.cc1
-rw-r--r--chromium/net/quic/platform/impl/quic_default_proof_providers_impl.cc6
-rw-r--r--chromium/net/quic/platform/impl/quic_socket_utils.cc1
-rw-r--r--chromium/net/quic/platform/impl/quic_test_impl.h2
-rw-r--r--chromium/net/quic/quic_chromium_client_session.cc356
-rw-r--r--chromium/net/quic/quic_chromium_client_session.h63
-rw-r--r--chromium/net/quic/quic_chromium_client_session_peer.cc5
-rw-r--r--chromium/net/quic/quic_chromium_client_session_peer.h2
-rw-r--r--chromium/net/quic/quic_chromium_client_session_test.cc359
-rw-r--r--chromium/net/quic/quic_chromium_client_stream.h2
-rw-r--r--chromium/net/quic/quic_chromium_packet_writer.cc4
-rw-r--r--chromium/net/quic/quic_chromium_packet_writer.h2
-rw-r--r--chromium/net/quic/quic_client_session_cache.cc18
-rw-r--r--chromium/net/quic/quic_client_session_cache.h2
-rw-r--r--chromium/net/quic/quic_client_session_cache_unittests.cc170
-rw-r--r--chromium/net/quic/quic_connection_logger.cc30
-rw-r--r--chromium/net/quic/quic_connection_logger.h4
-rw-r--r--chromium/net/quic/quic_connectivity_monitor.cc71
-rw-r--r--chromium/net/quic/quic_connectivity_monitor.h74
-rw-r--r--chromium/net/quic/quic_connectivity_probing_manager.cc48
-rw-r--r--chromium/net/quic/quic_connectivity_probing_manager.h13
-rw-r--r--chromium/net/quic/quic_connectivity_probing_manager_test.cc83
-rw-r--r--chromium/net/quic/quic_context.h11
-rw-r--r--chromium/net/quic/quic_flags_list.h235
-rw-r--r--chromium/net/quic/quic_http3_logger.cc84
-rw-r--r--chromium/net/quic/quic_http_stream.cc13
-rw-r--r--chromium/net/quic/quic_http_stream_test.cc11
-rw-r--r--chromium/net/quic/quic_http_utils.cc5
-rw-r--r--chromium/net/quic/quic_http_utils_test.cc19
-rw-r--r--chromium/net/quic/quic_network_transaction_unittest.cc695
-rw-r--r--chromium/net/quic/quic_proxy_client_socket.cc18
-rw-r--r--chromium/net/quic/quic_proxy_client_socket.h6
-rw-r--r--chromium/net/quic/quic_proxy_client_socket_unittest.cc4
-rw-r--r--chromium/net/quic/quic_session_key.cc7
-rw-r--r--chromium/net/quic/quic_stream_factory.cc183
-rw-r--r--chromium/net/quic/quic_stream_factory.h22
-rw-r--r--chromium/net/quic/quic_stream_factory_peer.cc5
-rw-r--r--chromium/net/quic/quic_stream_factory_peer.h2
-rw-r--r--chromium/net/quic/quic_stream_factory_test.cc448
-rw-r--r--chromium/net/quic/quic_test_packet_maker.cc124
-rw-r--r--chromium/net/quic/quic_test_packet_maker.h26
-rw-r--r--chromium/net/quic/quic_test_packet_printer.cc4
-rw-r--r--chromium/net/quic/quic_transport_client.cc132
-rw-r--r--chromium/net/quic/quic_transport_client.h68
-rw-r--r--chromium/net/quic/quic_transport_end_to_end_test.cc164
-rw-r--r--chromium/net/quic/quic_transport_error.cc24
-rw-r--r--chromium/net/quic/quic_transport_error.h53
-rw-r--r--chromium/net/quic/quic_transport_parameters_fuzzer.cc10
-rw-r--r--chromium/net/quic/quic_utils_chromium.cc31
-rw-r--r--chromium/net/quic/quic_utils_chromium.h26
-rw-r--r--chromium/net/quic/quic_utils_chromium_test.cc35
59 files changed, 3024 insertions, 1274 deletions
diff --git a/chromium/net/quic/OWNERS b/chromium/net/quic/OWNERS
index 9db36fa2026..4d12d7e8fff 100644
--- a/chromium/net/quic/OWNERS
+++ b/chromium/net/quic/OWNERS
@@ -1,6 +1,6 @@
dschinazi@chromium.org
nharper@chromium.org
-rch@chromium.org
+vasilvv@chromium.org
zhongyi@chromium.org
bnc@chromium.org
diff --git a/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc b/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc
index 6cfc33e5862..e5410eaa44d 100644
--- a/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc
+++ b/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -463,6 +463,7 @@ class BidirectionalStreamQuicImplTest
printer_(version_),
destination_(kDefaultServerHostName, kDefaultServerPort) {
quic::QuicEnableVersion(version_);
+ FLAGS_quic_enable_http3_grease_randomness = false;
IPAddress ip(192, 0, 2, 33);
peer_addr_ = IPEndPoint(ip, 443);
self_addr_ = IPEndPoint(ip, 8435);
@@ -857,18 +858,14 @@ INSTANTIATE_TEST_SUITE_P(Version,
::testing::PrintToStringParamName());
TEST_P(BidirectionalStreamQuicImplTest, GetRequest) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
if (VersionUsesHttp3(version_.transport_version))
AddWrite(ConstructInitialSettingsPacket());
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
AddWrite(ConstructClientAckPacket(3, 1, 2));
@@ -966,22 +963,18 @@ TEST_P(BidirectionalStreamQuicImplTest, GetRequest) {
}
TEST_P(BidirectionalStreamQuicImplTest, LoadTimingTwoRequests) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("GET", "/", DEFAULT_PRIORITY);
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
if (VersionUsesHttp3(version_.transport_version))
AddWrite(ConstructInitialSettingsPacket());
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
- nullptr));
+ GetNthClientInitiatedBidirectionalStreamId(0), kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY, nullptr));
// SetRequest() again for second request as |request_headers_| was moved.
SetRequest("GET", "/", DEFAULT_PRIORITY);
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(1), kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(1), kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
GetNthClientInitiatedBidirectionalStreamId(0), nullptr));
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
AddWrite(ConstructClientAckPacket(3, 1, 2));
@@ -1045,10 +1038,6 @@ TEST_P(BidirectionalStreamQuicImplTest, LoadTimingTwoRequests) {
// Tests that when request headers are not delayed, only data buffers are
// coalesced.
TEST_P(BidirectionalStreamQuicImplTest, CoalesceDataBuffersNotHeadersFrame) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -1061,7 +1050,8 @@ TEST_P(BidirectionalStreamQuicImplTest, CoalesceDataBuffersNotHeadersFrame) {
std::string header2 = ConstructDataHeader(kBody2.length());
std::vector<std::string> two_writes = {kBody1, kBody2};
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), !kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
if (!version_.UsesHttp3()) {
AddWrite(
@@ -1191,11 +1181,6 @@ TEST_P(BidirectionalStreamQuicImplTest, CoalesceDataBuffersNotHeadersFrame) {
// request headers with data buffers.
TEST_P(BidirectionalStreamQuicImplTest,
SendDataCoalesceDataBufferAndHeaderFrame) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -1206,8 +1191,7 @@ TEST_P(BidirectionalStreamQuicImplTest,
std::string header = ConstructDataHeader(strlen(kBody1));
if (version_.UsesHttp3()) {
AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
- !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
- {header, kBody1}));
+ !kFin, MEDIUM, &spdy_request_headers_frame_length, {header, kBody1}));
} else {
AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
!kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length, {kBody1}));
@@ -1312,11 +1296,6 @@ TEST_P(BidirectionalStreamQuicImplTest,
// request headers with data buffers.
TEST_P(BidirectionalStreamQuicImplTest,
SendvDataCoalesceDataBuffersAndHeaderFrame) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -1330,7 +1309,7 @@ TEST_P(BidirectionalStreamQuicImplTest,
if (version_.UsesHttp3()) {
AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
- !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
+ !kFin, MEDIUM, &spdy_request_headers_frame_length,
{header + kBody1 + header2 + kBody2}));
} else {
AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
@@ -1453,11 +1432,6 @@ TEST_P(BidirectionalStreamQuicImplTest,
// headers to be sent, if that write fails the stream does not crash.
TEST_P(BidirectionalStreamQuicImplTest,
SendDataWriteErrorCoalesceDataBufferAndHeaderFrame) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
if (VersionUsesHttp3(version_.transport_version))
AddWrite(ConstructInitialSettingsPacket());
@@ -1495,10 +1469,6 @@ TEST_P(BidirectionalStreamQuicImplTest,
// headers to be sent, if that write fails the stream does not crash.
TEST_P(BidirectionalStreamQuicImplTest,
SendvDataWriteErrorCoalesceDataBufferAndHeaderFrame) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
if (VersionUsesHttp3(version_.transport_version))
AddWrite(ConstructInitialSettingsPacket());
@@ -1537,11 +1507,6 @@ TEST_P(BidirectionalStreamQuicImplTest,
}
TEST_P(BidirectionalStreamQuicImplTest, PostRequest) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -1549,7 +1514,8 @@ TEST_P(BidirectionalStreamQuicImplTest, PostRequest) {
AddWrite(ConstructInitialSettingsPacket());
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), !kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
std::string header = ConstructDataHeader(strlen(kUploadData));
if (version_.UsesHttp3()) {
@@ -1637,18 +1603,14 @@ TEST_P(BidirectionalStreamQuicImplTest, PostRequest) {
}
TEST_P(BidirectionalStreamQuicImplTest, EarlyDataOverrideRequest) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("PUT", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
if (VersionUsesHttp3(version_.transport_version))
AddWrite(ConstructInitialSettingsPacket());
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
AddWrite(ConstructClientAckPacket(3, 1, 2));
@@ -1747,11 +1709,6 @@ TEST_P(BidirectionalStreamQuicImplTest, EarlyDataOverrideRequest) {
}
TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -1759,7 +1716,8 @@ TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) {
AddWrite(ConstructInitialSettingsPacket());
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), !kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
std::string header = ConstructDataHeader(strlen(kUploadData));
@@ -1862,18 +1820,14 @@ TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) {
}
TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterHeaders) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
if (VersionUsesHttp3(version_.transport_version))
AddWrite(ConstructInitialSettingsPacket());
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
Initialize();
@@ -1913,18 +1867,14 @@ TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterHeaders) {
}
TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterReadData) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
if (VersionUsesHttp3(version_.transport_version))
AddWrite(ConstructInitialSettingsPacket());
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
// Why does QUIC ack Rst? Is this expected?
@@ -1982,11 +1932,6 @@ TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterReadData) {
}
TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeReadData) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -1994,7 +1939,8 @@ TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeReadData) {
AddWrite(ConstructInitialSettingsPacket());
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), !kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
Initialize();
@@ -2099,11 +2045,6 @@ TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeStartNotConfirmed) {
}
TEST_P(BidirectionalStreamQuicImplTest, SessionCloseDuringOnStreamReady) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("POST", "/", DEFAULT_PRIORITY);
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
if (VersionUsesHttp3(version_.transport_version))
@@ -2132,11 +2073,6 @@ TEST_P(BidirectionalStreamQuicImplTest, SessionCloseDuringOnStreamReady) {
}
TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnStreamReady) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -2144,7 +2080,8 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnStreamReady) {
AddWrite(ConstructInitialSettingsPacket());
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), !kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
AddWrite(ConstructClientEarlyRstStreamPacket());
@@ -2171,11 +2108,6 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnStreamReady) {
}
TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamAfterReadData) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -2183,7 +2115,8 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamAfterReadData) {
AddWrite(ConstructInitialSettingsPacket());
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), !kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
AddWrite(ConstructClientAckAndRstStreamPacket(2, 1, 2));
@@ -2234,11 +2167,6 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamAfterReadData) {
}
TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnHeadersReceived) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -2246,7 +2174,8 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnHeadersReceived) {
AddWrite(ConstructInitialSettingsPacket());
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), !kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
AddWrite(ConstructClientAckAndRstStreamPacket(2, 1, 2));
@@ -2289,11 +2218,6 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnHeadersReceived) {
}
TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnDataRead) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -2301,7 +2225,8 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnDataRead) {
AddWrite(ConstructInitialSettingsPacket());
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), !kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
AddWrite(ConstructClientAckPacket(3, 1, 2));
AddWrite(ConstructClientRstStreamPacket());
@@ -2355,11 +2280,6 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnDataRead) {
}
TEST_P(BidirectionalStreamQuicImplTest, AsyncFinRead) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
const char kBody[] = "here is some data";
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
@@ -2368,7 +2288,8 @@ TEST_P(BidirectionalStreamQuicImplTest, AsyncFinRead) {
AddWrite(ConstructInitialSettingsPacket());
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
AddWrite(ConstructRequestHeadersPacketInner(
- GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
+ GetNthClientInitiatedBidirectionalStreamId(0), !kFin,
+ version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
&spdy_request_headers_frame_length));
std::string header = ConstructDataHeader(strlen(kBody));
if (version_.UsesHttp3()) {
@@ -2437,18 +2358,15 @@ TEST_P(BidirectionalStreamQuicImplTest, AsyncFinRead) {
}
TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnTrailersReceived) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
SetRequest("GET", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
if (VersionUsesHttp3(version_.transport_version))
AddWrite(ConstructInitialSettingsPacket());
- AddWrite(ConstructRequestHeadersPacket(kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
+ client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
+ AddWrite(ConstructRequestHeadersPacket(
+ kFin, version_.UsesHttp3() ? MEDIUM : DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length));
AddWrite(ConstructClientAckPacket(3, 1, 2)); // Ack the data packet
AddWrite(ConstructClientAckAndRstStreamPacket(4, 4, 2));
@@ -2467,6 +2385,7 @@ TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnTrailersReceived) {
DeleteStreamDelegate::ON_TRAILERS_RECEIVED));
delegate->Start(&request, net_log().bound(),
session()->CreateHandle(destination_));
+ ConfirmHandshake();
delegate->WaitUntilNextCallback(kOnStreamReady);
// Server acks the request.
diff --git a/chromium/net/quic/crypto/proof_verifier_chromium.cc b/chromium/net/quic/crypto/proof_verifier_chromium.cc
index ee05dce91ca..d49b1db3218 100644
--- a/chromium/net/quic/crypto/proof_verifier_chromium.cc
+++ b/chromium/net/quic/crypto/proof_verifier_chromium.cc
@@ -16,6 +16,7 @@
#include "crypto/signature_verifier.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_policy_enforcer.h"
@@ -459,7 +460,8 @@ int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) {
cert_verify_result.verified_cert.get(), cert_.get(),
verify_details_->ct_verify_result.scts,
TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
- verify_details_->ct_verify_result.policy_compliance);
+ verify_details_->ct_verify_result.policy_compliance,
+ proof_verifier_->network_isolation_key_);
if (ct_requirement_status != TransportSecurityState::CT_NOT_REQUIRED) {
verify_details_->ct_verify_result.policy_compliance_required = true;
if (verify_details_->cert_verify_result.is_issued_by_known_root) {
@@ -594,12 +596,14 @@ ProofVerifierChromium::ProofVerifierChromium(
CTPolicyEnforcer* ct_policy_enforcer,
TransportSecurityState* transport_security_state,
CTVerifier* cert_transparency_verifier,
- std::set<std::string> hostnames_to_allow_unknown_roots)
+ std::set<std::string> hostnames_to_allow_unknown_roots,
+ const NetworkIsolationKey& network_isolation_key)
: cert_verifier_(cert_verifier),
ct_policy_enforcer_(ct_policy_enforcer),
transport_security_state_(transport_security_state),
cert_transparency_verifier_(cert_transparency_verifier),
- hostnames_to_allow_unknown_roots_(hostnames_to_allow_unknown_roots) {
+ hostnames_to_allow_unknown_roots_(hostnames_to_allow_unknown_roots),
+ network_isolation_key_(network_isolation_key) {
DCHECK(cert_verifier_);
DCHECK(ct_policy_enforcer_);
DCHECK(transport_security_state_);
diff --git a/chromium/net/quic/crypto/proof_verifier_chromium.h b/chromium/net/quic/crypto/proof_verifier_chromium.h
index beacd3d0d63..f05da2eb259 100644
--- a/chromium/net/quic/crypto/proof_verifier_chromium.h
+++ b/chromium/net/quic/crypto/proof_verifier_chromium.h
@@ -13,6 +13,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "net/base/net_export.h"
+#include "net/base/network_isolation_key.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/ct_verify_result.h"
#include "net/cert/x509_certificate.h"
@@ -74,7 +75,8 @@ class NET_EXPORT_PRIVATE ProofVerifierChromium : public quic::ProofVerifier {
CTPolicyEnforcer* ct_policy_enforcer,
TransportSecurityState* transport_security_state,
CTVerifier* cert_transparency_verifier,
- std::set<std::string> hostnames_to_allow_unknown_roots);
+ std::set<std::string> hostnames_to_allow_unknown_roots,
+ const NetworkIsolationKey& network_isolation_key);
~ProofVerifierChromium() override;
// quic::ProofVerifier interface
@@ -120,6 +122,8 @@ class NET_EXPORT_PRIVATE ProofVerifierChromium : public quic::ProofVerifier {
std::set<std::string> hostnames_to_allow_unknown_roots_;
+ const NetworkIsolationKey network_isolation_key_;
+
DISALLOW_COPY_AND_ASSIGN(ProofVerifierChromium);
};
diff --git a/chromium/net/quic/crypto/proof_verifier_chromium_test.cc b/chromium/net/quic/crypto/proof_verifier_chromium_test.cc
index 62504d05827..e04f01a8566 100644
--- a/chromium/net/quic/crypto/proof_verifier_chromium_test.cc
+++ b/chromium/net/quic/crypto/proof_verifier_chromium_test.cc
@@ -10,6 +10,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_log_verifier.h"
@@ -113,6 +114,11 @@ const char kTestEmptySignature[] = "";
const char kLogDescription[] = "somelog";
+// This test exercises code that does not depend on the QUIC version in use
+// but that still requires a version so we just use the first one.
+const quic::QuicTransportVersion kTestTransportVersion =
+ quic::AllSupportedVersions().front().transport_version;
+
} // namespace
class ProofVerifierChromiumTest : public ::testing::Test {
@@ -152,7 +158,7 @@ class ProofVerifierChromiumTest : public ::testing::Test {
base::FilePath());
std::string signature;
source.GetProof(quic::QuicSocketAddress(), quic::QuicSocketAddress(),
- kTestHostname, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestConfig, kTestTransportVersion,
kTestChloHash,
std::make_unique<SignatureSaver>(&signature));
return signature;
@@ -204,14 +210,14 @@ TEST_F(ProofVerifierChromiumTest, VerifyProof) {
MockCertVerifier dummy_verifier;
dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -238,14 +244,14 @@ TEST_F(ProofVerifierChromiumTest, VerifyProof) {
// verification fails.
TEST_F(ProofVerifierChromiumTest, FailsIfCertFails) {
MockCertVerifier dummy_verifier;
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
@@ -264,14 +270,14 @@ TEST_F(ProofVerifierChromiumTest, ValidSCTList) {
MockCertVerifier cert_verifier;
- ProofVerifierChromium proof_verifier(&cert_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &cert_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, ct::GetSCTListForTesting(), kTestEmptySignature,
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
@@ -292,14 +298,14 @@ TEST_F(ProofVerifierChromiumTest, InvalidSCTList) {
ASSERT_NO_FATAL_FAILURE(GetSCTTestCertificates(&certs_));
MockCertVerifier cert_verifier;
- ProofVerifierChromium proof_verifier(&cert_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &cert_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, ct::GetSCTListWithInvalidSCT(),
kTestEmptySignature, verify_context_.get(), &error_details_, &details_,
std::move(callback));
@@ -319,14 +325,14 @@ TEST_F(ProofVerifierChromiumTest, InvalidSCTList) {
// signature fails.
TEST_F(ProofVerifierChromiumTest, FailsIfSignatureFails) {
FailsTestCertVerifier cert_verifier;
- ProofVerifierChromium proof_verifier(&cert_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &cert_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, kTestEmptySignature,
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
@@ -344,14 +350,14 @@ TEST_F(ProofVerifierChromiumTest, PreservesEVIfAllowed) {
.WillRepeatedly(
Return(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -387,14 +393,14 @@ TEST_F(ProofVerifierChromiumTest, StripsEVIfNotAllowed) {
.WillRepeatedly(
Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -436,14 +442,14 @@ TEST_F(ProofVerifierChromiumTest, CTEVHistogramNonCompliant) {
.WillRepeatedly(
Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -492,14 +498,14 @@ TEST_F(ProofVerifierChromiumTest, CTEVHistogramCompliant) {
.WillRepeatedly(
Return(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -544,14 +550,14 @@ TEST_F(ProofVerifierChromiumTest, IsFatalErrorNotSetForNonFatalError) {
dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_,
ERR_CERT_DATE_INVALID);
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
@@ -581,14 +587,14 @@ TEST_F(ProofVerifierChromiumTest, IsFatalErrorSetForFatalError) {
base::Time::Now() + base::TimeDelta::FromSeconds(1000);
transport_security_state_.AddHSTS(kTestHostname, expiry, true);
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
@@ -616,14 +622,14 @@ TEST_F(ProofVerifierChromiumTest, PKPEnforced) {
transport_security_state_.EnableStaticPinsForTesting();
ScopedTransportSecurityStateSource scoped_security_state_source;
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kCTAndPKPHost, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kCTAndPKPHost, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
@@ -662,14 +668,14 @@ TEST_F(ProofVerifierChromiumTest, PKPBypassFlagSet) {
transport_security_state_.EnableStaticPinsForTesting();
ScopedTransportSecurityStateSource scoped_security_state_source;
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {kCTAndPKPHost});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {kCTAndPKPHost}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kCTAndPKPHost, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kCTAndPKPHost, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -712,14 +718,14 @@ TEST_F(ProofVerifierChromiumTest, CTIsRequired) {
.WillRepeatedly(
Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
@@ -769,14 +775,14 @@ TEST_F(ProofVerifierChromiumTest, CTIsRequiredHistogramNonCompliant) {
.WillRepeatedly(
Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
@@ -824,14 +830,14 @@ TEST_F(ProofVerifierChromiumTest, CTIsRequiredHistogramCompliant) {
{
MockCertVerifier dummy_verifier;
dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {kTestHostname});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {kTestHostname}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -849,14 +855,14 @@ TEST_F(ProofVerifierChromiumTest, CTIsRequiredHistogramCompliant) {
dummy_result_.is_issued_by_known_root = true;
MockCertVerifier dummy_verifier;
dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -892,14 +898,14 @@ TEST_F(ProofVerifierChromiumTest, CTIsNotRequiredHistogram) {
MockCertVerifier dummy_verifier;
dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {kTestHostname});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {kTestHostname}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -938,14 +944,14 @@ TEST_F(ProofVerifierChromiumTest, PKPAndCTBothTested) {
.WillRepeatedly(
Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kCTAndPKPHost, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kCTAndPKPHost, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
@@ -989,14 +995,14 @@ TEST_F(ProofVerifierChromiumTest, CTComplianceStatusHistogram) {
{
MockCertVerifier dummy_verifier;
dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {kTestHostname});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {kTestHostname}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -1016,14 +1022,14 @@ TEST_F(ProofVerifierChromiumTest, CTComplianceStatusHistogram) {
dummy_result_.is_issued_by_known_root = true;
MockCertVerifier dummy_verifier;
dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -1065,15 +1071,15 @@ TEST_F(ProofVerifierChromiumTest, CTRequirementsFlagNotMet) {
.WillRepeatedly(
Return(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS));
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
{
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
@@ -1118,15 +1124,15 @@ TEST_F(ProofVerifierChromiumTest, CTRequirementsFlagMet) {
.WillRepeatedly(
Return(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
{
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
@@ -1160,14 +1166,14 @@ TEST_F(ProofVerifierChromiumTest, UnknownRootRejected) {
MockCertVerifier dummy_verifier;
dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status);
@@ -1191,14 +1197,14 @@ TEST_F(ProofVerifierChromiumTest, UnknownRootAcceptedWithOverride) {
MockCertVerifier dummy_verifier;
dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {kTestHostname});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {kTestHostname}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
@@ -1227,14 +1233,14 @@ TEST_F(ProofVerifierChromiumTest, UnknownRootAcceptedWithWildcardOverride) {
MockCertVerifier dummy_verifier;
dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
- ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
- &transport_security_state_,
- ct_verifier_.get(), {""});
+ ProofVerifierChromium proof_verifier(
+ &dummy_verifier, &ct_policy_enforcer_, &transport_security_state_,
+ ct_verifier_.get(), {""}, NetworkIsolationKey());
std::unique_ptr<DummyProofVerifierCallback> callback(
new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
- kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
+ kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_SUCCESS, status);
diff --git a/chromium/net/quic/crypto_test_utils_chromium.cc b/chromium/net/quic/crypto_test_utils_chromium.cc
index f284f7c4cdb..256dc0e28f5 100644
--- a/chromium/net/quic/crypto_test_utils_chromium.cc
+++ b/chromium/net/quic/crypto_test_utils_chromium.cc
@@ -11,6 +11,7 @@
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
@@ -53,7 +54,8 @@ class TestProofVerifierChromium : public ProofVerifierChromium {
ct_policy_enforcer.get(),
transport_security_state.get(),
cert_transparency_verifier.get(),
- {"test.example.com"}),
+ {"test.example.com"},
+ NetworkIsolationKey()),
cert_verifier_(std::move(cert_verifier)),
transport_security_state_(std::move(transport_security_state)),
cert_transparency_verifier_(std::move(cert_transparency_verifier)),
diff --git a/chromium/net/quic/mock_crypto_client_stream.cc b/chromium/net/quic/mock_crypto_client_stream.cc
index 9a8d2b55e39..3eb98fdef89 100644
--- a/chromium/net/quic/mock_crypto_client_stream.cc
+++ b/chromium/net/quic/mock_crypto_client_stream.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -32,7 +33,6 @@ using quic::NullEncrypter;
using quic::PACKET_8BYTE_CONNECTION_ID;
using quic::Perspective;
using quic::ProofVerifyContext;
-using quic::PROTOCOL_TLS1_3;
using quic::QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE;
using quic::QUIC_NO_ERROR;
using quic::QUIC_PROOF_INVALID;
@@ -49,6 +49,19 @@ using quic::TransportParameters;
using quiche::QuicheStringPiece;
using std::string;
+namespace {
+
+// TODO(crbug.com/1085541): Consider moving this method into QuicTestUtils.
+quic::QuicConnectionId TestConnectionId(uint64_t connection_number) {
+ const uint64_t connection_id64_net =
+ quiche::QuicheEndian::HostToNet64(connection_number);
+ return quic::QuicConnectionId(
+ reinterpret_cast<const char*>(&connection_id64_net),
+ sizeof(connection_id64_net));
+}
+
+} // namespace
+
namespace net {
MockCryptoClientStream::MockCryptoClientStream(
@@ -138,13 +151,17 @@ bool MockCryptoClientStream::CryptoConnect() {
ENCRYPTION_ZERO_RTT,
std::make_unique<NullDecrypter>(Perspective::IS_CLIENT));
}
- session()->connection()->SetEncrypter(
+ if (session()->version().UsesHttp3()) {
+ SetConfigNegotiated();
+ }
+ session()->OnNewEncryptionKeyAvailable(
ENCRYPTION_ZERO_RTT,
std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
}
- if (session()->connection()->version().handshake_protocol ==
- quic::PROTOCOL_QUIC_CRYPTO) {
+ if (session()->version().UsesQuicCrypto()) {
session()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ } else {
+ session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
}
break;
}
@@ -186,8 +203,7 @@ bool MockCryptoClientStream::CryptoConnect() {
ENCRYPTION_FORWARD_SECURE,
std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
}
- if (session()->connection()->version().handshake_protocol ==
- quic::PROTOCOL_TLS1_3) {
+ if (session()->version().UsesTls()) {
session()->OnOneRttKeysAvailable();
} else {
session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
@@ -238,44 +254,48 @@ void MockCryptoClientStream::OnOneRttPacketAcknowledged() {}
void MockCryptoClientStream::NotifySessionOneRttKeyAvailable() {
encryption_established_ = true;
- handshake_confirmed_ = true;
+ handshake_confirmed_ = true;
+ if (session()->version().UsesQuicCrypto())
SetConfigNegotiated();
- if (use_mock_crypter_) {
- if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
- session()->connection()->InstallDecrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
- } else {
- session()->connection()->SetDecrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
- }
- session()->connection()->SetEncrypter(
+ if (use_mock_crypter_) {
+ if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
+ session()->connection()->InstallDecrypter(
ENCRYPTION_FORWARD_SECURE,
- std::make_unique<MockEncrypter>(Perspective::IS_CLIENT));
+ std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
} else {
- if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
- session()->connection()->InstallDecrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullDecrypter>(Perspective::IS_CLIENT));
- } else {
- session()->connection()->SetDecrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullDecrypter>(Perspective::IS_CLIENT));
- }
- session()->connection()->SetEncrypter(ENCRYPTION_INITIAL, nullptr);
- session()->OnNewEncryptionKeyAvailable(
+ session()->connection()->SetDecrypter(
ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
+ std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
}
- if (session()->connection()->version().handshake_protocol ==
- quic::PROTOCOL_TLS1_3) {
- session()->OnOneRttKeysAvailable();
+ session()->connection()->SetEncrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<MockEncrypter>(Perspective::IS_CLIENT));
+ } else {
+ if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
+ session()->connection()->InstallDecrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullDecrypter>(Perspective::IS_CLIENT));
} else {
- session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ session()->connection()->SetDecrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullDecrypter>(Perspective::IS_CLIENT));
}
- session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
- session()->NeuterHandshakeData();
+ session()->connection()->SetEncrypter(ENCRYPTION_INITIAL, nullptr);
+ session()->OnNewEncryptionKeyAvailable(
+ ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
+ }
+ if (session()->version().UsesTls()) {
+ SetConfigNegotiated();
+ session()->OnOneRttKeysAvailable();
+ } else {
+ session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ }
+ session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ if (session()->version().UsesTls()) {
+ session()->DiscardOldEncryptionKey(ENCRYPTION_ZERO_RTT);
+ }
+ session()->NeuterHandshakeData();
}
// static
@@ -286,7 +306,8 @@ CryptoHandshakeMessage MockCryptoClientStream::GetDummyCHLOMessage() {
}
void MockCryptoClientStream::SetConfigNegotiated() {
- ASSERT_FALSE(session()->config()->negotiated());
+ if (!session()->version().UsesHttp3())
+ ASSERT_FALSE(session()->config()->negotiated());
QuicTagVector cgst;
// TODO(rtenneti): Enable the following code after BBR code is checked in.
#if 0
@@ -304,10 +325,27 @@ void MockCryptoClientStream::SetConfigNegotiated() {
config.SetInitialMaxStreamDataBytesUnidirectionalToSend(
quic::kMinimumFlowControlSendWindow);
+ if (quic::VersionHasIetfInvariantHeader(
+ session()->connection()->transport_version())) {
+ auto connection_id = TestConnectionId(0x1337);
+ config.SetStatelessResetTokenToSend(
+ quic::QuicUtils::GenerateStatelessResetToken(connection_id));
+ }
+ if (session()->version().AuthenticatesHandshakeConnectionIds()) {
+ if (session()->perspective() == Perspective::IS_CLIENT) {
+ config.SetOriginalConnectionIdToSend(
+ session()->connection()->connection_id());
+ config.SetInitialSourceConnectionIdToSend(
+ session()->connection()->connection_id());
+ } else {
+ config.SetInitialSourceConnectionIdToSend(
+ session()->connection()->client_connection_id());
+ }
+ }
+
QuicErrorCode error;
std::string error_details;
- if (session()->connection()->version().handshake_protocol ==
- PROTOCOL_TLS1_3) {
+ if (session()->version().UsesTls()) {
TransportParameters params;
ASSERT_TRUE(config.FillTransportParameters(&params));
error = session()->config()->ProcessTransportParameters(
@@ -324,8 +362,7 @@ void MockCryptoClientStream::SetConfigNegotiated() {
}
void MockCryptoClientStream::FillCryptoParams() {
- if (session()->connection()->version().handshake_protocol ==
- quic::PROTOCOL_QUIC_CRYPTO) {
+ if (session()->version().UsesQuicCrypto()) {
crypto_negotiated_params_->key_exchange = kC255;
crypto_negotiated_params_->aead = kAESG;
return;
diff --git a/chromium/net/quic/mock_quic_data.cc b/chromium/net/quic/mock_quic_data.cc
index 9c71eff9c95..d1b5cbc41cb 100644
--- a/chromium/net/quic/mock_quic_data.cc
+++ b/chromium/net/quic/mock_quic_data.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "net/quic/mock_quic_data.h"
+#include "net/base/hex_utils.h"
namespace net {
namespace test {
diff --git a/chromium/net/quic/network_connection.cc b/chromium/net/quic/network_connection.cc
index 6cf3d116f65..9c36d366445 100644
--- a/chromium/net/quic/network_connection.cc
+++ b/chromium/net/quic/network_connection.cc
@@ -4,6 +4,7 @@
#include "net/quic/network_connection.h"
+#include "base/logging.h"
#include "net/base/network_interfaces.h"
namespace net {
diff --git a/chromium/net/quic/platform/impl/quic_default_proof_providers_impl.cc b/chromium/net/quic/platform/impl/quic_default_proof_providers_impl.cc
index 28ec2766c6a..bbe4a7069e7 100644
--- a/chromium/net/quic/platform/impl/quic_default_proof_providers_impl.cc
+++ b/chromium/net/quic/platform/impl/quic_default_proof_providers_impl.cc
@@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
+#include "net/base/network_isolation_key.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_log_verifier.h"
#include "net/cert/ct_policy_enforcer.h"
@@ -64,7 +65,10 @@ class ProofVerifierChromiumWithOwnership : public net::ProofVerifierChromium {
&ct_policy_enforcer_,
&transport_security_state_,
&ct_verifier_,
- UnknownRootAllowlistForHost(host)),
+ UnknownRootAllowlistForHost(host),
+ // Fine to use an empty NetworkIsolationKey
+ // here, since this isn't used in Chromium.
+ net::NetworkIsolationKey()),
cert_verifier_(std::move(cert_verifier)) {}
private:
diff --git a/chromium/net/quic/platform/impl/quic_socket_utils.cc b/chromium/net/quic/platform/impl/quic_socket_utils.cc
index bb062039fe5..9fe56a19040 100644
--- a/chromium/net/quic/platform/impl/quic_socket_utils.cc
+++ b/chromium/net/quic/platform/impl/quic_socket_utils.cc
@@ -14,6 +14,7 @@
#include <unistd.h>
#include <string>
+#include "base/notreached.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
diff --git a/chromium/net/quic/platform/impl/quic_test_impl.h b/chromium/net/quic/platform/impl/quic_test_impl.h
index 98bc7b27c29..1bcda9fde67 100644
--- a/chromium/net/quic/platform/impl/quic_test_impl.h
+++ b/chromium/net/quic/platform/impl/quic_test_impl.h
@@ -5,7 +5,7 @@
#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_TEST_IMPL_H_
#define NET_QUIC_PLATFORM_IMPL_QUIC_TEST_IMPL_H_
-#include "base/logging.h"
+#include "base/check_op.h"
#include "net/test/test_with_task_environment.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
diff --git a/chromium/net/quic/quic_chromium_client_session.cc b/chromium/net/quic/quic_chromium_client_session.cc
index 780b8507c71..da5ac629afc 100644
--- a/chromium/net/quic/quic_chromium_client_session.cc
+++ b/chromium/net/quic/quic_chromium_client_session.cc
@@ -136,7 +136,7 @@ void RecordConnectionCloseErrorCode(const quic::QuicConnectionCloseFrame& frame,
quic::ConnectionCloseSource source,
const std::string& hostname,
bool handshake_confirmed) {
- bool is_google_host = HasGoogleHost(GURL("https://" + hostname));
+ bool is_google_host = IsGoogleHost(hostname);
std::string histogram = "Net.QuicSession.ConnectionCloseErrorCode";
if (source == quic::ConnectionCloseSource::FROM_SELF) {
@@ -161,10 +161,20 @@ void RecordConnectionCloseErrorCode(const quic::QuicConnectionCloseFrame& frame,
histogram += "IetfTransport";
RecordConnectionCloseErrorCodeImpl(histogram, frame.wire_error_code,
is_google_host, handshake_confirmed);
+ if (frame.quic_error_code == quic::QUIC_IETF_GQUIC_ERROR_MISSING) {
+ histogram += "GQuicErrorMissing";
+ RecordConnectionCloseErrorCodeImpl(histogram, frame.wire_error_code,
+ is_google_host, handshake_confirmed);
+ }
} else if (frame.close_type == quic::IETF_QUIC_APPLICATION_CONNECTION_CLOSE) {
histogram += "IetfApplication";
RecordConnectionCloseErrorCodeImpl(histogram, frame.wire_error_code,
is_google_host, handshake_confirmed);
+ if (frame.quic_error_code == quic::QUIC_IETF_GQUIC_ERROR_MISSING) {
+ histogram += "GQuicErrorMissing";
+ RecordConnectionCloseErrorCodeImpl(histogram, frame.wire_error_code,
+ is_google_host, handshake_confirmed);
+ }
}
}
@@ -826,8 +836,7 @@ QuicChromiumClientSession::QuicChromiumClientSession(
wait_for_new_network_(false),
ignore_read_error_(false),
headers_include_h2_stream_dependency_(
- headers_include_h2_stream_dependency &&
- this->connection()->transport_version() >= quic::QUIC_VERSION_43),
+ headers_include_h2_stream_dependency),
max_allowed_push_id_(max_allowed_push_id) {
// Make sure connection migration and goaway on path degrading are not turned
// on at the same time.
@@ -880,6 +889,9 @@ QuicChromiumClientSession::QuicChromiumClientSession(
QuicChromiumClientSession::~QuicChromiumClientSession() {
DCHECK(callback_.is_null());
+ for (auto& observer : connectivity_observer_list_)
+ observer.OnSessionRemoved(this);
+
net_log_.EndEvent(NetLogEventType::QUIC_SESSION);
DCHECK(waiting_for_confirmation_callbacks_.empty());
if (HasActiveRequestStreams())
@@ -995,6 +1007,13 @@ void QuicChromiumClientSession::Initialize() {
quic::QuicSpdyClientSessionBase::SetMaxPushId(max_allowed_push_id_);
}
set_max_inbound_header_list_size(kQuicMaxHeaderListSize);
+ if (config()->HasClientRequestedIndependentOption(
+ quic::kQLVE, quic::Perspective::IS_CLIENT)) {
+ connection()->EnableLegacyVersionEncapsulation(session_key_.host());
+ // Legacy Version Encapsulation needs CHLO padding to be disabled.
+ // TODO(dschinazi) remove this line once we deprecate quic_dont_pad_chlo.
+ crypto_config_->GetConfig()->set_disable_chlo_padding(true);
+ }
quic::QuicSpdyClientSessionBase::Initialize();
SetHpackEncoderDebugVisitor(std::make_unique<HpackEncoderDebugVisitor>());
SetHpackDecoderDebugVisitor(std::make_unique<HpackDecoderDebugVisitor>());
@@ -1078,6 +1097,16 @@ void QuicChromiumClientSession::RemoveHandle(Handle* handle) {
handles_.erase(handle);
}
+void QuicChromiumClientSession::AddConnectivityObserver(
+ ConnectivityObserver* observer) {
+ connectivity_observer_list_.AddObserver(observer);
+}
+
+void QuicChromiumClientSession::RemoveConnectivityObserver(
+ ConnectivityObserver* observer) {
+ connectivity_observer_list_.RemoveObserver(observer);
+}
+
// TODO(zhongyi): replace migration_session_* booleans with
// ConnectionMigrationMode.
ConnectionMigrationMode QuicChromiumClientSession::connection_migration_mode()
@@ -1363,7 +1392,7 @@ bool QuicChromiumClientSession::CanPool(
return SpdySession::CanPool(transport_security_state_, ssl_info,
*ssl_config_service_, session_key_.host(),
- hostname);
+ hostname, network_isolation_key);
}
bool QuicChromiumClientSession::ShouldCreateIncomingStream(
@@ -1383,7 +1412,7 @@ bool QuicChromiumClientSession::ShouldCreateIncomingStream(
if (quic::QuicUtils::IsClientInitiatedStreamId(
connection()->transport_version(), id) ||
(connection()->version().HasIetfQuicFrames() &&
- quic::QuicUtils::IsBidirectionalStreamId(id))) {
+ quic::QuicUtils::IsBidirectionalStreamId(id, connection()->version()))) {
LOG(WARNING) << "Received invalid push stream id " << id;
connection()->CloseConnection(
quic::QUIC_INVALID_STREAM_ID,
@@ -1537,36 +1566,26 @@ void QuicChromiumClientSession::OnConfigNegotiated() {
IPEndPoint old_address;
GetDefaultSocket()->GetPeerAddress(&old_address);
- // Migrate only if address families match, or if new address family is v6,
- // since a v4 address should be reachable over a v6 network (using a
- // v4-mapped v6 address).
+ // Migrate only if address families match.
IPEndPoint new_address;
if (old_address.GetFamily() == ADDRESS_FAMILY_IPV6) {
- if (config()->HasReceivedIPv6AlternateServerAddress()) {
+ if (!config()->HasReceivedIPv6AlternateServerAddress()) {
+ return;
+ }
new_address =
ToIPEndPoint(config()->ReceivedIPv6AlternateServerAddress());
- } else {
- new_address =
- ToIPEndPoint(config()->ReceivedIPv4AlternateServerAddress());
- // Use a v4-mapped v6 address.
- new_address =
- IPEndPoint(ConvertIPv4ToIPv4MappedIPv6(new_address.address()),
- new_address.port());
- }
} else if (old_address.GetFamily() == ADDRESS_FAMILY_IPV4) {
- if (config()->HasReceivedIPv4AlternateServerAddress()) {
- new_address =
- ToIPEndPoint(config()->ReceivedIPv4AlternateServerAddress());
- } else {
+ if (!config()->HasReceivedIPv4AlternateServerAddress()) {
return;
}
+ new_address = ToIPEndPoint(config()->ReceivedIPv4AlternateServerAddress());
}
DCHECK_EQ(new_address.GetFamily(), old_address.GetFamily());
// Specifying kInvalidNetworkHandle for the |network| parameter
// causes the session to use the default network for the new socket.
Migrate(NetworkChangeNotifier::kInvalidNetworkHandle, new_address,
- /*close_session_on_error=*/true, net_log_);
+ /*close_session_on_error=*/true);
}
void QuicChromiumClientSession::SetDefaultEncryptionLevel(
@@ -1694,6 +1713,10 @@ void QuicChromiumClientSession::OnConnectionClosed(
UMA_HISTOGRAM_COUNTS_1000(
"Net.QuicSession.ClosedByRtoAtClient.SentPacketCount",
connection()->GetStats().packets_sent);
+ UMA_HISTOGRAM_COUNTS_100(
+ "Net.QuicSession."
+ "MaxConsecutiveRtoWithForwardProgressAndBlackholeDetected",
+ connection()->GetStats().max_consecutive_rto_with_forward_progress);
}
}
@@ -1740,6 +1763,9 @@ void QuicChromiumClientSession::OnConnectionClosed(
UMA_HISTOGRAM_COUNTS_100(
"Net.QuicSession.CryptoRetransmitCount.HandshakeConfirmed",
connection()->GetStats().crypto_retransmit_count);
+ UMA_HISTOGRAM_COUNTS_100(
+ "Net.QuicSession.MaxConsecutiveRtoWithForwardProgress",
+ connection()->GetStats().max_consecutive_rto_with_forward_progress);
} else {
if (error == quic::QUIC_PUBLIC_RESET) {
RecordHandshakeFailureReason(HANDSHAKE_FAILURE_PUBLIC_RESET);
@@ -1812,8 +1838,7 @@ int QuicChromiumClientSession::HandleWriteError(
return error_code;
}
- NetworkChangeNotifier::NetworkHandle current_network =
- GetDefaultSocket()->GetBoundNetwork();
+ NetworkChangeNotifier::NetworkHandle current_network = GetCurrentNetwork();
net_log_.AddEventWithInt64Params(
NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_WRITE_ERROR, "network",
@@ -1867,8 +1892,7 @@ void QuicChromiumClientSession::MigrateSessionOnWriteError(
if (migrate_idle_session_ && CheckIdleTimeExceedsIdleMigrationPeriod())
return;
- if (!migrate_idle_session_ && GetNumActiveStreams() == 0 &&
- GetNumDrainingStreams() == 0) {
+ if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
// connection close packet to be sent since socket may be borked.
connection()->CloseConnection(quic::QUIC_PACKET_WRITE_ERROR,
"Write error for non-migratable session",
@@ -1878,9 +1902,9 @@ void QuicChromiumClientSession::MigrateSessionOnWriteError(
// Do not migrate if connection migration is disabled.
if (config()->DisableConnectionMigration()) {
- HistogramAndLogMigrationFailure(
- net_log_, MIGRATION_STATUS_DISABLED_BY_CONFIG, connection_id(),
- "Migration disabled by config");
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_DISABLED_BY_CONFIG,
+ connection_id(),
+ "Migration disabled by config");
// Close the connection since migration was disabled. Do not cause a
// connection close packet to be sent since socket may be borked.
connection()->CloseConnection(quic::QUIC_PACKET_WRITE_ERROR,
@@ -1890,22 +1914,21 @@ void QuicChromiumClientSession::MigrateSessionOnWriteError(
}
NetworkChangeNotifier::NetworkHandle new_network =
- stream_factory_->FindAlternateNetwork(
- GetDefaultSocket()->GetBoundNetwork());
+ stream_factory_->FindAlternateNetwork(GetCurrentNetwork());
if (new_network == NetworkChangeNotifier::kInvalidNetworkHandle) {
// No alternate network found.
- HistogramAndLogMigrationFailure(
- net_log_, MIGRATION_STATUS_NO_ALTERNATE_NETWORK, connection_id(),
- "No alternate network found");
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_NO_ALTERNATE_NETWORK,
+ connection_id(),
+ "No alternate network found");
OnNoNewNetwork();
return;
}
- if (GetDefaultSocket()->GetBoundNetwork() == default_network_ &&
+ if (GetCurrentNetwork() == default_network_ &&
current_migrations_to_non_default_network_on_write_error_ >=
max_migrations_to_non_default_network_on_write_error_) {
HistogramAndLogMigrationFailure(
- net_log_, MIGRATION_STATUS_ON_WRITE_ERROR_DISABLED, connection_id(),
+ MIGRATION_STATUS_ON_WRITE_ERROR_DISABLED, connection_id(),
"Exceeds maximum number of migrations on write error");
connection()->CloseConnection(
quic::QUIC_PACKET_WRITE_ERROR,
@@ -1915,16 +1938,13 @@ void QuicChromiumClientSession::MigrateSessionOnWriteError(
}
current_migrations_to_non_default_network_on_write_error_++;
- const NetLogWithSource migration_net_log = NetLogWithSource::Make(
- net_log_.net_log(), NetLogSourceType::QUIC_CONNECTION_MIGRATION);
- migration_net_log.BeginEventWithStringParams(
+ net_log_.BeginEventWithStringParams(
NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, "trigger",
"WriteError");
MigrationResult result =
Migrate(new_network, ToIPEndPoint(connection()->peer_address()),
- /*close_session_on_error=*/false, migration_net_log);
- migration_net_log.EndEvent(
- NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED);
+ /*close_session_on_error=*/false);
+ net_log_.EndEvent(NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED);
if (result == MigrationResult::FAILURE) {
// Close the connection if migration failed. Do not cause a
@@ -2019,8 +2039,7 @@ void QuicChromiumClientSession::OnProbeSucceeded(
// Close streams that are not migratable to the probed |network|.
ResetNonMigratableStreams();
- if (!migrate_idle_session_ && GetNumActiveStreams() == 0 &&
- GetNumDrainingStreams() == 0) {
+ if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
// If idle sessions won't be migrated, close the connection.
CloseSessionOnErrorLater(
ERR_NETWORK_CHANGED,
@@ -2041,10 +2060,14 @@ void QuicChromiumClientSession::OnProbeSucceeded(
return;
}
+ // Notify the connection that migration succeeds after probing.
+ if (connection()->IsPathDegrading())
+ connection()->OnSuccessfulMigrationAfterProbing();
+
net_log_.AddEventWithInt64Params(
NetLogEventType::QUIC_CONNECTION_MIGRATION_SUCCESS_AFTER_PROBING,
"migrate_to_network", network);
- HistogramAndLogMigrationSuccess(net_log_, connection_id());
+ HistogramAndLogMigrationSuccess(connection_id());
if (network == default_network_) {
DVLOG(1) << "Client successfully migrated to default network: "
<< default_network_;
@@ -2080,7 +2103,7 @@ void QuicChromiumClientSession::OnProbeFailed(
DVLOG(1) << "Connectivity probing failed on <network: " << network
<< ", peer_address: " << peer_address.ToString() << ">.";
DVLOG_IF(1, network == default_network_ &&
- GetDefaultSocket()->GetBoundNetwork() != default_network_)
+ GetCurrentNetwork() != default_network_)
<< "Client probing failed on the default network, still using "
"non-default network.";
}
@@ -2093,9 +2116,17 @@ bool QuicChromiumClientSession::OnSendConnectivityProbingPacket(
}
void QuicChromiumClientSession::OnNetworkConnected(
- NetworkChangeNotifier::NetworkHandle network,
- const NetLogWithSource& net_log) {
- DCHECK(migrate_session_on_network_change_v2_);
+ NetworkChangeNotifier::NetworkHandle network) {
+ if (connection()->IsPathDegrading()) {
+ base::TimeDelta duration =
+ tick_clock_->NowTicks() - most_recent_path_degrading_timestamp_;
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.QuicNetworkDegradingDurationTillConnected",
+ duration, base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10), 50);
+ }
+ if (!migrate_session_on_network_change_v2_)
+ return;
+
net_log_.AddEventWithInt64Params(
NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_NETWORK_CONNECTED,
"connected_network", network);
@@ -2104,15 +2135,8 @@ void QuicChromiumClientSession::OnNetworkConnected(
if (!wait_for_new_network_ && !connection()->IsPathDegrading())
return;
- if (connection()->IsPathDegrading()) {
- base::TimeDelta duration =
- tick_clock_->NowTicks() - most_recent_path_degrading_timestamp_;
- UMA_HISTOGRAM_CUSTOM_TIMES("Net.QuicNetworkDegradingDurationTillConnected",
- duration, base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMinutes(10), 50);
-
+ if (connection()->IsPathDegrading())
current_migration_cause_ = NEW_NETWORK_CONNECTED_POST_PATH_DEGRADING;
- }
if (wait_for_new_network_) {
wait_for_new_network_ = false;
@@ -2124,18 +2148,18 @@ void QuicChromiumClientSession::OnNetworkConnected(
} else {
// The connection is path degrading.
DCHECK(connection()->IsPathDegrading());
- OnPathDegrading();
+ MaybeMigrateToAlternateNetworkOnPathDegrading();
}
}
void QuicChromiumClientSession::OnNetworkDisconnectedV2(
- NetworkChangeNotifier::NetworkHandle disconnected_network,
- const NetLogWithSource& migration_net_log) {
- DCHECK(migrate_session_on_network_change_v2_);
+ NetworkChangeNotifier::NetworkHandle disconnected_network) {
+ LogMetricsOnNetworkDisconnected();
+ if (!migrate_session_on_network_change_v2_)
+ return;
net_log_.AddEventWithInt64Params(
NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_NETWORK_DISCONNECTED,
"disconnected_network", disconnected_network);
- LogMetricsOnNetworkDisconnected();
// Stop probing the disconnected network if there is one.
probing_manager_.CancelProbing(disconnected_network, peer_address());
@@ -2146,7 +2170,7 @@ void QuicChromiumClientSession::OnNetworkDisconnectedV2(
}
// Ignore the signal if the current active network is not affected.
- if (GetDefaultSocket()->GetBoundNetwork() != disconnected_network) {
+ if (GetCurrentNetwork() != disconnected_network) {
DVLOG(1) << "Client's current default network is not affected by the "
<< "disconnected one.";
return;
@@ -2179,29 +2203,31 @@ void QuicChromiumClientSession::OnNetworkDisconnectedV2(
}
void QuicChromiumClientSession::OnNetworkMadeDefault(
- NetworkChangeNotifier::NetworkHandle new_network,
- const NetLogWithSource& migration_net_log) {
- DCHECK(migrate_session_on_network_change_v2_);
+ NetworkChangeNotifier::NetworkHandle new_network) {
+ LogMetricsOnNetworkMadeDefault();
+
+ if (!migrate_session_on_network_change_v2_)
+ return;
+
+ DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, new_network);
net_log_.AddEventWithInt64Params(
NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_NETWORK_MADE_DEFAULT,
"new_default_network", new_network);
- LogMetricsOnNetworkMadeDefault();
+ default_network_ = new_network;
- DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, new_network);
DVLOG(1) << "Network: " << new_network
<< " becomes default, old default: " << default_network_;
- default_network_ = new_network;
current_migration_cause_ = ON_NETWORK_MADE_DEFAULT;
current_migrations_to_non_default_network_on_write_error_ = 0;
current_migrations_to_non_default_network_on_path_degrading_ = 0;
// Simply cancel the timer to migrate back to the default network if session
// is already on the default network.
- if (GetDefaultSocket()->GetBoundNetwork() == new_network) {
+ if (GetCurrentNetwork() == new_network) {
CancelMigrateBackToDefaultNetworkTimer();
- HistogramAndLogMigrationFailure(
- migration_net_log, MIGRATION_STATUS_ALREADY_MIGRATED, connection_id(),
- "Already migrated on the new network");
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_ALREADY_MIGRATED,
+ connection_id(),
+ "Already migrated on the new network");
return;
}
@@ -2221,10 +2247,8 @@ void QuicChromiumClientSession::MigrateNetworkImmediately(
// - otherwise, it's brought to default network, cancel the running timer to
// migrate back.
- if (!migrate_idle_session_ && GetNumActiveStreams() == 0 &&
- GetNumDrainingStreams() == 0) {
- HistogramAndLogMigrationFailure(net_log_,
- MIGRATION_STATUS_NO_MIGRATABLE_STREAMS,
+ if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_NO_MIGRATABLE_STREAMS,
connection_id(), "No active streams");
CloseSessionOnErrorLater(
ERR_NETWORK_CHANGED,
@@ -2238,17 +2262,17 @@ void QuicChromiumClientSession::MigrateNetworkImmediately(
// Do not migrate if connection migration is disabled.
if (config()->DisableConnectionMigration()) {
- HistogramAndLogMigrationFailure(
- net_log_, MIGRATION_STATUS_DISABLED_BY_CONFIG, connection_id(),
- "Migration disabled by config");
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_DISABLED_BY_CONFIG,
+ connection_id(),
+ "Migration disabled by config");
CloseSessionOnErrorLater(ERR_NETWORK_CHANGED,
quic::QUIC_CONNECTION_MIGRATION_DISABLED_BY_CONFIG,
quic::ConnectionCloseBehavior::SILENT_CLOSE);
return;
}
- if (network == GetDefaultSocket()->GetBoundNetwork()) {
- HistogramAndLogMigrationFailure(net_log_, MIGRATION_STATUS_ALREADY_MIGRATED,
+ if (network == GetCurrentNetwork()) {
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_ALREADY_MIGRATED,
connection_id(),
"Already bound to new network");
return;
@@ -2259,7 +2283,7 @@ void QuicChromiumClientSession::MigrateNetworkImmediately(
MigrationResult result =
Migrate(network, ToIPEndPoint(connection()->peer_address()),
- /*close_session_on_error=*/true, net_log_);
+ /*close_session_on_error=*/true);
if (result == MigrationResult::FAILURE)
return;
@@ -2308,6 +2332,9 @@ void QuicChromiumClientSession::OnWriteUnblocked() {
}
void QuicChromiumClientSession::OnPathDegrading() {
+ if (most_recent_path_degrading_timestamp_ == base::TimeTicks())
+ most_recent_path_degrading_timestamp_ = tick_clock_->NowTicks();
+
if (go_away_on_path_degrading_ && OneRttKeysAvailable()) {
net_log_.AddEvent(
NetLogEventType::QUIC_SESSION_CLIENT_GOAWAY_ON_PATH_DEGRADING);
@@ -2317,14 +2344,15 @@ void QuicChromiumClientSession::OnPathDegrading() {
GetNumActiveStreams());
UMA_HISTOGRAM_COUNTS_1M(
"Net.QuicSession.DrainingStreamsOnGoAwayAfterPathDegrading",
- GetNumDrainingStreams());
+ num_outgoing_draining_streams());
return;
}
- net_log_.AddEvent(
- NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_PATH_DEGRADING);
- if (most_recent_path_degrading_timestamp_ == base::TimeTicks())
- most_recent_path_degrading_timestamp_ = tick_clock_->NowTicks();
+ if (!go_away_on_path_degrading_) {
+ NetworkChangeNotifier::NetworkHandle current_network = GetCurrentNetwork();
+ for (auto& observer : connectivity_observer_list_)
+ observer.OnSessionPathDegrading(this, current_network);
+ }
if (!stream_factory_)
return;
@@ -2335,21 +2363,16 @@ void QuicChromiumClientSession::OnPathDegrading() {
return;
}
- current_migration_cause_ = CHANGE_NETWORK_ON_PATH_DEGRADING;
+ MaybeMigrateToAlternateNetworkOnPathDegrading();
+}
- if (migrate_session_early_v2_) {
- MaybeMigrateToAlternateNetworkOnPathDegrading();
+void QuicChromiumClientSession::OnForwardProgressMadeAfterPathDegrading() {
+ if (go_away_on_path_degrading_)
return;
- }
-
- HistogramAndLogMigrationFailure(
- net_log_, MIGRATION_STATUS_PATH_DEGRADING_NOT_ENABLED, connection_id(),
- "Migration on path degrading not enabled");
-}
-bool QuicChromiumClientSession::ShouldKeepConnectionAlive() const {
- return quic::QuicSpdySession::ShouldKeepConnectionAlive() ||
- GetNumDrainingOutgoingStreams() > 0;
+ NetworkChangeNotifier::NetworkHandle current_network = GetCurrentNetwork();
+ for (auto& observer : connectivity_observer_list_)
+ observer.OnSessionResumedPostPathDegrading(this, current_network);
}
void QuicChromiumClientSession::OnProofValid(
@@ -2488,43 +2511,50 @@ void QuicChromiumClientSession::MaybeMigrateToDifferentPortOnPathDegrading() {
// Migration before handshake is not allowed.
if (!OneRttKeysAvailable()) {
HistogramAndLogMigrationFailure(
- net_log_, MIGRATION_STATUS_PATH_DEGRADING_BEFORE_HANDSHAKE_CONFIRMED,
+ MIGRATION_STATUS_PATH_DEGRADING_BEFORE_HANDSHAKE_CONFIRMED,
connection_id(), "Path degrading before handshake confirmed");
return;
}
- const NetLogWithSource migration_net_log = NetLogWithSource::Make(
- net_log_.net_log(), NetLogSourceType::QUIC_PORT_MIGRATION);
- migration_net_log.BeginEvent(NetLogEventType::QUIC_PORT_MIGRATION_TRIGGERED);
+ net_log_.BeginEvent(NetLogEventType::QUIC_PORT_MIGRATION_TRIGGERED);
if (!stream_factory_)
return;
// Probe a different port, session will migrate to the probed port on success.
- StartProbing(default_network_, peer_address(), migration_net_log);
- migration_net_log.EndEvent(NetLogEventType::QUIC_PORT_MIGRATION_TRIGGERED);
+ StartProbing(default_network_, peer_address());
+ net_log_.EndEvent(NetLogEventType::QUIC_PORT_MIGRATION_TRIGGERED);
}
void QuicChromiumClientSession::
MaybeMigrateToAlternateNetworkOnPathDegrading() {
- DCHECK(migrate_session_early_v2_);
+ net_log_.AddEvent(
+ NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_PATH_DEGRADING);
+
+ current_migration_cause_ = CHANGE_NETWORK_ON_PATH_DEGRADING;
- if (GetDefaultSocket()->GetBoundNetwork() == default_network_ &&
+ if (!migrate_session_early_v2_) {
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_PATH_DEGRADING_NOT_ENABLED,
+ connection_id(),
+ "Migration on path degrading not enabled");
+ return;
+ }
+
+ if (GetCurrentNetwork() == default_network_ &&
current_migrations_to_non_default_network_on_path_degrading_ >=
max_migrations_to_non_default_network_on_path_degrading_) {
HistogramAndLogMigrationFailure(
- net_log_, MIGRATION_STATUS_ON_PATH_DEGRADING_DISABLED, connection_id(),
+ MIGRATION_STATUS_ON_PATH_DEGRADING_DISABLED, connection_id(),
"Exceeds maximum number of migrations on path degrading");
return;
}
NetworkChangeNotifier::NetworkHandle alternate_network =
- stream_factory_->FindAlternateNetwork(
- GetDefaultSocket()->GetBoundNetwork());
+ stream_factory_->FindAlternateNetwork(GetCurrentNetwork());
if (alternate_network == NetworkChangeNotifier::kInvalidNetworkHandle) {
- HistogramAndLogMigrationFailure(
- net_log_, MIGRATION_STATUS_NO_ALTERNATE_NETWORK, connection_id(),
- "No alternative network on path degrading");
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_NO_ALTERNATE_NETWORK,
+ connection_id(),
+ "No alternative network on path degrading");
return;
}
@@ -2532,37 +2562,31 @@ void QuicChromiumClientSession::
if (!OneRttKeysAvailable()) {
HistogramAndLogMigrationFailure(
- net_log_, MIGRATION_STATUS_PATH_DEGRADING_BEFORE_HANDSHAKE_CONFIRMED,
+ MIGRATION_STATUS_PATH_DEGRADING_BEFORE_HANDSHAKE_CONFIRMED,
connection_id(), "Path degrading before handshake confirmed");
return;
}
- const NetLogWithSource migration_net_log = NetLogWithSource::Make(
- net_log_.net_log(), NetLogSourceType::QUIC_CONNECTION_MIGRATION);
- migration_net_log.BeginEventWithStringParams(
+ net_log_.BeginEventWithStringParams(
NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, "trigger",
"PathDegrading");
// Probe the alternative network, session will migrate to the probed
// network and decide whether it wants to migrate back to the default
// network on success.
- MaybeStartProbing(alternate_network, peer_address(), migration_net_log);
- migration_net_log.EndEvent(
- NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED);
+ MaybeStartProbing(alternate_network, peer_address());
+ net_log_.EndEvent(NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED);
}
ProbingResult QuicChromiumClientSession::MaybeStartProbing(
NetworkChangeNotifier::NetworkHandle network,
- const quic::QuicSocketAddress& peer_address,
- const NetLogWithSource& migration_net_log) {
+ const quic::QuicSocketAddress& peer_address) {
if (!stream_factory_)
return ProbingResult::FAILURE;
CHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, network);
- if (!migrate_idle_session_ && GetNumActiveStreams() == 0 &&
- GetNumDrainingStreams() == 0) {
- HistogramAndLogMigrationFailure(migration_net_log,
- MIGRATION_STATUS_NO_MIGRATABLE_STREAMS,
+ if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_NO_MIGRATABLE_STREAMS,
connection_id(), "No active streams");
CloseSessionOnErrorLater(
ERR_NETWORK_CHANGED,
@@ -2578,19 +2602,18 @@ ProbingResult QuicChromiumClientSession::MaybeStartProbing(
if (config()->DisableConnectionMigration()) {
DVLOG(1) << "Client disables probing network with connection migration "
<< "disabled by config";
- HistogramAndLogMigrationFailure(
- migration_net_log, MIGRATION_STATUS_DISABLED_BY_CONFIG, connection_id(),
- "Migration disabled by config");
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_DISABLED_BY_CONFIG,
+ connection_id(),
+ "Migration disabled by config");
return ProbingResult::DISABLED_BY_CONFIG;
}
- return StartProbing(network, peer_address, migration_net_log);
+ return StartProbing(network, peer_address);
}
ProbingResult QuicChromiumClientSession::StartProbing(
NetworkChangeNotifier::NetworkHandle network,
- const quic::QuicSocketAddress& peer_address,
- const NetLogWithSource& migration_net_log) {
+ const quic::QuicSocketAddress& peer_address) {
// Check if probing manager is probing the same path.
if (probing_manager_.IsUnderProbing(network, peer_address))
return ProbingResult::PENDING;
@@ -2601,9 +2624,9 @@ ProbingResult QuicChromiumClientSession::StartProbing(
if (stream_factory_->ConfigureSocket(probing_socket.get(),
ToIPEndPoint(peer_address), network,
session_key_.socket_tag()) != OK) {
- HistogramAndLogMigrationFailure(
- migration_net_log, MIGRATION_STATUS_INTERNAL_ERROR, connection_id(),
- "Socket configuration failed");
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_INTERNAL_ERROR,
+ connection_id(),
+ "Socket configuration failed");
return ProbingResult::INTERNAL_ERROR;
}
@@ -2664,8 +2687,7 @@ void QuicChromiumClientSession::TryMigrateBackToDefaultNetwork(
// the same network, this will be a no-op. Otherwise, previous probe
// will be cancelled and manager starts to probe |default_network_|
// immediately.
- ProbingResult result =
- MaybeStartProbing(default_network_, peer_address(), net_log_);
+ ProbingResult result = MaybeStartProbing(default_network_, peer_address());
if (result == ProbingResult::DISABLED_WITH_IDLE_SESSION)
return;
@@ -2689,7 +2711,7 @@ void QuicChromiumClientSession::TryMigrateBackToDefaultNetwork(
void QuicChromiumClientSession::MaybeRetryMigrateBackToDefaultNetwork() {
base::TimeDelta retry_migrate_back_timeout =
base::TimeDelta::FromSeconds(UINT64_C(1) << retry_migrate_back_count_);
- if (default_network_ == GetDefaultSocket()->GetBoundNetwork()) {
+ if (default_network_ == GetCurrentNetwork()) {
// If session has been back on the default already by other direct
// migration attempt, cancel migrate back now.
CancelMigrateBackToDefaultNetworkTimer();
@@ -2707,7 +2729,7 @@ bool QuicChromiumClientSession::CheckIdleTimeExceedsIdleMigrationPeriod() {
if (!migrate_idle_session_)
return false;
- if (GetNumActiveStreams() != 0 || GetNumDrainingStreams() != 0) {
+ if (HasActiveRequestStreams()) {
return false;
}
@@ -2718,9 +2740,9 @@ bool QuicChromiumClientSession::CheckIdleTimeExceedsIdleMigrationPeriod() {
return false;
}
- HistogramAndLogMigrationFailure(
- net_log_, MIGRATION_STATUS_IDLE_MIGRATION_TIMEOUT, connection_id(),
- "Ilde migration period exceeded");
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_IDLE_MIGRATION_TIMEOUT,
+ connection_id(),
+ "Ilde migration period exceeded");
CloseSessionOnErrorLater(ERR_NETWORK_CHANGED, quic::QUIC_NETWORK_IDLE_TIMEOUT,
quic::ConnectionCloseBehavior::SILENT_CLOSE);
return true;
@@ -2840,7 +2862,6 @@ void QuicChromiumClientSession::LogHandshakeStatusOnMigrationSignal() const {
}
void QuicChromiumClientSession::HistogramAndLogMigrationFailure(
- const NetLogWithSource& net_log,
QuicConnectionMigrationStatus status,
quic::QuicConnectionId connection_id,
const char* reason) {
@@ -2849,7 +2870,7 @@ void QuicChromiumClientSession::HistogramAndLogMigrationFailure(
? NetLogEventType::QUIC_PORT_MIGRATION_FAILURE
: NetLogEventType::QUIC_CONNECTION_MIGRATION_FAILURE;
- net_log.AddEvent(event_type, [&] {
+ net_log_.AddEvent(event_type, [&] {
return NetLogQuicMigrationFailureParams(connection_id, reason);
});
@@ -2858,14 +2879,13 @@ void QuicChromiumClientSession::HistogramAndLogMigrationFailure(
}
void QuicChromiumClientSession::HistogramAndLogMigrationSuccess(
- const NetLogWithSource& net_log,
quic::QuicConnectionId connection_id) {
NetLogEventType event_type =
current_migration_cause_ == CHANGE_PORT_ON_PATH_DEGRADING
? NetLogEventType::QUIC_PORT_MIGRATION_SUCCESS
: NetLogEventType::QUIC_CONNECTION_MIGRATION_SUCCESS;
- net_log.AddEvent(event_type, [&] {
+ net_log_.AddEvent(event_type, [&] {
return NetLogQuicMigrationSuccessParams(connection_id);
});
@@ -3030,7 +3050,7 @@ void QuicChromiumClientSession::OnCryptoHandshakeComplete() {
// confirmed if the session is not created on the default network.
if (migrate_session_on_network_change_v2_ &&
default_network_ != NetworkChangeNotifier::kInvalidNetworkHandle &&
- GetDefaultSocket()->GetBoundNetwork() != default_network_) {
+ GetCurrentNetwork() != default_network_) {
current_migration_cause_ = ON_MIGRATE_BACK_TO_DEFAULT_NETWORK;
StartMigrateBackToDefaultNetworkTimer(
base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs));
@@ -3040,16 +3060,14 @@ void QuicChromiumClientSession::OnCryptoHandshakeComplete() {
MigrationResult QuicChromiumClientSession::Migrate(
NetworkChangeNotifier::NetworkHandle network,
IPEndPoint peer_address,
- bool close_session_on_error,
- const NetLogWithSource& migration_net_log) {
+ bool close_session_on_error) {
if (!stream_factory_)
return MigrationResult::FAILURE;
if (network != NetworkChangeNotifier::kInvalidNetworkHandle) {
// This is a migration attempt from connection migration.
ResetNonMigratableStreams();
- if (!migrate_idle_session_ && GetNumActiveStreams() == 0 &&
- GetNumDrainingStreams() == 0) {
+ if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
// If idle sessions can not be migrated, close the session if needed.
if (close_session_on_error) {
CloseSessionOnErrorLater(
@@ -3066,9 +3084,9 @@ MigrationResult QuicChromiumClientSession::Migrate(
stream_factory_->CreateSocket(net_log_.net_log(), net_log_.source()));
if (stream_factory_->ConfigureSocket(socket.get(), peer_address, network,
session_key_.socket_tag()) != OK) {
- HistogramAndLogMigrationFailure(
- migration_net_log, MIGRATION_STATUS_INTERNAL_ERROR, connection_id(),
- "Socket configuration failed");
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_INTERNAL_ERROR,
+ connection_id(),
+ "Socket configuration failed");
if (close_session_on_error) {
if (migrate_session_on_network_change_v2_) {
CloseSessionOnErrorLater(ERR_NETWORK_CHANGED,
@@ -3099,8 +3117,7 @@ MigrationResult QuicChromiumClientSession::Migrate(
// Migrate to the new socket.
if (!MigrateToSocket(std::move(socket), std::move(new_reader),
std::move(new_writer))) {
- HistogramAndLogMigrationFailure(migration_net_log,
- MIGRATION_STATUS_TOO_MANY_CHANGES,
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_TOO_MANY_CHANGES,
connection_id(), "Too many changes");
if (close_session_on_error) {
if (migrate_session_on_network_change_v2_) {
@@ -3116,7 +3133,7 @@ MigrationResult QuicChromiumClientSession::Migrate(
}
return MigrationResult::FAILURE;
}
- HistogramAndLogMigrationSuccess(migration_net_log, connection_id());
+ HistogramAndLogMigrationSuccess(connection_id());
return MigrationResult::SUCCESS;
}
@@ -3165,6 +3182,16 @@ const DatagramClientSocket* QuicChromiumClientSession::GetDefaultSocket()
return sockets_.back().get();
}
+NetworkChangeNotifier::NetworkHandle
+QuicChromiumClientSession::GetCurrentNetwork() const {
+ // If connection migration is enabled, alternate network interface may be
+ // used to send packet, it is identified as the bound network of the default
+ // socket. Otherwise, always use |default_network_|.
+ return migrate_session_on_network_change_v2_
+ ? GetDefaultSocket()->GetBoundNetwork()
+ : default_network_;
+}
+
bool QuicChromiumClientSession::IsAuthorized(const std::string& hostname) {
bool result = CanPool(
hostname, session_key_.privacy_mode(), session_key_.socket_tag(),
@@ -3268,4 +3295,17 @@ size_t QuicChromiumClientSession::EstimateMemoryUsage() const {
return base::trace_event::EstimateMemoryUsage(packet_readers_);
}
+bool QuicChromiumClientSession::ValidateStatelessReset(
+ const quic::QuicSocketAddress& self_address,
+ const quic::QuicSocketAddress& peer_address) {
+ if (probing_manager_.ValidateStatelessReset(self_address, peer_address)) {
+ // The stateless reset is received from probing path. We shouldn't close the
+ // connection, but should disable further port migration attempt.
+ if (allow_port_migration_)
+ allow_port_migration_ = false;
+ return false;
+ }
+ return true;
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_chromium_client_session.h b/chromium/net/quic/quic_chromium_client_session.h
index 34ea4fda6eb..3b1c2fda0ac 100644
--- a/chromium/net/quic/quic_chromium_client_session.h
+++ b/chromium/net/quic/quic_chromium_client_session.h
@@ -20,6 +20,7 @@
#include "base/containers/mru_cache.h"
#include "base/macros.h"
+#include "base/observer_list_types.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/completion_once_callback.h"
@@ -139,6 +140,25 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
public:
class StreamRequest;
+ // An interface that when implemented and added via
+ // AddConnectivityObserver(), provides notifications when connectivity
+ // quality changes.
+ class NET_EXPORT_PRIVATE ConnectivityObserver : public base::CheckedObserver {
+ public:
+ // Called when path degrading is detected on |network|.
+ virtual void OnSessionPathDegrading(
+ QuicChromiumClientSession* session,
+ NetworkChangeNotifier::NetworkHandle network) = 0;
+
+ // Called when forward progress is made after path degrading on |network|.
+ virtual void OnSessionResumedPostPathDegrading(
+ QuicChromiumClientSession* session,
+ NetworkChangeNotifier::NetworkHandle network) = 0;
+
+ // Called when |session| is removed.
+ virtual void OnSessionRemoved(QuicChromiumClientSession* session) = 0;
+ };
+
// Wrapper for interacting with the session in a restricted fashion which
// hides the details of the underlying session's lifetime. All methods of
// the Handle are safe to use even after the underlying session is destroyed.
@@ -422,6 +442,9 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
void AddHandle(Handle* handle);
void RemoveHandle(Handle* handle);
+ void AddConnectivityObserver(ConnectivityObserver* observer);
+ void RemoveConnectivityObserver(ConnectivityObserver* observer);
+
// Returns the session's connection migration mode.
ConnectionMigrationMode connection_migration_mode() const;
@@ -503,6 +526,9 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
void OnGoAway(const quic::QuicGoAwayFrame& frame) override;
void OnRstStream(const quic::QuicRstStreamFrame& frame) override;
void OnCanCreateNewOutgoingStream(bool unidirectional) override;
+ bool ValidateStatelessReset(
+ const quic::QuicSocketAddress& self_address,
+ const quic::QuicSocketAddress& peer_address) override;
// QuicClientSessionBase methods:
void OnConfigNegotiated() override;
@@ -520,7 +546,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
const quic::QuicSocketAddress& peer_address,
bool is_connectivity_probe) override;
void OnPathDegrading() override;
- bool ShouldKeepConnectionAlive() const override;
+ void OnForwardProgressMadeAfterPathDegrading() override;
// QuicChromiumPacketReader::Visitor methods:
void OnReadError(int result, const DatagramClientSocket* socket) override;
@@ -599,8 +625,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// closed.
MigrationResult Migrate(NetworkChangeNotifier::NetworkHandle network,
IPEndPoint peer_address,
- bool close_session_on_error,
- const NetLogWithSource& migration_net_log);
+ bool close_session_on_error);
// Migrates session onto new socket, i.e., sets |writer| to be the new
// default writer and post a task to write to |socket|. |reader| *must*
@@ -617,19 +642,16 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// Called when NetworkChangeNotifier notifies observers of a newly
// connected network. Migrates this session to the newly connected
// network if the session has a pending migration.
- void OnNetworkConnected(NetworkChangeNotifier::NetworkHandle network,
- const NetLogWithSource& net_log);
+ void OnNetworkConnected(NetworkChangeNotifier::NetworkHandle network);
// Called when NetworkChangeNotifier broadcasts to observers of
// |disconnected_network|.
void OnNetworkDisconnectedV2(
- NetworkChangeNotifier::NetworkHandle disconnected_network,
- const NetLogWithSource& migration_net_log);
+ NetworkChangeNotifier::NetworkHandle disconnected_network);
// Called when NetworkChangeNotifier broadcats to observers of a new default
// network. Migrates this session to |new_network| if appropriate.
- void OnNetworkMadeDefault(NetworkChangeNotifier::NetworkHandle new_network,
- const NetLogWithSource& migration_net_log);
+ void OnNetworkMadeDefault(NetworkChangeNotifier::NetworkHandle new_network);
// Schedules a migration alarm to wait for a new network.
void OnNoNewNetwork();
@@ -646,6 +668,11 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// returned socket.
const DatagramClientSocket* GetDefaultSocket() const;
+ // Returns the network interface that is currently used to send packets.
+ // If NetworkHandle is not supported, always return
+ // NetworkChangeNotifier::kInvalidNetworkHandle.
+ NetworkChangeNotifier::NetworkHandle GetCurrentNetwork() const;
+
bool IsAuthorized(const std::string& hostname) override;
bool HandlePromised(quic::QuicStreamId associated_id,
@@ -710,17 +737,17 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// If <network, peer_addres> is identical to the current path, the probe
// is sent on a different port.
ProbingResult StartProbing(NetworkChangeNotifier::NetworkHandle network,
- const quic::QuicSocketAddress& peer_address,
- const NetLogWithSource& migration_net_log);
+ const quic::QuicSocketAddress& peer_address);
// Perform a few checks before StartProbing. If any of those checks fails,
// StartProbing will be skipped.
ProbingResult MaybeStartProbing(NetworkChangeNotifier::NetworkHandle network,
- const quic::QuicSocketAddress& peer_address,
- const NetLogWithSource& migration_net_log);
+ const quic::QuicSocketAddress& peer_address);
// Helper method to perform a few checks and initiate connection migration
// attempt when path degrading is detected.
+ // Called when path is degrading and there is an alternate network or a new
+ // network is connected after path degrading.
void MaybeMigrateToAlternateNetworkOnPathDegrading();
// Helper method to initiate a port migration on path degrading is detected.
@@ -754,12 +781,10 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
void LogMetricsOnNetworkMadeDefault();
void LogMigrationResultToHistogram(QuicConnectionMigrationStatus status);
void LogHandshakeStatusOnMigrationSignal() const;
- void HistogramAndLogMigrationFailure(const NetLogWithSource& net_log,
- QuicConnectionMigrationStatus status,
+ void HistogramAndLogMigrationFailure(QuicConnectionMigrationStatus status,
quic::QuicConnectionId connection_id,
const char* reason);
- void HistogramAndLogMigrationSuccess(const NetLogWithSource& net_log,
- quic::QuicConnectionId connection_id);
+ void HistogramAndLogMigrationSuccess(quic::QuicConnectionId connection_id);
// Notifies the factory that this session is going away and no more streams
// should be created from it. This needs to be called before closing any
@@ -810,6 +835,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
std::unique_ptr<quic::QuicCryptoClientStream> crypto_stream_;
QuicStreamFactory* stream_factory_;
+ base::ObserverList<ConnectivityObserver> connectivity_observer_list_;
std::vector<std::unique_ptr<DatagramClientSocket>> sockets_;
TransportSecurityState* transport_security_state_;
SSLConfigService* ssl_config_service_;
@@ -847,7 +873,8 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// written to an alternate socket when the migration completes and the
// alternate socket is unblocked.
scoped_refptr<QuicChromiumPacketWriter::ReusableIOBuffer> packet_;
- // Stores the latest default network platform marks.
+ // Stores the latest default network platform marks if migration is enabled.
+ // Otherwise, stores the network interface that is used by the connection.
NetworkChangeNotifier::NetworkHandle default_network_;
QuicConnectivityProbingManager probing_manager_;
int retry_migrate_back_count_;
diff --git a/chromium/net/quic/quic_chromium_client_session_peer.cc b/chromium/net/quic/quic_chromium_client_session_peer.cc
index 2c460a8c34f..8d4747f8ac5 100644
--- a/chromium/net/quic/quic_chromium_client_session_peer.cc
+++ b/chromium/net/quic/quic_chromium_client_session_peer.cc
@@ -48,5 +48,10 @@ bool QuicChromiumClientSessionPeer::GetSessionGoingAway(
return session->going_away_;
}
+bool QuicChromiumClientSessionPeer::DoesSessionAllowPortMigration(
+ QuicChromiumClientSession* session) {
+ return session->allow_port_migration_;
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_chromium_client_session_peer.h b/chromium/net/quic/quic_chromium_client_session_peer.h
index 8b057727eb4..4832017dc31 100644
--- a/chromium/net/quic/quic_chromium_client_session_peer.h
+++ b/chromium/net/quic/quic_chromium_client_session_peer.h
@@ -34,6 +34,8 @@ class QuicChromiumClientSessionPeer {
static bool GetSessionGoingAway(QuicChromiumClientSession* session);
+ static bool DoesSessionAllowPortMigration(QuicChromiumClientSession* session);
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicChromiumClientSessionPeer);
};
diff --git a/chromium/net/quic/quic_chromium_client_session_test.cc b/chromium/net/quic/quic_chromium_client_session_test.cc
index 404d815f3af..075e6111ac9 100644
--- a/chromium/net/quic/quic_chromium_client_session_test.cc
+++ b/chromium/net/quic/quic_chromium_client_session_test.cc
@@ -31,6 +31,7 @@
#include "net/quic/quic_chromium_connection_helper.h"
#include "net/quic/quic_chromium_packet_reader.h"
#include "net/quic/quic_chromium_packet_writer.h"
+#include "net/quic/quic_connectivity_monitor.h"
#include "net/quic/quic_crypto_client_config_handle.h"
#include "net/quic/quic_crypto_client_stream_factory.h"
#include "net/quic/quic_http_utils.h"
@@ -77,6 +78,9 @@ const char kServerHostname[] = "test.example.com";
const uint16_t kServerPort = 443;
const size_t kMaxReadersPerQuicSession = 5;
+const NetworkChangeNotifier::NetworkHandle kDefaultNetworkForTests = 1;
+const NetworkChangeNotifier::NetworkHandle kNewNetworkForTests = 2;
+
struct TestParams {
quic::ParsedQuicVersion version;
bool client_headers_include_h2_stream_dependency;
@@ -128,6 +132,7 @@ class QuicChromiumClientSessionTest
base::span<MockWrite>())),
random_(0),
helper_(&clock_, &random_),
+ transport_security_state_(std::make_unique<TransportSecurityState>()),
session_key_(kServerHostname,
kServerPort,
PRIVACY_MODE_DISABLED,
@@ -135,6 +140,7 @@ class QuicChromiumClientSessionTest
NetworkIsolationKey(),
false /* disable_secure_dns */),
destination_(kServerHostname, kServerPort),
+ default_network_(NetworkChangeNotifier::kInvalidNetworkHandle),
client_maker_(version_,
quic::QuicUtils::CreateRandomConnectionId(&random_),
&clock_,
@@ -180,12 +186,11 @@ class QuicChromiumClientSessionTest
session_.reset(new TestingQuicChromiumClientSession(
connection, std::move(socket),
/*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
- &transport_security_state_, /*ssl_config_service=*/nullptr,
+ transport_security_state_.get(), /*ssl_config_service=*/nullptr,
base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)), session_key_,
/*require_confirmation=*/false,
/*max_allowed_push_id=*/0, migrate_session_early_v2_,
- /*migrate_session_on_network_change_v2=*/false,
- /*defaulet_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
+ /*migrate_session_on_network_change_v2=*/false, default_network_,
quic::QuicTime::Delta::FromMilliseconds(
kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
/*migrate_idle_session=*/false, /*allow_port_migration=*/false,
@@ -204,6 +209,10 @@ class QuicChromiumClientSessionTest
base::DefaultTickClock::GetInstance(),
base::ThreadTaskRunnerHandle::Get().get(),
/*socket_performance_watcher=*/nullptr, &net_log_));
+ if (connectivity_monitor_) {
+ connectivity_monitor_->SetInitialDefaultNetwork(default_network_);
+ session_->AddConnectivityObserver(connectivity_monitor_.get());
+ }
scoped_refptr<X509Certificate> cert(
ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"));
@@ -220,10 +229,13 @@ class QuicChromiumClientSessionTest
}
void TearDown() override {
- if (session_)
+ if (session_) {
+ if (connectivity_monitor_)
+ session_->RemoveConnectivityObserver(connectivity_monitor_.get());
session_->CloseSessionOnError(
ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
quic::ConnectionCloseBehavior::SILENT_CLOSE);
+ }
}
void CompleteCryptoHandshake() {
@@ -277,12 +289,14 @@ class QuicChromiumClientSessionTest
quic::test::MockRandom random_;
QuicChromiumConnectionHelper helper_;
quic::test::MockAlarmFactory alarm_factory_;
- TransportSecurityState transport_security_state_;
+ std::unique_ptr<TransportSecurityState> transport_security_state_;
MockCryptoClientStreamFactory crypto_client_stream_factory_;
quic::QuicClientPushPromiseIndex push_promise_index_;
QuicSessionKey session_key_;
HostPortPair destination_;
std::unique_ptr<TestingQuicChromiumClientSession> session_;
+ NetworkChangeNotifier::NetworkHandle default_network_;
+ std::unique_ptr<QuicConnectivityMonitor> connectivity_monitor_;
TestServerPushDelegate test_push_delegate_;
quic::QuicConnectionVisitorInterface* visitor_;
TestCompletionCallback callback_;
@@ -299,8 +313,88 @@ INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
::testing::ValuesIn(GetTestParams()),
::testing::PrintToStringParamName());
-// TODO(950069): Add testing for frame_origin in NetworkIsolationKey using
-// kAppendInitiatingFrameOriginToNetworkIsolationKey.
+// TODO(crbug.com/950069): Add testing for frame_origin in NetworkIsolationKey
+// using kAppendInitiatingFrameOriginToNetworkIsolationKey.
+
+// Basic test of ProofVerifyDetailsChromium is converted to SSLInfo retrieved
+// through QuicChromiumClientSession::GetSSLInfo(). Doesn't test some of the
+// more complicated fields.
+TEST_P(QuicChromiumClientSessionTest, GetSSLInfo1) {
+ MockQuicData quic_data(version_);
+ if (VersionUsesHttp3(version_.transport_version))
+ quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+ quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+ quic_data.AddRead(ASYNC, OK); // EOF
+ quic_data.AddSocketDataToFactory(&socket_factory_);
+
+ Initialize();
+
+ ProofVerifyDetailsChromium details;
+ details.is_fatal_cert_error = false;
+ details.cert_verify_result.verified_cert =
+ ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
+ details.cert_verify_result.is_issued_by_known_root = true;
+ details.ct_verify_result.policy_compliance =
+ ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS;
+ details.ct_verify_result.policy_compliance_required = true;
+
+ CompleteCryptoHandshake();
+ session_->OnProofVerifyDetailsAvailable(details);
+
+ SSLInfo ssl_info;
+ ASSERT_TRUE(session_->GetSSLInfo(&ssl_info));
+ EXPECT_TRUE(ssl_info.is_valid());
+
+ EXPECT_EQ(details.is_fatal_cert_error, ssl_info.is_fatal_cert_error);
+ EXPECT_TRUE(ssl_info.cert->EqualsIncludingChain(
+ details.cert_verify_result.verified_cert.get()));
+ EXPECT_EQ(details.cert_verify_result.cert_status, ssl_info.cert_status);
+ EXPECT_EQ(details.cert_verify_result.is_issued_by_known_root,
+ ssl_info.is_issued_by_known_root);
+ EXPECT_EQ(details.ct_verify_result.policy_compliance,
+ ssl_info.ct_policy_compliance);
+ EXPECT_EQ(details.ct_verify_result.policy_compliance_required,
+ ssl_info.ct_policy_compliance_required);
+}
+
+// Just like GetSSLInfo1, but uses different values.
+TEST_P(QuicChromiumClientSessionTest, GetSSLInfo2) {
+ MockQuicData quic_data(version_);
+ if (VersionUsesHttp3(version_.transport_version))
+ quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+ quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+ quic_data.AddRead(ASYNC, OK); // EOF
+ quic_data.AddSocketDataToFactory(&socket_factory_);
+
+ Initialize();
+
+ ProofVerifyDetailsChromium details;
+ details.is_fatal_cert_error = false;
+ details.cert_verify_result.verified_cert =
+ ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
+ details.cert_verify_result.is_issued_by_known_root = false;
+ details.ct_verify_result.policy_compliance =
+ ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS;
+ details.ct_verify_result.policy_compliance_required = false;
+
+ CompleteCryptoHandshake();
+ session_->OnProofVerifyDetailsAvailable(details);
+
+ SSLInfo ssl_info;
+ ASSERT_TRUE(session_->GetSSLInfo(&ssl_info));
+ EXPECT_TRUE(ssl_info.is_valid());
+
+ EXPECT_EQ(details.is_fatal_cert_error, ssl_info.is_fatal_cert_error);
+ EXPECT_TRUE(ssl_info.cert->EqualsIncludingChain(
+ details.cert_verify_result.verified_cert.get()));
+ EXPECT_EQ(details.cert_verify_result.cert_status, ssl_info.cert_status);
+ EXPECT_EQ(details.cert_verify_result.is_issued_by_known_root,
+ ssl_info.is_issued_by_known_root);
+ EXPECT_EQ(details.ct_verify_result.policy_compliance,
+ ssl_info.ct_policy_compliance);
+ EXPECT_EQ(details.ct_verify_result.policy_compliance_required,
+ ssl_info.ct_policy_compliance_required);
+}
TEST_P(QuicChromiumClientSessionTest, IsFatalErrorNotSetForNonFatalError) {
MockQuicData quic_data(version_);
@@ -872,7 +966,7 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionCloseBeforeStreamRequest) {
}
TEST_P(QuicChromiumClientSessionTest, ConnectionCloseBeforeHandshakeConfirmed) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
// TODO(nharper, b/112643533): Figure out why this test fails when TLS is
// enabled and fix it.
return;
@@ -1539,6 +1633,81 @@ TEST_P(QuicChromiumClientSessionTest, CanPool) {
}
}
+TEST_P(QuicChromiumClientSessionTest, CanPoolExpectCT) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatures(
+ /* enabled_features */
+ {TransportSecurityState::kDynamicExpectCTFeature,
+ features::kPartitionExpectCTStateByNetworkIsolationKey},
+ /* disabled_features */
+ {});
+
+ NetworkIsolationKey network_isolation_key =
+ NetworkIsolationKey::CreateTransient();
+ // Need to create a session key after setting
+ // kPartitionExpectCTStateByNetworkIsolationKey, otherwise, it will ignore the
+ // NetworkIsolationKey value.
+ session_key_ = QuicSessionKey(
+ kServerHostname, kServerPort, PRIVACY_MODE_DISABLED, SocketTag(),
+ network_isolation_key, false /* disable_secure_dns */);
+
+ // Need to create this after enabling
+ // kPartitionExpectCTStateByNetworkIsolationKey.
+ transport_security_state_ = std::make_unique<TransportSecurityState>();
+
+ MockQuicData quic_data(version_);
+ if (VersionUsesHttp3(version_.transport_version))
+ quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+ quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+ quic_data.AddRead(ASYNC, OK); // EOF
+ quic_data.AddSocketDataToFactory(&socket_factory_);
+ Initialize();
+
+ // Load a cert that is valid for:
+ // www.example.org
+ // mail.example.org
+ // www.example.com
+
+ // Details with a CT error.
+ ProofVerifyDetailsChromium details;
+ details.cert_verify_result.verified_cert =
+ ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
+ ASSERT_TRUE(details.cert_verify_result.verified_cert.get());
+ details.cert_verify_result.is_issued_by_known_root = true;
+ details.ct_verify_result.policy_compliance =
+ ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS;
+
+ CompleteCryptoHandshake();
+ session_->OnProofVerifyDetailsAvailable(details);
+
+ // Pooling succeeds if CT isn't required.
+ EXPECT_TRUE(session_->CanPool("www.example.org", PRIVACY_MODE_DISABLED,
+ SocketTag(), network_isolation_key,
+ false /* disable_secure_dns */));
+
+ // Adding Expect-CT data for different NetworkIsolationKeys should have no
+ // effect.
+ base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1);
+ transport_security_state_->AddExpectCT(
+ "www.example.org", expiry, true /* enforce */, GURL() /* report_url */,
+ NetworkIsolationKey::CreateTransient());
+ transport_security_state_->AddExpectCT(
+ "www.example.org", expiry, true /* enforce */, GURL() /* report_url */,
+ NetworkIsolationKey());
+ EXPECT_TRUE(session_->CanPool("www.example.org", PRIVACY_MODE_DISABLED,
+ SocketTag(), network_isolation_key,
+ false /* disable_secure_dns */));
+
+ // Adding Expect-CT data for the same NetworkIsolationKey should prevent
+ // pooling.
+ transport_security_state_->AddExpectCT(
+ "www.example.org", expiry, true /* enforce */, GURL() /* report_url */,
+ network_isolation_key);
+ EXPECT_FALSE(session_->CanPool("www.example.org", PRIVACY_MODE_DISABLED,
+ SocketTag(), network_isolation_key,
+ false /* disable_secure_dns */));
+}
+
// Much as above, but uses a non-empty NetworkIsolationKey.
TEST_P(QuicChromiumClientSessionTest, CanPoolWithNetworkIsolationKey) {
base::test::ScopedFeatureList feature_list;
@@ -1629,7 +1798,7 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionNotPooledWithDifferentPin) {
quic_data.AddSocketDataToFactory(&socket_factory_);
Initialize();
- transport_security_state_.EnableStaticPinsForTesting();
+ transport_security_state_->EnableStaticPinsForTesting();
ProofVerifyDetailsChromium details;
details.cert_verify_result.verified_cert =
@@ -1661,7 +1830,7 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithMatchingPin) {
quic_data.AddSocketDataToFactory(&socket_factory_);
Initialize();
- transport_security_state_.EnableStaticPinsForTesting();
+ transport_security_state_->EnableStaticPinsForTesting();
ProofVerifyDetailsChromium details;
details.cert_verify_result.verified_cert =
@@ -1752,7 +1921,7 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
quic::test::QuicStreamPeer::SendBuffer(stream).SaveStreamData(iov, 1, 0, 4);
quic::test::QuicStreamPeer::SetStreamBytesWritten(4, stream);
session_->WritevData(stream->id(), 4, 0, quic::NO_FIN,
- quic::NOT_RETRANSMISSION, QuicheNullOpt);
+ quic::NOT_RETRANSMISSION, QUICHE_NULLOPT);
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -2033,6 +2202,174 @@ TEST_P(QuicChromiumClientSessionTest, ResetOnEmptyResponseHeaders) {
EXPECT_TRUE(quic_data.AllWriteDataConsumed());
}
+// This test verifies that when NetworkHandle is not supported and there is no
+// network change, session reports to the connectivity monitor correctly on path
+// degrading detection and recovery.
+TEST_P(QuicChromiumClientSessionTest,
+ DegradingWithoutNetworkChange_NoNetworkHandle) {
+ // Add a connectivity monitor for testing.
+ default_network_ = NetworkChangeNotifier::kInvalidNetworkHandle;
+ connectivity_monitor_ =
+ std::make_unique<QuicConnectivityMonitor>(default_network_);
+
+ Initialize();
+
+ // Fire path degrading detection.
+ session_->ReallyOnPathDegrading();
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+
+ session_->OnForwardProgressMadeAfterPathDegrading();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+
+ // Fire again.
+ session_->ReallyOnPathDegrading();
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+
+ // Close the session but keep the session around, the connectivity monitor
+ // will not remove the tracking immediately.
+ session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
+ quic::ConnectionCloseBehavior::SILENT_CLOSE);
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+
+ // Delete the session will remove the degrading count in connectivity
+ // monitor.
+ session_.reset();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+}
+
+// This test verifies that when the NetworkHandle is not supported, and there
+// are speculated network change reported via OnIPAddressChange, session
+// still reports to the connectivity monitor correctly on path degrading
+// detection and recovery.
+TEST_P(QuicChromiumClientSessionTest, DegradingWithIPAddressChange) {
+ // Default network is always set to kInvalidNetworkHandle.
+ default_network_ = NetworkChangeNotifier::kInvalidNetworkHandle;
+ connectivity_monitor_ =
+ std::make_unique<QuicConnectivityMonitor>(default_network_);
+
+ Initialize();
+
+ session_->ReallyOnPathDegrading();
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+
+ session_->OnForwardProgressMadeAfterPathDegrading();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+
+ session_->ReallyOnPathDegrading();
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+
+ // When NetworkHandle is not supported, network change is notified via
+ // IP address change.
+ connectivity_monitor_->OnIPAddressChanged();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+
+ // When NetworkHandle is not supported and IP address changes,
+ // session either goes away or gets closed. When it goes away,
+ // reporting to connectivity monitor is disabled.
+ connectivity_monitor_->OnSessionGoingAwayOnIPAddressChange(session_.get());
+
+ // Even if session detects recovery or degradation, this session is no longer
+ // on the default network and connectivity monitor will not update.
+ session_->OnForwardProgressMadeAfterPathDegrading();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+ session_->ReallyOnPathDegrading();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+
+ session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
+ quic::ConnectionCloseBehavior::SILENT_CLOSE);
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+
+ session_.reset();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+}
+
+// This test verifies that when NetworkHandle is supported but migration is
+// not supported and there's no network change, session reports to
+// connectivity monitor correctly on path degrading detection or recovery.
+// Default network change is currently reported with valid NetworkHandles
+// while session's current network interface is tracked by |default_network_|.
+TEST_P(QuicChromiumClientSessionTest,
+ DegradingOnDeafultNetwork_WithoutMigration) {
+ default_network_ = kDefaultNetworkForTests;
+ connectivity_monitor_ =
+ std::make_unique<QuicConnectivityMonitor>(default_network_);
+
+ Initialize();
+
+ session_->ReallyOnPathDegrading();
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+
+ session_->OnForwardProgressMadeAfterPathDegrading();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+
+ session_->ReallyOnPathDegrading();
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+ // Close the session but keep the session around, the connectivity monitor
+ // should not remove the count immediately.
+ session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
+ quic::ConnectionCloseBehavior::SILENT_CLOSE);
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+
+ // Delete the session will remove the degrading count in connectivity
+ // monitor.
+ session_.reset();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+}
+
+// This test verifies that when NetworkHandle is supported but migrations is not
+// supported and there is network changes, session reports to the connectivity
+// monitor correctly on path degrading detection or recovery.
+TEST_P(QuicChromiumClientSessionTest,
+ DegradingWithDeafultNetworkChange_WithoutMigration) {
+ default_network_ = kDefaultNetworkForTests;
+ connectivity_monitor_ =
+ std::make_unique<QuicConnectivityMonitor>(default_network_);
+
+ Initialize();
+
+ session_->ReallyOnPathDegrading();
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+
+ session_->OnForwardProgressMadeAfterPathDegrading();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+
+ session_->ReallyOnPathDegrading();
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+
+ // Simulate the default network change.
+ connectivity_monitor_->OnDefaultNetworkUpdated(kNewNetworkForTests);
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+ session_->OnNetworkMadeDefault(kNewNetworkForTests);
+
+ // Session stays on the old default network, and recovers.
+ session_->OnForwardProgressMadeAfterPathDegrading();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+
+ // Session degrades again on the old default.
+ session_->ReallyOnPathDegrading();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+
+ // Simulate that default network switches back to the old default.
+ connectivity_monitor_->OnDefaultNetworkUpdated(kDefaultNetworkForTests);
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+ session_->OnNetworkMadeDefault(kDefaultNetworkForTests);
+
+ // Session recovers again on the (old) default.
+ session_->OnForwardProgressMadeAfterPathDegrading();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+
+ // Session degrades again on the (old) default.
+ session_->ReallyOnPathDegrading();
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+
+ session_->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR,
+ quic::ConnectionCloseBehavior::SILENT_CLOSE);
+ EXPECT_EQ(1u, connectivity_monitor_->GetNumDegradingSessions());
+
+ session_.reset();
+ EXPECT_EQ(0u, connectivity_monitor_->GetNumDegradingSessions());
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_chromium_client_stream.h b/chromium/net/quic/quic_chromium_client_stream.h
index 71372a16f52..6399b92a5e3 100644
--- a/chromium/net/quic/quic_chromium_client_stream.h
+++ b/chromium/net/quic/quic_chromium_client_stream.h
@@ -9,10 +9,10 @@
#include <stddef.h>
+#include <memory>
#include <vector>
#include "base/callback_forward.h"
-#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "net/base/completion_once_callback.h"
#include "net/base/ip_endpoint.h"
diff --git a/chromium/net/quic/quic_chromium_packet_writer.cc b/chromium/net/quic/quic_chromium_packet_writer.cc
index 2c5d194df73..e45613b9511 100644
--- a/chromium/net/quic/quic_chromium_packet_writer.cc
+++ b/chromium/net/quic/quic_chromium_packet_writer.cc
@@ -263,10 +263,10 @@ bool QuicChromiumPacketWriter::IsBatchMode() const {
return false;
}
-char* QuicChromiumPacketWriter::GetNextWriteLocation(
+quic::QuicPacketBuffer QuicChromiumPacketWriter::GetNextWriteLocation(
const quic::QuicIpAddress& self_address,
const quic::QuicSocketAddress& peer_address) {
- return nullptr;
+ return {nullptr, nullptr};
}
quic::WriteResult QuicChromiumPacketWriter::Flush() {
diff --git a/chromium/net/quic/quic_chromium_packet_writer.h b/chromium/net/quic/quic_chromium_packet_writer.h
index 82acb30f367..2f03d3914dc 100644
--- a/chromium/net/quic/quic_chromium_packet_writer.h
+++ b/chromium/net/quic/quic_chromium_packet_writer.h
@@ -94,7 +94,7 @@ class NET_EXPORT_PRIVATE QuicChromiumPacketWriter
const quic::QuicSocketAddress& peer_address) const override;
bool SupportsReleaseTime() const override;
bool IsBatchMode() const override;
- char* GetNextWriteLocation(
+ quic::QuicPacketBuffer GetNextWriteLocation(
const quic::QuicIpAddress& self_address,
const quic::QuicSocketAddress& peer_address) override;
quic::WriteResult Flush() override;
diff --git a/chromium/net/quic/quic_client_session_cache.cc b/chromium/net/quic/quic_client_session_cache.cc
index 7bc5945225a..64e8d962993 100644
--- a/chromium/net/quic/quic_client_session_cache.cc
+++ b/chromium/net/quic/quic_client_session_cache.cc
@@ -46,9 +46,9 @@ QuicClientSessionCache::QuicClientSessionCache()
QuicClientSessionCache::QuicClientSessionCache(size_t max_entries)
: clock_(base::DefaultClock::GetInstance()), cache_(max_entries) {
- memory_pressure_listener_.reset(
- new base::MemoryPressureListener(base::BindRepeating(
- &QuicClientSessionCache::OnMemoryPressure, base::Unretained(this))));
+ memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
+ FROM_HERE, base::BindRepeating(&QuicClientSessionCache::OnMemoryPressure,
+ base::Unretained(this)));
}
QuicClientSessionCache::~QuicClientSessionCache() {
@@ -103,6 +103,18 @@ std::unique_ptr<quic::QuicResumptionState> QuicClientSessionCache::Lookup(
return state;
}
+void QuicClientSessionCache::ClearEarlyData(
+ const quic::QuicServerId& server_id) {
+ auto iter = cache_.Get(server_id);
+ if (iter == cache_.end())
+ return;
+ for (auto& session : iter->second.sessions) {
+ if (session) {
+ session.reset(SSL_SESSION_copy_without_early_data(session.get()));
+ }
+ }
+}
+
void QuicClientSessionCache::FlushInvalidEntries() {
time_t now = clock_->Now().ToTimeT();
auto iter = cache_.begin();
diff --git a/chromium/net/quic/quic_client_session_cache.h b/chromium/net/quic/quic_client_session_cache.h
index 8d7506ee4ec..c59c28a2937 100644
--- a/chromium/net/quic/quic_client_session_cache.h
+++ b/chromium/net/quic/quic_client_session_cache.h
@@ -39,6 +39,8 @@ class NET_EXPORT_PRIVATE QuicClientSessionCache : public quic::SessionCache {
const quic::QuicServerId& server_id,
const SSL_CTX* ctx) override;
+ void ClearEarlyData(const quic::QuicServerId& server_id) override;
+
void SetClockForTesting(base::Clock* clock) { clock_ = clock; }
size_t size() const { return cache_.size(); }
diff --git a/chromium/net/quic/quic_client_session_cache_unittests.cc b/chromium/net/quic/quic_client_session_cache_unittests.cc
index 0fac11c6840..c1e241df403 100644
--- a/chromium/net/quic/quic_client_session_cache_unittests.cc
+++ b/chromium/net/quic/quic_client_session_cache_unittests.cc
@@ -8,6 +8,8 @@
#include "base/test/simple_test_clock.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
+#include "build/build_config.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
@@ -15,6 +17,7 @@ namespace net {
namespace {
+const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000);
const quic::QuicVersionLabel kFakeVersionLabel = 0x01234567;
const quic::QuicVersionLabel kFakeVersionLabel2 = 0x89ABCDEF;
const uint64_t kFakeIdleTimeoutMilliseconds = 12012;
@@ -53,37 +56,96 @@ std::unique_ptr<quic::TransportParameters> MakeFakeTransportParams() {
params->version = kFakeVersionLabel;
params->supported_versions.push_back(kFakeVersionLabel);
params->supported_versions.push_back(kFakeVersionLabel2);
- params->idle_timeout_milliseconds.set_value(kFakeIdleTimeoutMilliseconds);
+ params->max_idle_timeout_ms.set_value(kFakeIdleTimeoutMilliseconds);
params->stateless_reset_token = CreateFakeStatelessResetToken();
- params->max_packet_size.set_value(kFakeMaxPacketSize);
+ params->max_udp_payload_size.set_value(kFakeMaxPacketSize);
params->initial_max_data.set_value(kFakeInitialMaxData);
- params->disable_migration = kFakeDisableMigration;
+ params->disable_active_migration = kFakeDisableMigration;
params->custom_parameters[kCustomParameter1] = kCustomParameter1Value;
params->custom_parameters[kCustomParameter2] = kCustomParameter2Value;
return params;
}
+namespace {
+
+// Generated by running TlsClientHandshakerTest.ZeroRttResumption and in
+// TlsClientHandshaker::InsertSession calling SSL_SESSION_to_bytes to serialize
+// the received 0-RTT capable ticket.
+static const char kCachedSession[] =
+ "3082068702010102020304040213010420b9c2a657e565db0babd09e192a9fc4d768fbd706"
+ "9f03f9278a4a0be62392e55b0420d87ed2ab8cafc986fd2e288bd2d654cd57c3a2bed1d532"
+ "20726e55fed39d021ea10602045ed16771a205020302a300a382025f3082025b30820143a0"
+ "03020102020104300d06092a864886f70d01010b0500302c3110300e060355040a13074163"
+ "6d6520436f311830160603550403130f496e7465726d656469617465204341301e170d3133"
+ "303130313130303030305a170d3233313233313130303030305a302d3110300e060355040a"
+ "130741636d6520436f3119301706035504031310746573742e6578616d706c652e636f6d30"
+ "59301306072a8648ce3d020106082a8648ce3d030107034200040526220e77278300d06bc0"
+ "86aff4f999a828a2ed5cc75adc2972794befe885aa3a9b843de321b36b0a795289cebff1a5"
+ "428bad5e34665ce5e36daad08fb3ffd8a3523050300e0603551d0f0101ff04040302078030"
+ "130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000301b06"
+ "03551d11041430128210746573742e6578616d706c652e636f6d300d06092a864886f70d01"
+ "010b050003820101008c1f1e380831b6437a8b9284d28d4ead38d9503a9fc936db89048aa2"
+ "edd6ec2fb830d962ef7a4f384e679504f4d5520f3272e0b9e702b110aff31711578fa5aeb1"
+ "11e9d184c994b0f97e7b17d1995f3f477f25bc1258398ec0ec729caed55d594a009f48093a"
+ "17f33a7f3bb6e420cc3499838398a421d93c7132efa8bee5ed2645cbc55179c400da006feb"
+ "761badd356cac3bd7a0e6b22a511106a355ec62a4c0ac2541d2996adb4a918c866d10c3e31"
+ "62039a91d4ce600b276740d833380b37f66866d261bf6efa8855e7ae6c7d12a8a864cd9a1f"
+ "4663e07714b0204e51bbc189a2d04c2a5043202379ff1c8cbf30cbb44fde4ee9a1c0c976dc"
+ "4943df2c132ca4020400aa7f047d494e534543555245003072020101020203040402130104"
+ "000420d87ed2ab8cafc986fd2e288bd2d654cd57c3a2bed1d53220726e55fed39d021ea106"
+ "02045ed16771a205020302a300a4020400b20302011db5060404bd909308b807020500ffff"
+ "ffffb9050203093a80ba07040568332d3238bb030101ffbc03040100b20302011db3820307"
+ "30820303308201eba003020102020102300d06092a864886f70d01010b050030243110300e"
+ "060355040a130741636d6520436f3110300e06035504031307526f6f74204341301e170d31"
+ "33303130313130303030305a170d3233313233313130303030305a302c3110300e06035504"
+ "0a130741636d6520436f311830160603550403130f496e7465726d65646961746520434130"
+ "820122300d06092a864886f70d01010105000382010f003082010a0282010100cd3550e70a"
+ "6880e52bf0012b93110c50f723e1d8d2ed489aea3b649f82fae4ad2396a8a19b31d1d64ab2"
+ "79f1c18003184154a5303a82bd57109cfd5d34fd19d3211bcb06e76640e1278998822dd72e"
+ "0d5c059a740d45de325e784e81b4c86097f08b2a8ce057f6b9db5a53641d27e09347d993ee"
+ "acf67be7d297b1a6853775ffaaf78fae924e300b5654fd32f99d3cd82e95f56417ff26d265"
+ "e2b1786c835d67a4d8ae896b6eb34b35a5b1033c209779ed0bf8de25a13a507040ae9e0475"
+ "a26a2f15845b08c3e0554e47dbbc7925b02e580dbcaaa6f2eecde6b8028c5b00b33d44d0a6"
+ "bfb3e72e9d4670de45d1bd79bdc0f2470b71286091c29873152db4b1f30203010001a33830"
+ "36300e0603551d0f0101ff04040302020430130603551d25040c300a06082b060105050703"
+ "01300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003820101"
+ "00bc4f8234860558dd404a626403819bfc759029d625a002143e75ebdb2898d1befdd326c3"
+ "4b14dc3507d732bb29af7e6af31552db53052a2be0d950efee5e0f699304231611ed8bf73a"
+ "6f216a904c6c2f1a2186d1ed08a8005a7914394d71e7d4b643c808f86365c5fecad8b52934"
+ "2d3b3f03447126d278d75b1dab3ed53f23e36e9b3d695f28727916e5ee56ce22d387c81f05"
+ "919b2a37bd4981eb67d9f57b7072285dbbb61f48b6b14768c069a092aad5a094cf295dafd2"
+ "3ca008f89a5f5ab37a56e5f68df45091c7cb85574677127087a2887ba3baa6d4fc436c6e40"
+ "40885e81621d38974f0c7f0d792418c5adebb10e92a165f8d79b169617ff575c0d4a85b506"
+ "0404bd909308b603010100b70402020403b807020500ffffffffb9050203093a80ba070405"
+ "68332d3238bb030101ff";
+
+} // namespace
+
class QuicClientSessionCacheTest : public testing::Test {
public:
- QuicClientSessionCacheTest() : ssl_ctx_(SSL_CTX_new(TLS_method())) {}
+ QuicClientSessionCacheTest()
+ : ssl_ctx_(SSL_CTX_new(TLS_method())), clock_(MakeTestClock()) {}
protected:
bssl::UniquePtr<SSL_SESSION> NewSSLSession() {
- SSL_SESSION* session = SSL_SESSION_new(ssl_ctx_.get());
- if (!SSL_SESSION_set_protocol_version(session, TLS1_3_VERSION))
- return nullptr;
+ std::string cached_session =
+ quiche::QuicheTextUtils::HexDecode(kCachedSession);
+ SSL_SESSION* session = SSL_SESSION_from_bytes(
+ reinterpret_cast<const uint8_t*>(cached_session.data()),
+ cached_session.size(), ssl_ctx_.get());
return bssl::UniquePtr<SSL_SESSION>(session);
}
- bssl::UniquePtr<SSL_SESSION> MakeTestSession(base::Time now,
- base::TimeDelta timeout) {
+ bssl::UniquePtr<SSL_SESSION> MakeTestSession(
+ base::TimeDelta timeout = kTimeout) {
bssl::UniquePtr<SSL_SESSION> session = NewSSLSession();
- SSL_SESSION_set_time(session.get(), now.ToTimeT());
+ SSL_SESSION_set_time(session.get(), clock_->Now().ToTimeT());
SSL_SESSION_set_timeout(session.get(), timeout.InSeconds());
return session;
}
bssl::UniquePtr<SSL_CTX> ssl_ctx_;
+ std::unique_ptr<base::SimpleTestClock> clock_;
};
} // namespace
@@ -91,13 +153,14 @@ class QuicClientSessionCacheTest : public testing::Test {
// Tests that simple insertion and lookup work correctly.
TEST_F(QuicClientSessionCacheTest, SingleSession) {
QuicClientSessionCache cache;
+ cache.SetClockForTesting(clock_.get());
auto params = MakeFakeTransportParams();
- auto session = NewSSLSession();
+ auto session = MakeTestSession();
quic::QuicServerId id1("a.com", 443);
auto params2 = MakeFakeTransportParams();
- auto session2 = NewSSLSession();
+ auto session2 = MakeTestSession();
SSL_SESSION* unowned2 = session2.get();
quic::QuicServerId id2("b.com", 443);
@@ -115,7 +178,7 @@ TEST_F(QuicClientSessionCacheTest, SingleSession) {
// Lookup() will trigger a deletion of invalid entry.
EXPECT_EQ(0u, cache.size());
- auto session3 = NewSSLSession();
+ auto session3 = MakeTestSession();
SSL_SESSION* unowned3 = session3.get();
quic::QuicServerId id3("c.com", 443);
cache.Insert(id3, std::move(session3), *params, nullptr);
@@ -133,13 +196,14 @@ TEST_F(QuicClientSessionCacheTest, SingleSession) {
TEST_F(QuicClientSessionCacheTest, MultipleSessions) {
QuicClientSessionCache cache;
+ cache.SetClockForTesting(clock_.get());
auto params = MakeFakeTransportParams();
- auto session = NewSSLSession();
+ auto session = MakeTestSession();
quic::QuicServerId id1("a.com", 443);
- auto session2 = NewSSLSession();
+ auto session2 = MakeTestSession();
SSL_SESSION* unowned2 = session2.get();
- auto session3 = NewSSLSession();
+ auto session3 = MakeTestSession();
SSL_SESSION* unowned3 = session3.get();
cache.Insert(id1, std::move(session), *params, nullptr);
@@ -156,12 +220,13 @@ TEST_F(QuicClientSessionCacheTest, MultipleSessions) {
// the same server id, the existing entry is removed.
TEST_F(QuicClientSessionCacheTest, DifferentTransportParams) {
QuicClientSessionCache cache;
+ cache.SetClockForTesting(clock_.get());
auto params = MakeFakeTransportParams();
- auto session = NewSSLSession();
+ auto session = MakeTestSession();
quic::QuicServerId id1("a.com", 443);
- auto session2 = NewSSLSession();
- auto session3 = NewSSLSession();
+ auto session2 = MakeTestSession();
+ auto session3 = MakeTestSession();
SSL_SESSION* unowned3 = session3.get();
cache.Insert(id1, std::move(session), *params, nullptr);
@@ -177,12 +242,13 @@ TEST_F(QuicClientSessionCacheTest, DifferentTransportParams) {
TEST_F(QuicClientSessionCacheTest, DifferentApplicationState) {
QuicClientSessionCache cache;
+ cache.SetClockForTesting(clock_.get());
auto params = MakeFakeTransportParams();
- auto session = NewSSLSession();
+ auto session = MakeTestSession();
quic::QuicServerId id1("a.com", 443);
- auto session2 = NewSSLSession();
- auto session3 = NewSSLSession();
+ auto session2 = MakeTestSession();
+ auto session3 = MakeTestSession();
SSL_SESSION* unowned3 = session3.get();
quic::ApplicationState state;
state.push_back('a');
@@ -198,12 +264,13 @@ TEST_F(QuicClientSessionCacheTest, DifferentApplicationState) {
TEST_F(QuicClientSessionCacheTest, BothStatesDifferent) {
QuicClientSessionCache cache;
+ cache.SetClockForTesting(clock_.get());
auto params = MakeFakeTransportParams();
- auto session = NewSSLSession();
+ auto session = MakeTestSession();
quic::QuicServerId id1("a.com", 443);
- auto session2 = NewSSLSession();
- auto session3 = NewSSLSession();
+ auto session2 = MakeTestSession();
+ auto session3 = MakeTestSession();
SSL_SESSION* unowned3 = session3.get();
quic::ApplicationState state;
state.push_back('a');
@@ -222,16 +289,17 @@ TEST_F(QuicClientSessionCacheTest, BothStatesDifferent) {
// When the size limit is exceeded, the oldest entry should be erased.
TEST_F(QuicClientSessionCacheTest, SizeLimit) {
QuicClientSessionCache cache(2);
+ cache.SetClockForTesting(clock_.get());
auto params = MakeFakeTransportParams();
- auto session = NewSSLSession();
+ auto session = MakeTestSession();
quic::QuicServerId id1("a.com", 443);
- auto session2 = NewSSLSession();
+ auto session2 = MakeTestSession();
SSL_SESSION* unowned2 = session2.get();
quic::QuicServerId id2("b.com", 443);
- auto session3 = NewSSLSession();
+ auto session3 = MakeTestSession();
SSL_SESSION* unowned3 = session3.get();
quic::QuicServerId id3("c.com", 443);
@@ -245,19 +313,43 @@ TEST_F(QuicClientSessionCacheTest, SizeLimit) {
EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
}
+TEST_F(QuicClientSessionCacheTest, ClearEarlyData) {
+ QuicClientSessionCache cache;
+ cache.SetClockForTesting(clock_.get());
+ SSL_CTX_set_early_data_enabled(ssl_ctx_.get(), 1);
+ auto params = MakeFakeTransportParams();
+ auto session = MakeTestSession();
+ quic::QuicServerId id1("a.com", 443);
+ auto session2 = MakeTestSession();
+
+ EXPECT_TRUE(SSL_SESSION_early_data_capable(session.get()));
+ EXPECT_TRUE(SSL_SESSION_early_data_capable(session2.get()));
+
+ cache.Insert(id1, std::move(session), *params, nullptr);
+ cache.Insert(id1, std::move(session2), *params, nullptr);
+
+ cache.ClearEarlyData(id1);
+
+ auto resumption_state = cache.Lookup(id1, ssl_ctx_.get());
+ EXPECT_FALSE(
+ SSL_SESSION_early_data_capable(resumption_state->tls_session.get()));
+ resumption_state = cache.Lookup(id1, ssl_ctx_.get());
+ EXPECT_FALSE(
+ SSL_SESSION_early_data_capable(resumption_state->tls_session.get()));
+ EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
+}
+
// Expired session isn't considered valid and nullptr will be returned upon
// Lookup.
TEST_F(QuicClientSessionCacheTest, Expiration) {
- const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000);
QuicClientSessionCache cache;
- std::unique_ptr<base::SimpleTestClock> clock = MakeTestClock();
- cache.SetClockForTesting(clock.get());
+ cache.SetClockForTesting(clock_.get());
auto params = MakeFakeTransportParams();
- auto session = MakeTestSession(clock->Now(), kTimeout);
+ auto session = MakeTestSession();
quic::QuicServerId id1("a.com", 443);
- auto session2 = MakeTestSession(clock->Now(), 3 * kTimeout);
+ auto session2 = MakeTestSession(3 * kTimeout);
SSL_SESSION* unowned2 = session2.get();
quic::QuicServerId id2("b.com", 443);
@@ -266,7 +358,7 @@ TEST_F(QuicClientSessionCacheTest, Expiration) {
EXPECT_EQ(2u, cache.size());
// Expire the session.
- clock->Advance(kTimeout * 2);
+ clock_->Advance(kTimeout * 2);
// The entry has not been removed yet.
EXPECT_EQ(2u, cache.size());
@@ -278,16 +370,14 @@ TEST_F(QuicClientSessionCacheTest, Expiration) {
TEST_F(QuicClientSessionCacheTest, FlushOnMemoryNotifications) {
base::test::TaskEnvironment task_environment;
- const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000);
QuicClientSessionCache cache;
- std::unique_ptr<base::SimpleTestClock> clock = MakeTestClock();
- cache.SetClockForTesting(clock.get());
+ cache.SetClockForTesting(clock_.get());
auto params = MakeFakeTransportParams();
- auto session = MakeTestSession(clock->Now(), kTimeout);
+ auto session = MakeTestSession();
quic::QuicServerId id1("a.com", 443);
- auto session2 = MakeTestSession(clock->Now(), 3 * kTimeout);
+ auto session2 = MakeTestSession(3 * kTimeout);
quic::QuicServerId id2("b.com", 443);
cache.Insert(id1, std::move(session), *params, nullptr);
@@ -295,7 +385,7 @@ TEST_F(QuicClientSessionCacheTest, FlushOnMemoryNotifications) {
EXPECT_EQ(2u, cache.size());
// Expire the session.
- clock->Advance(kTimeout * 2);
+ clock_->Advance(kTimeout * 2);
// The entry has not been removed yet.
EXPECT_EQ(2u, cache.size());
diff --git a/chromium/net/quic/quic_connection_logger.cc b/chromium/net/quic/quic_connection_logger.cc
index 1293fac42ac..71803309b69 100644
--- a/chromium/net/quic/quic_connection_logger.cc
+++ b/chromium/net/quic/quic_connection_logger.cc
@@ -227,6 +227,14 @@ base::Value NetLogQuicCryptoHandshakeMessageParams(
return dict;
}
+base::Value NetLogQuicTransportParametersParams(
+ const quic::TransportParameters& transport_parameters) {
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetStringKey("quic_transport_parameters",
+ transport_parameters.ToString());
+ return dict;
+}
+
base::Value NetLogQuicOnConnectionClosedParams(
quic::QuicErrorCode error,
string error_details,
@@ -877,8 +885,6 @@ void QuicConnectionLogger::OnIncomingAck(
return;
net_log_.AddEvent(NetLogEventType::QUIC_SESSION_ACK_FRAME_RECEIVED,
[&] { return NetLogQuicAckFrameParams(&frame); });
-
- // TODO(rch, rtenneti) sort out histograms for QUIC_VERSION_34 and above.
}
void QuicConnectionLogger::OnStopWaitingFrame(
@@ -1142,6 +1148,26 @@ void QuicConnectionLogger::OnRttChanged(quic::QuicTime::Delta rtt) const {
}
}
+void QuicConnectionLogger::OnTransportParametersSent(
+ const quic::TransportParameters& transport_parameters) {
+ if (!net_log_.IsCapturing())
+ return;
+ net_log_.AddEvent(
+ NetLogEventType::QUIC_SESSION_TRANSPORT_PARAMETERS_SENT, [&] {
+ return NetLogQuicTransportParametersParams(transport_parameters);
+ });
+}
+
+void QuicConnectionLogger::OnTransportParametersReceived(
+ const quic::TransportParameters& transport_parameters) {
+ if (!net_log_.IsCapturing())
+ return;
+ net_log_.AddEvent(
+ NetLogEventType::QUIC_SESSION_TRANSPORT_PARAMETERS_RECEIVED, [&] {
+ return NetLogQuicTransportParametersParams(transport_parameters);
+ });
+}
+
void QuicConnectionLogger::RecordAggregatePacketLossRate() const {
// For short connections under 22 packets in length, we'll rely on the
// Net.QuicSession.21CumulativePacketsReceived_* histogram to indicate packet
diff --git a/chromium/net/quic/quic_connection_logger.h b/chromium/net/quic/quic_connection_logger.h
index 9c45bf983d9..879ebf1c986 100644
--- a/chromium/net/quic/quic_connection_logger.h
+++ b/chromium/net/quic/quic_connection_logger.h
@@ -109,6 +109,10 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger
void OnSuccessfulVersionNegotiation(
const quic::ParsedQuicVersion& version) override;
void OnRttChanged(quic::QuicTime::Delta rtt) const override;
+ void OnTransportParametersSent(
+ const quic::TransportParameters& transport_parameters) override;
+ void OnTransportParametersReceived(
+ const quic::TransportParameters& transport_parameters) override;
void OnCryptoHandshakeMessageReceived(
const quic::CryptoHandshakeMessage& message);
diff --git a/chromium/net/quic/quic_connectivity_monitor.cc b/chromium/net/quic/quic_connectivity_monitor.cc
new file mode 100644
index 00000000000..00d0a774465
--- /dev/null
+++ b/chromium/net/quic/quic_connectivity_monitor.cc
@@ -0,0 +1,71 @@
+// Copyright (c) 2020 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.
+
+#include "net/quic/quic_connectivity_monitor.h"
+
+#include "base/metrics/histogram_macros.h"
+
+namespace net {
+
+QuicConnectivityMonitor::QuicConnectivityMonitor(
+ NetworkChangeNotifier::NetworkHandle default_network)
+ : default_network_(default_network) {}
+
+QuicConnectivityMonitor::~QuicConnectivityMonitor() = default;
+
+size_t QuicConnectivityMonitor::GetNumDegradingSessions() const {
+ return degrading_sessions_.size();
+}
+
+void QuicConnectivityMonitor::SetInitialDefaultNetwork(
+ NetworkChangeNotifier::NetworkHandle default_network) {
+ default_network_ = default_network;
+}
+
+void QuicConnectivityMonitor::OnSessionPathDegrading(
+ QuicChromiumClientSession* session,
+ NetworkChangeNotifier::NetworkHandle network) {
+ if (network == default_network_)
+ degrading_sessions_.insert(session);
+}
+
+void QuicConnectivityMonitor::OnSessionResumedPostPathDegrading(
+ QuicChromiumClientSession* session,
+ NetworkChangeNotifier::NetworkHandle network) {
+ if (network == default_network_)
+ degrading_sessions_.erase(session);
+}
+
+void QuicConnectivityMonitor::OnSessionRemoved(
+ QuicChromiumClientSession* session) {
+ degrading_sessions_.erase(session);
+}
+
+void QuicConnectivityMonitor::OnDefaultNetworkUpdated(
+ NetworkChangeNotifier::NetworkHandle default_network) {
+ default_network_ = default_network;
+ degrading_sessions_.clear();
+}
+
+void QuicConnectivityMonitor::OnIPAddressChanged() {
+ // If NetworkHandle is supported, connectivity monitor will receive
+ // notifications via OnDefaultNetworkUpdated.
+ if (NetworkChangeNotifier::AreNetworkHandlesSupported())
+ return;
+
+ DCHECK_EQ(default_network_, NetworkChangeNotifier::kInvalidNetworkHandle);
+ degrading_sessions_.clear();
+}
+
+void QuicConnectivityMonitor::OnSessionGoingAwayOnIPAddressChange(
+ QuicChromiumClientSession* session) {
+ // This should only be called after ConnectivityMonitor gets notified via
+ // OnIPAddressChanged().
+ DCHECK(degrading_sessions_.empty());
+ // |session| that encounters IP address change will lose track which network
+ // it is bound to. Future connectivity monitoring may be misleading.
+ session->RemoveConnectivityObserver(this);
+}
+
+} // namespace net
diff --git a/chromium/net/quic/quic_connectivity_monitor.h b/chromium/net/quic/quic_connectivity_monitor.h
new file mode 100644
index 00000000000..b8b7274a8d8
--- /dev/null
+++ b/chromium/net/quic/quic_connectivity_monitor.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2020 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 NET_QUIC_QUIC_CONNECTIVITY_MONITOR_H_
+#define NET_QUIC_QUIC_CONNECTIVITY_MONITOR_H_
+
+#include "net/base/network_change_notifier.h"
+#include "net/quic/quic_chromium_client_session.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+
+namespace net {
+
+// Responsible for monitoring path degrading detection/recovery events on the
+// default network interface.
+// Reset all raw observations (reported by sessions) when the default network
+// is changed, which happens either:
+// - via OnDefaultNetworkUpdated if NetworkHandle is supported on the platform;
+// - via OnIPAddressChanged otherwise.
+class NET_EXPORT_PRIVATE QuicConnectivityMonitor
+ : public QuicChromiumClientSession::ConnectivityObserver {
+ public:
+ explicit QuicConnectivityMonitor(
+ NetworkChangeNotifier::NetworkHandle default_network);
+
+ ~QuicConnectivityMonitor() override;
+
+ // Returns the number of sessions that are currently degrading on the default
+ // network interface.
+ size_t GetNumDegradingSessions() const;
+
+ // Called to set up the initial default network, which happens when the
+ // default network tracking is lost upon |this| creation.
+ void SetInitialDefaultNetwork(
+ NetworkChangeNotifier::NetworkHandle default_network);
+
+ // Called when NetworkHandle is supported and the default network interface
+ // used by the platform is updated.
+ void OnDefaultNetworkUpdated(
+ NetworkChangeNotifier::NetworkHandle default_network);
+
+ // Called when NetworkHandle is NOT supported and the IP address of the
+ // primary interface changes. This includes when the primary interface itself
+ // changes.
+ void OnIPAddressChanged();
+
+ // Called when |session| is marked as going away due to IP address change.
+ void OnSessionGoingAwayOnIPAddressChange(QuicChromiumClientSession* session);
+
+ // QuicChromiumClientSession::ConnectivityObserver implementation.
+ void OnSessionPathDegrading(
+ QuicChromiumClientSession* session,
+ NetworkChangeNotifier::NetworkHandle network) override;
+
+ void OnSessionResumedPostPathDegrading(
+ QuicChromiumClientSession* session,
+ NetworkChangeNotifier::NetworkHandle network) override;
+
+ void OnSessionRemoved(QuicChromiumClientSession* session) override;
+
+ private:
+ // If NetworkHandle is not supported, always set to
+ // NetworkChangeNotifier::kInvalidNetworkHandle.
+ NetworkChangeNotifier::NetworkHandle default_network_;
+ // Sessions that are currently degrading on the |default_network_|.
+ quic::QuicHashSet<QuicChromiumClientSession*> degrading_sessions_;
+
+ base::WeakPtrFactory<QuicConnectivityMonitor> weak_factory_{this};
+ DISALLOW_COPY_AND_ASSIGN(QuicConnectivityMonitor);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_CONNECTIVITY_MONITOR_H_
diff --git a/chromium/net/quic/quic_connectivity_probing_manager.cc b/chromium/net/quic/quic_connectivity_probing_manager.cc
index 9f0d16fbee4..dd240252bf6 100644
--- a/chromium/net/quic/quic_connectivity_probing_manager.cc
+++ b/chromium/net/quic/quic_connectivity_probing_manager.cc
@@ -60,7 +60,9 @@ QuicConnectivityProbingManager::QuicConnectivityProbingManager(
network_(NetworkChangeNotifier::kInvalidNetworkHandle),
retry_count_(0),
probe_start_time_(base::TimeTicks()),
- task_runner_(task_runner) {
+ task_runner_(task_runner),
+ last_self_address_(IPEndPoint()),
+ stateless_reset_received_(false) {
retransmit_timer_.SetTaskRunner(task_runner_);
}
@@ -98,14 +100,19 @@ void QuicConnectivityProbingManager::CancelProbing(
void QuicConnectivityProbingManager::CancelProbingIfAny() {
if (is_running_) {
+ UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.StatelessResetDuringProbing",
+ stateless_reset_received_);
net_log_.AddEvent(
NetLogEventType::QUIC_CONNECTIVITY_PROBING_MANAGER_CANCEL_PROBING, [&] {
return NetLogProbingDestinationParams(network_, &peer_address_);
});
}
is_running_ = false;
+ if (socket_ != nullptr) {
+ socket_->GetLocalAddress(&last_self_address_);
+ }
network_ = NetworkChangeNotifier::kInvalidNetworkHandle;
- peer_address_ = quic::QuicSocketAddress();
+ stateless_reset_received_ = false;
socket_.reset();
writer_.reset();
reader_.reset();
@@ -198,6 +205,43 @@ void QuicConnectivityProbingManager::OnPacketReceived(
CancelProbingIfAny();
}
+bool QuicConnectivityProbingManager::ValidateStatelessReset(
+ const quic::QuicSocketAddress& self_address,
+ const quic::QuicSocketAddress& peer_address) {
+ IPEndPoint local_address;
+ if (!socket_) {
+ local_address = last_self_address_;
+ } else {
+ socket_->GetLocalAddress(&local_address);
+ }
+
+ if (local_address != ToIPEndPoint(self_address) ||
+ peer_address_ != peer_address) {
+ DVLOG(1) << "Probing lives at different path:";
+ DVLOG(1) << " peer_address: " << local_address.ToString();
+ DVLOG(1) << " self_address: " << self_address.ToString();
+ return false;
+ }
+
+ if (is_running_) {
+ stateless_reset_received_ = true;
+ } else {
+ UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.StatelessResetAfterProbingCancelled",
+ true);
+ }
+
+ net_log_.AddEvent(
+ NetLogEventType::
+ QUIC_CONNECTIVITY_PROBING_MANAGER_STATELESS_RESET_RECEIVED,
+ [&] {
+ return NetLogProbeReceivedParams(network_, &local_address,
+ &peer_address_);
+ });
+
+ NotifyDelegateProbeFailed();
+ return true;
+}
+
void QuicConnectivityProbingManager::SendConnectivityProbingPacket(
base::TimeDelta timeout) {
net_log_.AddEventWithInt64Params(
diff --git a/chromium/net/quic/quic_connectivity_probing_manager.h b/chromium/net/quic/quic_connectivity_probing_manager.h
index 9d4de8e25bb..d7e0a9c5067 100644
--- a/chromium/net/quic/quic_connectivity_probing_manager.h
+++ b/chromium/net/quic/quic_connectivity_probing_manager.h
@@ -7,6 +7,7 @@
#include "base/time/time.h"
#include "base/timer/timer.h"
+#include "net/base/ip_endpoint.h"
#include "net/base/net_export.h"
#include "net/log/net_log_with_source.h"
#include "net/quic/quic_chromium_packet_reader.h"
@@ -95,6 +96,11 @@ class NET_EXPORT_PRIVATE QuicConnectivityProbingManager
peer_address == peer_address_);
}
+ // Returns true if both |self_address| and |peer_address|
+ // match with the probing manager's socket address. Returns false otherwise.
+ bool ValidateStatelessReset(const quic::QuicSocketAddress& self_address,
+ const quic::QuicSocketAddress& peer_address);
+
private:
// Cancels undergoing probing.
void CancelProbingIfAny();
@@ -116,6 +122,8 @@ class NET_EXPORT_PRIVATE QuicConnectivityProbingManager
// if |is_running_| is true.
bool is_running_;
NetworkChangeNotifier::NetworkHandle network_;
+ // If |is_running| is false, |peer_address_| caches the peer address of the
+ // last probing path.
quic::QuicSocketAddress peer_address_;
std::unique_ptr<DatagramClientSocket> socket_;
@@ -129,6 +137,11 @@ class NET_EXPORT_PRIVATE QuicConnectivityProbingManager
base::SequencedTaskRunner* task_runner_;
+ // The cached local address set when probing is cancelled.
+ IPEndPoint last_self_address_;
+
+ bool stateless_reset_received_;
+
base::WeakPtrFactory<QuicConnectivityProbingManager> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(QuicConnectivityProbingManager);
};
diff --git a/chromium/net/quic/quic_connectivity_probing_manager_test.cc b/chromium/net/quic/quic_connectivity_probing_manager_test.cc
index 15bd236a20a..abce3d51857 100644
--- a/chromium/net/quic/quic_connectivity_probing_manager_test.cc
+++ b/chromium/net/quic/quic_connectivity_probing_manager_test.cc
@@ -378,6 +378,89 @@ TEST_F(QuicConnectivityProbingManagerTest, RetryProbingWithExponentailBackoff) {
EXPECT_EQ(0u, test_task_runner_->GetPendingTaskCount());
}
+TEST_F(QuicConnectivityProbingManagerTest, ProbingReceivedStatelessReset) {
+ int initial_timeout_ms = 100;
+ EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
+ .WillOnce(Return(true));
+ probing_manager_.StartProbing(
+ testNetworkHandle, testPeerAddress, std::move(socket_),
+ std::move(writer_), std::move(reader_),
+ base::TimeDelta::FromMilliseconds(initial_timeout_ms),
+ bound_test_net_log_.bound());
+ EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+
+ // Fast forward initial_timeout_ms, timeout the first connectivity probing
+ // packet, cause another probing packet to be sent with timeout set to
+ // 2 * initial_timeout_ms.
+ EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
+ .WillOnce(Return(true));
+ test_task_runner_->FastForwardBy(
+ base::TimeDelta::FromMilliseconds(initial_timeout_ms));
+ EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+
+ // Fast forward initial_timeout_ms, should be no-op.
+ EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
+ .Times(0);
+ test_task_runner_->FastForwardBy(
+ base::TimeDelta::FromMilliseconds(initial_timeout_ms));
+ EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+
+ EXPECT_CALL(session_, OnProbeFailed(testNetworkHandle, testPeerAddress))
+ .Times(1);
+ EXPECT_TRUE(
+ probing_manager_.ValidateStatelessReset(self_address_, testPeerAddress));
+ EXPECT_FALSE(session_.is_successfully_probed());
+ EXPECT_FALSE(
+ probing_manager_.IsUnderProbing(testNetworkHandle, testPeerAddress));
+ test_task_runner_->RunUntilIdle();
+}
+
+TEST_F(QuicConnectivityProbingManagerTest,
+ StatelessResetReceivedAfterProbingCancelled) {
+ int initial_timeout_ms = 100;
+
+ EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
+ .WillOnce(Return(true));
+ probing_manager_.StartProbing(
+ testNetworkHandle, testPeerAddress, std::move(socket_),
+ std::move(writer_), std::move(reader_),
+ base::TimeDelta::FromMilliseconds(initial_timeout_ms),
+ bound_test_net_log_.bound());
+ EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+
+ // Fast forward initial_timeout_ms, timeout the first connectivity probing
+ // packet, cause another probing packet to be sent with timeout set to
+ // 2 * initial_timeout_ms.
+ EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
+ .WillOnce(Return(true));
+ test_task_runner_->FastForwardBy(
+ base::TimeDelta::FromMilliseconds(initial_timeout_ms));
+ EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+
+ // Fast forward initial_timeout_ms, should be no-op.
+ EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
+ .Times(0);
+ test_task_runner_->FastForwardBy(
+ base::TimeDelta::FromMilliseconds(initial_timeout_ms));
+ EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+
+ // Request cancel probing, manager will no longer send connectivity probes.
+ EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, _)).Times(0);
+ EXPECT_CALL(session_, OnProbeFailed(_, _)).Times(0);
+ probing_manager_.CancelProbing(testNetworkHandle, testPeerAddress);
+ EXPECT_FALSE(
+ probing_manager_.IsUnderProbing(testNetworkHandle, testPeerAddress));
+
+ // Verify that the probing manager is still able to verify STATELESS_RESET
+ // received on the previous probing path.
+ EXPECT_TRUE(
+ probing_manager_.ValidateStatelessReset(self_address_, testPeerAddress));
+ EXPECT_FALSE(session_.is_successfully_probed());
+ EXPECT_FALSE(
+ probing_manager_.IsUnderProbing(testNetworkHandle, testPeerAddress));
+ test_task_runner_->RunUntilIdle();
+}
+
TEST_F(QuicConnectivityProbingManagerTest, CancelProbing) {
int initial_timeout_ms = 100;
diff --git a/chromium/net/quic/quic_context.h b/chromium/net/quic/quic_context.h
index 1f3ece3c0c7..e27af55433a 100644
--- a/chromium/net/quic/quic_context.h
+++ b/chromium/net/quic/quic_context.h
@@ -13,8 +13,8 @@
namespace net {
// Default QUIC version used in absence of any external configuration.
-constexpr quic::ParsedQuicVersion kDefaultSupportedQuicVersion{
- quic::PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_46};
+constexpr quic::ParsedQuicVersion kDefaultSupportedQuicVersion =
+ quic::ParsedQuicVersion::Q050();
// Returns a list containing only the current default version.
inline NET_EXPORT_PRIVATE quic::ParsedQuicVersionVector
@@ -165,6 +165,8 @@ struct NET_EXPORT QuicParams {
// The initial rtt that will be used in crypto handshake if no cached
// smoothed rtt is present.
base::TimeDelta initial_rtt_for_handshake;
+ // If true, QUIC with TLS will not try 0-RTT connection.
+ bool disable_tls_zero_rtt = false;
};
// QuicContext contains QUIC-related variables that are shared across all of the
@@ -187,6 +189,11 @@ class NET_EXPORT_PRIVATE QuicContext {
return params_.supported_versions;
}
+ void SetHelperForTesting(
+ std::unique_ptr<quic::QuicConnectionHelperInterface> helper) {
+ helper_ = std::move(helper);
+ }
+
private:
std::unique_ptr<quic::QuicConnectionHelperInterface> helper_;
diff --git a/chromium/net/quic/quic_flags_list.h b/chromium/net/quic/quic_flags_list.h
index e90d9ee34b2..8275a075e38 100644
--- a/chromium/net/quic/quic_flags_list.h
+++ b/chromium/net/quic/quic_flags_list.h
@@ -166,9 +166,6 @@ QUIC_FLAG(bool,
FLAGS_quic_reloadable_flag_quic_allow_client_enabled_bbr_v2,
false)
-// If true, will negotiate the ACK delay time.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_negotiate_ack_delay_time, true)
-
// If true, QuicFramer::WriteClientVersionNegotiationProbePacket uses
// length-prefixed connection IDs.
QUIC_FLAG(bool, FLAGS_quic_prober_uses_length_prefixed_connection_ids, false)
@@ -212,7 +209,7 @@ QUIC_FLAG(int32_t, FLAGS_quic_bbr2_default_probe_rtt_period_ms, 10000)
// The default loss threshold for QUIC BBRv2, should be a value
// between 0 and 1.
-QUIC_FLAG(double, FLAGS_quic_bbr2_default_loss_threshold, 0.3)
+QUIC_FLAG(double, FLAGS_quic_bbr2_default_loss_threshold, 0.02)
// The default minimum number of loss marking events to exit STARTUP.
QUIC_FLAG(int32_t, FLAGS_quic_bbr2_default_startup_full_loss_count, 8)
@@ -228,20 +225,26 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_q043, false)
QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_q046, false)
// If true, disable QUIC version Q048.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_q048, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_q048, true)
// If true, disable QUIC version Q049.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_q049, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_q049, true)
// If true, disable QUIC version Q050.
QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_q050, false)
-// If true, enable QUIC version T050.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_t050_v2, true)
-
// A testonly reloadable flag that will always default to false.
QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_testonly_default_false, false)
+// A testonly reloadable flag that will always default to true.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_testonly_default_true, true)
+
+// A testonly restart flag that will always default to false.
+QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_testonly_default_false, false)
+
+// A testonly restart flag that will always default to true.
+QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_testonly_default_true, true)
+
// In BBR, slow pacing rate if it is likely causing overshoot.
QUIC_FLAG(
bool,
@@ -263,20 +266,11 @@ QUIC_FLAG(bool,
// If true, use predictable grease settings identifiers and values.
QUIC_FLAG(bool, FLAGS_quic_enable_http3_grease_randomness, true)
-// If true, enable QUIC version h3-25.
-QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_enable_version_draft_25_v3,
- true)
+// If true, disable QUIC version h3-25.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_draft_25, false)
-// If true, enable QUIC version h3-27.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_draft_27, true)
-
-// If true, fix QUIC bandwidth sampler to avoid over estimating bandwidth in
-// the presence of ack aggregation.
-QUIC_FLAG(
- bool,
- FLAGS_quic_reloadable_flag_quic_avoid_overestimate_bandwidth_with_aggregation,
- true)
+// If true, disable QUIC version h3-27.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_draft_27, false)
// If true, QUIC BBRv2 to take ack height into account when calculating
// queuing_threshold in PROBE_UP.
@@ -285,38 +279,13 @@ QUIC_FLAG(
FLAGS_quic_reloadable_flag_quic_bbr2_add_ack_height_to_queueing_threshold,
true)
-// If true, quic::BandwidthSampler will start in application limited phase.
-QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_bw_sampler_app_limited_starting_value,
- true)
-
// If true, use idle network detector to detect handshake timeout and idle
// network timeout.
-QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_use_idle_network_detector,
- false)
-
-// If true, QUIC will enable connection options LRTT+BBQ2 by default.
-QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_bbr_default_exit_startup_on_loss,
- false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_idle_network_detector, true)
// If true, server push will be allowed in QUIC versions using HTTP/3.
QUIC_FLAG(bool, FLAGS_quic_enable_http3_server_push, false)
-// If true, disable QuicDispatcher workaround that replies to invalid QUIC
-// packets from the Android Conformance Test.
-QUIC_FLAG(
- bool,
- FLAGS_quic_reloadable_flag_quic_remove_android_conformance_test_workaround,
- true)
-
-// If true, lower the CWND gain in BBRv2 STARTUP to 2 when BBQ2 is in connection
-// options.
-QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_bbr2_lower_startup_cwnd_gain,
- true)
-
// The divisor that controls how often MAX_STREAMS frames are sent.
QUIC_FLAG(int32_t, FLAGS_quic_max_streams_window_divisor, 2)
@@ -333,25 +302,10 @@ QUIC_FLAG(bool,
FLAGS_quic_reloadable_flag_quic_bbr2_fewer_startup_round_trips,
false)
-// If true, remove draining_streams_ from QuicSession.
-QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_deprecate_draining_streams,
- true)
-
-// If true, break session/stream close loop.
-QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_break_session_stream_close_loop,
- true)
-
// Replace the usage of ConnectionData::encryption_level in
// quic_time_wait_list_manager with a new TimeWaitAction.
QUIC_FLAG(bool,
FLAGS_quic_restart_flag_quic_replace_time_wait_list_encryption_level,
- false)
-
-// If true, move Goolge QUIC stream accounting to LegacyQuicStreamIdManager.
-QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_stream_id_manager_handles_accounting,
true)
// If true, enables support for TLS resumption in QUIC.
@@ -360,58 +314,153 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_tls_resumption, false)
// When true, QUIC's BBRv2 ignores inflight_lo in PROBE_BW.
QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr2_ignore_inflight_lo, false)
-// If true, returns min_rtt in rtt_stats_ if it is available.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_use_available_min_rtt, true)
+// If true, do not change ACK in PostProcessAckFrame if an ACK has been queued.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_donot_change_queued_ack, true)
+
+// If true, reject IETF QUIC connections with invalid SNI.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_tls_enforce_valid_sni, true)
+
+// If true, support for IETF QUIC 0-rtt is enabled.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_zero_rtt_for_tls, true)
+
+// If true, default on PTO which unifies TLP + RTO loss recovery.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_default_on_pto, false)
-// If true, notify handshakers when connection closes.
+// When true, QUIC+TLS will not send nor parse the old-format Google-specific
+// transport parameters.
QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_notify_handshaker_on_connection_close,
+ FLAGS_quic_restart_flag_quic_google_transport_param_omit_old,
+ false)
+
+// When true, QUIC+TLS will send and parse the new-format Google-specific
+// transport parameters.
+QUIC_FLAG(bool,
+ FLAGS_quic_restart_flag_quic_google_transport_param_send_new,
true)
-// If true, for QUIC + TLS, change default encryption level when new encryption
-// key is available.
+// If true, check ShouldGeneratePacket for every crypto packet.
QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_change_default_encryption_level,
+ FLAGS_quic_reloadable_flag_quic_fix_checking_should_generate_packet,
true)
-// If true, do not change ACK in PostProcessAckFrame if an ACK has been queued.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_donot_change_queued_ack, false)
+// If true, notify stream ID manager even connection disconnects.
+QUIC_FLAG(
+ bool,
+ FLAGS_quic_reloadable_flag_quic_notify_stream_id_manager_when_disconnected,
+ true)
-// If true, reject IETF QUIC connections with invalid SNI.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_tls_enforce_valid_sni, false)
+// If true, return from QuicCryptoStream::WritePendingCryptoRetransmission after
+// partial writes.
+QUIC_FLAG(
+ bool,
+ FLAGS_quic_reloadable_flag_quic_fix_write_pending_crypto_retransmission,
+ true)
-// If true, update ack timeout upon receiving an retransmittable frame.
+// If true, clear last_inflight_packets_sent_time_ of a packet number space when
+// there is no bytes in flight.
QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_advance_ack_timeout_update,
- false)
+ FLAGS_quic_reloadable_flag_quic_fix_last_inflight_packets_sent_time,
+ true)
-// If true, only extend idle time on decryptable packets.
+// If true, QUIC will free writer-allocated packet buffer if writer->WritePacket
+// is not called.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_avoid_leak_writer_buffer, false)
+
+// If true, QuicConnection::SendAllPendingAcks will Update instead of Set the
+// ack alarm.
QUIC_FLAG(
bool,
- FLAGS_quic_reloadable_flag_quic_extend_idle_time_on_decryptable_packets,
- false)
+ FLAGS_quic_reloadable_flag_quic_update_ack_alarm_in_send_all_pending_acks,
+ true)
-// If true, support for IETF QUIC 0-rtt is enabled.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_zero_rtt_for_tls, false)
+// If true, the B2HI connection option limits reduction of inflight_hi to
+// (1-Beta)*CWND.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr2_limit_inflight_hi, false)
-// If true, default on PTO which unifies TLP + RTO loss recovery.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_default_on_pto, false)
+// When true, always check the amplification limit before writing, not just for
+// handshake packets.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_move_amplification_limit, true)
-// When true, QUIC+TLS will not send nor parse the old-format Google-specific
-// transport parameters.
+// If true, SendAllPendingAcks always send the earliest ACK.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_always_send_earliest_ack, true)
+
+// If true, check connection level flow control for send control stream and
+// qpack streams in QuicSession::WillingAndAbleToWrite.
QUIC_FLAG(bool,
- FLAGS_quic_restart_flag_quic_google_transport_param_omit_old,
+ FLAGS_quic_reloadable_flag_quic_fix_willing_and_able_to_write,
+ true)
+
+// If true, disable QUIC version h3-T050.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_t050, false)
+
+// If true, do not arm PTO on half RTT packets if they are the only ones in
+// flight.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_server_pto_timeout, true)
+
+// If true, default-enable 5RTO blachole detection.
+QUIC_FLAG(
+ bool,
+ FLAGS_quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection2,
+ true)
+
+// If true, session does not send duplicate MAX_STREAMS.
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_stop_sending_duplicate_max_streams,
+ true)
+
+// If true, enable QUIC version h3-29.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_draft_29, true)
+
+// If true, support HANDSHAKE_DONE frame in T050
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_support_handshake_done_in_t050,
+ true)
+
+// If true, save user agent into in QuicSession.
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_save_user_agent_in_quic_session,
false)
-// When true, QUIC+TLS will send and parse the new-format Google-specific
-// transport parameters.
+// When true, QUIC_CRYPTO versions of QUIC will not send the max ACK delay
+// unless it is configured to a non-default value.
QUIC_FLAG(bool,
- FLAGS_quic_restart_flag_quic_google_transport_param_send_new,
+ FLAGS_quic_reloadable_flag_quic_dont_send_max_ack_delay_if_default,
true)
-// If true, if a buffered MTU packet causes a write to return MSG_TOO_BIG, this
-// error will be ignored.
+// If true, remove the head of line blocking caused by an unprocessable packet
+// in the undecryptable packets list.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_undecryptable_packets, true)
+
+// If true, QUIC client only tries to retransmit data when 1-RTT key is
+// available.
QUIC_FLAG(
bool,
- FLAGS_quic_reloadable_flag_quic_ignore_msg_too_big_from_buffered_packets,
+ FLAGS_quic_reloadable_flag_quic_do_not_retransmit_immediately_on_zero_rtt_reject,
true)
+
+// If true, try to bundle INITIAL data when trying to send INITIAL ACK.
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_bundle_crypto_data_with_initial_ack,
+ true)
+
+// If true, do not use QuicUtil::IsBidirectionalStreamId() to determine gQUIC
+// stream type.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_gquic_stream_type, true)
+
+// When true, do not pad the QUIC_CRYPTO CHLO message itself. Note that the
+// packet containing the CHLO will still be padded.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_dont_pad_chlo, false)
+
+// If true, include MinPlaintextPacketSize when determine whether removing soft
+// limit for crypto frames.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_min_crypto_frame_size, true)
+
+// When true, QuicDispatcher supports decapsulation of Legacy Version
+// Encapsulation packets.
+QUIC_FLAG(
+ bool,
+ FLAGS_quic_reloadable_flag_quic_dispatcher_legacy_version_encapsulation,
+ false)
+
+// If true, update packet size when the first frame gets queued.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_update_packet_size, false)
diff --git a/chromium/net/quic/quic_http3_logger.cc b/chromium/net/quic/quic_http3_logger.cc
index c190156ff45..e93ff2987ea 100644
--- a/chromium/net/quic/quic_http3_logger.cc
+++ b/chromium/net/quic/quic_http3_logger.cc
@@ -9,10 +9,13 @@
#include <vector>
#include "base/metrics/histogram_macros.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
+#include "net/http/http_log_util.h"
#include "net/log/net_log_capture_mode.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_values.h"
+#include "net/spdy/spdy_log_util.h"
namespace net {
@@ -64,20 +67,19 @@ base::Value NetLogThreeIntParams(base::StringPiece name1,
return dict;
}
-base::Value NetLogHeadersToDict(const quic::QuicHeaderList& headers) {
- base::Value dict(base::Value::Type::DICTIONARY);
- for (auto header : headers) {
- dict.SetStringKey(header.first, header.second);
- }
- return dict;
-}
-
-base::Value NetLogHeadersToDict(const spdy::SpdyHeaderBlock& headers) {
- base::Value dict(base::Value::Type::DICTIONARY);
- for (auto header : headers) {
- dict.SetStringKey(header.first, header.second);
+base::ListValue ElideQuicHeaderListForNetLog(
+ const quic::QuicHeaderList& headers,
+ NetLogCaptureMode capture_mode) {
+ base::ListValue headers_list;
+ for (const auto& header : headers) {
+ base::StringPiece key = header.first;
+ base::StringPiece value = header.second;
+ headers_list.Append(NetLogStringValue(
+ base::StrCat({key, ": ",
+ ElideHeaderValueForNetLog(capture_mode, key.as_string(),
+ value.as_string())})));
}
- return dict;
+ return headers_list;
}
} // namespace
@@ -248,11 +250,13 @@ void QuicHttp3Logger::OnHeadersDecoded(quic::QuicStreamId stream_id,
return;
}
net_log_.AddEvent(
- NetLogEventType::HTTP3_HEADERS_DECODED, [stream_id, &headers] {
+ NetLogEventType::HTTP3_HEADERS_DECODED,
+ [stream_id, &headers](NetLogCaptureMode capture_mode) {
base::Value dict(base::Value::Type::DICTIONARY);
dict.SetKey("stream_id",
NetLogNumberValue(static_cast<uint64_t>(stream_id)));
- dict.SetKey("headers", NetLogHeadersToDict(headers));
+ dict.SetKey("headers",
+ ElideQuicHeaderListForNetLog(headers, capture_mode));
return dict;
});
}
@@ -279,16 +283,18 @@ void QuicHttp3Logger::OnPushPromiseDecoded(quic::QuicStreamId stream_id,
if (!net_log_.IsCapturing()) {
return;
}
- net_log_.AddEvent(NetLogEventType::HTTP3_PUSH_PROMISE_DECODED, [stream_id,
- push_id,
- &headers] {
- base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetKey("stream_id",
- NetLogNumberValue(static_cast<uint64_t>(stream_id)));
- dict.SetKey("push_id", NetLogNumberValue(static_cast<uint64_t>(push_id)));
- dict.SetKey("headers", NetLogHeadersToDict(headers));
- return dict;
- });
+ net_log_.AddEvent(
+ NetLogEventType::HTTP3_PUSH_PROMISE_DECODED,
+ [stream_id, push_id, &headers](NetLogCaptureMode capture_mode) {
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetKey("stream_id",
+ NetLogNumberValue(static_cast<uint64_t>(stream_id)));
+ dict.SetKey("push_id",
+ NetLogNumberValue(static_cast<uint64_t>(push_id)));
+ dict.SetKey("headers",
+ ElideQuicHeaderListForNetLog(headers, capture_mode));
+ return dict;
+ });
}
void QuicHttp3Logger::OnUnknownFrameReceived(
@@ -357,11 +363,13 @@ void QuicHttp3Logger::OnHeadersFrameSent(
return;
}
net_log_.AddEvent(
- NetLogEventType::HTTP3_HEADERS_SENT, [stream_id, &header_block] {
+ NetLogEventType::HTTP3_HEADERS_SENT,
+ [stream_id, &header_block](NetLogCaptureMode capture_mode) {
base::Value dict(base::Value::Type::DICTIONARY);
dict.SetKey("stream_id",
NetLogNumberValue(static_cast<uint64_t>(stream_id)));
- dict.SetKey("headers", NetLogHeadersToDict(header_block));
+ dict.SetKey("headers",
+ ElideSpdyHeaderBlockForNetLog(header_block, capture_mode));
return dict;
});
}
@@ -373,16 +381,18 @@ void QuicHttp3Logger::OnPushPromiseFrameSent(
if (!net_log_.IsCapturing()) {
return;
}
- net_log_.AddEvent(NetLogEventType::HTTP3_PUSH_PROMISE_SENT, [stream_id,
- push_id,
- &header_block] {
- base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetKey("stream_id",
- NetLogNumberValue(static_cast<uint64_t>(stream_id)));
- dict.SetKey("push_id", NetLogNumberValue(static_cast<uint64_t>(push_id)));
- dict.SetKey("headers", NetLogHeadersToDict(header_block));
- return dict;
- });
+ net_log_.AddEvent(
+ NetLogEventType::HTTP3_PUSH_PROMISE_SENT,
+ [stream_id, push_id, &header_block](NetLogCaptureMode capture_mode) {
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetKey("stream_id",
+ NetLogNumberValue(static_cast<uint64_t>(stream_id)));
+ dict.SetKey("push_id",
+ NetLogNumberValue(static_cast<uint64_t>(push_id)));
+ dict.SetKey("headers",
+ ElideSpdyHeaderBlockForNetLog(header_block, capture_mode));
+ return dict;
+ });
}
} // namespace net
diff --git a/chromium/net/quic/quic_http_stream.cc b/chromium/net/quic/quic_http_stream.cc
index 2107b89a840..5b21bb9e067 100644
--- a/chromium/net/quic/quic_http_stream.cc
+++ b/chromium/net/quic/quic_http_stream.cc
@@ -94,23 +94,26 @@ HttpResponseInfo::ConnectionInfo QuicHttpStream::ConnectionInfoFromQuicVersion(
case quic::QUIC_VERSION_46:
return HttpResponseInfo::CONNECTION_INFO_QUIC_46;
case quic::QUIC_VERSION_48:
- return quic_version.handshake_protocol == quic::PROTOCOL_TLS1_3
+ return quic_version.UsesTls()
? HttpResponseInfo::CONNECTION_INFO_QUIC_T048
: HttpResponseInfo::CONNECTION_INFO_QUIC_Q048;
case quic::QUIC_VERSION_49:
- return quic_version.handshake_protocol == quic::PROTOCOL_TLS1_3
+ return quic_version.UsesTls()
? HttpResponseInfo::CONNECTION_INFO_QUIC_T049
: HttpResponseInfo::CONNECTION_INFO_QUIC_Q049;
case quic::QUIC_VERSION_50:
- return quic_version.handshake_protocol == quic::PROTOCOL_TLS1_3
+ return quic_version.UsesTls()
? HttpResponseInfo::CONNECTION_INFO_QUIC_T050
: HttpResponseInfo::CONNECTION_INFO_QUIC_Q050;
case quic::QUIC_VERSION_IETF_DRAFT_25:
- DCHECK(quic_version.handshake_protocol == quic::PROTOCOL_TLS1_3);
+ DCHECK(quic_version.UsesTls());
return HttpResponseInfo::CONNECTION_INFO_QUIC_DRAFT_25;
case quic::QUIC_VERSION_IETF_DRAFT_27:
- DCHECK(quic_version.handshake_protocol == quic::PROTOCOL_TLS1_3);
+ DCHECK(quic_version.UsesTls());
return HttpResponseInfo::CONNECTION_INFO_QUIC_DRAFT_27;
+ case quic::QUIC_VERSION_IETF_DRAFT_29:
+ DCHECK(quic_version.UsesTls());
+ return HttpResponseInfo::CONNECTION_INFO_QUIC_DRAFT_29;
case quic::QUIC_VERSION_RESERVED_FOR_NEGOTIATION:
return HttpResponseInfo::CONNECTION_INFO_QUIC_999;
}
diff --git a/chromium/net/quic/quic_http_stream_test.cc b/chromium/net/quic/quic_http_stream_test.cc
index c5638861d8c..7432512b4d8 100644
--- a/chromium/net/quic/quic_http_stream_test.cc
+++ b/chromium/net/quic/quic_http_stream_test.cc
@@ -1111,7 +1111,7 @@ TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) {
// TODO(nharper): Figure out why this test does not send packets
// when TLS is used.
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
Initialize();
return;
@@ -1615,10 +1615,11 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
&spdy_request_headers_frame_length, {header, kUploadData}));
AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2));
- AddWrite(client_maker_.MakeRstPacket(
- packet_number++,
- /* include_version = */ true, stream_id_, quic::QUIC_STREAM_NO_ERROR,
- /* include_stop_sending_if_v99 = */ false));
+ AddWrite(client_maker_.MakeAckAndRstPacket(
+ packet_number++,
+ /* include_version = */ true, stream_id_, quic::QUIC_STREAM_NO_ERROR,
+ 4, 1, 1,
+ /* include_stop_sending_if_v99 = */ false));
} else {
AddWrite(ConstructRequestHeadersAndDataFramesPacket(
packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
diff --git a/chromium/net/quic/quic_http_utils.cc b/chromium/net/quic/quic_http_utils.cc
index 077bd50335e..1faf58cce2f 100644
--- a/chromium/net/quic/quic_http_utils.cc
+++ b/chromium/net/quic/quic_http_utils.cc
@@ -64,8 +64,9 @@ quic::ParsedQuicVersionVector FilterSupportedAltSvcVersions(
<< quic_alt_svc.protocol_id;
for (uint32_t quic_version : quic_alt_svc.version) {
- for (quic::ParsedQuicVersion supported : supported_versions) {
- if (supported.handshake_protocol == quic::PROTOCOL_QUIC_CRYPTO &&
+ for (const quic::ParsedQuicVersion& supported : supported_versions) {
+ if (supported.UsesQuicCrypto() &&
+ supported.SupportsGoogleAltSvcFormat() &&
static_cast<uint32_t>(supported.transport_version) == quic_version) {
supported_alt_svc_versions.push_back(supported);
RecordAltSvcFormat(GOOGLE_FORMAT);
diff --git a/chromium/net/quic/quic_http_utils_test.cc b/chromium/net/quic/quic_http_utils_test.cc
index d1609675277..34356cf2db1 100644
--- a/chromium/net/quic/quic_http_utils_test.cc
+++ b/chromium/net/quic/quic_http_utils_test.cc
@@ -11,9 +11,6 @@
#include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h"
#include "testing/gtest/include/gtest/gtest.h"
-using quic::ParsedQuicVersion;
-using quic::PROTOCOL_QUIC_CRYPTO;
-
namespace net {
namespace test {
@@ -45,20 +42,18 @@ TEST(QuicHttpUtilsTest, FilterSupportedAltSvcVersions) {
// finds the intersection of the two sets ... version C. Note that
// as QUIC versions are defined/undefined, the exact version numbers
// used may need to change. The actual version numbers are not
- // important.
+ // important. Note that FilterSupportedAltSvcVersions is only used
+ // for the old Google-specific Alt-Svc format which is now deprecated.
quic::ParsedQuicVersionVector supported_versions = {
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_48),
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_43),
+ quic::ParsedQuicVersion::Q050(),
+ quic::ParsedQuicVersion::Q043(),
};
- std::vector<uint32_t> alt_svc_versions_google = {quic::QUIC_VERSION_48,
- quic::QUIC_VERSION_46};
- std::vector<uint32_t> alt_svc_versions_ietf = {
- QuicVersionToQuicVersionLabel(quic::QUIC_VERSION_48),
- QuicVersionToQuicVersionLabel(quic::QUIC_VERSION_46)};
+ std::vector<uint32_t> alt_svc_versions_google = {
+ 33, quic::ParsedQuicVersion::Q043().transport_version};
quic::ParsedQuicVersionVector supported_alt_svc_versions = {
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_48)};
+ quic::ParsedQuicVersion::Q043()};
spdy::SpdyAltSvcWireFormat::AlternativeService altsvc;
altsvc.protocol_id = "quic";
diff --git a/chromium/net/quic/quic_network_transaction_unittest.cc b/chromium/net/quic/quic_network_transaction_unittest.cc
index 5dc3abdbe8c..e1068b88a76 100644
--- a/chromium/net/quic/quic_network_transaction_unittest.cc
+++ b/chromium/net/quic/quic_network_transaction_unittest.cc
@@ -38,6 +38,7 @@
#include "net/http/http_stream.h"
#include "net/http/http_stream_factory.h"
#include "net/http/http_transaction_test_util.h"
+#include "net/http/test_upload_data_stream_not_allow_http1.h"
#include "net/http/transport_security_state.h"
#include "net/log/net_log_event_type.h"
#include "net/log/test_net_log.h"
@@ -449,6 +450,16 @@ class QuicNetworkTransactionTest
}
std::unique_ptr<quic::QuicEncryptedPacket>
+ ConstructClientPriorityFramesPacket(
+ uint64_t packet_number,
+ bool should_include_version,
+ const std::vector<QuicTestPacketMaker::Http2StreamDependency>&
+ priority_frames) {
+ return client_maker_->MakeMultiplePriorityFramesPacket(
+ packet_number, should_include_version, priority_frames);
+ }
+
+ std::unique_ptr<quic::QuicEncryptedPacket>
ConstructClientAckAndPriorityFramesPacket(
uint64_t packet_number,
bool should_include_version,
@@ -462,6 +473,20 @@ class QuicNetworkTransactionTest
smallest_received, least_unacked, priority_frames);
}
+ std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckAndPriorityPacket(
+ uint64_t packet_number,
+ bool should_include_version,
+ uint64_t largest_received,
+ uint64_t smallest_received,
+ quic::QuicStreamId id,
+ quic::QuicStreamId parent_stream_id,
+ RequestPriority request_priority) {
+ return client_maker_->MakeAckAndPriorityPacket(
+ packet_number, should_include_version, largest_received,
+ smallest_received, id, parent_stream_id,
+ ConvertRequestPriorityToQuicPriority(request_priority));
+ }
+
// Uses default QuicTestPacketMaker.
spdy::SpdyHeaderBlock GetRequestHeaders(const std::string& method,
const std::string& scheme,
@@ -1723,7 +1748,8 @@ TEST_P(QuicNetworkTransactionTest, AlternativeServicesDifferentHost) {
}
TEST_P(QuicNetworkTransactionTest, DoNotUseQuicForUnsupportedVersion) {
- quic::ParsedQuicVersion unsupported_version = quic::UnsupportedQuicVersion();
+ quic::ParsedQuicVersion unsupported_version =
+ quic::ParsedQuicVersion::Unsupported();
// Add support for another QUIC version besides |version_|. Also find an
// unsupported version.
for (const quic::ParsedQuicVersion& version : quic::AllSupportedVersions()) {
@@ -1737,7 +1763,7 @@ TEST_P(QuicNetworkTransactionTest, DoNotUseQuicForUnsupportedVersion) {
break;
}
ASSERT_EQ(2u, supported_versions_.size());
- ASSERT_NE(quic::UnsupportedQuicVersion(), unsupported_version);
+ ASSERT_NE(quic::ParsedQuicVersion::Unsupported(), unsupported_version);
// Set up alternative service to use QUIC with a version that is not
// supported.
@@ -1816,10 +1842,10 @@ TEST_P(QuicNetworkTransactionTest, DoNotUseQuicForUnsupportedVersion) {
alt_svc_info_vector =
session_->http_server_properties()->GetAlternativeServiceInfos(
server, NetworkIsolationKey());
- // All PROTOCOL_QUIC_CRYPTO versions are sent in a single Alt-Svc entry,
- // therefore they aer accumulated in a single AlternativeServiceInfo, whereas
- // each PROTOCOL_TLS1_3 version has its own Alt-Svc entry and
- // AlternativeServiceInfo entry. Flatten to compare.
+ // Versions that support the legacy Google-specific Alt-Svc format are sent in
+ // a single Alt-Svc entry, therefore they are accumulated in a single
+ // AlternativeServiceInfo, whereas more recent versions all have their own
+ // Alt-Svc entry and AlternativeServiceInfo entry. Flatten to compare.
quic::ParsedQuicVersionVector alt_svc_negotiated_versions;
for (const auto& alt_svc_info : alt_svc_info_vector) {
EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol);
@@ -2177,7 +2203,8 @@ TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceWithVersionForQuic1) {
// Add support for another QUIC version besides |version_| on the client side.
// Also find a different version advertised by the server.
- quic::ParsedQuicVersion advertised_version_2 = quic::UnsupportedQuicVersion();
+ quic::ParsedQuicVersion advertised_version_2 =
+ quic::ParsedQuicVersion::Unsupported();
for (const quic::ParsedQuicVersion& version : quic::AllSupportedVersions()) {
if (version == version_)
continue;
@@ -2189,7 +2216,7 @@ TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceWithVersionForQuic1) {
break;
}
ASSERT_EQ(2u, supported_versions_.size());
- ASSERT_NE(quic::UnsupportedQuicVersion(), advertised_version_2);
+ ASSERT_NE(quic::ParsedQuicVersion::Unsupported(), advertised_version_2);
std::string QuicAltSvcWithVersionHeader =
base::StringPrintf("Alt-Svc: %s=\":443\", %s=\":443\"\r\n\r\n",
@@ -2251,23 +2278,15 @@ TEST_P(QuicNetworkTransactionTest,
// TestPacketMakers and the response.
// Find an alternative commonly supported version other than |version_|.
- quic::ParsedQuicVersion common_version_2 = quic::UnsupportedQuicVersion();
- if (version_.handshake_protocol == quic::PROTOCOL_QUIC_CRYPTO) {
- for (const quic::ParsedQuicVersion& version :
- quic::AllSupportedVersions()) {
- if (version == version_)
- continue;
+ quic::ParsedQuicVersion common_version_2 =
+ quic::ParsedQuicVersion::Unsupported();
+ for (const quic::ParsedQuicVersion& version : quic::AllSupportedVersions()) {
+ if (version != version_) {
common_version_2 = version;
break;
}
- } else if (version_.transport_version == quic::QUIC_VERSION_IETF_DRAFT_27) {
- common_version_2 = quic::ParsedQuicVersion(
- quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_IETF_DRAFT_25);
- } else {
- common_version_2 = quic::ParsedQuicVersion(
- quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_IETF_DRAFT_27);
}
- ASSERT_NE(quic::UnsupportedQuicVersion(), common_version_2);
+ ASSERT_NE(common_version_2, quic::ParsedQuicVersion::Unsupported());
// Setting up client's preference list: {|version_|, |common_version_2|}.
supported_versions_.clear();
@@ -2277,12 +2296,13 @@ TEST_P(QuicNetworkTransactionTest,
// Setting up server's Alt-Svc header in the following preference order:
// |common_version_2|, |version_|.
std::string QuicAltSvcWithVersionHeader;
- quic::ParsedQuicVersion picked_version = quic::UnsupportedQuicVersion();
- QuicAltSvcWithVersionHeader =
- "Alt-Svc: " + quic::AlpnForVersion(common_version_2) +
- "=\":443\"; ma=3600, " + quic::AlpnForVersion(version_) +
- "=\":443\"; ma=3600\r\n\r\n";
- picked_version = common_version_2; // Use server's preference.
+ quic::ParsedQuicVersion picked_version =
+ quic::ParsedQuicVersion::Unsupported();
+ QuicAltSvcWithVersionHeader =
+ "Alt-Svc: " + quic::AlpnForVersion(common_version_2) +
+ "=\":443\"; ma=3600, " + quic::AlpnForVersion(version_) +
+ "=\":443\"; ma=3600\r\n\r\n";
+ picked_version = common_version_2; // Use server's preference.
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
@@ -2534,10 +2554,10 @@ TEST_P(QuicNetworkTransactionTest,
const AlternativeServiceInfoVector alt_svc_info_vector =
session_->http_server_properties()->GetAlternativeServiceInfos(
https_server, NetworkIsolationKey());
- // However, all PROTOCOL_QUIC_CRYPTO versions are sent in a single Alt-Svc
- // entry, therefore they aer accumulated in a single AlternativeServiceInfo,
- // whereas each PROTOCOL_TLS1_3 version has its own Alt-Svc entry and
- // AlternativeServiceInfo entry. Flatten to compare.
+ // Versions that support the legacy Google-specific Alt-Svc format are sent in
+ // a single Alt-Svc entry, therefore they are accumulated in a single
+ // AlternativeServiceInfo, whereas more recent versions all have their own
+ // Alt-Svc entry and AlternativeServiceInfo entry. Flatten to compare.
quic::ParsedQuicVersionVector alt_svc_negotiated_versions;
for (const auto& alt_svc_info : alt_svc_info_vector) {
EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol);
@@ -2696,7 +2716,7 @@ TEST_P(QuicNetworkTransactionTest, GoAwayWithConnectionMigrationOnPortsOnly) {
// alternate network as well, QUIC is marked as broken and the brokenness will
// not expire when default network changes.
TEST_P(QuicNetworkTransactionTest, QuicFailsOnBothNetworksWhileTCPSucceeds) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 ||
+ if (version_.UsesTls() ||
GetQuicReloadableFlag(quic_use_idle_network_detector)) {
// QUIC with TLS1.3 handshake doesn't support 0-rtt.
// TODO(fayang): Add time driven idle network detection test.
@@ -2806,7 +2826,7 @@ TEST_P(QuicNetworkTransactionTest, QuicFailsOnBothNetworksWhileTCPSucceeds) {
// alternate network, QUIC is marked as broken. The brokenness will expire when
// the default network changes.
TEST_P(QuicNetworkTransactionTest, RetryOnAlternateNetworkWhileTCPSucceeds) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 ||
+ if (version_.UsesTls() ||
GetQuicReloadableFlag(quic_use_idle_network_detector)) {
// QUIC with TLS1.3 handshake doesn't support 0-rtt.
// TODO(fayang): Add time driven idle network detection test.
@@ -2928,7 +2948,7 @@ TEST_P(QuicNetworkTransactionTest, RetryOnAlternateNetworkWhileTCPSucceeds) {
// Much like above test, but verifies NetworkIsolationKeys are respected.
TEST_P(QuicNetworkTransactionTest,
RetryOnAlternateNetworkWhileTCPSucceedsWithNetworkIsolationKey) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 ||
+ if (version_.UsesTls() ||
GetQuicReloadableFlag(quic_use_idle_network_detector)) {
// QUIC with TLS1.3 handshake doesn't support 0-rtt.
// TODO(fayang): Add time driven idle network detection test.
@@ -3076,7 +3096,7 @@ TEST_P(QuicNetworkTransactionTest,
// before handshake is confirmed. If TCP doesn't succeed but QUIC on the
// alternative network succeeds, QUIC is not marked as broken.
TEST_P(QuicNetworkTransactionTest, RetryOnAlternateNetworkWhileTCPHanging) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 ||
+ if (version_.UsesTls() ||
GetQuicReloadableFlag(quic_use_idle_network_detector)) {
// QUIC with TLS1.3 handshake doesn't support 0-rtt.
// TODO(fayang): Add time driven idle network detection test.
@@ -3201,7 +3221,7 @@ TEST_P(QuicNetworkTransactionTest, RetryOnAlternateNetworkWhileTCPHanging) {
// Verify that if a QUIC connection times out, the QuicHttpStream will
// return QUIC_PROTOCOL_ERROR.
TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmed) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
// QUIC with TLS1.3 handshake doesn't support 0-rtt.
return;
}
@@ -3327,11 +3347,6 @@ TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmed) {
// Verify that if a QUIC protocol error occurs after the handshake is confirmed
// the request fails with QUIC_PROTOCOL_ERROR.
TEST_P(QuicNetworkTransactionTest, ProtocolErrorAfterHandshakeConfirmed) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
context_.params()->retry_without_alt_svc_on_quic_errors = false;
// The request will initially go out over QUIC.
MockQuicData quic_data(version_);
@@ -3355,10 +3370,13 @@ TEST_P(QuicNetworkTransactionTest, ProtocolErrorAfterHandshakeConfirmed) {
1, false, GetNthClientInitiatedBidirectionalStreamId(47),
quic::QUIC_STREAM_LAST_ERROR));
std::string quic_error_details = "Data for nonexistent stream";
- quic_data.AddWrite(SYNCHRONOUS,
- ConstructClientAckAndConnectionClosePacket(
- packet_num++, 1, 1, 1, quic::QUIC_INVALID_STREAM_ID,
- quic_error_details, quic::IETF_RST_STREAM));
+ quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientAckAndConnectionClosePacket(
+ packet_num++, 1, 1, 1,
+ version_.HasIetfQuicFrames() ? quic::QUIC_HTTP_STREAM_WRONG_DIRECTION
+ : quic::QUIC_INVALID_STREAM_ID,
+ quic_error_details, quic::IETF_RST_STREAM));
quic_data.AddSocketDataToFactory(&socket_factory_);
// In order for a new QUIC session to be established via alternate-protocol
@@ -3402,7 +3420,7 @@ TEST_P(QuicNetworkTransactionTest, ProtocolErrorAfterHandshakeConfirmed) {
// connection times out, then QUIC will be marked as broken and the request
// retried over TCP.
TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmedThenBroken2) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
// QUIC with TLS1.3 handshake doesn't support 0-rtt.
return;
}
@@ -3550,11 +3568,6 @@ TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmedThenBroken2) {
// retried over TCP and the QUIC will be marked as broken.
TEST_P(QuicNetworkTransactionTest,
ProtocolErrorAfterHandshakeConfirmedThenBroken) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
context_.params()->idle_connection_timeout = base::TimeDelta::FromSeconds(5);
// The request will initially go out over QUIC.
@@ -3580,10 +3593,13 @@ TEST_P(QuicNetworkTransactionTest,
1, false, GetNthClientInitiatedBidirectionalStreamId(47),
quic::QUIC_STREAM_LAST_ERROR));
std::string quic_error_details = "Data for nonexistent stream";
- quic_data.AddWrite(SYNCHRONOUS,
- ConstructClientAckAndConnectionClosePacket(
- packet_num++, 1, 1, 1, quic::QUIC_INVALID_STREAM_ID,
- quic_error_details, quic::IETF_RST_STREAM));
+ quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientAckAndConnectionClosePacket(
+ packet_num++, 1, 1, 1,
+ version_.HasIetfQuicFrames() ? quic::QUIC_HTTP_STREAM_WRONG_DIRECTION
+ : quic::QUIC_INVALID_STREAM_ID,
+ quic_error_details, quic::IETF_RST_STREAM));
quic_data.AddSocketDataToFactory(&socket_factory_);
// After that fails, it will be resent via TCP.
@@ -3648,7 +3664,7 @@ TEST_P(QuicNetworkTransactionTest,
// Much like above test, but verifies that NetworkIsolationKey is respected.
TEST_P(QuicNetworkTransactionTest,
ProtocolErrorAfterHandshakeConfirmedThenBrokenWithNetworkIsolationKey) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
// QUIC with TLS1.3 handshake doesn't support 0-rtt.
return;
}
@@ -3779,11 +3795,6 @@ TEST_P(QuicNetworkTransactionTest,
// request is reset from, then QUIC will be marked as broken and the request
// retried over TCP.
TEST_P(QuicNetworkTransactionTest, ResetAfterHandshakeConfirmedThenBroken) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
// The request will initially go out over QUIC.
MockQuicData quic_data(version_);
spdy::SpdyPriority priority =
@@ -3810,10 +3821,10 @@ TEST_P(QuicNetworkTransactionTest, ResetAfterHandshakeConfirmedThenBroken) {
quic::QUIC_HEADERS_TOO_LARGE));
if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(SYNCHRONOUS,
- ConstructClientDataPacket(
- packet_num++, GetQpackDecoderStreamId(), true, false,
- StreamCancellationQpackDecoderInstruction(0)));
+ quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckAndDataPacket(
+ packet_num++, true, GetQpackDecoderStreamId(), 1, 1, 1,
+ false, StreamCancellationQpackDecoderInstruction(0)));
}
quic_data.AddRead(ASYNC, OK);
@@ -4079,10 +4090,12 @@ TEST_P(QuicNetworkTransactionTest,
quic::QUIC_HEADERS_TOO_LARGE));
if (VersionUsesHttp3(version_.transport_version)) {
- mock_quic_data.AddWrite(
- SYNCHRONOUS, ConstructClientDataPacket(
- packet_num++, GetQpackDecoderStreamId(), true, false,
- StreamCancellationQpackDecoderInstruction(1)));
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientAckAndDataPacket(
+ packet_num++, /*include_version=*/true, GetQpackDecoderStreamId(),
+ 3, 2, 1,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(1)));
}
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
@@ -4992,7 +5005,7 @@ TEST_P(QuicNetworkTransactionTest, HungAlternativeService) {
}
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
// QUIC with TLS1.3 handshake doesn't support 0-rtt.
return;
}
@@ -5039,7 +5052,7 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
}
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
// QUIC with TLS1.3 handshake doesn't support 0-rtt.
return;
}
@@ -5117,11 +5130,6 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) {
}
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
MockQuicData mock_quic_data(version_);
int packet_num = 1;
client_maker_->SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -5181,11 +5189,6 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
}
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithTooEarlyResponse) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
uint64_t packet_number = 1;
MockQuicData mock_quic_data(version_);
client_maker_->SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -5282,11 +5285,6 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithTooEarlyResponse) {
}
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithMultipleTooEarlyResponse) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
uint64_t packet_number = 1;
MockQuicData mock_quic_data(version_);
client_maker_->SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -5339,7 +5337,7 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithMultipleTooEarlyResponse) {
SYNCHRONOUS,
ConstructClientAckAndDataPacket(
packet_number++, false, GetQpackDecoderStreamId(), 2, 1, 1, false,
- StreamCancellationQpackDecoderInstruction(1)));
+ StreamCancellationQpackDecoderInstruction(1, false)));
mock_quic_data.AddWrite(SYNCHRONOUS,
client_maker_->MakeRstPacket(
packet_number++, false,
@@ -5400,11 +5398,6 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithMultipleTooEarlyResponse) {
TEST_P(QuicNetworkTransactionTest,
LogGranularQuicErrorCodeOnQuicProtocolErrorLocal) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
context_.params()->retry_without_alt_svc_on_quic_errors = false;
MockQuicData mock_quic_data(version_);
int packet_num = 1;
@@ -5462,11 +5455,6 @@ TEST_P(QuicNetworkTransactionTest,
TEST_P(QuicNetworkTransactionTest,
LogGranularQuicErrorCodeOnQuicProtocolErrorRemote) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
context_.params()->retry_without_alt_svc_on_quic_errors = false;
MockQuicData mock_quic_data(version_);
int packet_num = 1;
@@ -5489,9 +5477,12 @@ TEST_P(QuicNetworkTransactionTest,
quic::QUIC_STREAM_LAST_ERROR));
std::string quic_error_details = "Data for nonexistent stream";
mock_quic_data.AddWrite(
- SYNCHRONOUS, ConstructClientAckAndConnectionClosePacket(
- packet_num++, 1, 1, 1, quic::QUIC_INVALID_STREAM_ID,
- quic_error_details, quic::IETF_RST_STREAM));
+ SYNCHRONOUS,
+ ConstructClientAckAndConnectionClosePacket(
+ packet_num++, 1, 1, 1,
+ version_.HasIetfQuicFrames() ? quic::QUIC_HTTP_STREAM_WRONG_DIRECTION
+ : quic::QUIC_INVALID_STREAM_ID,
+ quic_error_details, quic::IETF_RST_STREAM));
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
// The non-alternate protocol job needs to hang in order to guarantee that
@@ -5524,15 +5515,13 @@ TEST_P(QuicNetworkTransactionTest,
EXPECT_EQ(quic::QUIC_NO_ERROR, details.quic_connection_error);
trans.PopulateNetErrorDetails(&details);
- EXPECT_EQ(quic::QUIC_INVALID_STREAM_ID, details.quic_connection_error);
+ EXPECT_EQ(version_.HasIetfQuicFrames()
+ ? quic::QUIC_HTTP_STREAM_WRONG_DIRECTION
+ : quic::QUIC_INVALID_STREAM_ID,
+ details.quic_connection_error);
}
TEST_P(QuicNetworkTransactionTest, RstStreamErrorHandling) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
MockQuicData mock_quic_data(version_);
int packet_num = 1;
client_maker_->SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
@@ -5611,11 +5600,6 @@ TEST_P(QuicNetworkTransactionTest, RstStreamErrorHandling) {
}
TEST_P(QuicNetworkTransactionTest, RstStreamBeforeHeaders) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
context_.params()->retry_without_alt_svc_on_quic_errors = false;
MockQuicData mock_quic_data(version_);
int packet_num = 1;
@@ -5637,9 +5621,10 @@ TEST_P(QuicNetworkTransactionTest, RstStreamBeforeHeaders) {
if (VersionUsesHttp3(version_.transport_version)) {
mock_quic_data.AddWrite(
- SYNCHRONOUS, ConstructClientDataPacket(
- packet_num++, GetQpackDecoderStreamId(), true, false,
- StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ ConstructClientAckAndDataPacket(
+ packet_num++, false, GetQpackDecoderStreamId(), 1, 1, 1, false,
+ StreamCancellationQpackDecoderInstruction(0)));
}
mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
@@ -5810,7 +5795,7 @@ TEST_P(QuicNetworkTransactionTest, NoBrokenAlternateProtocolIfTcpFails) {
}
TEST_P(QuicNetworkTransactionTest, DelayTCPOnStartWithQuicSupportOnSameIP) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
// QUIC with TLS1.3 handshake doesn't support 0-rtt.
return;
}
@@ -5881,11 +5866,6 @@ TEST_P(QuicNetworkTransactionTest, DelayTCPOnStartWithQuicSupportOnSameIP) {
TEST_P(QuicNetworkTransactionTest,
DelayTCPOnStartWithQuicSupportOnDifferentIP) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // QUIC with TLS1.3 handshake doesn't support 0-rtt.
- return;
- }
-
// Tests that TCP job is delayed and QUIC job requires confirmation if QUIC
// was recently supported on a different IP address on start.
@@ -6031,7 +6011,7 @@ TEST_P(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
TEST_P(QuicNetworkTransactionTest,
FailedZeroRttBrokenAlternateProtocolWithNetworkIsolationKey) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
// QUIC with TLS1.3 handshake doesn't support 0-rtt.
return;
}
@@ -6656,38 +6636,52 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPush) {
1, GetNthClientInitiatedBidirectionalStreamId(0),
GetNthServerInitiatedUnidirectionalStreamId(0), false,
GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_));
- if ((client_headers_include_h2_stream_dependency_ &&
- version_.transport_version >= quic::QUIC_VERSION_43 &&
- !VersionUsesHttp3(version_.transport_version))) {
- mock_quic_data.AddWrite(
- SYNCHRONOUS,
- ConstructClientPriorityPacket(
- client_packet_number++, false,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
+ const bool should_send_priority_packet =
+ client_headers_include_h2_stream_dependency_ &&
+ !VersionUsesHttp3(version_.transport_version);
+ if (should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientAckAndPriorityPacket(
+ client_packet_number++, false,
+ /*largest_received=*/1, /*smallest_received=*/1,
+ GetNthServerInitiatedUnidirectionalStreamId(0),
+ GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
}
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
GetResponseHeaders("200 OK")));
- mock_quic_data.AddWrite(
- SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
+ if (!should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
+ }
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
3, GetNthServerInitiatedUnidirectionalStreamId(0), false,
false, GetResponseHeaders("200 OK")));
+ if (should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 3, 1, 1));
+ }
std::string header = ConstructDataHeader(6);
mock_quic_data.AddRead(
ASYNC, ConstructServerDataPacket(
4, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
header + "hello!"));
- mock_quic_data.AddWrite(
- SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 4, 3, 1));
+ if (!should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 4, 3, 1));
+ }
std::string header2 = ConstructDataHeader(10);
mock_quic_data.AddRead(
ASYNC, ConstructServerDataPacket(
5, GetNthServerInitiatedUnidirectionalStreamId(0), false, true,
header2 + "and hello!"));
+ if (should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 5, 3, 1));
+ }
if (!VersionUsesHttp3(version_.transport_version)) {
mock_quic_data.AddWrite(SYNCHRONOUS,
ConstructClientAckAndRstPacket(
@@ -6757,30 +6751,39 @@ TEST_P(QuicNetworkTransactionTest, CancelServerPushAfterConnectionClose) {
1, GetNthClientInitiatedBidirectionalStreamId(0),
GetNthServerInitiatedUnidirectionalStreamId(0), false,
GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_));
- if ((client_headers_include_h2_stream_dependency_ &&
- version_.transport_version >= quic::QUIC_VERSION_43 &&
- !VersionUsesHttp3(version_.transport_version))) {
- mock_quic_data.AddWrite(
- SYNCHRONOUS,
- ConstructClientPriorityPacket(
- client_packet_number++, false,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
+ const bool should_send_priority_packet =
+ client_headers_include_h2_stream_dependency_ &&
+ !VersionUsesHttp3(version_.transport_version);
+ if (should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientAckAndPriorityPacket(
+ client_packet_number++, false,
+ /*largest_received=*/1, /*smallest_received=*/1,
+ GetNthServerInitiatedUnidirectionalStreamId(0),
+ GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
}
// Response headers for first request.
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
GetResponseHeaders("200 OK")));
- // Client ACKs the response headers.
- mock_quic_data.AddWrite(
- SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
+ if (!should_send_priority_packet) {
+ // Client ACKs the response headers.
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
+ }
// Response body for first request.
std::string header = ConstructDataHeader(6);
mock_quic_data.AddRead(
ASYNC, ConstructServerDataPacket(
3, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
header + "hello!"));
+ if (should_send_priority_packet) {
+ // Client ACKs the response headers.
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 3, 1, 1));
+ }
// Write error for the third request.
mock_quic_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
@@ -7027,15 +7030,17 @@ TEST_P(QuicNetworkTransactionTest, RawHeaderSizeSuccessfullPushHeadersFirst) {
initial;
}
- if ((client_headers_include_h2_stream_dependency_ &&
- version_.transport_version >= quic::QUIC_VERSION_43 &&
- !VersionUsesHttp3(version_.transport_version))) {
- mock_quic_data.AddWrite(
- SYNCHRONOUS,
- ConstructClientPriorityPacket(
- client_packet_number++, false,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
+ const bool should_send_priority_packet =
+ client_headers_include_h2_stream_dependency_ &&
+ !VersionUsesHttp3(version_.transport_version);
+ if (should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientAckAndPriorityPacket(
+ client_packet_number++, false,
+ /*largest_received=*/1, /*smallest_received=*/1,
+ GetNthServerInitiatedUnidirectionalStreamId(0),
+ GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
}
const quic::QuicStreamOffset initial_offset = server_maker_.stream_offset(
@@ -7053,26 +7058,38 @@ TEST_P(QuicNetworkTransactionTest, RawHeaderSizeSuccessfullPushHeadersFirst) {
quic::QuicStreamOffset expected_raw_header_response_size =
final_offset - initial_offset;
- mock_quic_data.AddWrite(
- SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
+ if (!should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
+ }
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
3, GetNthServerInitiatedUnidirectionalStreamId(0), false,
false, GetResponseHeaders("200 OK")));
+ if (should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 3, 1, 1));
+ }
std::string header = ConstructDataHeader(20);
mock_quic_data.AddRead(
ASYNC, ConstructServerDataPacket(
4, GetNthServerInitiatedUnidirectionalStreamId(0), false, true,
header + "Pushed Resource Data"));
- mock_quic_data.AddWrite(
- SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 4, 3, 1));
+ if (!should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 4, 3, 1));
+ }
std::string header2 = ConstructDataHeader(18);
mock_quic_data.AddRead(
ASYNC, ConstructServerDataPacket(
5, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
header2 + "Main Resource Data"));
+ if (should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 5, 3, 1));
+ }
mock_quic_data.AddRead(ASYNC, ConstructServerConnectionClosePacket(6));
@@ -7709,48 +7726,70 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPushMatchesRequestWithBody) {
GetNthServerInitiatedUnidirectionalStreamId(0), false,
GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_));
- if ((client_headers_include_h2_stream_dependency_ &&
- version_.transport_version >= quic::QUIC_VERSION_43 &&
- !VersionUsesHttp3(version_.transport_version))) {
- mock_quic_data.AddWrite(
- SYNCHRONOUS,
- ConstructClientPriorityPacket(
- client_packet_number++, false,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
+ const bool should_send_priority_packet =
+ client_headers_include_h2_stream_dependency_ &&
+ !VersionUsesHttp3(version_.transport_version);
+ if (should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientAckAndPriorityPacket(
+ client_packet_number++, false,
+ /*largest_received=*/1, /*smallest_received=*/1,
+ GetNthServerInitiatedUnidirectionalStreamId(0),
+ GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
}
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
GetResponseHeaders("200 OK")));
- mock_quic_data.AddWrite(
- SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
+ if (!should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
+ }
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
3, GetNthServerInitiatedUnidirectionalStreamId(0), false,
false, GetResponseHeaders("200 OK")));
+ if (should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 3, 1, 1));
+ }
std::string header = ConstructDataHeader(6);
mock_quic_data.AddRead(
ASYNC, ConstructServerDataPacket(
4, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
header + "hello!"));
- mock_quic_data.AddWrite(
- SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 4, 3, 1));
+ if (!should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 4, 3, 1));
+ }
std::string header2 = ConstructDataHeader(10);
mock_quic_data.AddRead(
ASYNC, ConstructServerDataPacket(
5, GetNthServerInitiatedUnidirectionalStreamId(0), false, true,
header2 + "and hello!"));
+ if (should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 5, 3, 1));
+ }
// Because the matching request has a body, we will see the push
// stream get cancelled, and the matching request go out on the
// wire.
- mock_quic_data.AddWrite(SYNCHRONOUS,
- ConstructClientAckAndRstPacket(
- client_packet_number++,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED, 5, 5, 1));
+ if (should_send_priority_packet) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientRstPacket(client_packet_number++,
+ GetNthServerInitiatedUnidirectionalStreamId(0),
+ quic::QUIC_STREAM_CANCELLED));
+ } else {
+ mock_quic_data.AddWrite(SYNCHRONOUS,
+ ConstructClientAckAndRstPacket(
+ client_packet_number++,
+ GetNthServerInitiatedUnidirectionalStreamId(0),
+ quic::QUIC_STREAM_CANCELLED, 5, 5, 1));
+ }
const char kBody[] = "1";
std::string header3 = ConstructDataHeader(1);
if (!version_.HasIetfQuicFrames()) {
@@ -7839,30 +7878,28 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPushWithEmptyHostname) {
1, GetNthClientInitiatedBidirectionalStreamId(0),
GetNthServerInitiatedUnidirectionalStreamId(0), false,
std::move(pushed_request_headers), &server_maker_));
- mock_quic_data.AddWrite(
- SYNCHRONOUS,
- ConstructClientRstPacket(packet_num++,
- GetNthServerInitiatedUnidirectionalStreamId(0),
- quic::QUIC_INVALID_PROMISE_URL));
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientAckAndRstPacket(
+ packet_num++, GetNthServerInitiatedUnidirectionalStreamId(0),
+ quic::QUIC_INVALID_PROMISE_URL, 1, 1, 1));
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
GetResponseHeaders("200 OK")));
- mock_quic_data.AddWrite(SYNCHRONOUS,
- ConstructClientAckPacket(packet_num++, 2, 1, 1));
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
3, GetNthServerInitiatedUnidirectionalStreamId(0), false,
false, GetResponseHeaders("200 OK")));
+ mock_quic_data.AddWrite(SYNCHRONOUS,
+ ConstructClientAckPacket(packet_num++, 3, 1, 1));
std::string header = ConstructDataHeader(6);
mock_quic_data.AddRead(
ASYNC, ConstructServerDataPacket(
4, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
header + "hello!"));
- mock_quic_data.AddWrite(SYNCHRONOUS,
- ConstructClientAckPacket(packet_num++, 4, 3, 1));
mock_quic_data.AddRead(ASYNC, 0);
mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -9120,8 +9157,7 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPushUpdatesPriority) {
// Only run this test if HTTP/2 stream dependency info is sent by client (sent
// in HEADERS frames for requests and PRIORITY frames).
- if (version_.transport_version < quic::QUIC_VERSION_43 ||
- !client_headers_include_h2_stream_dependency_) {
+ if (!client_headers_include_h2_stream_dependency_) {
return;
}
@@ -9199,31 +9235,33 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPushUpdatesPriority) {
ConstructServerPushPromisePacket(
5, client_stream_0, push_stream_1, false,
GetRequestHeaders("GET", "https", "/pushed_1.jpg"), &server_maker_));
- mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientPriorityPacket(
- packet_num++, false, push_stream_1,
- push_stream_0, DEFAULT_PRIORITY));
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckAndPriorityPacket(
+ packet_num++, false,
+ /*largest_received=*/5, /*smallest_received=*/4,
+ push_stream_1, push_stream_0, DEFAULT_PRIORITY));
// Server sends the response headers for the two push promises.
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
6, push_stream_0, false, false, GetResponseHeaders("200 OK")));
- mock_quic_data.AddWrite(SYNCHRONOUS,
- ConstructClientAckPacket(packet_num++, 6, 5, 1));
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
7, push_stream_1, false, false, GetResponseHeaders("200 OK")));
+ mock_quic_data.AddWrite(SYNCHRONOUS,
+ ConstructClientAckPacket(packet_num++, 7, 5, 1));
// Request for "pushed_0.jpg" matches |push_stream_0|. |push_stream_0|'s
// priority updates to match the request's priority. Client sends PRIORITY
// frames to inform server of new HTTP/2 stream dependencies.
- mock_quic_data.AddWrite(
- SYNCHRONOUS,
- ConstructClientAckAndPriorityFramesPacket(
- packet_num++, false, 7, 7, 1,
- {{push_stream_1, client_stream_2,
- ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY)},
- {push_stream_0, client_stream_0,
- ConvertRequestPriorityToQuicPriority(HIGHEST)}}));
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientPriorityFramesPacket(
+ packet_num++, false,
+ {{push_stream_1, client_stream_2,
+ ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY)},
+ {push_stream_0, client_stream_0,
+ ConvertRequestPriorityToQuicPriority(HIGHEST)}}));
// Server sends data for the three requests and the two push promises.
std::string header = ConstructDataHeader(8);
@@ -9730,5 +9768,260 @@ TEST_P(QuicNetworkTransactionTest, NetworkIsolationTunnel) {
EXPECT_TRUE(mock_quic_data[1]->AllWriteDataConsumed());
}
+TEST_P(QuicNetworkTransactionTest, AllowHTTP1FalseProhibitsH1) {
+ MockRead http_reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING),
+ MockRead(ASYNC, OK)};
+ StaticSocketDataProvider http_data(http_reads, base::span<MockWrite>());
+ socket_factory_.AddSocketDataProvider(&http_data);
+ AddCertificate(&ssl_data_);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+
+ CreateSession();
+
+ request_.method = "POST";
+ UploadDataStreamNotAllowHTTP1 upload_data("");
+ request_.upload_data_stream = &upload_data;
+
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
+ TestCompletionCallback callback;
+ int rv = trans.Start(&request_, callback.callback(), net_log_.bound());
+ EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+ EXPECT_THAT(callback.WaitForResult(), IsError(ERR_H2_OR_QUIC_REQUIRED));
+}
+
+// Confirm mock class UploadDataStreamNotAllowHTTP1 can upload content over
+// QUIC.
+TEST_P(QuicNetworkTransactionTest, AllowHTTP1MockTest) {
+ context_.params()->origins_to_force_quic_on.insert(
+ HostPortPair::FromString("mail.example.org:443"));
+
+ MockQuicData mock_quic_data(version_);
+ int write_packet_index = 1;
+ if (VersionUsesHttp3(version_.transport_version)) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructInitialSettingsPacket(write_packet_index++));
+ }
+ const std::string upload_content = "foo";
+ if (!version_.HasIetfQuicFrames()) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientRequestHeadersAndDataFramesPacket(
+ write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
+ true, true, DEFAULT_PRIORITY,
+ GetRequestHeaders("POST", "https", "/"), 0, nullptr,
+ {upload_content}));
+ } else {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientRequestHeadersAndDataFramesPacket(
+ write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
+ true, true, DEFAULT_PRIORITY,
+ GetRequestHeaders("POST", "https", "/"), 0, nullptr,
+ {ConstructDataHeader(upload_content.length()), upload_content}));
+ }
+ mock_quic_data.AddRead(
+ ASYNC, ConstructServerResponseHeadersPacket(
+ 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
+ GetResponseHeaders("200 OK")));
+
+ std::string header2 = ConstructDataHeader(6);
+ mock_quic_data.AddRead(
+ ASYNC, ConstructServerDataPacket(
+ 2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
+ header2 + "hello!"));
+
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(write_packet_index++, 2, 1, 1));
+
+ mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
+ mock_quic_data.AddRead(ASYNC, 0); // EOF
+ mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+
+ // The non-alternate protocol job needs to hang in order to guarantee that
+ // the alternate-protocol job will "win".
+ AddHangingNonAlternateProtocolSocketData();
+
+ CreateSession();
+ request_.method = "POST";
+ UploadDataStreamNotAllowHTTP1 upload_data(upload_content);
+ request_.upload_data_stream = &upload_data;
+
+ SendRequestAndExpectQuicResponse("hello!");
+}
+
+TEST_P(QuicNetworkTransactionTest, AllowHTTP1UploadPauseAndResume) {
+ context_.params()->origins_to_force_quic_on.insert(
+ HostPortPair::FromString("mail.example.org:443"));
+
+ MockQuicData mock_quic_data(version_);
+ mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // Hanging read
+ int write_packet_index = 1;
+ mock_quic_data.AddWrite(
+ ASYNC, client_maker_->MakeDummyCHLOPacket(write_packet_index++));
+ client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructInitialSettingsPacket(write_packet_index++));
+ }
+ const std::string upload_content = "foo";
+ if (!version_.HasIetfQuicFrames()) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientRequestHeadersAndDataFramesPacket(
+ write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
+ true, true, DEFAULT_PRIORITY,
+ GetRequestHeaders("POST", "https", "/"), 0, nullptr,
+ {upload_content}));
+ } else {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientRequestHeadersAndDataFramesPacket(
+ write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
+ true, true, DEFAULT_PRIORITY,
+ GetRequestHeaders("POST", "https", "/"), 0, nullptr,
+ {ConstructDataHeader(upload_content.length()), upload_content}));
+ }
+ mock_quic_data.AddRead(
+ SYNCHRONOUS, ConstructServerResponseHeadersPacket(
+ 1, GetNthClientInitiatedBidirectionalStreamId(0), false,
+ false, GetResponseHeaders("200 OK")));
+ std::string header2 = ConstructDataHeader(6);
+ mock_quic_data.AddRead(
+ SYNCHRONOUS, ConstructServerDataPacket(
+ 2, GetNthClientInitiatedBidirectionalStreamId(0), false,
+ true, header2 + "hello!"));
+
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(write_packet_index++, 2, 1, 1));
+ mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
+ mock_quic_data.AddRead(ASYNC, 0); // EOF
+ mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+ SequencedSocketData* socket_data = mock_quic_data.GetSequencedSocketData();
+
+ CreateSession();
+
+ AddQuicAlternateProtocolMapping(
+ MockCryptoClientStream::COLD_START_WITH_CHLO_SENT);
+
+ // Set up request.
+ request_.method = "POST";
+ UploadDataStreamNotAllowHTTP1 upload_data(upload_content);
+ request_.upload_data_stream = &upload_data;
+
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
+ TestCompletionCallback callback;
+ int rv = trans.Start(&request_, callback.callback(), net_log_.bound());
+ EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+ base::RunLoop().RunUntilIdle();
+ // Resume QUIC job
+ crypto_client_stream_factory_.last_stream()
+ ->NotifySessionOneRttKeyAvailable();
+ socket_data->Resume();
+
+ base::RunLoop().RunUntilIdle();
+ CheckResponseData(&trans, "hello!");
+}
+
+TEST_P(QuicNetworkTransactionTest, AllowHTTP1UploadFailH1AndResumeQuic) {
+ // This test confirms failed main job should not bother quic job.
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"), MockRead(kQuicAlternativeServiceHeader),
+ MockRead("1.1 Body"),
+ MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+ MockRead(ASYNC, OK)};
+ StaticSocketDataProvider http_data(http_reads, base::span<MockWrite>());
+ socket_factory_.AddSocketDataProvider(&http_data);
+ AddCertificate(&ssl_data_);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+
+ MockQuicData mock_quic_data(version_);
+ mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // Hanging read
+ int write_packet_index = 1;
+ mock_quic_data.AddWrite(
+ ASYNC, client_maker_->MakeDummyCHLOPacket(write_packet_index++));
+ client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructInitialSettingsPacket(write_packet_index++));
+ }
+ const std::string upload_content = "foo";
+ if (!version_.HasIetfQuicFrames()) {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientRequestHeadersAndDataFramesPacket(
+ write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
+ true, true, DEFAULT_PRIORITY,
+ GetRequestHeaders("POST", "https", "/"), 0, nullptr,
+ {upload_content}));
+ } else {
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientRequestHeadersAndDataFramesPacket(
+ write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
+ true, true, DEFAULT_PRIORITY,
+ GetRequestHeaders("POST", "https", "/"), 0, nullptr,
+ {ConstructDataHeader(upload_content.length()), upload_content}));
+ }
+ mock_quic_data.AddRead(
+ SYNCHRONOUS, ConstructServerResponseHeadersPacket(
+ 1, GetNthClientInitiatedBidirectionalStreamId(0), false,
+ false, GetResponseHeaders("200 OK")));
+ std::string header = ConstructDataHeader(6);
+ mock_quic_data.AddRead(
+ SYNCHRONOUS, ConstructServerDataPacket(
+ 2, GetNthClientInitiatedBidirectionalStreamId(0), false,
+ true, header + "hello!"));
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS, ConstructClientAckPacket(write_packet_index++, 2, 1, 1));
+ mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
+ mock_quic_data.AddRead(ASYNC, 0); // EOF
+ mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+ SequencedSocketData* socket_data = mock_quic_data.GetSequencedSocketData();
+
+ // This packet won't be read because AllowHTTP1:false doesn't allow H/1
+ // connection.
+ MockRead http_reads2[] = {MockRead("HTTP/1.1 200 OK\r\n")};
+ StaticSocketDataProvider http_data2(http_reads2, base::span<MockWrite>());
+ socket_factory_.AddSocketDataProvider(&http_data2);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+
+ CreateSession();
+
+ // Send the first request via TCP and set up alternative service (QUIC) for
+ // the origin.
+ SendRequestAndExpectHttpResponse("1.1 Body");
+
+ // Settings to resume main H/1 job quickly while pausing quic job.
+ AddQuicAlternateProtocolMapping(
+ MockCryptoClientStream::COLD_START_WITH_CHLO_SENT);
+ ServerNetworkStats stats1;
+ stats1.srtt = base::TimeDelta::FromMicroseconds(10);
+ http_server_properties_->SetServerNetworkStats(
+ url::SchemeHostPort(request_.url), NetworkIsolationKey(), stats1);
+
+ // Set up request.
+ request_.method = "POST";
+ UploadDataStreamNotAllowHTTP1 upload_data(upload_content);
+ request_.upload_data_stream = &upload_data;
+
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
+ TestCompletionCallback callback;
+ int rv = trans.Start(&request_, callback.callback(), net_log_.bound());
+ EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+ // Confirm TCP job was resumed.
+ // We can not check its failure because HttpStreamFactory::JobController.
+ // main_job_net_error is not exposed.
+ while (socket_factory_.mock_data().next_index() < 3u)
+ base::RunLoop().RunUntilIdle();
+ // Resume QUIC job.
+ crypto_client_stream_factory_.last_stream()
+ ->NotifySessionOneRttKeyAvailable();
+ socket_data->Resume();
+ base::RunLoop().RunUntilIdle();
+ CheckResponseData(&trans, "hello!");
+}
+
+// TODO(yoichio): Add the TCP job reuse case. See crrev.com/c/2174099.
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_proxy_client_socket.cc b/chromium/net/quic/quic_proxy_client_socket.cc
index 2d87902522c..dad704704ac 100644
--- a/chromium/net/quic/quic_proxy_client_socket.cc
+++ b/chromium/net/quic/quic_proxy_client_socket.cc
@@ -458,25 +458,7 @@ int QuicProxyClientSocket::ProcessResponseHeaders(
DLOG(WARNING) << "Invalid headers";
return ERR_QUIC_PROTOCOL_ERROR;
}
- // Populate |connect_timing_| when response headers are received. This
- // should take care of 0-RTT where request is sent before handshake is
- // confirmed.
- connect_timing_ = session_->GetConnectTiming();
return OK;
}
-bool QuicProxyClientSocket::GetLoadTimingInfo(
- LoadTimingInfo* load_timing_info) const {
- bool is_first_stream = stream_->IsFirstStream();
- if (stream_)
- is_first_stream = stream_->IsFirstStream();
- if (is_first_stream) {
- load_timing_info->socket_reused = false;
- load_timing_info->connect_timing = connect_timing_;
- } else {
- load_timing_info->socket_reused = true;
- }
- return true;
-}
-
} // namespace net
diff --git a/chromium/net/quic/quic_proxy_client_socket.h b/chromium/net/quic/quic_proxy_client_socket.h
index 723b6670401..a65d0cc4bbb 100644
--- a/chromium/net/quic/quic_proxy_client_socket.h
+++ b/chromium/net/quic/quic_proxy_client_socket.h
@@ -10,7 +10,6 @@
#include <string>
#include "net/base/completion_once_callback.h"
-#include "net/base/load_timing_info.h"
#include "net/base/proxy_server.h"
#include "net/http/proxy_client_socket.h"
#include "net/quic/quic_chromium_client_session.h"
@@ -109,8 +108,6 @@ class NET_EXPORT_PRIVATE QuicProxyClientSocket : public ProxyClientSocket {
int DoReadReply();
int DoReadReplyComplete(int result);
- bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const;
-
State next_state_;
// Handle to the QUIC Stream that this sits on top of.
@@ -148,9 +145,6 @@ class NET_EXPORT_PRIVATE QuicProxyClientSocket : public ProxyClientSocket {
std::string user_agent_;
- // Session connect timing info.
- LoadTimingInfo::ConnectTiming connect_timing_;
-
const NetLogWithSource net_log_;
// The default weak pointer factory.
diff --git a/chromium/net/quic/quic_proxy_client_socket_unittest.cc b/chromium/net/quic/quic_proxy_client_socket_unittest.cc
index 045cfeec480..0129108e9fa 100644
--- a/chromium/net/quic/quic_proxy_client_socket_unittest.cc
+++ b/chromium/net/quic/quic_proxy_client_socket_unittest.cc
@@ -187,9 +187,7 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>,
IPAddress ip(192, 0, 2, 33);
peer_addr_ = IPEndPoint(ip, 443);
clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- quic::QuicEnableVersion(version_);
- }
+ quic::QuicEnableVersion(version_);
}
void SetUp() override {}
diff --git a/chromium/net/quic/quic_session_key.cc b/chromium/net/quic/quic_session_key.cc
index b2393c547a7..ff1a8f524fc 100644
--- a/chromium/net/quic/quic_session_key.cc
+++ b/chromium/net/quic/quic_session_key.cc
@@ -30,7 +30,12 @@ QuicSessionKey::QuicSessionKey(const std::string& host,
const NetworkIsolationKey& network_isolation_key,
bool disable_secure_dns)
: QuicSessionKey(
- quic::QuicServerId(host, port, privacy_mode == PRIVACY_MODE_ENABLED),
+ // TODO(crbug.com/1103350): Handle non-boolean privacy modes.
+ quic::QuicServerId(
+ host,
+ port,
+ privacy_mode == PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS ||
+ privacy_mode == PRIVACY_MODE_ENABLED),
socket_tag,
network_isolation_key,
disable_secure_dns) {}
diff --git a/chromium/net/quic/quic_stream_factory.cc b/chromium/net/quic/quic_stream_factory.cc
index 3358bd3d4be..6361607eb00 100644
--- a/chromium/net/quic/quic_stream_factory.cc
+++ b/chromium/net/quic/quic_stream_factory.cc
@@ -45,6 +45,7 @@
#include "net/quic/quic_chromium_connection_helper.h"
#include "net/quic/quic_chromium_packet_reader.h"
#include "net/quic/quic_chromium_packet_writer.h"
+#include "net/quic/quic_client_session_cache.h"
#include "net/quic/quic_context.h"
#include "net/quic/quic_crypto_client_stream_factory.h"
#include "net/quic/quic_http_stream.h"
@@ -118,39 +119,31 @@ base::Value NetLogQuicStreamFactoryJobParams(
return std::move(dict);
}
-// Helper class that is used to log a connection migration event.
-class ScopedConnectionMigrationEventLog {
- public:
- ScopedConnectionMigrationEventLog(NetLog* net_log, const char* trigger)
- : net_log_(NetLogWithSource::Make(
- net_log,
- NetLogSourceType::QUIC_CONNECTION_MIGRATION)) {
- net_log_.BeginEventWithStringParams(
- NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, "trigger",
- trigger);
- }
-
- ~ScopedConnectionMigrationEventLog() {
- net_log_.EndEvent(NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED);
+std::string QuicPlatformNotificationToString(
+ QuicPlatformNotification notification) {
+ switch (notification) {
+ case NETWORK_CONNECTED:
+ return "OnNetworkConnected";
+ case NETWORK_MADE_DEFAULT:
+ return "OnNetworkMadeDefault";
+ case NETWORK_DISCONNECTED:
+ return "OnNetworkDisconnected";
+ case NETWORK_SOON_TO_DISCONNECT:
+ return "OnNetworkSoonToDisconnect";
+ case NETWORK_IP_ADDRESS_CHANGED:
+ return "OnIPAddressChanged";
+ default:
+ QUIC_NOTREACHED();
+ break;
}
-
- const NetLogWithSource& net_log() { return net_log_; }
-
- private:
- const NetLogWithSource net_log_;
-};
+ return "InvalidNotification";
+}
void HistogramCreateSessionFailure(enum CreateSessionFailure error) {
UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error,
CREATION_ERROR_MAX);
}
-void LogPlatformNotificationInHistogram(
- enum QuicPlatformNotification notification) {
- UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.PlatformNotification",
- notification, NETWORK_NOTIFICATION_MAX);
-}
-
void LogConnectionIpPooling(bool pooled) {
UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ConnectionIpPooled", pooled);
}
@@ -225,8 +218,9 @@ class QuicStreamFactory::QuicCryptoClientConfigOwner {
public:
QuicCryptoClientConfigOwner(
std::unique_ptr<quic::ProofVerifier> proof_verifier,
+ std::unique_ptr<QuicClientSessionCache> session_cache,
QuicStreamFactory* quic_stream_factory)
- : config_(std::move(proof_verifier)),
+ : config_(std::move(proof_verifier), std::move(session_cache)),
quic_stream_factory_(quic_stream_factory) {
DCHECK(quic_stream_factory_);
}
@@ -390,8 +384,11 @@ class QuicStreamFactory::Job {
if (session_) {
QuicChromiumClientSession* session = session_;
session_ = nullptr;
+ // Use ERR_FAILED instead of ERR_ABORTED out of paranoia - ERR_ABORTED
+ // should only be used when the next layer up cancels a request, and has
+ // special semantic meaning for some consumers when they see it.
session->CloseSessionOnErrorLater(
- ERR_ABORTED, quic::QUIC_STALE_CONNECTION_CANCELLED,
+ ERR_FAILED, quic::QUIC_STALE_CONNECTION_CANCELLED,
quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
}
@@ -769,7 +766,7 @@ int QuicStreamFactory::Job::DoConnect() {
NetLogEventType::QUIC_STREAM_FACTORY_JOB_CONNECT, NetLogEventPhase::BEGIN,
"require_confirmation", require_confirmation);
- DCHECK_NE(quic_version_.transport_version, quic::QUIC_VERSION_UNSUPPORTED);
+ DCHECK_NE(quic_version_, quic::ParsedQuicVersion::Unsupported());
int rv = factory_->CreateSession(
key_, quic_version_, cert_verify_flags_, require_confirmation,
resolve_host_request_->GetAddressResults().value(),
@@ -956,7 +953,7 @@ int QuicStreamRequest::Request(
NetErrorDetails* net_error_details,
CompletionOnceCallback failed_on_default_network_callback,
CompletionOnceCallback callback) {
- DCHECK_NE(quic_version.transport_version, quic::QUIC_VERSION_UNSUPPORTED);
+ DCHECK_NE(quic_version, quic::ParsedQuicVersion::Unsupported());
DCHECK(net_error_details);
DCHECK(callback_.is_null());
DCHECK(host_resolution_callback_.is_null());
@@ -1106,6 +1103,7 @@ QuicStreamFactory::QuicStreamFactory(
need_to_check_persisted_supports_quic_(true),
prefer_aes_gcm_recorded_(false),
num_push_streams_created_(0),
+ connectivity_monitor_(default_network_),
tick_clock_(nullptr),
task_runner_(nullptr),
ssl_config_service_(ssl_config_service),
@@ -1114,6 +1112,8 @@ QuicStreamFactory::QuicStreamFactory(
features::kPartitionHttpServerPropertiesByNetworkIsolationKey)) {
DCHECK(transport_security_state_);
DCHECK(http_server_properties_);
+ if (params_.disable_tls_zero_rtt)
+ SetQuicReloadableFlag(quic_enable_zero_rtt_for_tls, false);
InitializeMigrationOptions();
}
@@ -1174,7 +1174,7 @@ int QuicStreamFactory::Create(const QuicSessionKey& session_key,
QuicStreamRequest* request) {
if (clock_skew_detector_.ClockSkewDetected(base::TimeTicks::Now(),
base::Time::Now())) {
- MarkAllActiveSessionsGoingAway();
+ MarkAllActiveSessionsGoingAway(kClockSkewDetected);
}
DCHECK(HostPortPair(session_key.server_id().host(),
session_key.server_id().port())
@@ -1308,7 +1308,6 @@ void QuicStreamFactory::OnSessionGoingAway(QuicChromiumClientSession* session) {
void QuicStreamFactory::OnSessionClosed(QuicChromiumClientSession* session) {
DCHECK_EQ(0u, session->GetNumActiveStreams());
OnSessionGoingAway(session);
-
for (const auto& iter : active_jobs_) {
if (iter.first == session->quic_session_key()) {
iter.second->OnSessionClosed(session);
@@ -1478,63 +1477,72 @@ std::unique_ptr<DatagramClientSocket> QuicStreamFactory::CreateSocket(
}
void QuicStreamFactory::OnIPAddressChanged() {
- LogPlatformNotificationInHistogram(NETWORK_IP_ADDRESS_CHANGED);
+ CollectDataOnPlatformNotification(
+ NETWORK_IP_ADDRESS_CHANGED, NetworkChangeNotifier::kInvalidNetworkHandle);
// Do nothing if connection migration is turned on.
if (params_.migrate_sessions_on_network_change_v2)
return;
+ connectivity_monitor_.OnIPAddressChanged();
+
set_is_quic_known_to_work_on_current_network(false);
if (params_.close_sessions_on_ip_change) {
CloseAllSessions(ERR_NETWORK_CHANGED, quic::QUIC_IP_ADDRESS_CHANGED);
} else {
DCHECK(params_.goaway_sessions_on_ip_change);
- MarkAllActiveSessionsGoingAway();
+ MarkAllActiveSessionsGoingAway(kIPAddressChanged);
}
}
void QuicStreamFactory::OnNetworkConnected(NetworkHandle network) {
- LogPlatformNotificationInHistogram(NETWORK_CONNECTED);
- if (!params_.migrate_sessions_on_network_change_v2)
- return;
-
- ScopedConnectionMigrationEventLog scoped_event_log(net_log_,
- "OnNetworkConnected");
+ CollectDataOnPlatformNotification(NETWORK_CONNECTED, network);
+ if (params_.migrate_sessions_on_network_change_v2) {
+ NetLogWithSource net_log = NetLogWithSource::Make(
+ net_log_, NetLogSourceType::QUIC_CONNECTION_MIGRATION);
+ net_log.AddEventWithStringParams(
+ NetLogEventType::QUIC_CONNECTION_MIGRATION_PLATFORM_NOTIFICATION,
+ "signal", "OnNetworkConnected");
+ }
+ // Broadcast network connected to all sessions.
+ // If migration is not turned on, session will not migrate but collect data.
auto it = all_sessions_.begin();
// Sessions may be deleted while iterating through the map.
while (it != all_sessions_.end()) {
QuicChromiumClientSession* session = it->first;
++it;
- session->OnNetworkConnected(network, scoped_event_log.net_log());
+ session->OnNetworkConnected(network);
}
}
void QuicStreamFactory::OnNetworkDisconnected(NetworkHandle network) {
- LogPlatformNotificationInHistogram(NETWORK_DISCONNECTED);
- if (!params_.migrate_sessions_on_network_change_v2)
- return;
-
- ScopedConnectionMigrationEventLog scoped_event_log(net_log_,
- "OnNetworkDisconnected");
+ CollectDataOnPlatformNotification(NETWORK_DISCONNECTED, network);
+ if (params_.migrate_sessions_on_network_change_v2) {
+ NetLogWithSource net_log = NetLogWithSource::Make(
+ net_log_, NetLogSourceType::QUIC_CONNECTION_MIGRATION);
+ net_log.AddEventWithStringParams(
+ NetLogEventType::QUIC_CONNECTION_MIGRATION_PLATFORM_NOTIFICATION,
+ "signal", "OnNetworkDisconnected");
+ }
+ // Broadcast network disconnected to all sessions.
+ // If migration is not turned on, session will not migrate but collect data.
auto it = all_sessions_.begin();
// Sessions may be deleted while iterating through the map.
while (it != all_sessions_.end()) {
QuicChromiumClientSession* session = it->first;
++it;
- session->OnNetworkDisconnectedV2(/*disconnected_network*/ network,
- scoped_event_log.net_log());
+ session->OnNetworkDisconnectedV2(/*disconnected_network*/ network);
}
}
// This method is expected to only be called when migrating from Cellular to
// WiFi on Android, and should always be preceded by OnNetworkMadeDefault().
void QuicStreamFactory::OnNetworkSoonToDisconnect(NetworkHandle network) {
- LogPlatformNotificationInHistogram(NETWORK_SOON_TO_DISCONNECT);
+ CollectDataOnPlatformNotification(NETWORK_SOON_TO_DISCONNECT, network);
}
void QuicStreamFactory::OnNetworkMadeDefault(NetworkHandle network) {
- LogPlatformNotificationInHistogram(NETWORK_MADE_DEFAULT);
- if (!params_.migrate_sessions_on_network_change_v2)
- return;
+ CollectDataOnPlatformNotification(NETWORK_MADE_DEFAULT, network);
+ connectivity_monitor_.OnDefaultNetworkUpdated(network);
// Clear alternative services that were marked as broken until default network
// changes.
@@ -1546,17 +1554,24 @@ void QuicStreamFactory::OnNetworkMadeDefault(NetworkHandle network) {
DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, network);
default_network_ = network;
- ScopedConnectionMigrationEventLog scoped_event_log(net_log_,
- "OnNetworkMadeDefault");
+
+ if (params_.migrate_sessions_on_network_change_v2) {
+ NetLogWithSource net_log = NetLogWithSource::Make(
+ net_log_, NetLogSourceType::QUIC_CONNECTION_MIGRATION);
+ net_log.AddEventWithStringParams(
+ NetLogEventType::QUIC_CONNECTION_MIGRATION_PLATFORM_NOTIFICATION,
+ "signal", "OnNetworkMadeDefault");
+ }
auto it = all_sessions_.begin();
// Sessions may be deleted while iterating through the map.
while (it != all_sessions_.end()) {
QuicChromiumClientSession* session = it->first;
++it;
- session->OnNetworkMadeDefault(network, scoped_event_log.net_log());
+ session->OnNetworkMadeDefault(network);
}
- set_is_quic_known_to_work_on_current_network(false);
+ if (params_.migrate_sessions_on_network_change_v2)
+ set_is_quic_known_to_work_on_current_network(false);
}
void QuicStreamFactory::OnCertDBChanged() {
@@ -1569,7 +1584,7 @@ void QuicStreamFactory::OnCertDBChanged() {
// Since the OnCertDBChanged method doesn't tell us what
// kind of change it is, we have to flush the socket
// pools to be safe.
- MarkAllActiveSessionsGoingAway();
+ MarkAllActiveSessionsGoingAway(kCertDBChanged);
}
void QuicStreamFactory::set_is_quic_known_to_work_on_current_network(
@@ -1742,6 +1757,7 @@ int QuicStreamFactory::CreateSession(
// creation, update |default_network_| when the first socket is bound
// to the default network.
default_network_ = *network;
+ connectivity_monitor_.SetInitialDefaultNetwork(default_network_);
} else {
UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.DefaultNetworkMatch",
default_network_ == *network);
@@ -1782,7 +1798,9 @@ int QuicStreamFactory::CreateSession(
quic::QuicConfig config = config_;
ConfigureInitialRttEstimate(
server_id, key.session_key().network_isolation_key(), &config);
- if (quic_version.transport_version <= quic::QUIC_VERSION_43 &&
+ // QUIC versions that use the IETF invariant header all have NSTP
+ // enabled by default, so we only need to add it for those that don't.
+ if (!quic_version.HasIetfInvariantHeader() &&
!config.HasClientSentConnectionOption(quic::kNSTP,
quic::Perspective::IS_CLIENT)) {
// Enable the no stop waiting frames connection option by default.
@@ -1827,6 +1845,7 @@ int QuicStreamFactory::CreateSession(
all_sessions_[*session] = key; // owning pointer
writer->set_delegate(*session);
+ (*session)->AddConnectivityObserver(&connectivity_monitor_);
(*session)->Initialize();
bool closed_during_initialize = !base::Contains(all_sessions_, *session) ||
@@ -1855,9 +1874,14 @@ void QuicStreamFactory::ActivateSession(const QuicSessionAliasKey& key,
session_peer_ip_[session] = peer_address;
}
-void QuicStreamFactory::MarkAllActiveSessionsGoingAway() {
+void QuicStreamFactory::MarkAllActiveSessionsGoingAway(
+ AllActiveSessionsGoingAwayReason reason) {
while (!active_sessions_.empty()) {
QuicChromiumClientSession* session = active_sessions_.begin()->second;
+ // If IP address change is detected, disable session's connectivity
+ // monitoring by remove the Delegate.
+ if (reason == kIPAddressChanged)
+ connectivity_monitor_.OnSessionGoingAwayOnIPAddressChange(session);
OnSessionGoingAway(session);
}
}
@@ -2014,8 +2038,6 @@ void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
quic::QuicConnectionId* connection_id) {
quic::QuicCryptoClientConfig::CachedState* cached =
crypto_config_handle.GetConfig()->LookupOrCreate(server_id);
- if (cached->has_server_designated_connection_id())
- *connection_id = cached->GetNextServerDesignatedConnectionId();
if (!cached->IsEmpty()) {
return;
@@ -2133,8 +2155,9 @@ QuicStreamFactory::CreateCryptoConfigHandle(
std::make_unique<ProofVerifierChromium>(
cert_verifier_, ct_policy_enforcer_, transport_security_state_,
cert_transparency_verifier_,
- HostsFromOrigins(params_.origins_to_force_quic_on)),
- this);
+ HostsFromOrigins(params_.origins_to_force_quic_on),
+ actual_network_isolation_key),
+ std::make_unique<QuicClientSessionCache>(), this);
quic::QuicCryptoClientConfig* crypto_config = crypto_config_owner->config();
crypto_config->set_user_agent_id(params_.user_agent_id);
@@ -2165,6 +2188,38 @@ void QuicStreamFactory::OnAllCryptoClientRefReleased(
active_crypto_config_map_.erase(map_iterator);
}
+void QuicStreamFactory::CollectDataOnPlatformNotification(
+ enum QuicPlatformNotification notification,
+ NetworkChangeNotifier::NetworkHandle affected_network) const {
+ UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.PlatformNotification",
+ notification, NETWORK_NOTIFICATION_MAX);
+ if (notification == NETWORK_SOON_TO_DISCONNECT ||
+ notification == NETWORK_DISCONNECTED) {
+ // If the disconnected network is not the default network, ignore
+ // stats collections.
+ if (affected_network != default_network_)
+ return;
+ }
+
+ // Skip degrading session collection if there are less than two sessions.
+ if (all_sessions_.size() < 2)
+ return;
+
+ size_t num_degrading_sessions =
+ connectivity_monitor_.GetNumDegradingSessions();
+ const std::string raw_histogram_name =
+ "Net.QuicStreamFactory.NumDegradingSessions." +
+ QuicPlatformNotificationToString(notification);
+ base::UmaHistogramExactLinear(raw_histogram_name, num_degrading_sessions,
+ 101);
+
+ int percentage = num_degrading_sessions * 100 / all_sessions_.size();
+ const std::string percentage_histogram_name =
+ "Net.QuicStreamFactory.PercentageDegradingSessions." +
+ QuicPlatformNotificationToString(notification);
+ base::UmaHistogramExactLinear(percentage_histogram_name, percentage, 101);
+}
+
std::unique_ptr<QuicCryptoClientConfigHandle>
QuicStreamFactory::GetCryptoConfigForTesting(
const NetworkIsolationKey& network_isolation_key) {
diff --git a/chromium/net/quic/quic_stream_factory.h b/chromium/net/quic/quic_stream_factory.h
index 6e33a290557..9dd5bb2ca03 100644
--- a/chromium/net/quic/quic_stream_factory.h
+++ b/chromium/net/quic/quic_stream_factory.h
@@ -17,7 +17,6 @@
#include "base/containers/mru_cache.h"
#include "base/gtest_prod_util.h"
-#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/tick_clock.h"
@@ -35,6 +34,7 @@
#include "net/quic/network_connection.h"
#include "net/quic/quic_chromium_client_session.h"
#include "net/quic/quic_clock_skew_detector.h"
+#include "net/quic/quic_connectivity_monitor.h"
#include "net/quic/quic_context.h"
#include "net/quic/quic_crypto_client_config_handle.h"
#include "net/quic/quic_session_key.h"
@@ -101,6 +101,12 @@ enum QuicPlatformNotification {
NETWORK_NOTIFICATION_MAX
};
+enum AllActiveSessionsGoingAwayReason {
+ kClockSkewDetected,
+ kIPAddressChanged,
+ kCertDBChanged
+};
+
// Encapsulates a pending request for a QuicChromiumClientSession.
// If the request is still pending when it is destroyed, it will
// cancel the request with the factory.
@@ -396,7 +402,9 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
NetworkChangeNotifier::NetworkHandle* network);
void ActivateSession(const QuicSessionAliasKey& key,
QuicChromiumClientSession* session);
- void MarkAllActiveSessionsGoingAway();
+ // Go away all active sessions. May disable session's connectivity monitoring
+ // based on the |reason|.
+ void MarkAllActiveSessionsGoingAway(AllActiveSessionsGoingAwayReason reason);
void ConfigureInitialRttEstimate(
const quic::QuicServerId& server_id,
@@ -457,6 +465,14 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
void OnAllCryptoClientRefReleased(
QuicCryptoClientConfigMap::iterator& map_iterator);
+ // Called when a network change happens.
+ // Collect platform notification metrics, and if the change affects the
+ // original default network interface, collect connectivity degradation
+ // metrics from |connectivity_monitor_| and add to histograms.
+ void CollectDataOnPlatformNotification(
+ enum QuicPlatformNotification notification,
+ NetworkChangeNotifier::NetworkHandle affected_network) const;
+
std::unique_ptr<QuicCryptoClientConfigHandle> GetCryptoConfigForTesting(
const NetworkIsolationKey& network_isolation_key);
@@ -556,6 +572,8 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
int num_push_streams_created_;
+ QuicConnectivityMonitor connectivity_monitor_;
+
quic::QuicClientPushPromiseIndex push_promise_index_;
const base::TickClock* tick_clock_;
diff --git a/chromium/net/quic/quic_stream_factory_peer.cc b/chromium/net/quic/quic_stream_factory_peer.cc
index ac673b84b67..63b316a5e30 100644
--- a/chromium/net/quic/quic_stream_factory_peer.cc
+++ b/chromium/net/quic/quic_stream_factory_peer.cc
@@ -185,6 +185,11 @@ int QuicStreamFactoryPeer::GetNumPushStreamsCreated(
return factory->num_push_streams_created_;
}
+size_t QuicStreamFactoryPeer::GetNumDegradingSessions(
+ QuicStreamFactory* factory) {
+ return factory->connectivity_monitor_.GetNumDegradingSessions();
+}
+
void QuicStreamFactoryPeer::SetAlarmFactory(
QuicStreamFactory* factory,
std::unique_ptr<quic::QuicAlarmFactory> alarm_factory) {
diff --git a/chromium/net/quic/quic_stream_factory_peer.h b/chromium/net/quic/quic_stream_factory_peer.h
index 507aedda772..7e2a59922fd 100644
--- a/chromium/net/quic/quic_stream_factory_peer.h
+++ b/chromium/net/quic/quic_stream_factory_peer.h
@@ -103,6 +103,8 @@ class QuicStreamFactoryPeer {
static int GetNumPushStreamsCreated(QuicStreamFactory* factory);
+ static size_t GetNumDegradingSessions(QuicStreamFactory* factory);
+
static void SetAlarmFactory(
QuicStreamFactory* factory,
std::unique_ptr<quic::QuicAlarmFactory> alarm_factory);
diff --git a/chromium/net/quic/quic_stream_factory_test.cc b/chromium/net/quic/quic_stream_factory_test.cc
index a4dd7ce26d3..031cfe38238 100644
--- a/chromium/net/quic/quic_stream_factory_test.cc
+++ b/chromium/net/quic/quic_stream_factory_test.cc
@@ -42,6 +42,7 @@
#include "net/quic/mock_quic_data.h"
#include "net/quic/properties_based_quic_server_info.h"
#include "net/quic/quic_chromium_alarm_factory.h"
+#include "net/quic/quic_chromium_client_session_peer.h"
#include "net/quic/quic_http_stream.h"
#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_server_info.h"
@@ -1002,11 +1003,6 @@ TEST_P(QuicStreamFactoryTest, Create) {
}
TEST_P(QuicStreamFactoryTest, CreateZeroRtt) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
Initialize();
factory_->set_is_quic_known_to_work_on_current_network(true);
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -1097,11 +1093,6 @@ TEST_P(QuicStreamFactoryTest, FactoryDestroyedWhenJobPending) {
}
TEST_P(QuicStreamFactoryTest, RequireConfirmation) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
host_resolver_->set_synchronous_mode(true);
@@ -1144,11 +1135,6 @@ TEST_P(QuicStreamFactoryTest, RequireConfirmation) {
}
TEST_P(QuicStreamFactoryTest, DontRequireConfirmationFromSameIP) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
host_resolver_->set_synchronous_mode(true);
@@ -3152,24 +3138,24 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNonMigratableStream(
quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
// A RESET will be sent to the peer to cancel the non-migratable stream.
if (VersionUsesHttp3(version_.transport_version)) {
- quic_data1.AddWrite(SYNCHRONOUS,
- client_maker_.MakeDataAndRstPacket(
- packet_num++, true, GetQpackDecoderStreamId(),
- StreamCancellationQpackDecoderInstruction(0),
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED));
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeDataRstAndAckPacket(
+ packet_num++, true, GetQpackDecoderStreamId(),
+ StreamCancellationQpackDecoderInstruction(0),
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ quic::QUIC_STREAM_CANCELLED, 1, 1));
} else {
- quic_data1.AddWrite(SYNCHRONOUS,
- client_maker_.MakeRstPacket(
- packet_num++, false,
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED));
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckAndRstPacket(
+ packet_num++, false,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
}
// Ping packet to send after migration is completed.
- quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeAckAndPingPacket(
- packet_num++, false, 1, 1, 1));
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, false));
} else {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
if (VersionUsesHttp3(version_.transport_version)) {
socket_data.AddWrite(
SYNCHRONOUS,
@@ -3586,8 +3572,7 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNoOpenStreams(
QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_TRUE(HasActiveSession(host_port_pair_));
- EXPECT_EQ(0u, session->GetNumActiveStreams());
- EXPECT_EQ(0u, session->GetNumDrainingStreams());
+ EXPECT_FALSE(session->HasActiveRequestStreams());
// Trigger connection migration.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
@@ -4079,9 +4064,11 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) {
EXPECT_EQ(OK, stream->SendRequest(request_headers, &response,
callback_.callback()));
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// Cause the connection to report path degrading to the session.
// Session will start to probe the alternate network.
- session->connection()->OnPathDegradingTimeout();
+ session->connection()->OnPathDegradingDetected();
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// Next connectivity probe is scheduled to be sent in 2 *
// kDefaultRTTMilliSecs.
@@ -4111,6 +4098,8 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) {
EXPECT_EQ(base::TimeDelta(), next_task_delay);
task_runner->FastForwardBy(next_task_delay);
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
// Response headers are received over the new network.
EXPECT_THAT(callback_.WaitForResult(), IsOk());
EXPECT_EQ(200, response.headers->response_code());
@@ -4136,6 +4125,8 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) {
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkMadeDefault(kNewNetworkForTests);
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
task_runner->FastForwardBy(next_task_delay);
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
@@ -4271,9 +4262,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading(
if (async_write_before)
session->SendPing();
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// Cause the connection to report path degrading to the session.
// Session will start to probe the alternate network.
- session->connection()->OnPathDegradingTimeout();
+ session->connection()->OnPathDegradingDetected();
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// Next connectivity probe is scheduled to be sent in 2 *
// kDefaultRTTMilliSecs.
@@ -4303,10 +4296,14 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading(
EXPECT_EQ(base::TimeDelta(), next_task_delay);
task_runner->FastForwardBy(next_task_delay);
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
// Response headers are received over the new network.
EXPECT_THAT(callback_.WaitForResult(), IsOk());
EXPECT_EQ(200, response.headers->response_code());
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
// Now there are two pending tasks, the nearest one was to send connectivity
// probe and has been cancelled due to successful migration.
EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
@@ -4328,6 +4325,8 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading(
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkMadeDefault(kNewNetworkForTests);
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
task_runner->FastForwardBy(next_task_delay);
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
@@ -4352,6 +4351,143 @@ TEST_P(QuicStreamFactoryTest, MigratePortOnPathDegrading_WithoutNetworkHandle) {
TestSimplePortMigrationOnPathDegrading();
}
+// Verifies that if a stateless reset is received on port migration probing
+// path, the session is still alive and probing is considered failed.
+TEST_P(QuicStreamFactoryTest, PortMigrationProbingReceivedStatelessReset) {
+ if (!VersionHasIetfInvariantHeader(version_.transport_version)) {
+ // STATELESS_RESET is only supported after QUIC V46.
+ return;
+ }
+ quic_params_->allow_port_migration = true;
+ socket_factory_.reset(new TestMigrationSocketFactory);
+ Initialize();
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ // Using a testing task runner so that we can control time.
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
+ QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
+
+ int packet_number = 1;
+ MockQuicData quic_data1(version_);
+ quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // hanging read
+ if (VersionUsesHttp3(version_.transport_version)) {
+ quic_data1.AddWrite(SYNCHRONOUS,
+ ConstructInitialSettingsPacket(packet_number++));
+ }
+ quic_data1.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(packet_number++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ true, true));
+ if (VersionUsesHttp3(version_.transport_version)) {
+ quic_data1.AddWrite(
+ SYNCHRONOUS, client_maker_.MakeDataPacket(
+ packet_number + 1, GetQpackDecoderStreamId(), true,
+ false, StreamCancellationQpackDecoderInstruction(0)));
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRstPacket(
+ packet_number + 2, false,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ quic::QUIC_STREAM_CANCELLED));
+ } else {
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRstPacket(
+ packet_number + 1, false,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ quic::QUIC_STREAM_CANCELLED));
+ }
+ quic_data1.AddSocketDataToFactory(socket_factory_.get());
+
+ // Set up the second socket data provider that is used after migration.
+ // The response to the earlier request is read on the new socket.
+ MockQuicData quic_data2(version_);
+ // Connectivity probe to be sent on the new path.
+ quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
+ packet_number, true));
+ quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // Pause
+ // Stateless reset to receive from the server.
+ quic_data2.AddRead(ASYNC, server_maker_.MakeStatelessResetPacket());
+ quic_data2.AddSocketDataToFactory(socket_factory_.get());
+
+ // Create request and QuicHttpStream.
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(
+ ERR_IO_PENDING,
+ request.Request(
+ host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ SocketTag(), NetworkIsolationKey(), false /* disable_secure_dns */,
+ /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
+ failed_on_default_network_callback_, callback_.callback()));
+ EXPECT_THAT(callback_.WaitForResult(), IsOk());
+ std::unique_ptr<HttpStream> stream = CreateStream(&request);
+ EXPECT_TRUE(stream.get());
+
+ // Cause QUIC stream to be created.
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = url_;
+ request_info.traffic_annotation =
+ MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info, true, DEFAULT_PRIORITY,
+ net_log_, CompletionOnceCallback()));
+
+ // Ensure that session is alive and active.
+ QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+
+ // Send GET request on stream.
+ HttpResponseInfo response;
+ HttpRequestHeaders request_headers;
+ EXPECT_EQ(OK, stream->SendRequest(request_headers, &response,
+ callback_.callback()));
+
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
+ // Cause the connection to report path degrading to the session.
+ // Session will start to probe a different port.
+ session->connection()->OnPathDegradingDetected();
+
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
+ // Next connectivity probe is scheduled to be sent in 2 *
+ // kDefaultRTTMilliSecs.
+ EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
+ base::TimeDelta next_task_delay = task_runner->NextPendingTaskDelay();
+ EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs),
+ next_task_delay);
+
+ // The connection should still be alive, and not marked as going away.
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
+ EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
+
+ // Resume quic data and a STATELESS_RESET is read from the probing path.
+ quic_data2.Resume();
+
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
+ // Verify that the session is still active, and the request stream is active.
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
+ EXPECT_FALSE(
+ QuicChromiumClientSessionPeer::DoesSessionAllowPortMigration(session));
+
+ // The task to resend connectivity probe is cancelled due to probe failure.
+ task_runner->FastForwardBy(next_task_delay);
+ EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
+
+ stream.reset();
+ EXPECT_TRUE(quic_data1.AllReadDataConsumed());
+ EXPECT_TRUE(quic_data1.AllWriteDataConsumed());
+ EXPECT_TRUE(quic_data2.AllReadDataConsumed());
+ EXPECT_TRUE(quic_data2.AllWriteDataConsumed());
+}
+
// Verifies that port migration can be attempted on the default network and
// succeed when path degrading is detected. NetworkHandle is supported.
TEST_P(QuicStreamFactoryTest, MigratePortOnPathDegrading_WithNetworkHandle) {
@@ -4488,9 +4624,13 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() {
EXPECT_EQ(OK, stream->SendRequest(request_headers, &response,
callback_.callback()));
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
// Cause the connection to report path degrading to the session.
// Session will start to probe a different port.
- session->connection()->OnPathDegradingTimeout();
+ session->connection()->OnPathDegradingDetected();
+
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// Next connectivity probe is scheduled to be sent in 2 *
// kDefaultRTTMilliSecs.
@@ -4512,6 +4652,9 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() {
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_TRUE(HasActiveSession(host_port_pair_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
+ // Successful port migration causes the path no longer degrading on the same
+ // network.
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// There should be pending tasks, the nearest one will complete
// migration to the new port.
@@ -4524,6 +4667,8 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() {
EXPECT_THAT(callback_.WaitForResult(), IsOk());
EXPECT_EQ(200, response.headers->response_code());
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
// Now there is one pending task to send connectivity probe and has been
// cancelled due to successful migration.
EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
@@ -4660,9 +4805,15 @@ TEST_P(QuicStreamFactoryTest, MultiplePortMigrationsExceedsMaxLimit) {
quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // EOF.
quic_data2.AddSocketDataToFactory(socket_factory_.get());
+ EXPECT_EQ(0u,
+ QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
// Cause the connection to report path degrading to the session.
// Session will start to probe a different port.
- session->connection()->OnPathDegradingTimeout();
+ session->connection()->OnPathDegradingDetected();
+
+ EXPECT_EQ(1u,
+ QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// Next connectivity probe is scheduled to be sent in 2 *
// kDefaultRTTMilliSecs.
@@ -4784,9 +4935,15 @@ TEST_P(QuicStreamFactoryTest, GoawayOnPathDegrading) {
EXPECT_EQ(OK, stream->SendRequest(request_headers, &response,
callback_.callback()));
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
// Trigger the connection to report path degrading to the session.
// Session will mark itself GOAWAY.
- session->connection()->OnPathDegradingTimeout();
+ session->connection()->OnPathDegradingDetected();
+
+ /// Path degrading detection on go_away_on_path_degrading detection is
+ // disabled.
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// The connection should still be alive, but marked as going away.
EXPECT_FALSE(HasActiveSession(host_port_pair_));
@@ -4920,9 +5077,11 @@ TEST_P(QuicStreamFactoryTest, DoNotMigrateToBadSocketOnPathDegrading) {
EXPECT_EQ(OK, stream->SendRequest(request_headers, &response,
callback_.callback()));
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// Cause the connection to report path degrading to the session.
// Session will start to probe the alternate network.
- session->connection()->OnPathDegradingTimeout();
+ session->connection()->OnPathDegradingDetected();
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
@@ -5063,10 +5222,12 @@ void QuicStreamFactoryTestBase::TestMigrateSessionWithDrainingStream(
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, session->GetNumActiveStreams());
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// Cause the connection to report path degrading to the session.
// Session should still start to probe the alternate network.
- session->connection()->OnPathDegradingTimeout();
+ session->connection()->OnPathDegradingDetected();
EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// Next connectivity probe is scheduled to be sent in 2 *
// kDefaultRTTMilliSecs.
@@ -5085,7 +5246,7 @@ void QuicStreamFactoryTestBase::TestMigrateSessionWithDrainingStream(
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_TRUE(HasActiveSession(host_port_pair_));
EXPECT_EQ(0u, session->GetNumActiveStreams());
- EXPECT_EQ(1u, session->GetNumDrainingStreams());
+ EXPECT_TRUE(session->HasActiveRequestStreams());
// There should be three pending tasks, the nearest one will complete
// migration to the new network.
@@ -5233,12 +5394,18 @@ TEST_P(QuicStreamFactoryTest, MigrateOnNewNetworkConnectAfterPathDegrading) {
EXPECT_EQ(OK, stream->SendRequest(request_headers, &response,
callback_.callback()));
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
// Cause the connection to report path degrading to the session.
// Due to lack of alternate network, session will not mgirate connection.
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
- session->connection()->OnPathDegradingTimeout();
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+ session->connection()->OnPathDegradingDetected();
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
// Deliver a signal that a alternate network is connected now, this should
// cause the connection to start early migration on path degrading.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
@@ -5275,6 +5442,10 @@ TEST_P(QuicStreamFactoryTest, MigrateOnNewNetworkConnectAfterPathDegrading) {
EXPECT_EQ(base::TimeDelta(), next_task_delay);
task_runner->FastForwardBy(next_task_delay);
+ // Although the session successfully migrates, it is still considered
+ // degrading sessions.
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+
// Response headers are received over the new network.
EXPECT_THAT(callback_.WaitForResult(), IsOk());
EXPECT_EQ(200, response.headers->response_code());
@@ -5523,8 +5694,10 @@ TEST_P(QuicStreamFactoryTest, MigrateOnPathDegradingWithNoNewNetwork) {
// Trigger connection migration on path degrading. Since there are no networks
// to migrate to, the session will remain on the original network, not marked
// as going away.
- session->connection()->OnPathDegradingTimeout();
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+ session->connection()->OnPathDegradingDetected();
EXPECT_TRUE(session->connection()->IsPathDegrading());
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
EXPECT_TRUE(HasActiveSession(host_port_pair_));
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
@@ -5586,24 +5759,25 @@ void QuicStreamFactoryTestBase::TestMigrateSessionEarlyNonMigratableStream(
quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
// A RESET will be sent to the peer to cancel the non-migratable stream.
if (VersionUsesHttp3(version_.transport_version)) {
- quic_data1.AddWrite(SYNCHRONOUS,
- client_maker_.MakeDataAndRstPacket(
- packet_num++, true, GetQpackDecoderStreamId(),
- StreamCancellationQpackDecoderInstruction(0),
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED));
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeDataRstAndAckPacket(
+ packet_num++, true, GetQpackDecoderStreamId(),
+ StreamCancellationQpackDecoderInstruction(0),
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ quic::QUIC_STREAM_CANCELLED, 1, 1));
} else {
- quic_data1.AddWrite(SYNCHRONOUS,
- client_maker_.MakeRstPacket(
- packet_num++, false,
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED));
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckAndRstPacket(
+ packet_num++, false,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
}
// Ping packet to send after migration is completed.
- quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeAckAndPingPacket(
- packet_num++, false, 1, 1, 1));
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, false));
+
} else {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
if (VersionUsesHttp3(version_.transport_version)) {
socket_data.AddWrite(
SYNCHRONOUS,
@@ -6152,8 +6326,10 @@ TEST_P(QuicStreamFactoryTest,
// Cause the connection to report path degrading to the session.
// Session will ignore the signal as handshake is not completed.
- session->connection()->OnPathDegradingTimeout();
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
+ session->connection()->OnPathDegradingDetected();
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
EXPECT_FALSE(HasActiveSession(host_port_pair_));
EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
@@ -6212,9 +6388,11 @@ void QuicStreamFactoryTestBase::TestNoAlternateNetworkBeforeHandshake(
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
+ EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// Cause the connection to report path degrading to the session.
// Session will ignore the signal as handshake is not completed.
- session->connection()->OnPathDegradingTimeout();
+ session->connection()->OnPathDegradingDetected();
+ EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
EXPECT_FALSE(HasActiveSession(host_port_pair_));
EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
@@ -10135,8 +10313,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigration) {
const uint8_t kTestIpAddress[] = {1, 2, 3, 4};
const uint16_t kTestPort = 123;
session->Migrate(NetworkChangeNotifier::kInvalidNetworkHandle,
- IPEndPoint(IPAddress(kTestIpAddress), kTestPort), true,
- net_log_);
+ IPEndPoint(IPAddress(kTestIpAddress), kTestPort), true);
session->GetDefaultSocket()->GetPeerAddress(&ip);
DVLOG(1) << "Socket migrated to: " << ip.address().ToString() << " "
@@ -10184,7 +10361,10 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv6) {
VerifyServerMigration(config, alt_address);
}
-TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv4) {
+TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv4Fails) {
+ quic_params_->allow_server_migration = true;
+ Initialize();
+
// Add a resolver rule to make initial connection to an IPv6 address.
host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
"fe80::aebc:32ff:febb:1e33", "");
@@ -10192,9 +10372,75 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv4) {
IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 123);
quic::QuicConfig config;
config.SetIPv4AlternateServerAddressToSend(ToQuicSocketAddress(alt_address));
- IPEndPoint expected_address(
- ConvertIPv4ToIPv4MappedIPv6(alt_address.address()), alt_address.port());
- VerifyServerMigration(config, expected_address);
+
+ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+ crypto_client_stream_factory_.SetConfig(config);
+
+ // Set up only socket data provider.
+ MockQuicData socket_data1(version_);
+ socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+ int packet_num = 1;
+ if (VersionUsesHttp3(version_.transport_version)) {
+ socket_data1.AddWrite(SYNCHRONOUS,
+ ConstructInitialSettingsPacket(packet_num++));
+ socket_data1.AddWrite(
+ SYNCHRONOUS, client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(), true, false,
+ StreamCancellationQpackDecoderInstruction(0)));
+ }
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRstPacket(packet_num++, true,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ quic::QUIC_STREAM_CANCELLED));
+ socket_data1.AddSocketDataToFactory(socket_factory_.get());
+
+ // Create request and QuicHttpStream.
+ QuicStreamRequest request(factory_.get());
+ EXPECT_EQ(
+ ERR_IO_PENDING,
+ request.Request(
+ host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ SocketTag(), NetworkIsolationKey(), false /* disable_secure_dns */,
+ /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
+ failed_on_default_network_callback_, callback_.callback()));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ std::unique_ptr<HttpStream> stream = CreateStream(&request);
+ EXPECT_TRUE(stream.get());
+
+ // Cause QUIC stream to be created.
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("https://www.example.org/");
+ request_info.traffic_annotation =
+ MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info, true, DEFAULT_PRIORITY,
+ net_log_, CompletionOnceCallback()));
+
+ // Ensure that session is alive and active.
+ QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(host_port_pair_));
+
+ IPEndPoint actual_address;
+ session->GetDefaultSocket()->GetPeerAddress(&actual_address);
+ // No migration should have happened.
+ IPEndPoint expected_address =
+ IPEndPoint(IPAddress(0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0xae, 0xbc, 0x32, 0xff,
+ 0xfe, 0xbb, 0x1e, 0x33),
+ kDefaultServerPort);
+ EXPECT_EQ(actual_address, expected_address);
+ DVLOG(1) << "Socket connected to: " << actual_address.address().ToString()
+ << " " << actual_address.port();
+ DVLOG(1) << "Expected address: " << expected_address.address().ToString()
+ << " " << expected_address.port();
+
+ stream.reset();
+ EXPECT_TRUE(socket_data1.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
}
TEST_P(QuicStreamFactoryTest, ServerMigrationIPv4ToIPv6Fails) {
@@ -10431,11 +10677,6 @@ TEST_P(QuicStreamFactoryTest, CryptoConfigWhenProofIsInvalid) {
}
TEST_P(QuicStreamFactoryTest, EnableNotLoadFromDiskCache) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
Initialize();
factory_->set_is_quic_known_to_work_on_current_network(true);
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -10581,20 +10822,10 @@ TEST_P(QuicStreamFactoryTest, ReducePingTimeoutOnConnectionTimeOutOpenStreams) {
// Verifies that the QUIC stream factory is initialized correctly.
TEST_P(QuicStreamFactoryTest, MaybeInitialize) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
VerifyInitialization(false /* vary_network_isolation_key */);
}
TEST_P(QuicStreamFactoryTest, MaybeInitializeWithNetworkIsolationKey) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
base::test::ScopedFeatureList feature_list;
feature_list.InitWithFeatures(
// enabled_features
@@ -10822,11 +11053,6 @@ TEST_P(QuicStreamFactoryTest, CryptoConfigCacheMRUWithNetworkIsolationKey) {
// around, so evictions happen immediately.
TEST_P(QuicStreamFactoryTest,
CryptoConfigCacheMRUWithRealRequestsAndWithNetworkIsolationKey) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
const int kNumSessionsToMake = kMaxRecentCryptoConfigs + 5;
base::test::ScopedFeatureList feature_list;
@@ -10968,11 +11194,6 @@ TEST_P(QuicStreamFactoryTest,
}
TEST_P(QuicStreamFactoryTest, YieldAfterPackets) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
Initialize();
factory_->set_is_quic_known_to_work_on_current_network(true);
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -11025,11 +11246,6 @@ TEST_P(QuicStreamFactoryTest, YieldAfterPackets) {
}
TEST_P(QuicStreamFactoryTest, YieldAfterDuration) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
Initialize();
factory_->set_is_quic_known_to_work_on_current_network(true);
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -12306,11 +12522,6 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceHostResolveAsyncStaleMatch) {
// async, and then the result matches.
TEST_P(QuicStreamFactoryTest,
ResultAfterDNSRaceHostResolveAsyncConnectAsyncStaleMatch) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
quic_params_->race_stale_dns_on_connection = true;
host_resolver_ = std::make_unique<MockCachingHostResolver>();
Initialize();
@@ -12382,11 +12593,6 @@ TEST_P(QuicStreamFactoryTest,
// return, then connection finishes and matches with the result.
TEST_P(QuicStreamFactoryTest,
ResultAfterDNSRaceHostResolveAsyncStaleMatchConnectAsync) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
quic_params_->race_stale_dns_on_connection = true;
host_resolver_ = std::make_unique<MockCachingHostResolver>();
Initialize();
@@ -12532,10 +12738,6 @@ TEST_P(QuicStreamFactoryTest,
// With dns race experiment on, dns resolve async, stale used and connects
// async, finishes before dns, but no match
TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleAsyncResolveAsyncNoMatch) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // TODO(fayang): 0-rtt is not supported in IETF QUIC yet. Fix it.
- return;
- }
quic_params_->race_stale_dns_on_connection = true;
host_resolver_ = std::make_unique<MockCachingHostResolver>();
Initialize();
@@ -12550,7 +12752,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleAsyncResolveAsyncNoMatch) {
host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
kNonCachedIPAddress, "");
- // Set up a different address in the stale resolvercache.
+ // Set up a different address in the stale resolver cache.
HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
@@ -12621,10 +12823,6 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleAsyncResolveAsyncNoMatch) {
// With dns race experiment on, dns resolve async, stale used and connects
// async, dns finishes first, but no match
TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncStaleAsyncNoMatch) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // TODO(fayang): 0-rtt is not supported in IETF QUIC yet. Fix it.
- return;
- }
quic_params_->race_stale_dns_on_connection = true;
host_resolver_ = std::make_unique<MockCachingHostResolver>();
Initialize();
@@ -12988,10 +13186,6 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleErrorDNSNoMatchError) {
// With dns race experiment on, dns resolve async and stale connect async, dns
// resolve returns error and then preconnect finishes
TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncErrorStaleAsync) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // TODO(fayang): 0-rtt is not supported in IETF QUIC yet. Fix it.
- return;
- }
quic_params_->race_stale_dns_on_connection = true;
host_resolver_ = std::make_unique<MockCachingHostResolver>();
Initialize();
@@ -13002,8 +13196,6 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncErrorStaleAsync) {
host_resolver_->set_ondemand_mode(true);
host_resolver_->rules()->AddSimulatedFailure(host_port_pair_.host());
factory_->set_is_quic_known_to_work_on_current_network(false);
- crypto_client_stream_factory_.set_handshake_mode(
- MockCryptoClientStream::ZERO_RTT);
// Set up an address in stale resolver cache.
HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
@@ -13020,7 +13212,6 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncErrorStaleAsync) {
// Socket data for stale connection which is supposed to disconnect.
MockQuicData quic_data(version_);
quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
int packet_number = 1;
if (VersionUsesHttp3(version_.transport_version)) {
quic_data.AddWrite(SYNCHRONOUS,
@@ -13053,10 +13244,6 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncErrorStaleAsync) {
// resolve returns error and then preconnect fails.
TEST_P(QuicStreamFactoryTest,
ResultAfterDNSRaceResolveAsyncErrorStaleAsyncError) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- // TODO(fayang): 0-rtt is not supported in IETF QUIC yet. Fix it.
- return;
- }
quic_params_->race_stale_dns_on_connection = true;
host_resolver_ = std::make_unique<MockCachingHostResolver>();
Initialize();
@@ -13066,8 +13253,6 @@ TEST_P(QuicStreamFactoryTest,
// Add asynchronous failure to host resolver.
host_resolver_->set_ondemand_mode(true);
factory_->set_is_quic_known_to_work_on_current_network(false);
- crypto_client_stream_factory_.set_handshake_mode(
- MockCryptoClientStream::ZERO_RTT);
host_resolver_->rules()->AddSimulatedFailure(host_port_pair_.host());
// Set up an address in stale resolver cache.
@@ -13084,7 +13269,6 @@ TEST_P(QuicStreamFactoryTest,
MockQuicData quic_data(version_);
quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
int packet_number = 1;
if (VersionUsesHttp3(version_.transport_version)) {
quic_data.AddWrite(SYNCHRONOUS,
@@ -13163,11 +13347,6 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceHostResolveAsync) {
// With stale dns and migration before handshake experiment on, migration failed
// after handshake confirmed, and then fresh resolve returns.
TEST_P(QuicStreamFactoryTest, StaleNetworkFailedAfterHandshake) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
quic_params_->race_stale_dns_on_connection = true;
host_resolver_ = std::make_unique<MockCachingHostResolver>();
@@ -13243,11 +13422,6 @@ TEST_P(QuicStreamFactoryTest, StaleNetworkFailedAfterHandshake) {
// With stale dns experiment on, the stale session is killed while waiting for
// handshake
TEST_P(QuicStreamFactoryTest, StaleNetworkFailedBeforeHandshake) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 &&
- version_.HasIetfQuicFrames()) {
- // 0-rtt is not supported in IETF QUIC yet.
- return;
- }
quic_params_->race_stale_dns_on_connection = true;
host_resolver_ = std::make_unique<MockCachingHostResolver>();
InitializeConnectionMigrationV2Test(
@@ -13326,7 +13500,7 @@ TEST_P(QuicStreamFactoryTest, StaleNetworkFailedBeforeHandshake) {
}
TEST_P(QuicStreamFactoryTest, ConfigInitialRttForHandshake) {
- if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ if (version_.UsesTls()) {
// IETF QUIC uses a different handshake timeout management system.
return;
}
diff --git a/chromium/net/quic/quic_test_packet_maker.cc b/chromium/net/quic/quic_test_packet_maker.cc
index db63151afa8..7539328b11e 100644
--- a/chromium/net/quic/quic_test_packet_maker.cc
+++ b/chromium/net/quic/quic_test_packet_maker.cc
@@ -91,6 +91,10 @@ quic::QuicFrames CloneFrames(const quic::QuicFrames& frames) {
frame.new_token_frame =
new quic::QuicNewTokenFrame(*frame.new_token_frame);
break;
+ case quic::ACK_FREQUENCY_FRAME:
+ frame.ack_frequency_frame =
+ new quic::QuicAckFrequencyFrame(*frame.ack_frequency_frame);
+ break;
case quic::NUM_FRAME_TYPES:
DCHECK(false) << "Cannot clone frame type: " << frame.type;
@@ -99,6 +103,15 @@ quic::QuicFrames CloneFrames(const quic::QuicFrames& frames) {
return new_frames;
}
+// TODO(crbug.com/1085541): Consider moving this method into QuicTestUtils.
+quic::QuicConnectionId TestConnectionId(uint64_t connection_number) {
+ const uint64_t connection_id64_net =
+ quiche::QuicheEndian::HostToNet64(connection_number);
+ return quic::QuicConnectionId(
+ reinterpret_cast<const char*>(&connection_id64_net),
+ sizeof(connection_id64_net));
+}
+
} // namespace
QuicTestPacketMaker::QuicTestPacketMaker(
@@ -120,8 +133,7 @@ QuicTestPacketMaker::QuicTestPacketMaker(
encryption_level_(quic::ENCRYPTION_FORWARD_SECURE),
long_header_type_(quic::INVALID_PACKET_TYPE),
client_headers_include_h2_stream_dependency_(
- client_headers_include_h2_stream_dependency &&
- version.transport_version >= quic::QUIC_VERSION_43),
+ client_headers_include_h2_stream_dependency),
save_packet_frames_(false) {
DCHECK(!(perspective_ == quic::Perspective::IS_SERVER &&
client_headers_include_h2_stream_dependency_));
@@ -246,7 +258,7 @@ std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeRstPacket(
InitializeHeader(num, include_version);
if (!version_.HasIetfQuicFrames() ||
- quic::QuicUtils::IsBidirectionalStreamId(stream_id)) {
+ quic::QuicUtils::IsBidirectionalStreamId(stream_id, version_)) {
AddQuicRstStreamFrame(stream_id, error_code);
}
@@ -299,6 +311,30 @@ QuicTestPacketMaker::MakeDataAndRstPacket(
}
std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeDataRstAndAckPacket(
+ uint64_t num,
+ bool include_version,
+ quic::QuicStreamId data_stream_id,
+ quiche::QuicheStringPiece data,
+ quic::QuicStreamId rst_stream_id,
+ quic::QuicRstStreamErrorCode rst_error_code,
+ uint64_t largest_received,
+ uint64_t smallest_received) {
+ InitializeHeader(num, include_version);
+
+ AddQuicAckFrame(largest_received, smallest_received);
+
+ AddQuicStreamFrame(data_stream_id, /* fin = */ false, data);
+ AddQuicRstStreamFrame(rst_stream_id, rst_error_code);
+
+ if (version_.HasIetfQuicFrames()) {
+ AddQuicStopSendingFrame(rst_stream_id, rst_error_code);
+ }
+
+ return BuildPacket();
+}
+
+std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndRstPacket(
uint64_t num,
bool include_version,
@@ -327,7 +363,7 @@ QuicTestPacketMaker::MakeAckAndRstPacket(
AddQuicAckFrame(largest_received, smallest_received);
if (!version_.HasIetfQuicFrames() ||
- quic::QuicUtils::IsBidirectionalStreamId(stream_id)) {
+ quic::QuicUtils::IsBidirectionalStreamId(stream_id, version_)) {
AddQuicRstStreamFrame(stream_id, error_code);
}
@@ -351,6 +387,8 @@ QuicTestPacketMaker::MakeRstAckAndConnectionClosePacket(
const std::string& quic_error_details) {
InitializeHeader(num, include_version);
+ AddQuicAckFrame(largest_received, smallest_received);
+
AddQuicRstStreamFrame(stream_id, error_code);
if (version_.HasIetfQuicFrames()) {
@@ -423,6 +461,8 @@ QuicTestPacketMaker::MakeDataRstAckAndConnectionClosePacket(
const std::string& quic_error_details) {
InitializeHeader(num, include_version);
+ AddQuicAckFrame(largest_received, smallest_received);
+
AddQuicStreamFrame(data_stream_id, /* fin = */ false, data);
AddQuicRstStreamFrame(rst_stream_id, error_code);
@@ -790,6 +830,44 @@ QuicTestPacketMaker::MakePriorityPacket(uint64_t packet_number,
}
std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeAckAndPriorityPacket(
+ uint64_t packet_number,
+ bool should_include_version,
+ uint64_t largest_received,
+ uint64_t smallest_received,
+ quic::QuicStreamId id,
+ quic::QuicStreamId parent_stream_id,
+ spdy::SpdyPriority priority) {
+ InitializeHeader(packet_number, should_include_version);
+
+ AddQuicAckFrame(largest_received, smallest_received);
+
+ if (!client_headers_include_h2_stream_dependency_) {
+ parent_stream_id = 0;
+ }
+ int weight = spdy::Spdy3PriorityToHttp2Weight(priority);
+ bool exclusive = client_headers_include_h2_stream_dependency_;
+
+ if (!VersionUsesHttp3(version_.transport_version)) {
+ spdy::SpdyPriorityIR priority_frame(id, parent_stream_id, weight,
+ exclusive);
+ spdy::SpdySerializedFrame spdy_frame(
+ spdy_request_framer_.SerializeFrame(priority_frame));
+ AddQuicStreamFrame(
+ GetHeadersStreamId(), false,
+ quiche::QuicheStringPiece(spdy_frame.data(), spdy_frame.size()));
+
+ return BuildPacket();
+ }
+ if (priority != quic::QuicStream::kDefaultUrgency) {
+ std::string priority_data = GenerateHttp3PriorityData(priority, id);
+ AddQuicStreamFrame(2, false, priority_data);
+ }
+
+ return BuildPacket();
+}
+
+std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndPriorityUpdatePacket(
uint64_t packet_number,
bool should_include_version,
@@ -809,6 +887,30 @@ QuicTestPacketMaker::MakeAckAndPriorityUpdatePacket(
}
std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeMultiplePriorityFramesPacket(
+ uint64_t packet_number,
+ bool should_include_version,
+ const std::vector<Http2StreamDependency>& priority_frames) {
+ InitializeHeader(packet_number, should_include_version);
+
+ const bool exclusive = client_headers_include_h2_stream_dependency_;
+ std::string coalesced_data;
+ for (const Http2StreamDependency& info : priority_frames) {
+ spdy::SpdyPriorityIR priority_frame(
+ info.stream_id, info.parent_stream_id,
+ spdy::Spdy3PriorityToHttp2Weight(info.spdy_priority), exclusive);
+ auto spdy_frame = spdy_request_framer_.SerializeFrame(priority_frame);
+ coalesced_data += std::string(spdy_frame.data(), spdy_frame.size());
+ }
+ AddQuicStreamFrame(quic::VersionUsesHttp3(version_.transport_version)
+ ? GetFirstBidirectionalStreamId()
+ : GetHeadersStreamId(),
+ false, coalesced_data);
+
+ return BuildPacket();
+}
+
+std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndMultiplePriorityFramesPacket(
uint64_t packet_number,
bool should_include_version,
@@ -847,6 +949,14 @@ QuicTestPacketMaker::MakeRetransmissionPacket(uint64_t original_packet_number,
saved_frames_[quic::QuicPacketNumber(original_packet_number)], nullptr);
}
+std::unique_ptr<quic::QuicEncryptedPacket>
+QuicTestPacketMaker::MakeStatelessResetPacket() {
+ auto connection_id = TestConnectionId(0x1337);
+ return quic::QuicFramer::BuildIetfStatelessResetPacket(
+ connection_id,
+ quic::QuicUtils::GenerateStatelessResetToken(connection_id));
+}
+
void QuicTestPacketMaker::RemoveSavedStreamFrames(
quic::QuicStreamId stream_id) {
for (auto& kv : saved_frames_) {
@@ -939,7 +1049,7 @@ std::string QuicTestPacketMaker::QpackEncodeHeaders(
&headers_frame_header);
// Possible add a PUSH stream type.
- if (!quic::QuicUtils::IsBidirectionalStreamId(stream_id) &&
+ if (!quic::QuicUtils::IsBidirectionalStreamId(stream_id, version_) &&
stream_offsets_[stream_id] == 0) {
// Push stream type header
data += "\x01";
@@ -1223,7 +1333,7 @@ spdy::SpdySerializedFrame QuicTestPacketMaker::MakeSpdyHeadersFrame(
}
bool QuicTestPacketMaker::ShouldIncludeVersion(bool include_version) const {
- if (version_.transport_version > quic::QUIC_VERSION_43) {
+ if (version_.HasIetfInvariantHeader()) {
return encryption_level_ < quic::ENCRYPTION_FORWARD_SECURE;
}
return include_version;
@@ -1231,7 +1341,7 @@ bool QuicTestPacketMaker::ShouldIncludeVersion(bool include_version) const {
quic::QuicPacketNumberLength QuicTestPacketMaker::GetPacketNumberLength()
const {
- if (version_.transport_version > quic::QUIC_VERSION_43 &&
+ if (version_.HasIetfInvariantHeader() &&
encryption_level_ < quic::ENCRYPTION_FORWARD_SECURE &&
!version_.SendsVariableLengthPacketNumberInLongHeader()) {
return quic::PACKET_4BYTE_PACKET_NUMBER;
diff --git a/chromium/net/quic/quic_test_packet_maker.h b/chromium/net/quic/quic_test_packet_maker.h
index 8df27cfbdb6..d0549ec20b2 100644
--- a/chromium/net/quic/quic_test_packet_maker.h
+++ b/chromium/net/quic/quic_test_packet_maker.h
@@ -116,6 +116,16 @@ class QuicTestPacketMaker {
quic::QuicStreamId rst_stream_id,
quic::QuicRstStreamErrorCode rst_error_code);
+ std::unique_ptr<quic::QuicReceivedPacket> MakeDataRstAndAckPacket(
+ uint64_t num,
+ bool include_version,
+ quic::QuicStreamId data_stream_id,
+ quiche::QuicheStringPiece data,
+ quic::QuicStreamId rst_stream_id,
+ quic::QuicRstStreamErrorCode rst_error_code,
+ uint64_t largest_received,
+ uint64_t smallest_received);
+
std::unique_ptr<quic::QuicReceivedPacket> MakeAckAndRstPacket(
uint64_t num,
bool include_version,
@@ -297,6 +307,20 @@ class QuicTestPacketMaker {
quic::QuicStreamId parent_stream_id,
spdy::SpdyPriority priority);
+ std::unique_ptr<quic::QuicReceivedPacket> MakeAckAndPriorityPacket(
+ uint64_t packet_number,
+ bool should_include_version,
+ uint64_t largest_received,
+ uint64_t smallest_received,
+ quic::QuicStreamId id,
+ quic::QuicStreamId parent_stream_id,
+ spdy::SpdyPriority priority);
+
+ std::unique_ptr<quic::QuicReceivedPacket> MakeMultiplePriorityFramesPacket(
+ uint64_t packet_number,
+ bool should_include_version,
+ const std::vector<Http2StreamDependency>& priority_frames);
+
std::unique_ptr<quic::QuicReceivedPacket>
MakeAckAndMultiplePriorityFramesPacket(
uint64_t packet_number,
@@ -320,6 +344,8 @@ class QuicTestPacketMaker {
quic::QuicStreamId id,
spdy::SpdyPriority priority);
+ std::unique_ptr<quic::QuicEncryptedPacket> MakeStatelessResetPacket();
+
// Removes all stream frames associated with |stream_id|.
void RemoveSavedStreamFrames(quic::QuicStreamId stream_id);
diff --git a/chromium/net/quic/quic_test_packet_printer.cc b/chromium/net/quic/quic_test_packet_printer.cc
index 2a5741df791..86edab085bd 100644
--- a/chromium/net/quic/quic_test_packet_printer.cc
+++ b/chromium/net/quic/quic_test_packet_printer.cc
@@ -180,6 +180,10 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface {
*output_ << "OnHandshakeDoneFrame: " << frame;
return true;
}
+ bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) override {
+ *output_ << "OnAckFrequencyFrame: " << frame;
+ return true;
+ }
void OnPacketComplete() override { *output_ << "OnPacketComplete\n"; }
bool IsValidStatelessResetToken(QuicUint128 token) const override {
*output_ << "IsValidStatelessResetToken\n";
diff --git a/chromium/net/quic/quic_transport_client.cc b/chromium/net/quic/quic_transport_client.cc
index 6da53b0ac2e..8b2c4f3ea69 100644
--- a/chromium/net/quic/quic_transport_client.cc
+++ b/chromium/net/quic/quic_transport_client.cc
@@ -4,6 +4,8 @@
#include "net/quic/quic_transport_client.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
#include "net/proxy_resolution/proxy_resolution_request.h"
@@ -17,6 +19,10 @@
namespace net {
namespace {
+// From
+// https://wicg.github.io/web-transport/#dom-quictransportconfiguration-server_certificate_fingerprints
+constexpr int kCustomCertificateMaxValidityDays = 14;
+
std::set<std::string> HostsFromOrigins(std::set<HostPortPair> origins) {
std::set<std::string> hosts;
for (const auto& origin : origins) {
@@ -24,17 +30,47 @@ std::set<std::string> HostsFromOrigins(std::set<HostPortPair> origins) {
}
return hosts;
}
+
+std::unique_ptr<quic::ProofVerifier> CreateProofVerifier(
+ const NetworkIsolationKey& isolation_key,
+ URLRequestContext* context,
+ const QuicTransportClient::Parameters& parameters) {
+ if (parameters.server_certificate_fingerprints.empty()) {
+ return std::make_unique<ProofVerifierChromium>(
+ context->cert_verifier(), context->ct_policy_enforcer(),
+ context->transport_security_state(),
+ context->cert_transparency_verifier(),
+ HostsFromOrigins(
+ context->quic_context()->params()->origins_to_force_quic_on),
+ isolation_key);
+ }
+
+ auto verifier = std::make_unique<quic::WebTransportFingerprintProofVerifier>(
+ context->quic_context()->clock(), kCustomCertificateMaxValidityDays);
+ for (const quic::CertificateFingerprint& fingerprint :
+ parameters.server_certificate_fingerprints) {
+ bool success = verifier->AddFingerprint(fingerprint);
+ if (!success) {
+ DLOG(WARNING) << "Failed to add a certificate fingerprint: "
+ << fingerprint.fingerprint;
+ }
+ }
+ return verifier;
+}
} // namespace
-constexpr quic::ParsedQuicVersion
- QuicTransportClient::kQuicVersionForOriginTrial;
+QuicTransportClient::Parameters::Parameters() = default;
+QuicTransportClient::Parameters::~Parameters() = default;
+QuicTransportClient::Parameters::Parameters(const Parameters&) = default;
+QuicTransportClient::Parameters::Parameters(Parameters&&) = default;
QuicTransportClient::QuicTransportClient(
const GURL& url,
const url::Origin& origin,
Visitor* visitor,
const NetworkIsolationKey& isolation_key,
- URLRequestContext* context)
+ URLRequestContext* context,
+ const Parameters& parameters)
: url_(url),
origin_(origin),
isolation_key_(isolation_key),
@@ -53,15 +89,8 @@ QuicTransportClient::QuicTransportClient(
// (currently, all certificate verification errors result in "TLS
// handshake error" even when more detailed message is available). This
// requires implementing ProofHandler::OnProofVerifyDetailsAvailable.
- crypto_config_(
- std::make_unique<ProofVerifierChromium>(
- context->cert_verifier(),
- context->ct_policy_enforcer(),
- context->transport_security_state(),
- context->cert_transparency_verifier(),
- std::set<std::string>(HostsFromOrigins(
- quic_context_->params()->origins_to_force_quic_on))),
- /* session_cache */ nullptr) {}
+ crypto_config_(CreateProofVerifier(isolation_key_, context, parameters),
+ /* session_cache */ nullptr) {}
QuicTransportClient::~QuicTransportClient() = default;
@@ -139,13 +168,13 @@ int QuicTransportClient::DoInit() {
// Ensure that for the duration of the origin trial, a fixed QUIC transport
// version is available.
- supported_versions_.push_back(kQuicVersionForOriginTrial);
+ supported_versions_ = QuicVersionsForWebTransportOriginTrial();
// Add other supported versions if available.
for (quic::ParsedQuicVersion& version :
quic_context_->params()->supported_versions) {
if (!quic::IsVersionValidForQuicTransport(version))
continue;
- if (version == kQuicVersionForOriginTrial)
+ if (base::Contains(supported_versions_, version))
continue; // Skip as we've already added it above.
supported_versions_.push_back(version);
}
@@ -227,6 +256,20 @@ int QuicTransportClient::DoConnect() {
if (rv != OK)
return rv;
+ CreateConnection();
+ next_connect_state_ = CONNECT_STATE_CONFIRM_CONNECTION;
+ return ERR_IO_PENDING;
+}
+
+void QuicTransportClient::CreateConnection() {
+ // Delete the objects in the same order they would be normally deleted by the
+ // destructor.
+ packet_reader_ = nullptr;
+ session_ = nullptr;
+ connection_ = nullptr;
+
+ IPEndPoint server_address =
+ *resolve_host_request_->GetAddressResults()->begin();
quic::QuicConnectionId connection_id =
quic::QuicUtils::CreateRandomConnectionId(
quic_context_->random_generator());
@@ -251,9 +294,6 @@ int QuicTransportClient::DoConnect() {
session_->Initialize();
packet_reader_->StartReading();
session_->CryptoConnect();
-
- next_connect_state_ = CONNECT_STATE_CONFIRM_CONNECTION;
- return ERR_IO_PENDING;
}
int QuicTransportClient::DoConfirmConnection() {
@@ -292,6 +332,18 @@ void QuicTransportClient::TransitionToState(State next_state) {
error_.safe_to_report_details = session_->alpn_received();
}
+ base::UmaHistogramEnumeration("Net.QuicTransportClient.FailedAtState",
+ last_state, NUM_STATES);
+ base::UmaHistogramSparse("Net.QuicTransportClient.Error",
+ std::abs(error_.net_error));
+ if (last_state == CONNECTING) {
+ base::UmaHistogramEnumeration(
+ "Net.QuicTransportClient.FailedAtConnectState", next_connect_state_,
+ CONNECT_STATE_NUM_STATES);
+ base::UmaHistogramSparse("Net.QuicTransportClient.ConnectionError",
+ std::abs(error_.net_error));
+ }
+
DCHECK_NE(error_.net_error, OK);
if (error_.details.empty()) {
error_.details = ErrorToString(error_.net_error);
@@ -372,7 +424,38 @@ void QuicTransportClient::OnConnectionClosed(
quic::QuicConnectionId /*server_connection_id*/,
quic::QuicErrorCode error,
const std::string& error_details,
- quic::ConnectionCloseSource /*source*/) {
+ quic::ConnectionCloseSource source) {
+ if (!retried_with_new_version_ &&
+ session_->error() == quic::QUIC_INVALID_VERSION) {
+ retried_with_new_version_ = true;
+ base::EraseIf(
+ supported_versions_, [this](const quic::ParsedQuicVersion& version) {
+ return !base::Contains(
+ session_->connection()->server_supported_versions(), version);
+ });
+ if (!supported_versions_.empty()) {
+ // Since this is a callback from QuicConnection, we can't replace the
+ // connection object in this method; do it from the top of the event loop
+ // instead.
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&QuicTransportClient::CreateConnection,
+ weak_factory_.GetWeakPtr()));
+ return;
+ }
+ // If there are no supported versions, treat this as a regular error.
+ }
+
+ std::string histogram_name;
+ switch (source) {
+ case quic::ConnectionCloseSource::FROM_SELF:
+ histogram_name = "Net.QuicTransportClient.ConnectionCloseCodeClient";
+ break;
+ case quic::ConnectionCloseSource::FROM_PEER:
+ histogram_name = "Net.QuicTransportClient.ConnectionCloseCodeServer";
+ break;
+ }
+ base::UmaHistogramSparse(histogram_name, error);
+
if (error == quic::QUIC_NO_ERROR) {
TransitionToState(CLOSED);
return;
@@ -392,17 +475,4 @@ void QuicTransportClient::OnConnectionClosed(
TransitionToState(FAILED);
}
-std::string QuicTransportErrorToString(const QuicTransportError& error) {
- std::string message =
- ExtendedErrorToString(error.net_error, error.quic_error);
- if (error.details == message)
- return message;
- return quiche::QuicheStrCat(message, " (", error.details, ")");
-}
-
-std::ostream& operator<<(std::ostream& os, const QuicTransportError& error) {
- os << QuicTransportErrorToString(error);
- return os;
-}
-
} // namespace net
diff --git a/chromium/net/quic/quic_transport_client.h b/chromium/net/quic/quic_transport_client.h
index 4f0f58ff8c8..de270225642 100644
--- a/chromium/net/quic/quic_transport_client.h
+++ b/chromium/net/quic/quic_transport_client.h
@@ -13,11 +13,13 @@
#include "net/quic/quic_chromium_packet_reader.h"
#include "net/quic/quic_chromium_packet_writer.h"
#include "net/quic/quic_context.h"
+#include "net/quic/quic_transport_error.h"
#include "net/socket/client_socket_factory.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h"
+#include "net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -27,29 +29,6 @@ class ProxyResolutionRequest;
class QuicChromiumAlarmFactory;
class URLRequestContext;
-struct NET_EXPORT QuicTransportError {
- // |net_error| is always set to a meaningful value.
- int net_error = OK;
-
- // |quic_error| is set to a QUIC error, or to quic::QUIC_NO_ERROR if the error
- // originates non-QUIC parts of the stack.
- quic::QuicErrorCode quic_error = quic::QUIC_NO_ERROR;
-
- // Human-readable error summary.
- std::string details;
-
- // QuicTransport requires that the connection errors have to be
- // undistinguishable until the peer is confirmed to be a QuicTransport
- // endpoint. See https://wicg.github.io/web-transport/#protocol-security
- bool safe_to_report_details = false;
-};
-
-NET_EXPORT
-std::string QuicTransportErrorToString(const QuicTransportError& error);
-
-NET_EXPORT
-std::ostream& operator<<(std::ostream& os, const QuicTransportError& error);
-
// QuicTransportClient is the top-level API for QuicTransport in //net.
class NET_EXPORT QuicTransportClient
: public quic::QuicTransportClientSession::ClientVisitor,
@@ -65,6 +44,9 @@ class NET_EXPORT QuicTransportClient
// | |
// +---> FAILED <---+
//
+ // These values are logged to UMA. Entries should not be renumbered and
+ // numeric values should never be reused. Please keep in sync with
+ // "QuicTransportClientState" in src/tools/metrics/histograms/enums.xml.
enum State {
// The client object has been created but Connect() has not been called.
NEW,
@@ -78,6 +60,9 @@ class NET_EXPORT QuicTransportClient
CLOSED,
// The connection has been closed abruptly.
FAILED,
+
+ // Total number of possible states.
+ NUM_STATES,
};
class NET_EXPORT Visitor {
@@ -97,17 +82,35 @@ class NET_EXPORT QuicTransportClient
virtual void OnCanCreateNewOutgoingUnidirectionalStream() = 0;
};
- // QUIC protocol version that is used in the origin trial.
- static constexpr quic::ParsedQuicVersion kQuicVersionForOriginTrial =
- quic::ParsedQuicVersion(quic::PROTOCOL_TLS1_3,
- quic::QUIC_VERSION_IETF_DRAFT_27);
+ struct NET_EXPORT Parameters {
+ Parameters();
+ ~Parameters();
+ Parameters(const Parameters&);
+ Parameters(Parameters&&);
+
+ // A vector of fingerprints for expected server certificates, as described
+ // in
+ // https://wicg.github.io/web-transport/#dom-quictransportconfiguration-server_certificate_fingerprints
+ // When empty, Web PKI is used.
+ std::vector<quic::CertificateFingerprint> server_certificate_fingerprints;
+ };
+
+ // QUIC protocol versions that are used in the origin trial.
+ static quic::ParsedQuicVersionVector
+ QuicVersionsForWebTransportOriginTrial() {
+ return quic::ParsedQuicVersionVector{
+ quic::ParsedQuicVersion::Draft29(), // Enabled in M85.
+ quic::ParsedQuicVersion::Draft27() // Enabled in M84.
+ };
+ }
// |visitor| and |context| must outlive this object.
QuicTransportClient(const GURL& url,
const url::Origin& origin,
Visitor* visitor,
const NetworkIsolationKey& isolation_key,
- URLRequestContext* context);
+ URLRequestContext* context,
+ const Parameters& parameters);
~QuicTransportClient() override;
State state() const { return state_; }
@@ -154,6 +157,11 @@ class NET_EXPORT QuicTransportClient
private:
// State of the connection establishment process.
+ //
+ // These values are logged to UMA. Entries should not be renumbered and
+ // numeric values should never be reused. Please keep in sync with
+ // "QuicTransportClientConnectState" in
+ // src/tools/metrics/histograms/enums.xml.
enum ConnectState {
CONNECT_STATE_NONE,
CONNECT_STATE_INIT,
@@ -163,6 +171,8 @@ class NET_EXPORT QuicTransportClient
CONNECT_STATE_RESOLVE_HOST_COMPLETE,
CONNECT_STATE_CONNECT,
CONNECT_STATE_CONFIRM_CONNECTION,
+
+ CONNECT_STATE_NUM_STATES,
};
// DoLoop processing the Connect() call.
@@ -177,6 +187,7 @@ class NET_EXPORT QuicTransportClient
int DoResolveHostComplete(int rv);
// Establishes the QUIC connection.
int DoConnect();
+ void CreateConnection();
// Verifies that the connection has succeeded.
int DoConfirmConnection();
@@ -201,6 +212,7 @@ class NET_EXPORT QuicTransportClient
State state_ = NEW;
ConnectState next_connect_state_ = CONNECT_STATE_NONE;
QuicTransportError error_;
+ bool retried_with_new_version_ = false;
ProxyInfo proxy_info_;
std::unique_ptr<ProxyResolutionRequest> proxy_resolution_request_;
diff --git a/chromium/net/quic/quic_transport_end_to_end_test.cc b/chromium/net/quic/quic_transport_end_to_end_test.cc
index 9783a05ac60..95ae1538fa6 100644
--- a/chromium/net/quic/quic_transport_end_to_end_test.cc
+++ b/chromium/net/quic/quic_transport_end_to_end_test.cc
@@ -10,6 +10,7 @@
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
+#include "net/quic/crypto/proof_source_chromium.h"
#include "net/test/test_data_directory.h"
#include "net/test/test_with_task_environment.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
@@ -37,10 +38,48 @@ class MockVisitor : public QuicTransportClient::Visitor {
MOCK_METHOD0(OnCanCreateNewOutgoingUnidirectionalStream, void());
};
+// A clock that only mocks out WallNow(), but uses real Now() and
+// ApproximateNow(). Useful for certificate verification.
+class TestWallClock : public quic::QuicClock {
+ public:
+ quic::QuicTime Now() const override {
+ return quic::QuicChromiumClock::GetInstance()->Now();
+ }
+ quic::QuicTime ApproximateNow() const override {
+ return quic::QuicChromiumClock::GetInstance()->ApproximateNow();
+ }
+ quic::QuicWallTime WallNow() const override { return wall_now_; }
+
+ void set_wall_now(quic::QuicWallTime now) { wall_now_ = now; }
+
+ private:
+ quic::QuicWallTime wall_now_ = quic::QuicWallTime::Zero();
+};
+
+class TestConnectionHelper : public quic::QuicConnectionHelperInterface {
+ public:
+ const quic::QuicClock* GetClock() const override { return &clock_; }
+ quic::QuicRandom* GetRandomGenerator() override {
+ return quic::QuicRandom::GetInstance();
+ }
+ quic::QuicBufferAllocator* GetStreamSendBufferAllocator() override {
+ return &allocator_;
+ }
+
+ TestWallClock& clock() { return clock_; }
+
+ private:
+ TestWallClock clock_;
+ quic::SimpleBufferAllocator allocator_;
+};
+
class QuicTransportEndToEndTest : public TestWithTaskEnvironment {
public:
QuicTransportEndToEndTest() {
- quic::QuicEnableVersion(QuicTransportClient::kQuicVersionForOriginTrial);
+ for (const quic::ParsedQuicVersion& version :
+ QuicTransportClient::QuicVersionsForWebTransportOriginTrial()) {
+ quic::QuicEnableVersion(version);
+ }
origin_ = url::Origin::Create(GURL{"https://example.org"});
isolation_key_ = NetworkIsolationKey(origin_, origin_);
@@ -56,7 +95,9 @@ class QuicTransportEndToEndTest : public TestWithTaskEnvironment {
host_resolver->rules()->AddRule("test.example.com", "127.0.0.1");
builder.set_host_resolver(std::move(host_resolver));
- auto quic_context = std::make_unique<QuicContext>();
+ auto helper = std::make_unique<TestConnectionHelper>();
+ helper_ = helper.get();
+ auto quic_context = std::make_unique<QuicContext>(std::move(helper));
quic_context->params()->supported_versions.clear();
// This is required to bypass the check that only allows known certificate
// roots in QUIC.
@@ -75,8 +116,6 @@ class QuicTransportEndToEndTest : public TestWithTaskEnvironment {
LOG(INFO) << "Connection error: " << client_->error();
run_loop_->Quit();
});
-
- StartServer();
}
GURL GetURL(const std::string& suffix) {
@@ -84,10 +123,13 @@ class QuicTransportEndToEndTest : public TestWithTaskEnvironment {
"quic-transport://test.example.com:", port_, suffix)};
}
- void StartServer() {
+ void StartServer(std::unique_ptr<quic::ProofSource> proof_source = nullptr) {
+ if (proof_source == nullptr) {
+ proof_source = quic::test::crypto_test_utils::ProofSourceForTesting();
+ }
server_ = std::make_unique<QuicTransportSimpleServer>(
/* port */ 0, std::vector<url::Origin>({origin_}),
- quic::test::crypto_test_utils::ProofSourceForTesting());
+ std::move(proof_source));
ASSERT_EQ(EXIT_SUCCESS, server_->Start());
port_ = server_->server_address().port();
}
@@ -105,6 +147,7 @@ class QuicTransportEndToEndTest : public TestWithTaskEnvironment {
QuicFlagSaver flags_; // Save/restore all QUIC flag values.
std::unique_ptr<URLRequestContext> context_;
std::unique_ptr<QuicTransportClient> client_;
+ TestConnectionHelper* helper_; // Owned by |context_|.
MockVisitor visitor_;
std::unique_ptr<QuicTransportSimpleServer> server_;
std::unique_ptr<base::RunLoop> run_loop_;
@@ -115,8 +158,10 @@ class QuicTransportEndToEndTest : public TestWithTaskEnvironment {
};
TEST_F(QuicTransportEndToEndTest, Connect) {
+ StartServer();
client_ = std::make_unique<QuicTransportClient>(
- GetURL("/discard"), origin_, &visitor_, isolation_key_, context_.get());
+ GetURL("/discard"), origin_, &visitor_, isolation_key_, context_.get(),
+ QuicTransportClient::Parameters());
client_->Connect();
EXPECT_CALL(visitor_, OnConnected()).WillOnce(StopRunning());
Run();
@@ -125,8 +170,10 @@ TEST_F(QuicTransportEndToEndTest, Connect) {
}
TEST_F(QuicTransportEndToEndTest, EchoUnidirectionalStream) {
+ StartServer();
client_ = std::make_unique<QuicTransportClient>(
- GetURL("/echo"), origin_, &visitor_, isolation_key_, context_.get());
+ GetURL("/echo"), origin_, &visitor_, isolation_key_, context_.get(),
+ QuicTransportClient::Parameters());
client_->Connect();
EXPECT_CALL(visitor_, OnConnected()).WillOnce(StopRunning());
Run();
@@ -151,6 +198,107 @@ TEST_F(QuicTransportEndToEndTest, EchoUnidirectionalStream) {
EXPECT_EQ("test", data);
}
+TEST_F(QuicTransportEndToEndTest, CertificateFingerprint) {
+ auto proof_source = std::make_unique<net::ProofSourceChromium>();
+ base::FilePath certs_dir = net::GetTestCertsDirectory();
+ ASSERT_TRUE(proof_source->Initialize(
+ certs_dir.AppendASCII("quic-short-lived.pem"),
+ certs_dir.AppendASCII("quic-leaf-cert.key"),
+ certs_dir.AppendASCII("quic-leaf-cert.key.sct")));
+ StartServer(std::move(proof_source));
+ // Set clock to a time in which quic-short-lived.pem is valid
+ // (2020-06-05T20:35:00.000Z).
+ helper_->clock().set_wall_now(
+ quic::QuicWallTime::FromUNIXSeconds(1591389300));
+
+ QuicTransportClient::Parameters parameters;
+ parameters.server_certificate_fingerprints.push_back(
+ quic::CertificateFingerprint{
+ .algorithm = quic::CertificateFingerprint::kSha256,
+ .fingerprint = "ED:3D:D7:C3:67:10:94:68:D1:DC:D1:26:5C:B2:74:D7:1C:"
+ "A2:63:3E:94:94:C0:84:39:D6:64:FA:08:B9:77:37"});
+ client_ = std::make_unique<QuicTransportClient>(GetURL("/discard"), origin_,
+ &visitor_, isolation_key_,
+ context_.get(), parameters);
+ client_->Connect();
+ EXPECT_CALL(visitor_, OnConnected()).WillOnce(StopRunning());
+ Run();
+ ASSERT_TRUE(client_->session() != nullptr);
+ EXPECT_TRUE(client_->session()->IsSessionReady());
+}
+
+TEST_F(QuicTransportEndToEndTest, CertificateFingerprintValidiyTooLong) {
+ StartServer();
+ QuicTransportClient::Parameters parameters;
+ // The default QUIC test certificate is valid for ten years, which exceeds
+ // the two-week limit.
+ parameters.server_certificate_fingerprints.push_back(
+ quic::CertificateFingerprint{
+ .algorithm = quic::CertificateFingerprint::kSha256,
+ .fingerprint = "25:17:B1:79:76:C8:94:BD:F0:B5:5C:0B:CC:70:C8:69:2B:"
+ "27:B8:84:F0:30:FE:A8:62:99:37:63:D2:A9:D6:EE"});
+ client_ = std::make_unique<QuicTransportClient>(GetURL("/discard"), origin_,
+ &visitor_, isolation_key_,
+ context_.get(), parameters);
+ client_->Connect();
+ EXPECT_CALL(visitor_, OnConnectionFailed()).WillOnce(StopRunning());
+ Run();
+ EXPECT_TRUE(client_->session() == nullptr);
+ EXPECT_EQ(client_->error().quic_error, quic::QUIC_HANDSHAKE_FAILED);
+}
+
+TEST_F(QuicTransportEndToEndTest, CertificateFingerprintMismatch) {
+ StartServer();
+
+ QuicTransportClient::Parameters parameters;
+ parameters.server_certificate_fingerprints.push_back(
+ quic::CertificateFingerprint{
+ .algorithm = quic::CertificateFingerprint::kSha256,
+ .fingerprint = "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:"
+ "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"});
+ client_ = std::make_unique<QuicTransportClient>(GetURL("/discard"), origin_,
+ &visitor_, isolation_key_,
+ context_.get(), parameters);
+ client_->Connect();
+ EXPECT_CALL(visitor_, OnConnectionFailed()).WillOnce(StopRunning());
+ Run();
+ EXPECT_TRUE(client_->session() == nullptr);
+ EXPECT_EQ(client_->error().quic_error, quic::QUIC_HANDSHAKE_FAILED);
+}
+
+TEST_F(QuicTransportEndToEndTest, OldVersion) {
+ // Ensure all WebTransport versions are enabled except the first one.
+ quic::QuicDisableVersion(
+ QuicTransportClient::QuicVersionsForWebTransportOriginTrial().front());
+
+ StartServer();
+ client_ = std::make_unique<QuicTransportClient>(
+ GetURL("/discard"), origin_, &visitor_, isolation_key_, context_.get(),
+ QuicTransportClient::Parameters());
+ client_->Connect();
+ EXPECT_CALL(visitor_, OnConnected()).WillOnce(StopRunning());
+ Run();
+ ASSERT_TRUE(client_->session() != nullptr);
+ EXPECT_TRUE(client_->session()->IsSessionReady());
+}
+
+TEST_F(QuicTransportEndToEndTest, NoCommonVersion) {
+ // Disable all WebTransport versions.
+ for (const quic::ParsedQuicVersion& version :
+ QuicTransportClient::QuicVersionsForWebTransportOriginTrial()) {
+ quic::QuicDisableVersion(version);
+ }
+
+ StartServer();
+ client_ = std::make_unique<QuicTransportClient>(
+ GetURL("/discard"), origin_, &visitor_, isolation_key_, context_.get(),
+ QuicTransportClient::Parameters());
+ client_->Connect();
+ EXPECT_CALL(visitor_, OnConnectionFailed()).WillOnce(StopRunning());
+ Run();
+ EXPECT_TRUE(client_->session() == nullptr);
+ EXPECT_EQ(client_->error().quic_error, quic::QUIC_INVALID_VERSION);
+}
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_transport_error.cc b/chromium/net/quic/quic_transport_error.cc
new file mode 100644
index 00000000000..8c76d6705e9
--- /dev/null
+++ b/chromium/net/quic/quic_transport_error.cc
@@ -0,0 +1,24 @@
+// Copyright 2020 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.
+
+#include "net/quic/quic_transport_error.h"
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+
+namespace net {
+
+std::string QuicTransportErrorToString(const QuicTransportError& error) {
+ std::string message =
+ ExtendedErrorToString(error.net_error, error.quic_error);
+ if (error.details == message)
+ return message;
+ return quiche::QuicheStrCat(message, " (", error.details, ")");
+}
+
+std::ostream& operator<<(std::ostream& os, const QuicTransportError& error) {
+ os << QuicTransportErrorToString(error);
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/quic_transport_error.h b/chromium/net/quic/quic_transport_error.h
new file mode 100644
index 00000000000..d970e094074
--- /dev/null
+++ b/chromium/net/quic/quic_transport_error.h
@@ -0,0 +1,53 @@
+// Copyright 2020 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 NET_QUIC_QUIC_TRANSPORT_ERROR_H_
+#define NET_QUIC_QUIC_TRANSPORT_ERROR_H_
+
+#include <ostream>
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_export.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+
+namespace net {
+
+struct NET_EXPORT QuicTransportError {
+ QuicTransportError() = default;
+ QuicTransportError(int net_error,
+ quic::QuicErrorCode quic_error,
+ base::StringPiece details,
+ bool safe_to_report_details)
+ : net_error(net_error),
+ quic_error(quic_error),
+ details(details),
+ safe_to_report_details(safe_to_report_details) {}
+
+ // |net_error| is always set to a meaningful value.
+ int net_error = OK;
+
+ // |quic_error| is set to a QUIC error, or to quic::QUIC_NO_ERROR if the error
+ // originates non-QUIC parts of the stack.
+ quic::QuicErrorCode quic_error = quic::QUIC_NO_ERROR;
+
+ // Human-readable error summary.
+ std::string details;
+
+ // QuicTransport requires that the connection errors have to be
+ // undistinguishable until the peer is confirmed to be a QuicTransport
+ // endpoint. See https://wicg.github.io/web-transport/#protocol-security
+ bool safe_to_report_details = false;
+};
+
+NET_EXPORT
+std::string QuicTransportErrorToString(const QuicTransportError& error);
+
+NET_EXPORT
+std::ostream& operator<<(std::ostream& os, const QuicTransportError& error);
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_TRANSPORT_ERROR_H_
diff --git a/chromium/net/quic/quic_transport_parameters_fuzzer.cc b/chromium/net/quic/quic_transport_parameters_fuzzer.cc
index 4225bc00b6b..e6b1b129f7a 100644
--- a/chromium/net/quic/quic_transport_parameters_fuzzer.cc
+++ b/chromium/net/quic/quic_transport_parameters_fuzzer.cc
@@ -19,14 +19,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
quic::TransportParameters transport_parameters;
std::vector<uint8_t> remaining_bytes =
data_provider.ConsumeRemainingBytes<uint8_t>();
- quic::ParsedQuicVersion version = quic::UnsupportedQuicVersion();
- for (const quic::ParsedQuicVersion& vers : quic::AllSupportedVersions()) {
- if (vers.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- version = vers;
- break;
- }
- }
- CHECK_NE(version.transport_version, quic::QUIC_VERSION_UNSUPPORTED);
+ quic::ParsedQuicVersion version = quic::AllSupportedVersionsWithTls().front();
+ CHECK(version.UsesTls());
std::string error_details;
quic::ParseTransportParameters(version, perspective, remaining_bytes.data(),
remaining_bytes.size(), &transport_parameters,
diff --git a/chromium/net/quic/quic_utils_chromium.cc b/chromium/net/quic/quic_utils_chromium.cc
deleted file mode 100644
index 90e08fcfa11..00000000000
--- a/chromium/net/quic/quic_utils_chromium.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2016 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.
-
-#include "net/quic/quic_utils_chromium.h"
-
-#include "base/containers/adapters.h"
-#include "base/strings/string_split.h"
-#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
-
-namespace net {
-
-quic::QuicTagVector ParseQuicConnectionOptions(
- const std::string& connection_options) {
- quic::QuicTagVector options;
- // Tokens are expected to be no more than 4 characters long, but
- // handle overflow gracefully.
- for (const quiche::QuicheStringPiece& token :
- base::SplitStringPiece(connection_options, ",", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_ALL)) {
- uint32_t option = 0;
- for (char token_char : base::Reversed(token)) {
- option <<= 8;
- option |= static_cast<unsigned char>(token_char);
- }
- options.push_back(option);
- }
- return options;
-}
-
-} // namespace net
diff --git a/chromium/net/quic/quic_utils_chromium.h b/chromium/net/quic/quic_utils_chromium.h
deleted file mode 100644
index 7f8a7de9064..00000000000
--- a/chromium/net/quic/quic_utils_chromium.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2014 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.
-//
-// Some helpers for quic that are for chromium codebase.
-
-#ifndef NET_QUIC_QUIC_UTILS_CHROMIUM_H_
-#define NET_QUIC_QUIC_UTILS_CHROMIUM_H_
-
-#include <string>
-
-#include "base/logging.h"
-#include "net/base/net_export.h"
-#include "net/third_party/quiche/src/quic/core/quic_tag.h"
-#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-
-namespace net {
-
-// Returns the list of QUIC tags represented by the comma separated
-// string in |connection_options|.
-NET_EXPORT quic::QuicTagVector ParseQuicConnectionOptions(
- const std::string& connection_options);
-
-} // namespace net
-
-#endif // NET_QUIC_QUIC_UTILS_CHROMIUM_H_
diff --git a/chromium/net/quic/quic_utils_chromium_test.cc b/chromium/net/quic/quic_utils_chromium_test.cc
deleted file mode 100644
index 2af22a0d5e3..00000000000
--- a/chromium/net/quic/quic_utils_chromium_test.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2014 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.
-
-#include "net/quic/quic_utils_chromium.h"
-
-#include <map>
-
-#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::ElementsAre;
-using ::testing::IsEmpty;
-
-namespace net {
-namespace test {
-namespace {
-
-TEST(QuicUtilsChromiumTest, ParseQuicConnectionOptions) {
- quic::QuicTagVector empty_options = ParseQuicConnectionOptions("");
- EXPECT_TRUE(empty_options.empty());
-
- quic::QuicTagVector parsed_options =
- ParseQuicConnectionOptions("TIMER,TBBR,REJ");
- quic::QuicTagVector expected_options;
- expected_options.push_back(quic::kTIME);
- expected_options.push_back(quic::kTBBR);
- expected_options.push_back(quic::kREJ);
- EXPECT_EQ(expected_options, parsed_options);
-}
-
-} // namespace
-} // namespace test
-} // namespace net