diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-06 12:48:11 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:33:43 +0000 |
commit | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (patch) | |
tree | fa14ba0ca8d2683ba2efdabd246dc9b18a1229c6 /chromium/net/quic | |
parent | 79b4f909db1049fca459c07cca55af56a9b54fe3 (diff) | |
download | qtwebengine-chromium-7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3.tar.gz |
BASELINE: Update Chromium to 84.0.4147.141
Change-Id: Ib85eb4cfa1cbe2b2b81e5022c8cad5c493969535
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/net/quic')
47 files changed, 1306 insertions, 1234 deletions
diff --git a/chromium/net/quic/address_utils.h b/chromium/net/quic/address_utils.h index 286146ccd73..3c8d096257d 100644 --- a/chromium/net/quic/address_utils.h +++ b/chromium/net/quic/address_utils.h @@ -5,6 +5,8 @@ #ifndef NET_QUIC_ADDRESS_UTILS_H_ #define NET_QUIC_ADDRESS_UTILS_H_ +#include <string.h> + #include "net/base/ip_address.h" #include "net/base/ip_endpoint.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h" diff --git a/chromium/net/quic/bidirectional_stream_quic_impl.cc b/chromium/net/quic/bidirectional_stream_quic_impl.cc index 84260c10264..a8d332f2f21 100644 --- a/chromium/net/quic/bidirectional_stream_quic_impl.cc +++ b/chromium/net/quic/bidirectional_stream_quic_impl.cc @@ -84,12 +84,12 @@ void BidirectionalStreamQuicImpl::Start( delegate_ = delegate; request_info_ = request_info; - // Only allow SAFE methods to use early data, unless overriden by the caller. - bool use_early_data = !HttpUtil::IsMethodSafe(request_info_->method); + // Only allow SAFE methods to use early data, unless overridden by the caller. + bool use_early_data = HttpUtil::IsMethodSafe(request_info_->method); use_early_data |= request_info_->allow_early_data_override; int rv = session_->RequestStream( - use_early_data, + !use_early_data, base::BindOnce(&BidirectionalStreamQuicImpl::OnStreamReady, weak_factory_.GetWeakPtr()), traffic_annotation); diff --git a/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc b/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc index 3fbb7b393e0..6cfc33e5862 100644 --- a/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc +++ b/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc @@ -425,7 +425,6 @@ class BidirectionalStreamQuicImplTest protected: static const bool kFin = true; static const bool kIncludeVersion = true; - static const bool kIncludeCongestionFeedback = true; // Holds a packet to be written to the wire, and the IO mode that should // be used by the mock socket when performing the write. @@ -742,7 +741,7 @@ class BidirectionalStreamQuicImplTest return client_maker_.MakeAckAndRstPacket( ++packet_number_, !kIncludeVersion, stream_id_, quic::QUIC_STREAM_CANCELLED, largest_received, smallest_received, - least_unacked, !kIncludeCongestionFeedback); + least_unacked); } std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndDataPacket( @@ -768,8 +767,7 @@ class BidirectionalStreamQuicImplTest uint64_t smallest_received, uint64_t least_unacked) { return client_maker_.MakeAckPacket(++packet_number_, largest_received, - smallest_received, least_unacked, - !kIncludeCongestionFeedback); + smallest_received, least_unacked); } std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket( @@ -778,8 +776,7 @@ class BidirectionalStreamQuicImplTest uint64_t smallest_received, uint64_t least_unacked) { return server_maker_.MakeAckPacket(packet_number, largest_received, - smallest_received, least_unacked, - !kIncludeCongestionFeedback); + smallest_received, least_unacked); } std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() { @@ -1650,18 +1647,10 @@ TEST_P(BidirectionalStreamQuicImplTest, EarlyDataOverrideRequest) { client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT); if (VersionUsesHttp3(version_.transport_version)) AddWrite(ConstructInitialSettingsPacket()); - client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE); AddWrite(ConstructRequestHeadersPacketInner( - GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY, + GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length)); - std::string header = ConstructDataHeader(strlen(kUploadData)); - if (version_.UsesHttp3()) { - AddWrite(ConstructClientDataPacket(kIncludeVersion, kFin, - header + std::string(kUploadData))); - } else { - AddWrite(ConstructClientDataPacket(kIncludeVersion, kFin, kUploadData)); - } - + client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE); AddWrite(ConstructClientAckPacket(3, 1, 2)); Initialize(); @@ -1670,50 +1659,51 @@ TEST_P(BidirectionalStreamQuicImplTest, EarlyDataOverrideRequest) { request.method = "PUT"; request.allow_early_data_override = true; request.url = GURL("http://www.google.com/"); - request.end_stream_on_headers = false; + request.end_stream_on_headers = true; request.priority = DEFAULT_PRIORITY; scoped_refptr<IOBuffer> read_buffer = base::MakeRefCounted<IOBuffer>(kReadBufferSize); std::unique_ptr<TestDelegateBase> delegate( new TestDelegateBase(read_buffer.get(), kReadBufferSize)); + delegate->set_trailers_expected(true); delegate->Start(&request, net_log().bound(), session()->CreateHandle(destination_)); - ConfirmHandshake(); delegate->WaitUntilNextCallback(kOnStreamReady); - - // Send a DATA frame. - scoped_refptr<StringIOBuffer> buf = - base::MakeRefCounted<StringIOBuffer>(kUploadData); - - delegate->SendData(buf, buf->size(), true); - delegate->WaitUntilNextCallback(kOnDataSent); + ConfirmHandshake(); // Server acks the request. ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1)); // Server sends the response headers. spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); + size_t spdy_response_headers_frame_length; ProcessPacket( ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers), &spdy_response_headers_frame_length)); delegate->WaitUntilNextCallback(kOnHeadersReceived); + LoadTimingInfo load_timing_info; + EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info)); + ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false); TestCompletionCallback cb; int rv = delegate->ReadData(cb.callback()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); EXPECT_EQ("200", delegate->response_headers().find(":status")->second); const char kResponseBody[] = "Hello world!"; // Server sends data. - std::string header2 = ConstructDataHeader(strlen(kResponseBody)); + std::string header = ConstructDataHeader(strlen(kResponseBody)); ProcessPacket(ConstructServerDataPacket(3, !kIncludeVersion, !kFin, - header2 + kResponseBody)); + header + kResponseBody)); + EXPECT_EQ(12, cb.WaitForResult()); - EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), cb.WaitForResult()); + EXPECT_EQ(std::string(kResponseBody), delegate->data_received()); + TestCompletionCallback cb2; + EXPECT_THAT(delegate->ReadData(cb2.callback()), IsError(ERR_IO_PENDING)); - size_t spdy_trailers_frame_length; spdy::SpdyHeaderBlock trailers; + size_t spdy_trailers_frame_length; trailers["foo"] = "bar"; if (!quic::VersionUsesHttp3(version_.transport_version)) { trailers[quic::kFinalOffsetHeaderKey] = @@ -1724,20 +1714,36 @@ TEST_P(BidirectionalStreamQuicImplTest, EarlyDataOverrideRequest) { &spdy_trailers_frame_length)); delegate->WaitUntilNextCallback(kOnTrailersReceived); + EXPECT_THAT(cb2.WaitForResult(), IsOk()); trailers.erase(quic::kFinalOffsetHeaderKey); EXPECT_EQ(trailers, delegate->trailers()); - EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk()); - EXPECT_EQ(1, delegate->on_data_read_count()); - EXPECT_EQ(1, delegate->on_data_sent_count()); + EXPECT_THAT(delegate->ReadData(cb2.callback()), IsOk()); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(2, delegate->on_data_read_count()); + EXPECT_EQ(0, delegate->on_data_sent_count()); EXPECT_EQ(kProtoQUIC, delegate->GetProtocol()); - EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length + - strlen(kUploadData) + header.length()), + EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length), delegate->GetTotalSentBytes()); EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length + - strlen(kResponseBody) + header2.length() + + strlen(kResponseBody) + header.length() + spdy_trailers_frame_length), delegate->GetTotalReceivedBytes()); + // Check that NetLog was filled as expected. + auto entries = net_log().GetEntries(); + size_t pos = ExpectLogContainsSomewhere( + entries, /*min_offset=*/0, + NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS, + NetLogEventPhase::NONE); + pos = ExpectLogContainsSomewhere( + entries, /*min_offset=*/pos, + NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS, + NetLogEventPhase::NONE); + ExpectLogContainsSomewhere( + entries, /*min_offset=*/pos, + NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS, + NetLogEventPhase::NONE); } TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) { diff --git a/chromium/net/quic/crypto/proof_source_chromium.cc b/chromium/net/quic/crypto/proof_source_chromium.cc index e62642c7d5a..39e76c5df32 100644 --- a/chromium/net/quic/crypto/proof_source_chromium.cc +++ b/chromium/net/quic/crypto/proof_source_chromium.cc @@ -130,6 +130,7 @@ bool ProofSourceChromium::GetProofInner( } void ProofSourceChromium::GetProof(const quic::QuicSocketAddress& server_addr, + const quic::QuicSocketAddress& client_addr, const std::string& hostname, const std::string& server_config, quic::QuicTransportVersion quic_version, @@ -149,12 +150,14 @@ void ProofSourceChromium::GetProof(const quic::QuicSocketAddress& server_addr, quic::QuicReferenceCountedPointer<quic::ProofSource::Chain> ProofSourceChromium::GetCertChain(const quic::QuicSocketAddress& server_address, + const quic::QuicSocketAddress& client_address, const std::string& hostname) { return chain_; } void ProofSourceChromium::ComputeTlsSignature( const quic::QuicSocketAddress& server_address, + const quic::QuicSocketAddress& client_address, const std::string& hostname, uint16_t signature_algorithm, quiche::QuicheStringPiece in, @@ -188,4 +191,13 @@ void ProofSourceChromium::ComputeTlsSignature( callback->Run(true, sig, nullptr); } +quic::ProofSource::TicketCrypter* ProofSourceChromium::GetTicketCrypter() { + return ticket_crypter_.get(); +} + +void ProofSourceChromium::SetTicketCrypter( + std::unique_ptr<quic::ProofSource::TicketCrypter> ticket_crypter) { + ticket_crypter_ = std::move(ticket_crypter); +} + } // namespace net diff --git a/chromium/net/quic/crypto/proof_source_chromium.h b/chromium/net/quic/crypto/proof_source_chromium.h index 46f92c50021..c16a2073b41 100644 --- a/chromium/net/quic/crypto/proof_source_chromium.h +++ b/chromium/net/quic/crypto/proof_source_chromium.h @@ -33,7 +33,8 @@ class NET_EXPORT_PRIVATE ProofSourceChromium : public quic::ProofSource { const base::FilePath& sct_path); // quic::ProofSource interface - void GetProof(const quic::QuicSocketAddress& server_ip, + void GetProof(const quic::QuicSocketAddress& server_address, + const quic::QuicSocketAddress& client_address, const std::string& hostname, const std::string& server_config, quic::QuicTransportVersion quic_version, @@ -42,15 +43,20 @@ class NET_EXPORT_PRIVATE ProofSourceChromium : public quic::ProofSource { quic::QuicReferenceCountedPointer<Chain> GetCertChain( const quic::QuicSocketAddress& server_address, + const quic::QuicSocketAddress& client_address, const std::string& hostname) override; void ComputeTlsSignature( const quic::QuicSocketAddress& server_address, + const quic::QuicSocketAddress& client_address, const std::string& hostname, uint16_t signature_algorithm, quiche::QuicheStringPiece in, std::unique_ptr<SignatureCallback> callback) override; + TicketCrypter* GetTicketCrypter() override; + void SetTicketCrypter(std::unique_ptr<TicketCrypter> ticket_crypter); + private: bool GetProofInner( const quic::QuicSocketAddress& server_ip, @@ -64,6 +70,7 @@ class NET_EXPORT_PRIVATE ProofSourceChromium : public quic::ProofSource { std::unique_ptr<crypto::RSAPrivateKey> private_key_; quic::QuicReferenceCountedPointer<quic::ProofSource::Chain> chain_; std::string signed_certificate_timestamp_; + std::unique_ptr<TicketCrypter> ticket_crypter_; DISALLOW_COPY_AND_ASSIGN(ProofSourceChromium); }; diff --git a/chromium/net/quic/crypto/proof_test_chromium.cc b/chromium/net/quic/crypto/proof_test_chromium.cc index c361241b6e2..5720991912f 100644 --- a/chromium/net/quic/crypto/proof_test_chromium.cc +++ b/chromium/net/quic/crypto/proof_test_chromium.cc @@ -147,6 +147,7 @@ TEST_P(ProofTest, Verify) { string error_details; quic::QuicCryptoProof proof, first_proof; quic::QuicSocketAddress server_addr; + quic::QuicSocketAddress client_addr; std::unique_ptr<quic::ProofSource::Callback> cb( new TestCallback(&called, &ok, &chain, &proof)); @@ -155,10 +156,10 @@ TEST_P(ProofTest, Verify) { // GetProof here expects the async method to invoke the callback // synchronously. - source->GetProof(server_addr, hostname, server_config, quic_version, - first_chlo_hash, std::move(first_cb)); - source->GetProof(server_addr, hostname, server_config, quic_version, - second_chlo_hash, std::move(cb)); + source->GetProof(server_addr, client_addr, hostname, server_config, + quic_version, first_chlo_hash, std::move(first_cb)); + source->GetProof(server_addr, client_addr, hostname, server_config, + quic_version, second_chlo_hash, std::move(cb)); ASSERT_TRUE(called); ASSERT_TRUE(first_called); ASSERT_TRUE(ok); @@ -220,8 +221,10 @@ TEST_P(ProofTest, TlsSignature) { quic::QuicSocketAddress server_address; const string hostname = "test.example.com"; + quic::QuicSocketAddress client_address; + quic::QuicReferenceCountedPointer<quic::ProofSource::Chain> chain = - source->GetCertChain(server_address, hostname); + source->GetCertChain(server_address, client_address, hostname); ASSERT_GT(chain->certs.size(), 0ul); // Generate a value to be signed similar to the example in TLS 1.3 section @@ -238,8 +241,9 @@ TEST_P(ProofTest, TlsSignature) { bool success; std::unique_ptr<TestingSignatureCallback> callback = std::make_unique<TestingSignatureCallback>(&success, &sig); - source->ComputeTlsSignature(server_address, hostname, SSL_SIGN_RSA_PSS_SHA256, - to_be_signed, std::move(callback)); + source->ComputeTlsSignature(server_address, client_address, hostname, + SSL_SIGN_RSA_PSS_SHA256, to_be_signed, + std::move(callback)); EXPECT_TRUE(success); // Verify that the signature from ComputeTlsSignature can be verified with the @@ -280,12 +284,13 @@ TEST_P(ProofTest, UseAfterFree) { string error_details; quic::QuicCryptoProof proof; quic::QuicSocketAddress server_addr; + quic::QuicSocketAddress client_addr; std::unique_ptr<quic::ProofSource::Callback> cb( new TestCallback(&called, &ok, &chain, &proof)); // GetProof here expects the async method to invoke the callback // synchronously. - source->GetProof(server_addr, hostname, server_config, + source->GetProof(server_addr, client_addr, hostname, server_config, GetParam().transport_version, chlo_hash, std::move(cb)); ASSERT_TRUE(called); ASSERT_TRUE(ok); diff --git a/chromium/net/quic/crypto/proof_verifier_chromium.cc b/chromium/net/quic/crypto/proof_verifier_chromium.cc index b14acf942b7..ee05dce91ca 100644 --- a/chromium/net/quic/crypto/proof_verifier_chromium.cc +++ b/chromium/net/quic/crypto/proof_verifier_chromium.cc @@ -79,6 +79,7 @@ class ProofVerifierChromium::Job { // asynchronously when the verification completes. quic::QuicAsyncStatus VerifyCertChain( const std::string& hostname, + const uint16_t port, const std::vector<std::string>& certs, const std::string& ocsp_response, const std::string& cert_sct, @@ -155,9 +156,6 @@ class ProofVerifierChromium::Job { // passed to CertVerifier::Verify. int cert_verify_flags_; - // If set to true, enforces policy checking in DoVerifyCertComplete(). - bool enforce_policy_checking_; - State next_state_; base::TimeTicks start_time_; @@ -181,7 +179,6 @@ ProofVerifierChromium::Job::Job( transport_security_state_(transport_security_state), cert_transparency_verifier_(cert_transparency_verifier), cert_verify_flags_(cert_verify_flags), - enforce_policy_checking_(true), next_state_(STATE_NONE), start_time_(base::TimeTicks::Now()), net_log_(net_log) { @@ -242,8 +239,8 @@ quic::QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( // We call VerifySignature first to avoid copying of server_config and // signature. - if (!signature.empty() && !VerifySignature(server_config, quic_version, - chlo_hash, signature, certs[0])) { + if (!VerifySignature(server_config, quic_version, chlo_hash, signature, + certs[0])) { *error_details = "Failed to verify signature of server config"; DLOG(WARNING) << *error_details; verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; @@ -251,13 +248,13 @@ quic::QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( return quic::QUIC_FAILURE; } - DCHECK(enforce_policy_checking_); return VerifyCert(hostname, port, /*ocsp_response=*/std::string(), cert_sct, error_details, verify_details, std::move(callback)); } quic::QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain( const string& hostname, + const uint16_t port, const std::vector<string>& certs, const std::string& ocsp_response, const std::string& cert_sct, @@ -282,10 +279,15 @@ quic::QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain( if (!GetX509Certificate(certs, error_details, verify_details)) return quic::QUIC_FAILURE; - enforce_policy_checking_ = false; - // |port| is not needed because |enforce_policy_checking_| is false. - return VerifyCert(hostname, /*port=*/0, ocsp_response, cert_sct, - error_details, verify_details, std::move(callback)); + // Note that this is a completely synchronous operation: The CT Log Verifier + // gets all the data it needs for SCT verification and does not do any + // external communication. + cert_transparency_verifier_->Verify( + hostname, cert_.get(), std::string(), cert_sct, + &verify_details_->ct_verify_result.scts, net_log_); + + return VerifyCert(hostname, port, ocsp_response, cert_sct, error_details, + verify_details, std::move(callback)); } bool ProofVerifierChromium::Job::GetX509Certificate( @@ -411,7 +413,7 @@ int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) { // If the connection was good, check HPKP and CT status simultaneously, // but prefer to treat the HPKP error as more serious, if there was one. - if (enforce_policy_checking_ && result == OK) { + if (result == OK) { ct::SCTList verified_scts = ct::SCTsMatchingStatus( verify_details_->ct_verify_result.scts, ct::SCT_STATUS_OK); @@ -558,6 +560,11 @@ bool ProofVerifierChromium::Job::VerifySignature( return false; } + if (signature.empty()) { + DLOG(WARNING) << "Signature is empty, thus cannot possibly be valid"; + return false; + } + crypto::SignatureVerifier verifier; if (!x509_util::SignatureVerifierInitWithCertificate( &verifier, algorithm, base::as_bytes(base::make_span(signature)), @@ -637,6 +644,7 @@ quic::QuicAsyncStatus ProofVerifierChromium::VerifyProof( quic::QuicAsyncStatus ProofVerifierChromium::VerifyCertChain( const std::string& hostname, + const uint16_t port, const std::vector<std::string>& certs, const std::string& ocsp_response, const std::string& cert_sct, @@ -655,7 +663,7 @@ quic::QuicAsyncStatus ProofVerifierChromium::VerifyCertChain( cert_transparency_verifier_, chromium_context->cert_verify_flags, chromium_context->net_log); quic::QuicAsyncStatus status = - job->VerifyCertChain(hostname, certs, ocsp_response, cert_sct, + job->VerifyCertChain(hostname, port, certs, ocsp_response, cert_sct, error_details, verify_details, std::move(callback)); if (status == quic::QUIC_PENDING) { Job* job_ptr = job.get(); diff --git a/chromium/net/quic/crypto/proof_verifier_chromium.h b/chromium/net/quic/crypto/proof_verifier_chromium.h index 83269f3595b..beacd3d0d63 100644 --- a/chromium/net/quic/crypto/proof_verifier_chromium.h +++ b/chromium/net/quic/crypto/proof_verifier_chromium.h @@ -93,6 +93,7 @@ class NET_EXPORT_PRIVATE ProofVerifierChromium : public quic::ProofVerifier { std::unique_ptr<quic::ProofVerifierCallback> callback) override; quic::QuicAsyncStatus VerifyCertChain( const std::string& hostname, + const uint16_t port, const std::vector<std::string>& certs, const std::string& ocsp_response, const std::string& cert_sct, diff --git a/chromium/net/quic/crypto/proof_verifier_chromium_test.cc b/chromium/net/quic/crypto/proof_verifier_chromium_test.cc index ad8b8167647..62504d05827 100644 --- a/chromium/net/quic/crypto/proof_verifier_chromium_test.cc +++ b/chromium/net/quic/crypto/proof_verifier_chromium_test.cc @@ -104,10 +104,13 @@ class DummyProofVerifierCallback : public quic::ProofVerifierCallback { }; const char kTestHostname[] = "test.example.com"; -const char kTestChloHash[] = "CHLO hash"; -const char kTestEmptySCT[] = ""; const uint16_t kTestPort = 8443; const char kTestConfig[] = "server config bytes"; +const char kTestChloHash[] = "CHLO hash"; +const char kTestEmptyOCSPResponse[] = ""; +const char kTestEmptySCT[] = ""; +const char kTestEmptySignature[] = ""; + const char kLogDescription[] = "somelog"; } // namespace @@ -148,8 +151,9 @@ class ProofVerifierChromiumTest : public ::testing::Test { GetTestCertsDirectory().AppendASCII("quic-leaf-cert.key"), base::FilePath()); std::string signature; - source.GetProof(quic::QuicSocketAddress(), kTestHostname, kTestConfig, - quic::QUIC_VERSION_43, kTestChloHash, + source.GetProof(quic::QuicSocketAddress(), quic::QuicSocketAddress(), + kTestHostname, kTestConfig, quic::QUIC_VERSION_43, + kTestChloHash, std::make_unique<SignatureSaver>(&signature)); return signature; } @@ -217,6 +221,17 @@ TEST_F(ProofVerifierChromiumTest, VerifyProof) { static_cast<ProofVerifyDetailsChromium*>(details_.get()); EXPECT_EQ(dummy_result_.cert_status, verify_details->cert_verify_result.cert_status); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_SUCCESS, status); + + ASSERT_TRUE(details_.get()); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_EQ(dummy_result_.cert_status, + verify_details->cert_verify_result.cert_status); } // Tests that the quic::ProofVerifier fails verification if certificate @@ -234,6 +249,12 @@ TEST_F(ProofVerifierChromiumTest, FailsIfCertFails) { kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(), verify_context_.get(), &error_details_, &details_, std::move(callback)); ASSERT_EQ(quic::QUIC_FAILURE, status); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_FAILURE, status); } // Valid SCT, but invalid signature. @@ -251,10 +272,18 @@ TEST_F(ProofVerifierChromiumTest, ValidSCTList) { new DummyProofVerifierCallback); quic::QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43, - kTestChloHash, certs_, ct::GetSCTListForTesting(), kTestEmptySCT, + kTestChloHash, certs_, ct::GetSCTListForTesting(), kTestEmptySignature, verify_context_.get(), &error_details_, &details_, std::move(callback)); ASSERT_EQ(quic::QUIC_FAILURE, status); CheckSCT(/*sct_expected_ok=*/true); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, + ct::GetSCTListForTesting(), verify_context_.get(), &error_details_, + &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_FAILURE, status); + CheckSCT(/*sct_expected_ok=*/true); } // Invalid SCT and signature. @@ -271,8 +300,17 @@ TEST_F(ProofVerifierChromiumTest, InvalidSCTList) { new DummyProofVerifierCallback); quic::QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43, - kTestChloHash, certs_, ct::GetSCTListWithInvalidSCT(), kTestEmptySCT, - verify_context_.get(), &error_details_, &details_, std::move(callback)); + kTestChloHash, certs_, ct::GetSCTListWithInvalidSCT(), + kTestEmptySignature, verify_context_.get(), &error_details_, &details_, + std::move(callback)); + ASSERT_EQ(quic::QUIC_FAILURE, status); + CheckSCT(/*sct_expected_ok=*/false); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, + ct::GetSCTListWithInvalidSCT(), verify_context_.get(), &error_details_, + &details_, std::move(callback)); ASSERT_EQ(quic::QUIC_FAILURE, status); CheckSCT(/*sct_expected_ok=*/false); } @@ -289,8 +327,8 @@ TEST_F(ProofVerifierChromiumTest, FailsIfSignatureFails) { new DummyProofVerifierCallback); quic::QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43, - kTestChloHash, certs_, kTestEmptySCT, kTestConfig, verify_context_.get(), - &error_details_, &details_, std::move(callback)); + kTestChloHash, certs_, kTestEmptySCT, kTestEmptySignature, + verify_context_.get(), &error_details_, &details_, std::move(callback)); ASSERT_EQ(quic::QUIC_FAILURE, status); } @@ -323,6 +361,18 @@ TEST_F(ProofVerifierChromiumTest, PreservesEVIfAllowed) { static_cast<ProofVerifyDetailsChromium*>(details_.get()); EXPECT_EQ(dummy_result_.cert_status, verify_details->cert_verify_result.cert_status); + + // Repeat the test with VerifyCertChain. + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_SUCCESS, status); + + ASSERT_TRUE(details_.get()); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_EQ(dummy_result_.cert_status, + verify_details->cert_verify_result.cert_status); } // Tests that the certificate policy enforcer is consulted for EV @@ -355,6 +405,18 @@ TEST_F(ProofVerifierChromiumTest, StripsEVIfNotAllowed) { EXPECT_EQ(CERT_STATUS_CT_COMPLIANCE_FAILED, verify_details->cert_verify_result.cert_status & (CERT_STATUS_CT_COMPLIANCE_FAILED | CERT_STATUS_IS_EV)); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_SUCCESS, status); + + ASSERT_TRUE(details_.get()); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_EQ(CERT_STATUS_CT_COMPLIANCE_FAILED, + verify_details->cert_verify_result.cert_status & + (CERT_STATUS_CT_COMPLIANCE_FAILED | CERT_STATUS_IS_EV)); } // Tests that the when a certificate's EV status is stripped to EV @@ -396,6 +458,21 @@ TEST_F(ProofVerifierChromiumTest, CTEVHistogramNonCompliant) { histograms.ExpectUniqueSample( kHistogramName, static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS), 1); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + + ASSERT_TRUE(details_.get()); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_EQ(CERT_STATUS_CT_COMPLIANCE_FAILED, + verify_details->cert_verify_result.cert_status & + (CERT_STATUS_CT_COMPLIANCE_FAILED | CERT_STATUS_IS_EV)); + + histograms.ExpectUniqueSample( + kHistogramName, + static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS), 2); } // Tests that when a connection is CT-compliant and its EV status is preserved, @@ -436,6 +513,20 @@ TEST_F(ProofVerifierChromiumTest, CTEVHistogramCompliant) { histograms.ExpectUniqueSample( kHistogramName, static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS), 1); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + + ASSERT_TRUE(details_.get()); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_TRUE(verify_details->cert_verify_result.cert_status & + CERT_STATUS_IS_EV); + + histograms.ExpectUniqueSample( + kHistogramName, + static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS), 2); } HashValueVector MakeHashValueVector(uint8_t tag) { @@ -468,6 +559,15 @@ TEST_F(ProofVerifierChromiumTest, IsFatalErrorNotSetForNonFatalError) { ProofVerifyDetailsChromium* verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); EXPECT_FALSE(verify_details->is_fatal_cert_error); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_FAILURE, status); + + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_FALSE(verify_details->is_fatal_cert_error); } TEST_F(ProofVerifierChromiumTest, IsFatalErrorSetForFatalError) { @@ -495,6 +595,14 @@ TEST_F(ProofVerifierChromiumTest, IsFatalErrorSetForFatalError) { ProofVerifyDetailsChromium* verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); EXPECT_TRUE(verify_details->is_fatal_cert_error); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_FAILURE, status); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_TRUE(verify_details->is_fatal_cert_error); } // Test that PKP is enforced for certificates that chain up to known roots. @@ -527,6 +635,19 @@ TEST_F(ProofVerifierChromiumTest, PKPEnforced) { CERT_STATUS_PINNED_KEY_MISSING); EXPECT_FALSE(verify_details->pkp_bypassed); EXPECT_NE("", verify_details->pinning_failure_log); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kCTAndPKPHost, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_FAILURE, status); + + ASSERT_TRUE(details_.get()); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_TRUE(verify_details->cert_verify_result.cert_status & + CERT_STATUS_PINNED_KEY_MISSING); + EXPECT_FALSE(verify_details->pkp_bypassed); + EXPECT_NE("", verify_details->pinning_failure_log); } // Test |pkp_bypassed| is set when PKP is bypassed due to a local @@ -557,6 +678,16 @@ TEST_F(ProofVerifierChromiumTest, PKPBypassFlagSet) { ProofVerifyDetailsChromium* verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); EXPECT_TRUE(verify_details->pkp_bypassed); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kCTAndPKPHost, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_SUCCESS, status); + + ASSERT_TRUE(details_.get()); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_TRUE(verify_details->pkp_bypassed); } // Test that when CT is required (in this case, by the delegate), the @@ -598,6 +729,17 @@ TEST_F(ProofVerifierChromiumTest, CTIsRequired) { static_cast<ProofVerifyDetailsChromium*>(details_.get()); EXPECT_TRUE(verify_details->cert_verify_result.cert_status & CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_FAILURE, status); + + ASSERT_TRUE(details_.get()); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_TRUE(verify_details->cert_verify_result.cert_status & + CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED); } // Test that when CT is required (in this case, by the delegate) and CT @@ -642,6 +784,16 @@ TEST_F(ProofVerifierChromiumTest, CTIsRequiredHistogramNonCompliant) { histograms.ExpectUniqueSample( kHistogramName, static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS), 1); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_FAILURE, status); + + histograms.ExpectUniqueSample( + kHistogramName, + static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS), 2); } // Test that when CT is required (in this case, by the delegate) and CT @@ -684,6 +836,12 @@ TEST_F(ProofVerifierChromiumTest, CTIsRequiredHistogramCompliant) { verify_context_.get(), &error_details_, &details_, std::move(callback)); ASSERT_EQ(quic::QUIC_SUCCESS, status); + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_SUCCESS, status); + histograms.ExpectTotalCount(kHistogramName, 0); } // Now test that the histogram is recorded for public roots. @@ -707,6 +865,17 @@ TEST_F(ProofVerifierChromiumTest, CTIsRequiredHistogramCompliant) { kHistogramName, static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS), 1); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_SUCCESS, status); + + histograms.ExpectUniqueSample( + kHistogramName, + static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS), + 2); } } @@ -735,6 +904,12 @@ TEST_F(ProofVerifierChromiumTest, CTIsNotRequiredHistogram) { verify_context_.get(), &error_details_, &details_, std::move(callback)); ASSERT_EQ(quic::QUIC_SUCCESS, status); + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_SUCCESS, status); + histograms.ExpectTotalCount(kHistogramName, 0); } @@ -782,6 +957,19 @@ TEST_F(ProofVerifierChromiumTest, PKPAndCTBothTested) { CERT_STATUS_PINNED_KEY_MISSING); EXPECT_TRUE(verify_details->cert_verify_result.cert_status & CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kCTAndPKPHost, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_FAILURE, status); + + ASSERT_TRUE(details_.get()); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_TRUE(verify_details->cert_verify_result.cert_status & + CERT_STATUS_PINNED_KEY_MISSING); + EXPECT_TRUE(verify_details->cert_verify_result.cert_status & + CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED); } // Test that CT compliance status is recorded in a histogram. @@ -813,6 +1001,12 @@ TEST_F(ProofVerifierChromiumTest, CTComplianceStatusHistogram) { verify_context_.get(), &error_details_, &details_, std::move(callback)); ASSERT_EQ(quic::QUIC_SUCCESS, status); + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_SUCCESS, status); + // The histogram should not have been recorded. histograms.ExpectTotalCount(kHistogramName, 0); } @@ -839,6 +1033,18 @@ TEST_F(ProofVerifierChromiumTest, CTComplianceStatusHistogram) { kHistogramName, static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS), 1); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_SUCCESS, status); + + // The histogram should have been recorded with the CT compliance status. + histograms.ExpectUniqueSample( + kHistogramName, + static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS), + 2); } } @@ -863,18 +1069,36 @@ TEST_F(ProofVerifierChromiumTest, CTRequirementsFlagNotMet) { &transport_security_state_, ct_verifier_.get(), {}); - std::unique_ptr<DummyProofVerifierCallback> callback( - new DummyProofVerifierCallback); - proof_verifier.VerifyProof( - kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43, - kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(), - verify_context_.get(), &error_details_, &details_, std::move(callback)); + { + std::unique_ptr<DummyProofVerifierCallback> callback( + new DummyProofVerifierCallback); + proof_verifier.VerifyProof( + kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43, + kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(), + verify_context_.get(), &error_details_, &details_, std::move(callback)); + + // The flag should be set in the CTVerifyResult. + ProofVerifyDetailsChromium* proof_details = + reinterpret_cast<ProofVerifyDetailsChromium*>(details_.get()); + const ct::CTVerifyResult& ct_verify_result = + proof_details->ct_verify_result; + EXPECT_TRUE(ct_verify_result.policy_compliance_required); + } - // The flag should be set in the CTVerifyResult. - ProofVerifyDetailsChromium* proof_details = - reinterpret_cast<ProofVerifyDetailsChromium*>(details_.get()); - const ct::CTVerifyResult& ct_verify_result = proof_details->ct_verify_result; - EXPECT_TRUE(ct_verify_result.policy_compliance_required); + { + std::unique_ptr<DummyProofVerifierCallback> callback( + new DummyProofVerifierCallback); + proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + + // The flag should be set in the CTVerifyResult. + ProofVerifyDetailsChromium* proof_details = + reinterpret_cast<ProofVerifyDetailsChromium*>(details_.get()); + const ct::CTVerifyResult& ct_verify_result = + proof_details->ct_verify_result; + EXPECT_TRUE(ct_verify_result.policy_compliance_required); + } } // Tests that when CT is required and the connection is compliant, the relevant @@ -898,18 +1122,36 @@ TEST_F(ProofVerifierChromiumTest, CTRequirementsFlagMet) { &transport_security_state_, ct_verifier_.get(), {}); - std::unique_ptr<DummyProofVerifierCallback> callback( - new DummyProofVerifierCallback); - proof_verifier.VerifyProof( - kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43, - kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(), - verify_context_.get(), &error_details_, &details_, std::move(callback)); + { + std::unique_ptr<DummyProofVerifierCallback> callback( + new DummyProofVerifierCallback); + proof_verifier.VerifyProof( + kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43, + kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(), + verify_context_.get(), &error_details_, &details_, std::move(callback)); + + // The flag should be set in the CTVerifyResult. + ProofVerifyDetailsChromium* proof_details = + reinterpret_cast<ProofVerifyDetailsChromium*>(details_.get()); + const ct::CTVerifyResult& ct_verify_result = + proof_details->ct_verify_result; + EXPECT_TRUE(ct_verify_result.policy_compliance_required); + } - // The flag should be set in the CTVerifyResult. - ProofVerifyDetailsChromium* proof_details = - reinterpret_cast<ProofVerifyDetailsChromium*>(details_.get()); - const ct::CTVerifyResult& ct_verify_result = proof_details->ct_verify_result; - EXPECT_TRUE(ct_verify_result.policy_compliance_required); + { + std::unique_ptr<DummyProofVerifierCallback> callback( + new DummyProofVerifierCallback); + proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + + // The flag should be set in the CTVerifyResult. + ProofVerifyDetailsChromium* proof_details = + reinterpret_cast<ProofVerifyDetailsChromium*>(details_.get()); + const ct::CTVerifyResult& ct_verify_result = + proof_details->ct_verify_result; + EXPECT_TRUE(ct_verify_result.policy_compliance_required); + } } TEST_F(ProofVerifierChromiumTest, UnknownRootRejected) { @@ -932,6 +1174,15 @@ TEST_F(ProofVerifierChromiumTest, UnknownRootRejected) { EXPECT_EQ( "Failed to verify certificate chain: net::ERR_QUIC_CERT_ROOT_NOT_KNOWN", error_details_); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_FAILURE, status); + EXPECT_EQ( + "Failed to verify certificate chain: net::ERR_QUIC_CERT_ROOT_NOT_KNOWN", + error_details_); } TEST_F(ProofVerifierChromiumTest, UnknownRootAcceptedWithOverride) { @@ -957,6 +1208,17 @@ TEST_F(ProofVerifierChromiumTest, UnknownRootAcceptedWithOverride) { static_cast<ProofVerifyDetailsChromium*>(details_.get()); EXPECT_EQ(dummy_result_.cert_status, verify_details->cert_verify_result.cert_status); + + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); + ASSERT_EQ(quic::QUIC_SUCCESS, status); + + ASSERT_TRUE(details_.get()); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_EQ(dummy_result_.cert_status, + verify_details->cert_verify_result.cert_status); } TEST_F(ProofVerifierChromiumTest, UnknownRootAcceptedWithWildcardOverride) { @@ -982,29 +1244,17 @@ TEST_F(ProofVerifierChromiumTest, UnknownRootAcceptedWithWildcardOverride) { static_cast<ProofVerifyDetailsChromium*>(details_.get()); EXPECT_EQ(dummy_result_.cert_status, verify_details->cert_verify_result.cert_status); -} - -// Tests that the VerifyCertChain verifies certificates. -TEST_F(ProofVerifierChromiumTest, VerifyCertChain) { - 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(), {}); - - std::unique_ptr<DummyProofVerifierCallback> callback( - new DummyProofVerifierCallback); - quic::QuicAsyncStatus status = proof_verifier.VerifyCertChain( - kTestHostname, certs_, /*ocsp_response=*/std::string(), - /*cert_sct=*/std::string(), verify_context_.get(), &error_details_, - &details_, std::move(callback)); + callback = std::make_unique<DummyProofVerifierCallback>(); + status = proof_verifier.VerifyCertChain( + kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT, + verify_context_.get(), &error_details_, &details_, std::move(callback)); ASSERT_EQ(quic::QUIC_SUCCESS, status); ASSERT_TRUE(details_.get()); - ProofVerifyDetailsChromium* verify_details = - static_cast<ProofVerifyDetailsChromium*>(details_.get()); - EXPECT_EQ(0u, verify_details->cert_verify_result.cert_status); + verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get()); + EXPECT_EQ(dummy_result_.cert_status, + verify_details->cert_verify_result.cert_status); } } // namespace test diff --git a/chromium/net/quic/crypto_test_utils_chromium.cc b/chromium/net/quic/crypto_test_utils_chromium.cc index dd86b0fa86b..f284f7c4cdb 100644 --- a/chromium/net/quic/crypto_test_utils_chromium.cc +++ b/chromium/net/quic/crypto_test_utils_chromium.cc @@ -5,7 +5,7 @@ #include <utility> #include "base/callback_helpers.h" -#include "base/logging.h" +#include "base/check.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/stl_util.h" @@ -31,6 +31,7 @@ #include "net/test/test_data_directory.h" #include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h" #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h" +#include "net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.h" using std::string; @@ -90,6 +91,7 @@ std::unique_ptr<quic::ProofSource> ProofSourceForTesting() { CHECK(source->Initialize(certs_dir.AppendASCII("quic-chain.pem"), certs_dir.AppendASCII("quic-leaf-cert.key"), certs_dir.AppendASCII("quic-leaf-cert.key.sct"))); + source->SetTicketCrypter(std::make_unique<quic::test::TestTicketCrypter>()); return std::move(source); } diff --git a/chromium/net/quic/mock_crypto_client_stream.cc b/chromium/net/quic/mock_crypto_client_stream.cc index 2eba6804eb7..9a8d2b55e39 100644 --- a/chromium/net/quic/mock_crypto_client_stream.cc +++ b/chromium/net/quic/mock_crypto_client_stream.cc @@ -26,7 +26,6 @@ using quic::ENCRYPTION_ZERO_RTT; using quic::kAESG; using quic::kC255; using quic::kDefaultMaxStreamsPerConnection; -using quic::kMaximumIdleTimeoutSecs; using quic::kQBIC; using quic::NullDecrypter; using quic::NullEncrypter; @@ -65,7 +64,8 @@ MockCryptoClientStream::MockCryptoClientStream( session, std::move(verify_context), crypto_config, - session), + session, + /*has_application_state = */ true), QuicCryptoHandshaker(this, session), handshake_mode_(handshake_mode), encryption_established_(false), @@ -182,7 +182,7 @@ bool MockCryptoClientStream::CryptoConnect() { std::make_unique<NullDecrypter>(Perspective::IS_CLIENT)); } session()->connection()->SetEncrypter(ENCRYPTION_INITIAL, nullptr); - session()->connection()->SetEncrypter( + session()->OnNewEncryptionKeyAvailable( ENCRYPTION_FORWARD_SECURE, std::make_unique<NullEncrypter>(Perspective::IS_CLIENT)); } @@ -264,7 +264,7 @@ void MockCryptoClientStream::NotifySessionOneRttKeyAvailable() { std::make_unique<NullDecrypter>(Perspective::IS_CLIENT)); } session()->connection()->SetEncrypter(ENCRYPTION_INITIAL, nullptr); - session()->connection()->SetEncrypter( + session()->OnNewEncryptionKeyAvailable( ENCRYPTION_FORWARD_SECURE, std::make_unique<NullEncrypter>(Perspective::IS_CLIENT)); } @@ -294,9 +294,6 @@ void MockCryptoClientStream::SetConfigNegotiated() { #endif cgst.push_back(kQBIC); QuicConfig config(config_); - config.SetIdleNetworkTimeout( - QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs), - QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs)); config.SetBytesForConnectionIdToSend(PACKET_8BYTE_CONNECTION_ID); config.SetMaxBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection / 2); config.SetMaxUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection / 2); @@ -313,8 +310,8 @@ void MockCryptoClientStream::SetConfigNegotiated() { PROTOCOL_TLS1_3) { TransportParameters params; ASSERT_TRUE(config.FillTransportParameters(¶ms)); - error = session()->config()->ProcessTransportParameters(params, CLIENT, - &error_details); + error = session()->config()->ProcessTransportParameters( + params, CLIENT, /*is_resumption=*/false, &error_details); } else { CryptoHandshakeMessage msg; config.ToHandshakeMessage( diff --git a/chromium/net/quic/platform/impl/quic_chromium_clock.h b/chromium/net/quic/platform/impl/quic_chromium_clock.h index 7fb3e2ce960..78ef0b5e170 100644 --- a/chromium/net/quic/platform/impl/quic_chromium_clock.h +++ b/chromium/net/quic/platform/impl/quic_chromium_clock.h @@ -5,6 +5,7 @@ #ifndef NET_QUIC_PLATFORM_IMPL_QUIC_CHROMIUM_CLOCK_H_ #define NET_QUIC_PLATFORM_IMPL_QUIC_CHROMIUM_CLOCK_H_ +#include "base/macros.h" #include "base/time/time.h" #include "net/third_party/quiche/src/quic/core/quic_clock.h" #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" diff --git a/chromium/net/quic/platform/impl/quic_containers_impl.h b/chromium/net/quic/platform/impl/quic_containers_impl.h index 8f2db453906..b634aa59313 100644 --- a/chromium/net/quic/platform/impl/quic_containers_impl.h +++ b/chromium/net/quic/platform/impl/quic_containers_impl.h @@ -11,7 +11,6 @@ #include "base/containers/queue.h" #include "base/containers/small_map.h" -#include "net/base/interval_set.h" #include "net/third_party/quiche/src/common/simple_linked_hash_map.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" @@ -32,6 +31,9 @@ template <typename Key, typename std::unordered_map<Key, Value, Hash>::allocator_type> using QuicUnorderedMapImpl = std::unordered_map<Key, Value, Hash, Eq, Alloc>; +template <typename Key, typename Value, typename Hash> +using QuicHashMapImpl = std::unordered_map<Key, Value, Hash>; + // TODO(mpw): s/std::unordered_set/gtl::node_hash_set/ once node_hash_set is // PG3-compatible. template <typename Key, @@ -41,6 +43,9 @@ template <typename Key, typename std::unordered_set<Key, Hash>::allocator_type> using QuicUnorderedSetImpl = std::unordered_set<Key, Hash, Eq, Alloc>; +template <typename Key, typename Hash> +using QuicHashSetImpl = std::unordered_set<Key, Hash>; + // A map which offers insertion-ordered iteration. template <typename Key, typename Value, typename Hash> using QuicLinkedHashMapImpl = quiche::SimpleLinkedHashMap<Key, Value, Hash>; @@ -51,11 +56,6 @@ using QuicLinkedHashMapImpl = quiche::SimpleLinkedHashMap<Key, Value, Hash>; template <typename Key, typename Value, int Size> using QuicSmallMapImpl = base::small_map<std::unordered_map<Key, Value>, Size>; -// A data structure used to represent a sorted set of non-empty, non-adjacent, -// and mutually disjoint intervals. -template <typename T> -using QuicIntervalSetImpl = net::IntervalSet<T>; - // Represents a simple queue which may be backed by a list or // a flat circular buffer. // 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 c84146d84bb..28ec2766c6a 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 @@ -16,8 +16,10 @@ #include "net/http/transport_security_state.h" #include "net/quic/crypto/proof_source_chromium.h" #include "net/quic/crypto/proof_verifier_chromium.h" +#include "net/quic/platform/impl/quic_chromium_clock.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" +#include "net/third_party/quiche/src/quic/tools/simple_ticket_crypter.h" DEFINE_QUIC_COMMAND_LINE_FLAG( bool, @@ -82,6 +84,8 @@ std::unique_ptr<ProofVerifier> CreateDefaultProofVerifierImpl( std::unique_ptr<ProofSource> CreateDefaultProofSourceImpl() { auto proof_source = std::make_unique<net::ProofSourceChromium>(); + proof_source->SetTicketCrypter( + std::make_unique<SimpleTicketCrypter>(QuicChromiumClock::GetInstance())); CHECK(proof_source->Initialize( #if defined(OS_WIN) base::FilePath(base::UTF8ToUTF16(GetQuicFlag(FLAGS_certificate_file))), diff --git a/chromium/net/quic/platform/impl/quic_macros_impl.h b/chromium/net/quic/platform/impl/quic_macros_impl.h index f503011907c..43f243d18f7 100644 --- a/chromium/net/quic/platform/impl/quic_macros_impl.h +++ b/chromium/net/quic/platform/impl/quic_macros_impl.h @@ -10,4 +10,7 @@ #define QUIC_MUST_USE_RESULT_IMPL WARN_UNUSED_RESULT #define QUIC_UNUSED_IMPL ALLOW_UNUSED_TYPE +// TODO(wub): Use ABSL_CONST_INIT when absl is allowed. +#define QUIC_CONST_INIT_IMPL + #endif // NET_QUIC_PLATFORM_IMPL_QUIC_MACROS_IMPL_H_ diff --git a/chromium/net/quic/quic_address_mismatch.cc b/chromium/net/quic/quic_address_mismatch.cc index 9a26c26521b..16df1ebe2a7 100644 --- a/chromium/net/quic/quic_address_mismatch.cc +++ b/chromium/net/quic/quic_address_mismatch.cc @@ -4,7 +4,7 @@ #include "net/quic/quic_address_mismatch.h" -#include "base/logging.h" +#include "base/check_op.h" #include "net/base/ip_address.h" namespace net { diff --git a/chromium/net/quic/quic_chromium_alarm_factory.cc b/chromium/net/quic/quic_chromium_alarm_factory.cc index 2eaf0bf7d71..d3102e958a1 100644 --- a/chromium/net/quic/quic_chromium_alarm_factory.cc +++ b/chromium/net/quic/quic_chromium_alarm_factory.cc @@ -5,8 +5,8 @@ #include "net/quic/quic_chromium_alarm_factory.h" #include "base/bind.h" +#include "base/check.h" #include "base/location.h" -#include "base/logging.h" #include "base/metrics/sparse_histogram.h" #include "base/task_runner.h" #include "base/time/time.h" diff --git a/chromium/net/quic/quic_chromium_client_session.cc b/chromium/net/quic/quic_chromium_client_session.cc index 1e4034ad2a7..780b8507c71 100644 --- a/chromium/net/quic/quic_chromium_client_session.cc +++ b/chromium/net/quic/quic_chromium_client_session.cc @@ -70,6 +70,12 @@ const size_t kWaitTimeForNewNetworkSecs = 10; const size_t kMinRetryTimeForDefaultNetworkSecs = 1; +// Default value for maximum number of consecutive pings that can be sent +// with aggressive initial retransmittable on wire timeout if there is no new +// data received. After which, the timeout will be exponentially back off until +// exceeds the default ping timeout. +const int kDefaultMaxAggressiveRetransmittableOnWirePingCount = 200; + // Maximum RTT time for this session when set initial timeout for probing // network. const int kDefaultRTTMilliSecs = 300; @@ -102,36 +108,10 @@ void RecordUnexpectedNotGoingAway(Location location) { NUM_LOCATIONS); } -void RecordConnectionCloseErrorCode(const quic::QuicConnectionCloseFrame& frame, - quic::ConnectionCloseSource source, - const std::string& hostname, - bool handshake_confirmed) { - bool is_google_host = HasGoogleHost(GURL("https://" + hostname)); - std::string histogram = "Net.QuicSession.ConnectionCloseErrorCode"; - - uint64_t error = 0; - if (source == quic::ConnectionCloseSource::FROM_PEER) { - histogram += "Server"; - // When receiving a CONNECTION_CLOSE frame, record error code received on - // the wire. - switch (frame.close_type) { - case quic::GOOGLE_QUIC_CONNECTION_CLOSE: - error = frame.quic_error_code; - break; - case quic::IETF_QUIC_TRANSPORT_CONNECTION_CLOSE: - error = frame.transport_error_code; - histogram += "IetfTransport"; - break; - case quic::IETF_QUIC_APPLICATION_CONNECTION_CLOSE: - error = frame.application_error_code; - histogram += "IetfApplication"; - } - } else { - // When sending a CONNECTION_CLOSE frame, record QuicErrorCode. - histogram += "Client"; - error = frame.extracted_error_code; - } - +void RecordConnectionCloseErrorCodeImpl(const std::string& histogram, + uint64_t error, + bool is_google_host, + bool handshake_confirmed) { base::UmaHistogramSparse(histogram, error); if (handshake_confirmed) { @@ -141,17 +121,53 @@ void RecordConnectionCloseErrorCode(const quic::QuicConnectionCloseFrame& frame, } if (is_google_host) { - histogram += "Google"; - base::UmaHistogramSparse(histogram, error); + base::UmaHistogramSparse(histogram + "Google", error); if (handshake_confirmed) { - base::UmaHistogramSparse(histogram + ".HandshakeConfirmed", error); + base::UmaHistogramSparse(histogram + "Google.HandshakeConfirmed", error); } else { - base::UmaHistogramSparse(histogram + ".HandshakeNotConfirmed", error); + base::UmaHistogramSparse(histogram + "Google.HandshakeNotConfirmed", + error); } } } +void RecordConnectionCloseErrorCode(const quic::QuicConnectionCloseFrame& frame, + quic::ConnectionCloseSource source, + const std::string& hostname, + bool handshake_confirmed) { + bool is_google_host = HasGoogleHost(GURL("https://" + hostname)); + std::string histogram = "Net.QuicSession.ConnectionCloseErrorCode"; + + if (source == quic::ConnectionCloseSource::FROM_SELF) { + // When sending a CONNECTION_CLOSE frame, it is sufficient to record + // |quic_error_code|. + histogram += "Client"; + RecordConnectionCloseErrorCodeImpl(histogram, frame.quic_error_code, + is_google_host, handshake_confirmed); + return; + } + + histogram += "Server"; + + // Record |quic_error_code|. Note that when using IETF QUIC, this is + // extracted from the CONNECTION_CLOSE frame reason phrase, and might be + // QUIC_IETF_GQUIC_ERROR_MISSING. + RecordConnectionCloseErrorCodeImpl(histogram, frame.quic_error_code, + is_google_host, handshake_confirmed); + + // For IETF QUIC frames, also record the error code received on the wire. + if (frame.close_type == quic::IETF_QUIC_TRANSPORT_CONNECTION_CLOSE) { + histogram += "IetfTransport"; + 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); + } +} + base::Value NetLogQuicMigrationFailureParams( quic::QuicConnectionId connection_id, base::StringPiece reason) { @@ -851,6 +867,13 @@ QuicChromiumClientSession::QuicChromiumClientSession( if (!retransmittable_on_wire_timeout.IsZero()) { connection->set_initial_retransmittable_on_wire_timeout( retransmittable_on_wire_timeout); + if (GetQuicFlag( + FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count) == + 0) { + // Set a default value for this flag if no custom value is provided. + SetQuicFlag(FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count, + kDefaultMaxAggressiveRetransmittableOnWirePingCount); + } } } @@ -1128,7 +1151,7 @@ bool QuicChromiumClientSession::ShouldCreateOutgoingBidirectionalStream() { } if (!CanOpenNextOutgoingBidirectionalStream()) { DVLOG(1) << "Failed to create a new outgoing stream. " - << "Already " << GetNumOpenOutgoingStreams() << " open."; + << "Already " << GetNumActiveStreams() << " open."; return false; } if (goaway_received()) { @@ -1175,11 +1198,11 @@ QuicChromiumClientSession::CreateOutgoingReliableStreamImpl( ActivateStream(base::WrapUnique(stream)); ++num_total_streams_; UMA_HISTOGRAM_COUNTS_1M("Net.QuicSession.NumOpenStreams", - GetNumOpenOutgoingStreams()); + GetNumActiveStreams()); // The previous histogram puts 100 in a bucket betweeen 86-113 which does // not shed light on if chrome ever things it has more than 100 streams open. UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.TooManyOpenStreams", - GetNumOpenOutgoingStreams() > 100); + GetNumActiveStreams() > 100); return stream; } @@ -1504,33 +1527,41 @@ void QuicChromiumClientSession::OnCanCreateNewOutgoingStream( void QuicChromiumClientSession::OnConfigNegotiated() { quic::QuicSpdyClientSessionBase::OnConfigNegotiated(); - if (!stream_factory_ || !config()->HasReceivedAlternateServerAddress()) + if (!stream_factory_ || !stream_factory_->allow_server_migration() || + (!config()->HasReceivedIPv6AlternateServerAddress() && + !config()->HasReceivedIPv4AlternateServerAddress())) { return; + } // Server has sent an alternate address to connect to. - IPEndPoint new_address = - ToIPEndPoint(config()->ReceivedAlternateServerAddress()); 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). - if (old_address.GetFamily() != new_address.GetFamily() && - old_address.GetFamily() == ADDRESS_FAMILY_IPV4) { - return; - } - - if (old_address.GetFamily() != new_address.GetFamily()) { - DCHECK_EQ(old_address.GetFamily(), ADDRESS_FAMILY_IPV6); - DCHECK_EQ(new_address.GetFamily(), ADDRESS_FAMILY_IPV4); - // Use a v4-mapped v6 address. - new_address = IPEndPoint(ConvertIPv4ToIPv4MappedIPv6(new_address.address()), - new_address.port()); + IPEndPoint new_address; + if (old_address.GetFamily() == ADDRESS_FAMILY_IPV6) { + if (config()->HasReceivedIPv6AlternateServerAddress()) { + 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 { + return; + } } - - if (!stream_factory_->allow_server_migration()) - return; + 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. @@ -1607,7 +1638,7 @@ void QuicChromiumClientSession::OnConnectionClosed( RecordConnectionCloseErrorCode(frame, source, session_key_.host(), OneRttKeysAvailable()); - const quic::QuicErrorCode error = frame.extracted_error_code; + const quic::QuicErrorCode error = frame.quic_error_code; const std::string& error_details = frame.error_details; if (source == quic::ConnectionCloseSource::FROM_PEER) { @@ -1669,9 +1700,9 @@ void QuicChromiumClientSession::OnConnectionClosed( if (error == quic::QUIC_NETWORK_IDLE_TIMEOUT) { UMA_HISTOGRAM_COUNTS_1M( "Net.QuicSession.ConnectionClose.NumOpenStreams.TimedOut", - GetNumOpenOutgoingStreams()); + GetNumActiveStreams()); if (OneRttKeysAvailable()) { - if (GetNumOpenOutgoingStreams() > 0) { + if (GetNumActiveStreams() > 0) { UMA_HISTOGRAM_BOOLEAN( "Net.QuicSession.TimedOutWithOpenStreams.HasUnackedPackets", connection()->sent_packet_manager().HasInFlightPackets()); @@ -1688,7 +1719,7 @@ void QuicChromiumClientSession::OnConnectionClosed( } else { UMA_HISTOGRAM_COUNTS_1M( "Net.QuicSession.ConnectionClose.NumOpenStreams.HandshakeTimedOut", - GetNumOpenOutgoingStreams()); + GetNumActiveStreams()); UMA_HISTOGRAM_COUNTS_1M( "Net.QuicSession.ConnectionClose.NumTotalStreams.HandshakeTimedOut", num_total_streams_); @@ -1703,9 +1734,12 @@ void QuicChromiumClientSession::OnConnectionClosed( // then QUIC traffic has become blackholed. if (stream_factory_ && (error == quic::QUIC_TOO_MANY_RTOS || (error == quic::QUIC_NETWORK_IDLE_TIMEOUT && - GetNumOpenOutgoingStreams() > 0))) { + GetNumActiveStreams() > 0))) { stream_factory_->OnBlackholeAfterHandshakeConfirmed(this); } + UMA_HISTOGRAM_COUNTS_100( + "Net.QuicSession.CryptoRetransmitCount.HandshakeConfirmed", + connection()->GetStats().crypto_retransmit_count); } else { if (error == quic::QUIC_PUBLIC_RESET) { RecordHandshakeFailureReason(HANDSHAKE_FAILURE_PUBLIC_RESET); @@ -1720,6 +1754,9 @@ void QuicChromiumClientSession::OnConnectionClosed( "Net.QuicSession.ConnectionClose.HandshakeFailureUnknown.QuicError", error); } + UMA_HISTOGRAM_COUNTS_100( + "Net.QuicSession.CryptoRetransmitCount.HandshakeNotConfirmed", + connection()->GetStats().crypto_retransmit_count); } base::UmaHistogramSparse("Net.QuicSession.QuicVersion", @@ -2841,7 +2878,7 @@ base::Value QuicChromiumClientSession::GetInfoAsValue( base::DictionaryValue dict; dict.SetString("version", QuicVersionToString(connection()->transport_version())); - dict.SetInteger("open_streams", GetNumOpenOutgoingStreams()); + dict.SetInteger("open_streams", GetNumActiveStreams()); std::unique_ptr<base::ListValue> stream_list(new base::ListValue()); for (StreamMap::const_iterator it = stream_map().begin(); it != stream_map().end(); ++it) { diff --git a/chromium/net/quic/quic_chromium_client_session_test.cc b/chromium/net/quic/quic_chromium_client_session_test.cc index 71e76fced2b..404d815f3af 100644 --- a/chromium/net/quic/quic_chromium_client_session_test.cc +++ b/chromium/net/quic/quic_chromium_client_session_test.cc @@ -107,7 +107,7 @@ class TestingQuicChromiumClientSession : public QuicChromiumClientSession { public: using QuicChromiumClientSession::QuicChromiumClientSession; - MOCK_METHOD0(OnPathDegrading, void()); + MOCK_METHOD(void, OnPathDegrading, (), (override)); void ReallyOnPathDegrading() { QuicChromiumClientSession::OnPathDegrading(); } }; @@ -592,7 +592,7 @@ TEST_P(QuicChromiumClientSessionTest, AsyncStreamRequest) { for (size_t i = 0; i < kMaxOpenStreams; i++) { QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); } - EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(kMaxOpenStreams, session_->GetNumActiveStreams()); // Request a stream and verify that it's pending. std::unique_ptr<QuicChromiumClientSession::Handle> handle = @@ -664,7 +664,7 @@ TEST_P(QuicChromiumClientSessionTest, ReadAfterConnectionClose) { for (size_t i = 0; i < kMaxOpenStreams; i++) { QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); } - EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(kMaxOpenStreams, session_->GetNumActiveStreams()); // Request two streams which will both be pending. // In V99 each will generate a max stream id for each attempt. @@ -727,7 +727,7 @@ TEST_P(QuicChromiumClientSessionTest, ClosedWithAsyncStreamRequest) { for (size_t i = 0; i < kMaxOpenStreams; i++) { QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); } - EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(kMaxOpenStreams, session_->GetNumActiveStreams()); // Request two streams which will both be pending. // In V99 each will generate a max stream id for each attempt. @@ -798,7 +798,7 @@ TEST_P(QuicChromiumClientSessionTest, CancelPendingStreamRequest) { for (size_t i = 0; i < kMaxOpenStreams; i++) { QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); } - EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(kMaxOpenStreams, session_->GetNumActiveStreams()); // Request a stream and verify that it's pending. std::unique_ptr<QuicChromiumClientSession::Handle> handle = @@ -826,7 +826,7 @@ TEST_P(QuicChromiumClientSessionTest, CancelPendingStreamRequest) { quic::QUIC_STREAM_CANCELLED); session_->OnStopSendingFrame(stop_sending); } - EXPECT_EQ(kMaxOpenStreams - 1, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(kMaxOpenStreams - 1, session_->GetNumActiveStreams()); quic_data.Resume(); EXPECT_TRUE(quic_data.AllReadDataConsumed()); @@ -944,7 +944,7 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionCloseWithPendingStreamRequest) { for (size_t i = 0; i < kMaxOpenStreams; i++) { QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); } - EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(kMaxOpenStreams, session_->GetNumActiveStreams()); // Request a stream and verify that it's pending. std::unique_ptr<QuicChromiumClientSession::Handle> handle = @@ -1013,7 +1013,7 @@ TEST_P(QuicChromiumClientSessionTest, MaxNumStreams) { EXPECT_FALSE( QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get())); - EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(kMaxOpenStreams, session_->GetNumActiveStreams()); // Close a stream and ensure I can now open a new one. quic::QuicStreamId stream_id = streams[0]->id(); @@ -1027,7 +1027,7 @@ TEST_P(QuicChromiumClientSessionTest, MaxNumStreams) { quic::QuicRstStreamFrame rst1(quic::kInvalidControlFrameId, stream_id, quic::QUIC_STREAM_NO_ERROR, 0); session_->OnRstStream(rst1); - EXPECT_EQ(kMaxOpenStreams - 1, session_->GetNumOpenOutgoingStreams()); + EXPECT_EQ(kMaxOpenStreams - 1, session_->GetNumActiveStreams()); base::RunLoop().RunUntilIdle(); EXPECT_TRUE( QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get())); @@ -1175,7 +1175,7 @@ TEST_P(QuicChromiumClientSessionTest, PendingStreamOnRst) { quic::QuicStreamFrame data(GetNthServerInitiatedUnidirectionalStreamId(0), false, 1, quiche::QuicheStringPiece("SP")); session_->OnStreamFrame(data); - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, session_->GetNumActiveStreams()); quic::QuicRstStreamFrame rst(quic::kInvalidControlFrameId, GetNthServerInitiatedUnidirectionalStreamId(0), quic::QUIC_STREAM_CANCELLED, 0); @@ -1207,7 +1207,7 @@ TEST_P(QuicChromiumClientSessionTest, ClosePendingStream) { quic::QuicStreamId id = GetNthServerInitiatedUnidirectionalStreamId(0); quic::QuicStreamFrame data(id, false, 1, quiche::QuicheStringPiece("SP")); session_->OnStreamFrame(data); - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); + EXPECT_EQ(0u, session_->GetNumActiveStreams()); session_->CloseStream(id); } @@ -1899,70 +1899,6 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) { EXPECT_TRUE(new_socket_data.AllWriteDataConsumed()); } -TEST_P(QuicChromiumClientSessionTest, DetectPathDegradingDuringHandshake) { - if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) { - // TODO(nharper, b/112643533): Figure out why this test fails when TLS is - // enabled and fix it. - return; - } - migrate_session_early_v2_ = true; - - MockQuicData quic_data(version_); - quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read - quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeDummyCHLOPacket(1)); - quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeDummyCHLOPacket(2)); - quic_data.AddSocketDataToFactory(&socket_factory_); - - // Set the crypto handshake mode to cold start and send CHLO packets. - crypto_client_stream_factory_.set_handshake_mode( - MockCryptoClientStream::COLD_START_WITH_CHLO_SENT); - Initialize(); - - session_->CryptoConnect(callback_.callback()); - - // Check retransmission alarm is set after sending the initial CHLO packet. - quic::QuicAlarm* retransmission_alarm = - quic::test::QuicConnectionPeer::GetRetransmissionAlarm( - session_->connection()); - EXPECT_TRUE(retransmission_alarm->IsSet()); - quic::QuicTime retransmission_time = retransmission_alarm->deadline(); - - // Check path degrading alarm is set after sending the initial CHLO packet. - quic::QuicAlarm* path_degrading_alarm = - quic::test::QuicConnectionPeer::GetPathDegradingAlarm( - session_->connection()); - EXPECT_TRUE(path_degrading_alarm->IsSet()); - quic::QuicTime path_degrading_time = path_degrading_alarm->deadline(); - EXPECT_LE(retransmission_time, path_degrading_time); - - // Do not create outgoing stream since encryption is not established. - std::unique_ptr<QuicChromiumClientSession::Handle> handle = - session_->CreateHandle(destination_); - TestCompletionCallback callback; - EXPECT_TRUE(handle->IsConnected()); - EXPECT_FALSE(handle->OneRttKeysAvailable()); - EXPECT_EQ( - ERR_IO_PENDING, - handle->RequestStream(/*require_handshake_confirmation=*/true, - callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS)); - - // Fire the retransmission alarm to retransmit the crypto packet. - quic::QuicTime::Delta delay = retransmission_time - clock_.ApproximateNow(); - clock_.AdvanceTime(delay); - alarm_factory_.FireAlarm(retransmission_alarm); - - // Fire the path degrading alarm to notify session that path is degrading - // during crypto handshake. - delay = path_degrading_time - clock_.ApproximateNow(); - clock_.AdvanceTime(delay); - EXPECT_CALL(*session_.get(), OnPathDegrading()); - alarm_factory_.FireAlarm(path_degrading_alarm); - - EXPECT_TRUE(session_->connection()->IsPathDegrading()); - EXPECT_TRUE(quic_data.AllReadDataConsumed()); - EXPECT_TRUE(quic_data.AllWriteDataConsumed()); -} - TEST_P(QuicChromiumClientSessionTest, GoAwayOnPathDegradingOnlyWhenHandshakeConfirmed) { go_away_on_path_degrading_ = true; @@ -1994,8 +1930,8 @@ TEST_P(QuicChromiumClientSessionTest, RetransmittableOnWireTimeout) { quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++, true)); - quic_data.AddRead( - ASYNC, server_maker_.MakeAckPacket(1, packet_num - 1, 1, 1, false)); + quic_data.AddRead(ASYNC, + server_maker_.MakeAckPacket(1, packet_num - 1, 1, 1)); quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++, false)); diff --git a/chromium/net/quic/quic_chromium_client_stream_test.cc b/chromium/net/quic/quic_chromium_client_stream_test.cc index 612f0420da5..a4923d1e689 100644 --- a/chromium/net/quic/quic_chromium_client_stream_test.cc +++ b/chromium/net/quic/quic_chromium_client_stream_test.cc @@ -955,10 +955,22 @@ TEST_P(QuicChromiumClientStreamTest, HeadersAndDataBeforeHandle) { // Regression test for https://crbug.com/1043531. TEST_P(QuicChromiumClientStreamTest, ResetOnEmptyResponseHeaders) { + if (!VersionUsesHttp3(version_.transport_version)) { + // QuicSpdyStream resets itself on empty headers, + // because it is used to signal that headers were too large. + EXPECT_CALL(session_, + SendRstStream(stream_->id(), quic::QUIC_HEADERS_TOO_LARGE, 0)); + } + const spdy::SpdyHeaderBlock empty_response_headers; ProcessHeaders(empty_response_headers); - int rv = handle_->ReadInitialHeaders(&headers_, CompletionOnceCallback()); - EXPECT_THAT(rv, IsError(ERR_INVALID_RESPONSE)); + + if (VersionUsesHttp3(version_.transport_version)) { + // Empty headers are allowed by QuicSpdyStream, + // but an error is generated by QuicChromiumClientStream. + int rv = handle_->ReadInitialHeaders(&headers_, CompletionOnceCallback()); + EXPECT_THAT(rv, IsError(ERR_INVALID_RESPONSE)); + } } } // namespace diff --git a/chromium/net/quic/quic_chromium_packet_writer.cc b/chromium/net/quic/quic_chromium_packet_writer.cc index 143c2986363..2c5d194df73 100644 --- a/chromium/net/quic/quic_chromium_packet_writer.cc +++ b/chromium/net/quic/quic_chromium_packet_writer.cc @@ -8,8 +8,8 @@ #include <utility> #include "base/bind.h" +#include "base/check_op.h" #include "base/location.h" -#include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/sparse_histogram.h" #include "net/base/io_buffer.h" diff --git a/chromium/net/quic/quic_client_session_cache.cc b/chromium/net/quic/quic_client_session_cache.cc index fc475951c9d..7bc5945225a 100644 --- a/chromium/net/quic/quic_client_session_cache.cc +++ b/chromium/net/quic/quic_client_session_cache.cc @@ -12,20 +12,31 @@ namespace net { namespace { const size_t kDefaultMaxEntries = 1024; -// Check whether the SSL session inside |state| is expired at |now|. -bool IsExpired(quic::QuicResumptionState* state, time_t now) { +// Returns false if the SSL |session| doesn't exist or it is expired at |now|. +bool IsValid(SSL_SESSION* session, time_t now) { + if (!session) + return false; + if (now < 0) - return true; + return false; - SSL_SESSION* session = state->tls_session.get(); uint64_t now_u64 = static_cast<uint64_t>(now); // now_u64 may be slightly behind because of differences in how // time is calculated at this layer versus BoringSSL. // Add a second of wiggle room to account for this. - return now_u64 < SSL_SESSION_get_time(session) - 1 || - now_u64 >= - SSL_SESSION_get_time(session) + SSL_SESSION_get_timeout(session); + return !(now_u64 < SSL_SESSION_get_time(session) - 1 || + now_u64 >= SSL_SESSION_get_time(session) + + SSL_SESSION_get_timeout(session)); +} + +bool DoApplicationStatesMatch(const quic::ApplicationState* state, + quic::ApplicationState* other) { + if ((state && !other) || (!state && other)) + return false; + if ((!state && !other) || *state == *other) + return true; + return false; } } // namespace @@ -46,8 +57,30 @@ QuicClientSessionCache::~QuicClientSessionCache() { void QuicClientSessionCache::Insert( const quic::QuicServerId& server_id, - std::unique_ptr<quic::QuicResumptionState> state) { - cache_.Put(server_id, std::move(state)); + bssl::UniquePtr<SSL_SESSION> session, + const quic::TransportParameters& params, + const quic::ApplicationState* application_state) { + DCHECK(session) << "TLS session is not inserted into client cache."; + auto iter = cache_.Get(server_id); + if (iter == cache_.end()) { + CreateAndInsertEntry(server_id, std::move(session), params, + application_state); + return; + } + + DCHECK(iter->second.params); + // The states are both the same, so only need to insert sessions. + if (params == *iter->second.params && + DoApplicationStatesMatch(application_state, + iter->second.application_state.get())) { + iter->second.PushSession(std::move(session)); + return; + } + // Erase the existing entry because this Insert call must come from a + // different QUIC session. + cache_.Erase(iter); + CreateAndInsertEntry(server_id, std::move(session), params, + application_state); } std::unique_ptr<quic::QuicResumptionState> QuicClientSessionCache::Lookup( @@ -58,18 +91,23 @@ std::unique_ptr<quic::QuicResumptionState> QuicClientSessionCache::Lookup( return nullptr; time_t now = clock_->Now().ToTimeT(); - std::unique_ptr<quic::QuicResumptionState> state = std::move(iter->second); - cache_.Erase(iter); - if (IsExpired(state.get(), now)) - state = nullptr; + if (!IsValid(iter->second.PeekSession(), now)) { + cache_.Erase(iter); + return nullptr; + } + auto state = std::make_unique<quic::QuicResumptionState>(); + state->tls_session = iter->second.PopSession(); + state->transport_params = iter->second.params.get(); + state->application_state = iter->second.application_state.get(); + return state; } -void QuicClientSessionCache::FlushExpiredStates() { +void QuicClientSessionCache::FlushInvalidEntries() { time_t now = clock_->Now().ToTimeT(); auto iter = cache_.begin(); while (iter != cache_.end()) { - if (IsExpired(iter->second.get(), now)) { + if (!IsValid(iter->second.PeekSession(), now)) { iter = cache_.Erase(iter); } else { ++iter; @@ -83,7 +121,7 @@ void QuicClientSessionCache::OnMemoryPressure( case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: break; case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: - FlushExpiredStates(); + FlushInvalidEntries(); break; case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: Flush(); @@ -91,4 +129,48 @@ void QuicClientSessionCache::OnMemoryPressure( } } +void QuicClientSessionCache::Flush() { + cache_.Clear(); +} + +void QuicClientSessionCache::CreateAndInsertEntry( + const quic::QuicServerId& server_id, + bssl::UniquePtr<SSL_SESSION> session, + const quic::TransportParameters& params, + const quic::ApplicationState* application_state) { + Entry entry; + entry.PushSession(std::move(session)); + entry.params = std::make_unique<quic::TransportParameters>(params); + if (application_state) { + entry.application_state = + std::make_unique<quic::ApplicationState>(*application_state); + } + cache_.Put(server_id, std::move(entry)); +} + +QuicClientSessionCache::Entry::Entry() = default; +QuicClientSessionCache::Entry::Entry(Entry&&) = default; +QuicClientSessionCache::Entry::~Entry() = default; + +void QuicClientSessionCache::Entry::PushSession( + bssl::UniquePtr<SSL_SESSION> session) { + if (sessions[0] != nullptr) { + sessions[1] = std::move(sessions[0]); + } + sessions[0] = std::move(session); +} + +bssl::UniquePtr<SSL_SESSION> QuicClientSessionCache::Entry::PopSession() { + if (sessions[0] == nullptr) + return nullptr; + bssl::UniquePtr<SSL_SESSION> session = std::move(sessions[0]); + sessions[0] = std::move(sessions[1]); + sessions[1] = nullptr; + return session; +} + +SSL_SESSION* QuicClientSessionCache::Entry::PeekSession() { + return sessions[0].get(); +} + } // namespace net diff --git a/chromium/net/quic/quic_client_session_cache.h b/chromium/net/quic/quic_client_session_cache.h index c102eff48e5..8d7506ee4ec 100644 --- a/chromium/net/quic/quic_client_session_cache.h +++ b/chromium/net/quic/quic_client_session_cache.h @@ -31,7 +31,9 @@ class NET_EXPORT_PRIVATE QuicClientSessionCache : public quic::SessionCache { ~QuicClientSessionCache() override; void Insert(const quic::QuicServerId& server_id, - std::unique_ptr<quic::QuicResumptionState> state) override; + bssl::UniquePtr<SSL_SESSION> session, + const quic::TransportParameters& params, + const quic::ApplicationState* application_state) override; std::unique_ptr<quic::QuicResumptionState> Lookup( const quic::QuicServerId& server_id, @@ -41,17 +43,40 @@ class NET_EXPORT_PRIVATE QuicClientSessionCache : public quic::SessionCache { size_t size() const { return cache_.size(); } - void Flush() { cache_.Clear(); } + void Flush(); void OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); private: - void FlushExpiredStates(); + struct Entry { + Entry(); + Entry(Entry&&); + ~Entry(); + + // Adds a new |session| onto sessions, dropping the oldest one if two are + // already stored. + void PushSession(bssl::UniquePtr<SSL_SESSION> session); + + // Retrieves the latest session from the entry, meanwhile removing it. + bssl::UniquePtr<SSL_SESSION> PopSession(); + + SSL_SESSION* PeekSession(); + + bssl::UniquePtr<SSL_SESSION> sessions[2]; + std::unique_ptr<quic::TransportParameters> params; + std::unique_ptr<quic::ApplicationState> application_state; + }; + void FlushInvalidEntries(); + + // Creates a new entry and insert into |cache_|. + void CreateAndInsertEntry(const quic::QuicServerId& server_id, + bssl::UniquePtr<SSL_SESSION> session, + const quic::TransportParameters& params, + const quic::ApplicationState* application_state); base::Clock* clock_; - base::MRUCache<quic::QuicServerId, std::unique_ptr<quic::QuicResumptionState>> - cache_; + base::MRUCache<quic::QuicServerId, Entry> cache_; std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; }; diff --git a/chromium/net/quic/quic_client_session_cache_unittests.cc b/chromium/net/quic/quic_client_session_cache_unittests.cc index d9b731281ce..0fac11c6840 100644 --- a/chromium/net/quic/quic_client_session_cache_unittests.cc +++ b/chromium/net/quic/quic_client_session_cache_unittests.cc @@ -15,6 +15,28 @@ namespace net { namespace { +const quic::QuicVersionLabel kFakeVersionLabel = 0x01234567; +const quic::QuicVersionLabel kFakeVersionLabel2 = 0x89ABCDEF; +const uint64_t kFakeIdleTimeoutMilliseconds = 12012; +const uint8_t kFakeStatelessResetTokenData[16] = { + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F}; +const uint64_t kFakeMaxPacketSize = 9001; +const uint64_t kFakeInitialMaxData = 101; +const bool kFakeDisableMigration = true; +const auto kCustomParameter1 = + static_cast<quic::TransportParameters::TransportParameterId>(0xffcd); +const char* kCustomParameter1Value = "foo"; +const auto kCustomParameter2 = + static_cast<quic::TransportParameters::TransportParameterId>(0xff34); +const char* kCustomParameter2Value = "bar"; + +std::vector<uint8_t> CreateFakeStatelessResetToken() { + return std::vector<uint8_t>( + kFakeStatelessResetTokenData, + kFakeStatelessResetTokenData + base::size(kFakeStatelessResetTokenData)); +} + std::unique_ptr<base::SimpleTestClock> MakeTestClock() { std::unique_ptr<base::SimpleTestClock> clock = std::make_unique<base::SimpleTestClock>(); @@ -24,6 +46,23 @@ std::unique_ptr<base::SimpleTestClock> MakeTestClock() { return clock; } +// Make a TransportParameters that has a few fields set to help test comparison. +std::unique_ptr<quic::TransportParameters> MakeFakeTransportParams() { + auto params = std::make_unique<quic::TransportParameters>(); + params->perspective = quic::Perspective::IS_CLIENT; + params->version = kFakeVersionLabel; + params->supported_versions.push_back(kFakeVersionLabel); + params->supported_versions.push_back(kFakeVersionLabel2); + params->idle_timeout_milliseconds.set_value(kFakeIdleTimeoutMilliseconds); + params->stateless_reset_token = CreateFakeStatelessResetToken(); + params->max_packet_size.set_value(kFakeMaxPacketSize); + params->initial_max_data.set_value(kFakeInitialMaxData); + params->disable_migration = kFakeDisableMigration; + params->custom_parameters[kCustomParameter1] = kCustomParameter1Value; + params->custom_parameters[kCustomParameter2] = kCustomParameter2Value; + return params; +} + class QuicClientSessionCacheTest : public testing::Test { public: QuicClientSessionCacheTest() : ssl_ctx_(SSL_CTX_new(TLS_method())) {} @@ -50,39 +89,40 @@ class QuicClientSessionCacheTest : public testing::Test { } // namespace // Tests that simple insertion and lookup work correctly. -TEST_F(QuicClientSessionCacheTest, Basic) { +TEST_F(QuicClientSessionCacheTest, SingleSession) { QuicClientSessionCache cache; - std::unique_ptr<quic::QuicResumptionState> state1 = - std::make_unique<quic::QuicResumptionState>(); - state1->application_state.push_back('a'); - state1->tls_session = NewSSLSession(); + auto params = MakeFakeTransportParams(); + auto session = NewSSLSession(); quic::QuicServerId id1("a.com", 443); - std::unique_ptr<quic::QuicResumptionState> state2 = - std::make_unique<quic::QuicResumptionState>(); - state2->application_state.push_back('b'); - state2->tls_session = NewSSLSession(); + + auto params2 = MakeFakeTransportParams(); + auto session2 = NewSSLSession(); + SSL_SESSION* unowned2 = session2.get(); quic::QuicServerId id2("b.com", 443); EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get())); EXPECT_EQ(nullptr, cache.Lookup(id2, ssl_ctx_.get())); EXPECT_EQ(0u, cache.size()); - cache.Insert(id1, std::move(state1)); + cache.Insert(id1, std::move(session), *params, nullptr); EXPECT_EQ(1u, cache.size()); - EXPECT_EQ('a', cache.Lookup(id1, ssl_ctx_.get())->application_state.front()); + EXPECT_EQ(*params, *(cache.Lookup(id1, ssl_ctx_.get())->transport_params)); EXPECT_EQ(nullptr, cache.Lookup(id2, ssl_ctx_.get())); + // No session is available for id1, even though the entry exists. + EXPECT_EQ(1u, cache.size()); + EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get())); + // Lookup() will trigger a deletion of invalid entry. + EXPECT_EQ(0u, cache.size()); - std::unique_ptr<quic::QuicResumptionState> state3 = - std::make_unique<quic::QuicResumptionState>(); - state3->application_state.push_back('c'); - state3->tls_session = NewSSLSession(); + auto session3 = NewSSLSession(); + SSL_SESSION* unowned3 = session3.get(); quic::QuicServerId id3("c.com", 443); - cache.Insert(id3, std::move(state3)); - cache.Insert(id2, std::move(state2)); + cache.Insert(id3, std::move(session3), *params, nullptr); + cache.Insert(id2, std::move(session2), *params2, nullptr); EXPECT_EQ(2u, cache.size()); - EXPECT_EQ('b', cache.Lookup(id2, ssl_ctx_.get())->application_state.front()); - EXPECT_EQ('c', cache.Lookup(id3, ssl_ctx_.get())->application_state.front()); + EXPECT_EQ(unowned2, cache.Lookup(id2, ssl_ctx_.get())->tls_session.get()); + EXPECT_EQ(unowned3, cache.Lookup(id3, ssl_ctx_.get())->tls_session.get()); // Verify that the cache is cleared after Lookups. EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get())); @@ -91,35 +131,117 @@ TEST_F(QuicClientSessionCacheTest, Basic) { EXPECT_EQ(0u, cache.size()); } +TEST_F(QuicClientSessionCacheTest, MultipleSessions) { + QuicClientSessionCache cache; + + auto params = MakeFakeTransportParams(); + auto session = NewSSLSession(); + quic::QuicServerId id1("a.com", 443); + auto session2 = NewSSLSession(); + SSL_SESSION* unowned2 = session2.get(); + auto session3 = NewSSLSession(); + SSL_SESSION* unowned3 = session3.get(); + + cache.Insert(id1, std::move(session), *params, nullptr); + cache.Insert(id1, std::move(session2), *params, nullptr); + cache.Insert(id1, std::move(session3), *params, nullptr); + // The latest session is popped first. + EXPECT_EQ(unowned3, cache.Lookup(id1, ssl_ctx_.get())->tls_session.get()); + EXPECT_EQ(unowned2, cache.Lookup(id1, ssl_ctx_.get())->tls_session.get()); + // Only two sessions are cached. + EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get())); +} + +// Test that when a different TransportParameter is inserted for +// the same server id, the existing entry is removed. +TEST_F(QuicClientSessionCacheTest, DifferentTransportParams) { + QuicClientSessionCache cache; + + auto params = MakeFakeTransportParams(); + auto session = NewSSLSession(); + quic::QuicServerId id1("a.com", 443); + auto session2 = NewSSLSession(); + auto session3 = NewSSLSession(); + SSL_SESSION* unowned3 = session3.get(); + + cache.Insert(id1, std::move(session), *params, nullptr); + cache.Insert(id1, std::move(session2), *params, nullptr); + // tweak the transport parameters a little bit. + params->perspective = quic::Perspective::IS_SERVER; + cache.Insert(id1, std::move(session3), *params, nullptr); + auto resumption_state = cache.Lookup(id1, ssl_ctx_.get()); + EXPECT_EQ(unowned3, resumption_state->tls_session.get()); + EXPECT_EQ(*params.get(), *resumption_state->transport_params); + EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get())); +} + +TEST_F(QuicClientSessionCacheTest, DifferentApplicationState) { + QuicClientSessionCache cache; + + auto params = MakeFakeTransportParams(); + auto session = NewSSLSession(); + quic::QuicServerId id1("a.com", 443); + auto session2 = NewSSLSession(); + auto session3 = NewSSLSession(); + SSL_SESSION* unowned3 = session3.get(); + quic::ApplicationState state; + state.push_back('a'); + + cache.Insert(id1, std::move(session), *params, &state); + cache.Insert(id1, std::move(session2), *params, &state); + cache.Insert(id1, std::move(session3), *params, nullptr); + auto resumption_state = cache.Lookup(id1, ssl_ctx_.get()); + EXPECT_EQ(unowned3, resumption_state->tls_session.get()); + EXPECT_EQ(nullptr, resumption_state->application_state); + EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get())); +} + +TEST_F(QuicClientSessionCacheTest, BothStatesDifferent) { + QuicClientSessionCache cache; + + auto params = MakeFakeTransportParams(); + auto session = NewSSLSession(); + quic::QuicServerId id1("a.com", 443); + auto session2 = NewSSLSession(); + auto session3 = NewSSLSession(); + SSL_SESSION* unowned3 = session3.get(); + quic::ApplicationState state; + state.push_back('a'); + + cache.Insert(id1, std::move(session), *params, &state); + cache.Insert(id1, std::move(session2), *params, &state); + params->perspective = quic::Perspective::IS_SERVER; + cache.Insert(id1, std::move(session3), *params, nullptr); + auto resumption_state = cache.Lookup(id1, ssl_ctx_.get()); + EXPECT_EQ(unowned3, resumption_state->tls_session.get()); + EXPECT_EQ(*params.get(), *resumption_state->transport_params); + EXPECT_EQ(nullptr, resumption_state->application_state); + EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get())); +} + // When the size limit is exceeded, the oldest entry should be erased. TEST_F(QuicClientSessionCacheTest, SizeLimit) { QuicClientSessionCache cache(2); - std::unique_ptr<quic::QuicResumptionState> state1 = - std::make_unique<quic::QuicResumptionState>(); - state1->application_state.push_back('a'); - state1->tls_session = NewSSLSession(); + auto params = MakeFakeTransportParams(); + auto session = NewSSLSession(); quic::QuicServerId id1("a.com", 443); - std::unique_ptr<quic::QuicResumptionState> state2 = - std::make_unique<quic::QuicResumptionState>(); - state2->application_state.push_back('b'); - state2->tls_session = NewSSLSession(); + auto session2 = NewSSLSession(); + SSL_SESSION* unowned2 = session2.get(); quic::QuicServerId id2("b.com", 443); - std::unique_ptr<quic::QuicResumptionState> state3 = - std::make_unique<quic::QuicResumptionState>(); - state3->application_state.push_back('c'); - state3->tls_session = NewSSLSession(); + auto session3 = NewSSLSession(); + SSL_SESSION* unowned3 = session3.get(); quic::QuicServerId id3("c.com", 443); - cache.Insert(id1, std::move(state1)); - cache.Insert(id2, std::move(state2)); - cache.Insert(id3, std::move(state3)); + cache.Insert(id1, std::move(session), *params, nullptr); + cache.Insert(id2, std::move(session2), *params, nullptr); + cache.Insert(id3, std::move(session3), *params, nullptr); EXPECT_EQ(2u, cache.size()); - EXPECT_EQ('b', cache.Lookup(id2, ssl_ctx_.get())->application_state.front()); - EXPECT_EQ('c', cache.Lookup(id3, ssl_ctx_.get())->application_state.front()); + EXPECT_EQ(unowned2, cache.Lookup(id2, ssl_ctx_.get())->tls_session.get()); + EXPECT_EQ(unowned3, cache.Lookup(id3, ssl_ctx_.get())->tls_session.get()); EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get())); } @@ -131,20 +253,16 @@ TEST_F(QuicClientSessionCacheTest, Expiration) { std::unique_ptr<base::SimpleTestClock> clock = MakeTestClock(); cache.SetClockForTesting(clock.get()); - std::unique_ptr<quic::QuicResumptionState> state1 = - std::make_unique<quic::QuicResumptionState>(); - state1->tls_session = MakeTestSession(clock->Now(), kTimeout); + auto params = MakeFakeTransportParams(); + auto session = MakeTestSession(clock->Now(), kTimeout); quic::QuicServerId id1("a.com", 443); - std::unique_ptr<quic::QuicResumptionState> state2 = - std::make_unique<quic::QuicResumptionState>(); - state2->tls_session = MakeTestSession(clock->Now(), 3 * kTimeout); - ; - state2->application_state.push_back('b'); + auto session2 = MakeTestSession(clock->Now(), 3 * kTimeout); + SSL_SESSION* unowned2 = session2.get(); quic::QuicServerId id2("b.com", 443); - cache.Insert(id1, std::move(state1)); - cache.Insert(id2, std::move(state2)); + cache.Insert(id1, std::move(session), *params, nullptr); + cache.Insert(id2, std::move(session2), *params, nullptr); EXPECT_EQ(2u, cache.size()); // Expire the session. @@ -154,8 +272,8 @@ TEST_F(QuicClientSessionCacheTest, Expiration) { EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get())); EXPECT_EQ(1u, cache.size()); - EXPECT_EQ('b', cache.Lookup(id2, ssl_ctx_.get())->application_state.front()); - EXPECT_EQ(0u, cache.size()); + EXPECT_EQ(unowned2, cache.Lookup(id2, ssl_ctx_.get())->tls_session.get()); + EXPECT_EQ(1u, cache.size()); } TEST_F(QuicClientSessionCacheTest, FlushOnMemoryNotifications) { @@ -165,20 +283,15 @@ TEST_F(QuicClientSessionCacheTest, FlushOnMemoryNotifications) { std::unique_ptr<base::SimpleTestClock> clock = MakeTestClock(); cache.SetClockForTesting(clock.get()); - std::unique_ptr<quic::QuicResumptionState> state1 = - std::make_unique<quic::QuicResumptionState>(); - state1->tls_session = MakeTestSession(clock->Now(), kTimeout); + auto params = MakeFakeTransportParams(); + auto session = MakeTestSession(clock->Now(), kTimeout); quic::QuicServerId id1("a.com", 443); - std::unique_ptr<quic::QuicResumptionState> state2 = - std::make_unique<quic::QuicResumptionState>(); - state2->tls_session = MakeTestSession(clock->Now(), 3 * kTimeout); - ; - state2->application_state.push_back('b'); + auto session2 = MakeTestSession(clock->Now(), 3 * kTimeout); quic::QuicServerId id2("b.com", 443); - cache.Insert(id1, std::move(state1)); - cache.Insert(id2, std::move(state2)); + cache.Insert(id1, std::move(session), *params, nullptr); + cache.Insert(id2, std::move(session2), *params, nullptr); EXPECT_EQ(2u, cache.size()); // Expire the session. @@ -191,7 +304,7 @@ TEST_F(QuicClientSessionCacheTest, FlushOnMemoryNotifications) { base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); base::RunLoop().RunUntilIdle(); - // session1 is expired and should be flushed. + // session is expired and should be flushed. EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get())); EXPECT_EQ(1u, cache.size()); @@ -202,4 +315,4 @@ TEST_F(QuicClientSessionCacheTest, FlushOnMemoryNotifications) { EXPECT_EQ(0u, cache.size()); } -} // namespace net
\ No newline at end of file +} // namespace net diff --git a/chromium/net/quic/quic_connection_logger.cc b/chromium/net/quic/quic_connection_logger.cc index a8c5285f833..1293fac42ac 100644 --- a/chromium/net/quic/quic_connection_logger.cc +++ b/chromium/net/quic/quic_connection_logger.cc @@ -707,8 +707,30 @@ void QuicConnectionLogger::OnIncorrectConnectionId( ++num_incorrect_connection_ids_; } -void QuicConnectionLogger::OnUndecryptablePacket() { +void QuicConnectionLogger::OnUndecryptablePacket( + quic::EncryptionLevel decryption_level, + bool dropped) { ++num_undecryptable_packets_; + if (!net_log_.IsCapturing()) + return; + if (dropped) { + net_log_.AddEventWithStringParams( + NetLogEventType::QUIC_SESSION_DROPPED_UNDECRYPTABLE_PACKET, + "encryption_level", quic::EncryptionLevelToString(decryption_level)); + return; + } + net_log_.AddEventWithStringParams( + NetLogEventType::QUIC_SESSION_BUFFERED_UNDECRYPTABLE_PACKET, + "encryption_level", quic::EncryptionLevelToString(decryption_level)); +} + +void QuicConnectionLogger::OnAttemptingToProcessUndecryptablePacket( + quic::EncryptionLevel decryption_level) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEventWithStringParams( + NetLogEventType::QUIC_SESSION_ATTEMPTING_TO_PROCESS_UNDECRYPTABLE_PACKET, + "encryption_level", quic::EncryptionLevelToString(decryption_level)); } void QuicConnectionLogger::OnDuplicatePacket( diff --git a/chromium/net/quic/quic_connection_logger.h b/chromium/net/quic/quic_connection_logger.h index 58bbcf60d99..9c45bf983d9 100644 --- a/chromium/net/quic/quic_connection_logger.h +++ b/chromium/net/quic/quic_connection_logger.h @@ -46,7 +46,7 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger void OnFrameAddedToPacket(const quic::QuicFrame& frame) override; void OnStreamFrameCoalesced(const quic::QuicStreamFrame& frame) override; - // QuicConnectionDebugVisitorInterface + // QuicConnectionDebugVisitor Interface void OnPacketSent(const quic::SerializedPacket& serialized_packet, quic::TransmissionType transmission_type, quic::QuicTime sent_time) override; @@ -67,7 +67,10 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger const quic::QuicEncryptedPacket& packet) override; void OnUnauthenticatedHeader(const quic::QuicPacketHeader& header) override; void OnIncorrectConnectionId(quic::QuicConnectionId connection_id) override; - void OnUndecryptablePacket() override; + void OnUndecryptablePacket(quic::EncryptionLevel decryption_level, + bool dropped) override; + void OnAttemptingToProcessUndecryptablePacket( + quic::EncryptionLevel decryption_level) override; void OnDuplicatePacket(quic::QuicPacketNumber packet_number) override; void OnProtocolVersionMismatch(quic::ParsedQuicVersion version) override; void OnPacketHeader(const quic::QuicPacketHeader& header) override; diff --git a/chromium/net/quic/quic_connectivity_probing_manager_test.cc b/chromium/net/quic/quic_connectivity_probing_manager_test.cc index c29be701ebc..15bd236a20a 100644 --- a/chromium/net/quic/quic_connectivity_probing_manager_test.cc +++ b/chromium/net/quic/quic_connectivity_probing_manager_test.cc @@ -45,21 +45,29 @@ class MockQuicChromiumClientSession ~MockQuicChromiumClientSession() override {} // QuicChromiumPacketReader::Visitor interface. - MOCK_METHOD2(OnReadError, - void(int result, const DatagramClientSocket* socket)); - - MOCK_METHOD3(OnPacket, - bool(const quic::QuicReceivedPacket& packet, - const quic::QuicSocketAddress& local_address, - const quic::QuicSocketAddress& peer_address)); - - MOCK_METHOD2(OnProbeFailed, - void(NetworkChangeNotifier::NetworkHandle network, - const quic::QuicSocketAddress& peer_address)); - - MOCK_METHOD2(OnSendConnectivityProbingPacket, - bool(QuicChromiumPacketWriter* writer, - const quic::QuicSocketAddress& peer_address)); + MOCK_METHOD(void, + OnReadError, + (int result, const DatagramClientSocket* socket), + (override)); + + MOCK_METHOD(bool, + OnPacket, + (const quic::QuicReceivedPacket& packet, + const quic::QuicSocketAddress& local_address, + const quic::QuicSocketAddress& peer_address), + (override)); + + MOCK_METHOD(void, + OnProbeFailed, + (NetworkChangeNotifier::NetworkHandle network, + const quic::QuicSocketAddress& peer_address), + (override)); + + MOCK_METHOD(bool, + OnSendConnectivityProbingPacket, + (QuicChromiumPacketWriter * writer, + const quic::QuicSocketAddress& peer_address), + (override)); void OnProbeSucceeded( NetworkChangeNotifier::NetworkHandle network, diff --git a/chromium/net/quic/quic_context.cc b/chromium/net/quic/quic_context.cc index b240cbf44e7..2a70761dd82 100644 --- a/chromium/net/quic/quic_context.cc +++ b/chromium/net/quic/quic_context.cc @@ -44,8 +44,6 @@ quic::QuicConfig InitializeQuicConfig(const QuicParams& params) { quic::QuicConfig config; config.SetIdleNetworkTimeout( quic::QuicTime::Delta::FromMicroseconds( - params.idle_connection_timeout.InMicroseconds()), - quic::QuicTime::Delta::FromMicroseconds( params.idle_connection_timeout.InMicroseconds())); config.set_max_time_before_crypto_handshake( quic::QuicTime::Delta::FromMicroseconds( diff --git a/chromium/net/quic/quic_context.h b/chromium/net/quic/quic_context.h index fbdc2699c52..1f3ece3c0c7 100644 --- a/chromium/net/quic/quic_context.h +++ b/chromium/net/quic/quic_context.h @@ -157,8 +157,6 @@ struct NET_EXPORT QuicParams { bool go_away_on_path_degrading = false; // If true, bidirectional streams over QUIC will be disabled. bool disable_bidirectional_streams = false; - // If true, race cert verification with host resolution. - bool race_cert_verification = false; // If true, estimate the initial RTT for QUIC connections based on network. bool estimate_initial_rtt = false; // If true, client headers will include HTTP/2 stream dependency info diff --git a/chromium/net/quic/quic_crypto_client_stream_factory.cc b/chromium/net/quic/quic_crypto_client_stream_factory.cc index ad819a22c45..8b866bb405f 100644 --- a/chromium/net/quic/quic_crypto_client_stream_factory.cc +++ b/chromium/net/quic/quic_crypto_client_stream_factory.cc @@ -22,7 +22,8 @@ class DefaultCryptoStreamFactory : public QuicCryptoClientStreamFactory { quic::QuicCryptoClientConfig* crypto_config) override { return new quic::QuicCryptoClientStream(server_id, session, std::move(proof_verify_context), - crypto_config, session); + crypto_config, session, + /*has_application_state = */ true); } }; diff --git a/chromium/net/quic/quic_flags_list.h b/chromium/net/quic/quic_flags_list.h index 40c559284d4..e90d9ee34b2 100644 --- a/chromium/net/quic/quic_flags_list.h +++ b/chromium/net/quic/quic_flags_list.h @@ -105,13 +105,6 @@ QUIC_FLAG( FLAGS_quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time, false) -// If true, enable experiment for testing PCC congestion-control. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_pcc3, false) - -// When true, ensure BBR allows at least one MSS to be sent in response to an -// ACK in packet conservation. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_one_mss_conservation, false) - // When true and the BBR9 connection option is present, BBR only considers // bandwidth samples app-limited if they're not filling the pipe. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_flexible_app_limited, false) @@ -127,12 +120,6 @@ QUIC_FLAG( FLAGS_quic_reloadable_flag_quic_bbr_no_bytes_acked_in_startup_recovery, false) -// If true, enables the BBS4 and BBS5 connection options, which reduce BBR's -// pacing rate in STARTUP as more losses occur as a fraction of CWND. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_bbr_startup_rate_reduction, - false) - // If true and using Leto for QUIC shared-key calculations, GFE will react to a // failure to contact Leto by sending a REJ containing a fallback ServerConfig, // allowing the client to continue the handshake. @@ -180,7 +167,7 @@ QUIC_FLAG(bool, false) // If true, will negotiate the ACK delay time. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_negotiate_ack_delay_time, false) +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_negotiate_ack_delay_time, true) // If true, QuicFramer::WriteClientVersionNegotiationProbePacket uses // length-prefixed connection IDs. @@ -250,7 +237,7 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_q049, false) 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, true) +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) @@ -276,17 +263,6 @@ QUIC_FLAG(bool, // If true, use predictable grease settings identifiers and values. QUIC_FLAG(bool, FLAGS_quic_enable_http3_grease_randomness, true) -// When the EACK connection option is sent by the client, an ack-eliciting frame -// is bundled with ACKs sent after the PTO fires. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_bundle_retransmittable_with_pto_ack, - true) -// If true, use QuicClock::Now() as the source of packet receive time instead of -// WallNow(). -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_use_quic_time_for_received_timestamp2, - true) - // If true, enable QUIC version h3-25. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_draft_25_v3, @@ -302,114 +278,140 @@ QUIC_FLAG( FLAGS_quic_reloadable_flag_quic_avoid_overestimate_bandwidth_with_aggregation, true) -// If true, emit more granular errors instead of -// SpdyFramerError::SPDY_DECOMPRESS_FAILURE in Http2DecoderAdapter. -// This flag is duplicated in spdy_flags_impl.h due to mixed usage of flags. -// Please update the flag value in spdy when this flag is flipped. +// If true, QUIC BBRv2 to take ack height into account when calculating +// queuing_threshold in PROBE_UP. +QUIC_FLAG( + bool, + 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_spdy_enable_granular_decompress_errors, + FLAGS_quic_reloadable_flag_quic_bw_sampler_app_limited_starting_value, true) -// If true, only do minimum validation of coalesced packets (only validate -// connection ID). +// 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) + +// 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_minimum_validation_of_coalesced_packets, + FLAGS_quic_reloadable_flag_quic_remove_android_conformance_test_workaround, true) -// If true, arm the 1st PTO with earliest in flight sent time. +// 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_arm_pto_with_earliest_sent_time, + FLAGS_quic_reloadable_flag_quic_bbr2_lower_startup_cwnd_gain, true) -// If true, QuicSession::WritevData() will support writing data at a specified -// encryption level. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_writevdata_at_level, true) +// The divisor that controls how often MAX_STREAMS frames are sent. +QUIC_FLAG(int32_t, FLAGS_quic_max_streams_window_divisor, 2) -// If true, use standard deviation when calculating PTO timeout. +// If true, QUIC BBRv2\'s PROBE_BW mode will not reduce cwnd below +// BDP+ack_height. QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_use_standard_deviation_for_pto, - true) + FLAGS_quic_reloadable_flag_quic_bbr2_avoid_too_low_probe_bw_cwnd, + false) -// If true, QUIC BBRv2 to avoid unnecessary PROBE_RTTs after quiescence. +// When true, the 1RTT and 2RTT connection options decrease the number of round +// trips in BBRv2 STARTUP without a 25% bandwidth increase to 1 or 2 round trips +// respectively. QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_bbr2_avoid_unnecessary_probe_rtt, + 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, use passed in ack_frame to calculate minimum size of the serialized -// ACK frame. +// If true, break session/stream close loop. QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_use_ack_frame_to_get_min_size, + FLAGS_quic_reloadable_flag_quic_break_session_stream_close_loop, true) -// If true, skip packet threshold loss detection if largest acked is a runt. -QUIC_FLAG( - bool, - FLAGS_quic_reloadable_flag_quic_skip_packet_threshold_loss_detection_with_runt, - 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, QUIC BBRv2 to take ack height into account when calculating -// queuing_threshold in PROBE_UP. -QUIC_FLAG( - bool, - FLAGS_quic_reloadable_flag_quic_bbr2_add_ack_height_to_queueing_threshold, - 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, send PING when PTO skips packet number and there is no data to send. -QUIC_FLAG( - bool, - FLAGS_quic_reloadable_flag_quic_send_ping_when_pto_skips_packet_number, - true) +// If true, enables support for TLS resumption in QUIC. +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, QuicSession\'s various write methods will set transmission type. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_write_with_transmission, true) +// 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, fix a bug in QUIC BBR where bandwidth estimate becomes 0 after a -// loss only event. +// If true, notify handshakers when connection closes. QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_bbr_fix_zero_bw_on_loss_only_event, + FLAGS_quic_reloadable_flag_quic_notify_handshaker_on_connection_close, true) -// If true, trigger QUIC_BUG in two ShouldCreateIncomingStream() overrides when -// called with locally initiated stream ID. +// If true, for QUIC + TLS, change default encryption level when new encryption +// key is available. QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_create_incoming_stream_bug, - false) + FLAGS_quic_reloadable_flag_quic_change_default_encryption_level, + true) -// If true, quic::BandwidthSampler will start in application limited phase. +// 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, reject IETF QUIC connections with invalid SNI. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_tls_enforce_valid_sni, false) + +// If true, update ack timeout upon receiving an retransmittable frame. QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_bw_sampler_app_limited_starting_value, + FLAGS_quic_reloadable_flag_quic_advance_ack_timeout_update, false) -// If true, QUIC connection will ignore one packet write error after MTU probe. +// If true, only extend idle time on decryptable packets. QUIC_FLAG( bool, - FLAGS_quic_reloadable_flag_quic_ignore_one_write_error_after_mtu_probe, + FLAGS_quic_reloadable_flag_quic_extend_idle_time_on_decryptable_packets, false) -// If true, send H3 SETTINGs when 1-RTT write key is available (rather then both -// keys are available). -QUIC_FLAG(bool, - FLAGS_quic_restart_flag_quic_send_settings_on_write_key_available, - false) +// 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, use blackhole detector in QuicConnection to detect path degrading -// and network blackhole. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_blackhole_detector, false) +// 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, use idle network detector to detect handshake timeout and idle -// network timeout. +// When true, QUIC+TLS will not send nor parse the old-format Google-specific +// transport parameters. QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_use_idle_network_detector, + FLAGS_quic_restart_flag_quic_google_transport_param_omit_old, false) -// If true, when QUIC switches from BbrSender to Bbr2Sender, Bbr2Sender will -// copy the bandwidth sampler states from BbrSender. +// When true, QUIC+TLS will send and parse the new-format Google-specific +// transport parameters. QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_bbr_copy_sampler_state_from_v1_to_v2, - false) + FLAGS_quic_restart_flag_quic_google_transport_param_send_new, + true) -// 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) +// If true, if a buffered MTU packet causes a write to return MSG_TOO_BIG, this +// error will be ignored. +QUIC_FLAG( + bool, + FLAGS_quic_reloadable_flag_quic_ignore_msg_too_big_from_buffered_packets, + true) diff --git a/chromium/net/quic/quic_http3_logger.cc b/chromium/net/quic/quic_http3_logger.cc index 8240046a419..c190156ff45 100644 --- a/chromium/net/quic/quic_http3_logger.cc +++ b/chromium/net/quic/quic_http3_logger.cc @@ -158,18 +158,31 @@ void QuicHttp3Logger::OnSettingsFrameReceived( UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ReceivedSettings.CountPlusOne", frame.values.size() + 1, /* min = */ 1, /* max = */ 10, /* buckets = */ 10); + int reserved_identifier_count = 0; for (const auto& value : frame.values) { if (value.first == quic::SETTINGS_QPACK_MAX_TABLE_CAPACITY) { - UMA_HISTOGRAM_COUNTS_10000( - "Net.QuicSession.ReceivedSettings.MaxTableCapacity", value.second); + UMA_HISTOGRAM_COUNTS_1M( + "Net.QuicSession.ReceivedSettings.MaxTableCapacity2", value.second); } else if (value.first == quic::SETTINGS_MAX_HEADER_LIST_SIZE) { - UMA_HISTOGRAM_COUNTS_10000( - "Net.QuicSession.ReceivedSettings.MaxHeaderListSize", value.second); + UMA_HISTOGRAM_COUNTS_1M( + "Net.QuicSession.ReceivedSettings.MaxHeaderListSize2", value.second); } else if (value.first == quic::SETTINGS_QPACK_BLOCKED_STREAMS) { UMA_HISTOGRAM_COUNTS_1000( "Net.QuicSession.ReceivedSettings.BlockedStreams", value.second); + } else if (value.first >= 0x21 && value.first % 0x1f == 2) { + // Reserved setting identifiers are defined at + // https://quicwg.org/base-drafts/draft-ietf-quic-http.html#name-defined-settings-parameters. + // These should not be treated specially on the receive side, because they + // are sent to exercise the requirement that unknown identifiers are + // ignored. Here an exception is made for logging only, to understand + // what kind of identifiers are received. + reserved_identifier_count++; } } + UMA_HISTOGRAM_CUSTOM_COUNTS( + "Net.QuicSession.ReceivedSettings.ReservedCountPlusOne", + reserved_identifier_count + 1, /* min = */ 1, + /* max = */ 5, /* buckets = */ 5); if (!net_log_.IsCapturing()) return; diff --git a/chromium/net/quic/quic_http_stream_test.cc b/chromium/net/quic/quic_http_stream_test.cc index d2c530db894..c5638861d8c 100644 --- a/chromium/net/quic/quic_http_stream_test.cc +++ b/chromium/net/quic/quic_http_stream_test.cc @@ -209,7 +209,6 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>, protected: static const bool kFin = true; static const bool kIncludeVersion = true; - static const bool kIncludeCongestionFeedback = true; // Holds a packet to be written to the wire, and the IO mode that should // be used by the mock socket when performing the write. @@ -540,7 +539,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>, uint64_t packet_number) { return client_maker_.MakeAckAndRstPacket( packet_number, !kIncludeVersion, stream_id_, - quic::QUIC_STREAM_CANCELLED, 2, 1, 2, !kIncludeCongestionFeedback); + quic::QUIC_STREAM_CANCELLED, 2, 1, 2); } std::unique_ptr<quic::QuicReceivedPacket> ConstructClientAckPacket( @@ -549,8 +548,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>, uint64_t smallest_received, uint64_t least_unacked) { return client_maker_.MakeAckPacket(packet_number, largest_received, - smallest_received, least_unacked, - !kIncludeCongestionFeedback); + smallest_received, least_unacked); } std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket( @@ -559,8 +557,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>, uint64_t smallest_received, uint64_t least_unacked) { return server_maker_.MakeAckPacket(packet_number, largest_received, - smallest_received, least_unacked, - !kIncludeCongestionFeedback); + smallest_received, least_unacked); } std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() { @@ -1103,7 +1100,6 @@ TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) { quic::QuicConnectionCloseFrame frame; frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY; - frame.extracted_error_code = quic::QUIC_PEER_GOING_AWAY; session_->connection()->OnConnectionCloseFrame(frame); NetErrorDetails details; @@ -1155,7 +1151,6 @@ TEST_P(QuicHttpStreamTest, LogGranularQuicErrorIfHandshakeNotConfirmed) { quic::QuicConnectionCloseFrame frame; frame.quic_error_code = quic::QUIC_PEER_GOING_AWAY; - frame.extracted_error_code = quic::QUIC_PEER_GOING_AWAY; session_->connection()->OnConnectionCloseFrame(frame); NetErrorDetails details; @@ -1603,6 +1598,104 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) { stream_->GetTotalReceivedBytes()); } +TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) { + SetRequest("POST", "/", DEFAULT_PRIORITY); + size_t chunk_size = strlen(kUploadData); + size_t spdy_request_headers_frame_length; + int packet_number = 1; + + if (version_.UsesHttp3()) { + AddWrite(ConstructInitialSettingsPacket(packet_number++)); + } + + std::string header = ConstructDataHeader(chunk_size); + if (version_.HasIetfQuicFrames()) { + AddWrite(ConstructRequestHeadersAndDataFramesPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + 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)); + } else { + AddWrite(ConstructRequestHeadersAndDataFramesPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0, + &spdy_request_headers_frame_length, {kUploadData})); + AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2)); + AddWrite(client_maker_.MakeAckAndRstPacket( + packet_number++, + /* include_version = */ false, stream_id_, + quic::QUIC_RST_ACKNOWLEDGEMENT, 4, 1, 1, + /* include_stop_sending_if_v99 = */ false)); + } + + Initialize(); + + upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0); + auto* chunked_upload_stream = + static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get()); + chunked_upload_stream->AppendData(kUploadData, chunk_size, false); + + request_.method = "POST"; + request_.url = GURL("https://www.example.org/"); + request_.upload_data_stream = upload_data_stream_.get(); + ASSERT_THAT(request_.upload_data_stream->Init( + TestCompletionCallback().callback(), NetLogWithSource()), + IsOk()); + ASSERT_THAT(stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY, + net_log_.bound(), callback_.callback()), + IsOk()); + ASSERT_THAT(stream_->SendRequest(headers_, &response_, callback_.callback()), + IsError(ERR_IO_PENDING)); + + // Ack both packets in the request. + ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1)); + + // Send the response headers (but not the body). + SetResponse("200 OK", string()); + size_t spdy_response_headers_frame_length; + ProcessPacket(ConstructResponseHeadersPacket( + 2, !kFin, &spdy_response_headers_frame_length)); + + // Send the response body. + const char kResponseBody[] = "Hello world!"; + std::string header2 = ConstructDataHeader(strlen(kResponseBody)); + ProcessPacket( + ConstructServerDataPacket(3, false, kFin, header2 + kResponseBody)); + + // Server resets stream with H3_NO_ERROR before request body is complete. + ProcessPacket(server_maker_.MakeRstPacket(4, /* include_version = */ false, + stream_id_, + quic::QUIC_STREAM_NO_ERROR)); + + // Finish feeding request body to QuicHttpStream. Data will be discarded. + chunked_upload_stream->AppendData(kUploadData, chunk_size, true); + EXPECT_THAT(callback_.WaitForResult(), IsOk()); + + // Verify response. + EXPECT_THAT(stream_->ReadResponseHeaders(callback_.callback()), IsOk()); + ASSERT_TRUE(response_.headers.get()); + EXPECT_EQ(200, response_.headers->response_code()); + EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain")); + ASSERT_EQ(static_cast<int>(strlen(kResponseBody)), + stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(), + callback_.callback())); + EXPECT_TRUE(stream_->IsResponseBodyComplete()); + EXPECT_TRUE(AtEof()); + + // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the + // headers and payload. + EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length + + strlen(kUploadData) + header.length()), + stream_->GetTotalSentBytes()); + EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length + + strlen(kResponseBody) + header2.length()), + stream_->GetTotalReceivedBytes()); +} + TEST_P(QuicHttpStreamTest, DestroyedEarly) { SetRequest("GET", "/", DEFAULT_PRIORITY); size_t spdy_request_headers_frame_length; diff --git a/chromium/net/quic/quic_network_transaction_unittest.cc b/chromium/net/quic/quic_network_transaction_unittest.cc index a95b95a9cfe..5dc3abdbe8c 100644 --- a/chromium/net/quic/quic_network_transaction_unittest.cc +++ b/chromium/net/quic/quic_network_transaction_unittest.cc @@ -159,23 +159,30 @@ std::string PrintToString(const PoolingTestParams& p) { "Dependency"); } -std::string GenerateQuicAltSvcHeader() { +std::string GenerateQuicAltSvcHeader( + const quic::ParsedQuicVersionVector& versions) { std::string altsvc_header = "Alt-Svc: "; std::string version_string; - for (const auto& version : quic::AllSupportedVersions()) { - if (version.handshake_protocol == quic::PROTOCOL_TLS1_3) { - altsvc_header.append(quic::AlpnForVersion(version)); - altsvc_header.append("=\":443\", "); + bool first_version = true; + for (const auto& version : versions) { + if (first_version) { + first_version = false; } else { + altsvc_header.append(", "); + } + altsvc_header.append(quic::AlpnForVersion(version)); + altsvc_header.append("=\":443\""); + if (version.SupportsGoogleAltSvcFormat()) { if (!version_string.empty()) { version_string.append(","); } version_string.append(base::NumberToString(version.transport_version)); } } - altsvc_header.append("quic=\":443\"; v=\""); - altsvc_header.append(version_string); - altsvc_header.append("\"\r\n"); + if (!version_string.empty()) { + altsvc_header.append(", quic=\":443\"; v=\"" + version_string + "\""); + } + altsvc_header.append("\r\n"); return altsvc_header; } @@ -361,7 +368,7 @@ class QuicNetworkTransactionTest uint64_t smallest_received, uint64_t least_unacked) { return client_maker_->MakeAckPacket(packet_number, largest_received, - smallest_received, least_unacked, true); + smallest_received, least_unacked); } std::unique_ptr<quic::QuicEncryptedPacket> ConstructClientAckAndRstPacket( @@ -371,9 +378,9 @@ class QuicNetworkTransactionTest uint64_t largest_received, uint64_t smallest_received, uint64_t least_unacked) { - return client_maker_->MakeAckAndRstPacket( - num, false, stream_id, error_code, largest_received, smallest_received, - least_unacked, true); + return client_maker_->MakeAckAndRstPacket(num, false, stream_id, error_code, + largest_received, + smallest_received, least_unacked); } std::unique_ptr<quic::QuicEncryptedPacket> ConstructClientRstPacket( @@ -390,7 +397,7 @@ class QuicNetworkTransactionTest uint64_t smallest_received, uint64_t least_unacked) { return client_maker_->MakeAckPacket(packet_number, largest_received, - smallest_received, least_unacked, true); + smallest_received, least_unacked); } std::unique_ptr<quic::QuicEncryptedPacket> @@ -427,7 +434,7 @@ class QuicNetworkTransactionTest uint64_t smallest_received, uint64_t least_unacked) { return server_maker_.MakeAckPacket(packet_number, largest_received, - smallest_received, least_unacked, false); + smallest_received, least_unacked); } std::unique_ptr<quic::QuicReceivedPacket> ConstructClientPriorityPacket( @@ -965,12 +972,22 @@ class QuicNetworkTransactionTest } std::string StreamCancellationQpackDecoderInstruction(int n) const { + return StreamCancellationQpackDecoderInstruction(n, true); + } + + std::string StreamCancellationQpackDecoderInstruction( + int n, + bool create_stream) const { const quic::QuicStreamId cancelled_stream_id = GetNthClientInitiatedBidirectionalStreamId(n); EXPECT_LT(cancelled_stream_id, 63u); const unsigned char opcode = 0x40; - return {opcode | static_cast<unsigned char>(cancelled_stream_id)}; + if (create_stream) { + return {0x03, opcode | static_cast<unsigned char>(cancelled_stream_id)}; + } else { + return {opcode | static_cast<unsigned char>(cancelled_stream_id)}; + } } static void AddCertificate(SSLSocketDataProvider* ssl_data) { @@ -1745,7 +1762,7 @@ TEST_P(QuicNetworkTransactionTest, DoNotUseQuicForUnsupportedVersion) { // in the stored AlternativeService is not supported by the client. However, // the response from the server will advertise new Alt-Svc with supported // versions. - std::string altsvc_header = GenerateQuicAltSvcHeader(); + std::string altsvc_header = GenerateQuicAltSvcHeader(supported_versions_); MockRead http_reads[] = { MockRead("HTTP/1.1 200 OK\r\n"), MockRead(altsvc_header.c_str()), @@ -1807,7 +1824,11 @@ TEST_P(QuicNetworkTransactionTest, DoNotUseQuicForUnsupportedVersion) { for (const auto& alt_svc_info : alt_svc_info_vector) { EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol); for (const auto& version : alt_svc_info.advertised_versions()) { - alt_svc_negotiated_versions.push_back(version); + if (std::find(alt_svc_negotiated_versions.begin(), + alt_svc_negotiated_versions.end(), + version) == alt_svc_negotiated_versions.end()) { + alt_svc_negotiated_versions.push_back(version); + } } } @@ -2225,9 +2246,7 @@ TEST_P(QuicNetworkTransactionTest, // Client and server both support more than one QUIC_VERSION. // Client prefers |version_|, and then common_version_2. // Server prefers common_version_2, and then |version_|. - // In non-TLS version, |version_| will be picked. - // In TLS version, server's preference will be honored. - // TODO(crbug.com/1063060): fix the behavior to be consistent. + // We should honor the server's preference. // The picked version is verified via checking the version used by the // TestPacketMakers and the response. @@ -2259,18 +2278,11 @@ TEST_P(QuicNetworkTransactionTest, // |common_version_2|, |version_|. std::string QuicAltSvcWithVersionHeader; quic::ParsedQuicVersion picked_version = quic::UnsupportedQuicVersion(); - if (version_.handshake_protocol == quic::PROTOCOL_QUIC_CRYPTO) { - QuicAltSvcWithVersionHeader = base::StringPrintf( - "Alt-Svc: quic=\":443\";v=\"%d,%d\"\r\n\r\n", - common_version_2.transport_version, version_.transport_version); - picked_version = version_; // Use client's preference. - } else { 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"), @@ -2468,7 +2480,7 @@ TEST_P(QuicNetworkTransactionTest, } } - std::string altsvc_header = GenerateQuicAltSvcHeader(); + std::string altsvc_header = GenerateQuicAltSvcHeader(supported_versions_); MockRead http_reads[] = { MockRead("HTTP/1.1 200 OK\r\n"), MockRead(altsvc_header.c_str()), @@ -2530,7 +2542,11 @@ TEST_P(QuicNetworkTransactionTest, for (const auto& alt_svc_info : alt_svc_info_vector) { EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol); for (const auto& version : alt_svc_info.advertised_versions()) { - alt_svc_negotiated_versions.push_back(version); + if (std::find(alt_svc_negotiated_versions.begin(), + alt_svc_negotiated_versions.end(), + version) == alt_svc_negotiated_versions.end()) { + alt_svc_negotiated_versions.push_back(version); + } } } @@ -2680,8 +2696,10 @@ 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_.handshake_protocol == quic::PROTOCOL_TLS1_3 || + 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. return; } SetUpTestForRetryConnectionOnAlternateNetwork(); @@ -2788,8 +2806,10 @@ 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_.handshake_protocol == quic::PROTOCOL_TLS1_3 || + 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. return; } @@ -2908,8 +2928,10 @@ 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_.handshake_protocol == quic::PROTOCOL_TLS1_3 || + 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. return; } @@ -3054,8 +3076,10 @@ 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_.handshake_protocol == quic::PROTOCOL_TLS1_3 || + 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. return; } @@ -3298,291 +3322,7 @@ TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmed) { EXPECT_THAT(callback.WaitForResult(), IsError(ERR_QUIC_PROTOCOL_ERROR)); } -// Verify that if a QUIC connection RTOs, the QuicHttpStream will -// return QUIC_PROTOCOL_ERROR. -TEST_P(QuicNetworkTransactionTest, TooManyRtosAfterHandshakeConfirmed) { - 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; - context_.params()->connection_options.push_back(quic::k5RTO); - - // The request will initially go out over QUIC. - MockQuicData quic_data(version_); - spdy::SpdyPriority priority = - ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY); - - client_maker_->set_save_packet_frames(true); - client_maker_->SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT); - int packet_number = 1; - if (VersionUsesHttp3(version_.transport_version)) { - quic_data.AddWrite( - SYNCHRONOUS, client_maker_->MakeInitialSettingsPacket(packet_number++)); - } - quic_data.AddWrite( - SYNCHRONOUS, - client_maker_->MakeRequestHeadersPacket( - packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), true, - true, priority, GetRequestHeaders("GET", "https", "/"), 0, nullptr)); - - client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE); - if (VersionUsesHttp3(version_.transport_version)) { - // TLP 1 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(1, 3, true)); - // TLP 2 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(2, 4, true)); - // RTO 1 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(1, 5, true)); - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(2, 6, true)); - // RTO 2 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(1, 7, true)); - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(2, 8, true)); - // RTO 3 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(1, 9, true)); - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(2, 10, true)); - // RTO 4 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(1, 11, true)); - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(2, 12, true)); - // RTO 5 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeConnectionClosePacket( - 13, true, quic::QUIC_TOO_MANY_RTOS, - "5 consecutive retransmission timeouts")); - } else { - // TLP 1 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(1, 2, true)); - // TLP 2 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(1, 3, true)); - // RTO 1 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(1, 4, true)); - // RTO 2 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(1, 5, true)); - // RTO 3 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(1, 6, true)); - // RTO 4 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRetransmissionPacket(1, 7, true)); - // RTO 5 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeConnectionClosePacket( - 8, true, quic::QUIC_TOO_MANY_RTOS, - "5 consecutive retransmission timeouts")); - } - - quic_data.AddRead(ASYNC, OK); - quic_data.AddSocketDataToFactory(&socket_factory_); - - // In order for a new QUIC session to be established via alternate-protocol - // without racing an HTTP connection, we need the host resolution to happen - // synchronously. Of course, even though QUIC *could* perform a 0-RTT - // connection to the the server, in this test we require confirmation - // before encrypting so the HTTP job will still start. - host_resolver_.set_synchronous_mode(true); - host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", - ""); - - CreateSession(); - // Use a TestTaskRunner to avoid waiting in real time for timeouts. - QuicStreamFactoryPeer::SetAlarmFactory( - session_->quic_stream_factory(), - std::make_unique<QuicChromiumAlarmFactory>(quic_task_runner_.get(), - context_.clock())); - - AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); - - 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)); - - // Pump the message loop to get the request started. - base::RunLoop().RunUntilIdle(); - // Explicitly confirm the handshake. - crypto_client_stream_factory_.last_stream() - ->NotifySessionOneRttKeyAvailable(); - - // Run the QUIC session to completion. - quic_task_runner_->RunUntilIdle(); - - ExpectQuicAlternateProtocolMapping(); - ASSERT_TRUE(quic_data.AllWriteDataConsumed()); - EXPECT_THAT(callback.WaitForResult(), IsError(ERR_QUIC_PROTOCOL_ERROR)); -} - -// Verify that if a QUIC connection RTOs, while there are no active streams -// QUIC will not be marked as broken. -TEST_P(QuicNetworkTransactionTest, - TooManyRtosAfterHandshakeConfirmedAndStreamReset) { - if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) { - // QUIC with TLS1.3 handshake doesn't support 0-rtt. - return; - } - - context_.params()->connection_options.push_back(quic::k5RTO); - - // The request will initially go out over QUIC. - MockQuicData quic_data(version_); - spdy::SpdyPriority priority = - ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY); - - client_maker_->set_save_packet_frames(true); - client_maker_->SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT); - int packet_number = 1; - if (VersionUsesHttp3(version_.transport_version)) { - quic_data.AddWrite( - SYNCHRONOUS, client_maker_->MakeInitialSettingsPacket(packet_number++)); - } - quic_data.AddWrite( - SYNCHRONOUS, - client_maker_->MakeRequestHeadersPacket( - packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), true, - true, priority, GetRequestHeaders("GET", "https", "/"), 0, nullptr)); - - client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE); - - if (!VersionUsesHttp3(version_.transport_version)) { - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRstPacket( - packet_number++, true, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); - // TLP 1 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 1, packet_number++, true)); - // TLP 2 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 2, packet_number++, true)); - // RTO 1 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 1, packet_number++, true)); - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 2, packet_number++, true)); - // RTO 2 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 1, packet_number++, true)); - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 2, packet_number++, true)); - // RTO 3 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 1, packet_number++, true)); - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 2, packet_number++, true)); - // RTO 4 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 1, packet_number++, true)); - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 2, packet_number++, true)); - // RTO 5 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeConnectionClosePacket( - packet_number++, true, quic::QUIC_TOO_MANY_RTOS, - "5 consecutive retransmission timeouts")); - } else { - quic_data.AddWrite( - SYNCHRONOUS, ConstructClientDataPacket( - packet_number++, GetQpackDecoderStreamId(), true, - false, StreamCancellationQpackDecoderInstruction(0))); - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeRstPacket( - packet_number++, true, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); - client_maker_->RemoveSavedStreamFrames( - GetNthClientInitiatedBidirectionalStreamId(0)); - - // TLP 1 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 1, packet_number++, true)); - // TLP 2 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 2, packet_number++, true)); - // RTO 1 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 3, packet_number++, true)); - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 4, packet_number++, true)); - // RTO 2 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 1, packet_number++, true)); - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 2, packet_number++, true)); - // RTO 3 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 3, packet_number++, true)); - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 4, packet_number++, true)); - // RTO 4 - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 1, packet_number++, true)); - quic_data.AddWrite(SYNCHRONOUS, client_maker_->MakeRetransmissionPacket( - 2, packet_number++, true)); - // RTO 5 - quic_data.AddWrite(SYNCHRONOUS, - client_maker_->MakeConnectionClosePacket( - packet_number++, true, quic::QUIC_TOO_MANY_RTOS, - "5 consecutive retransmission timeouts")); - } - - quic_data.AddRead(ASYNC, OK); - quic_data.AddSocketDataToFactory(&socket_factory_); - - // In order for a new QUIC session to be established via alternate-protocol - // without racing an HTTP connection, we need the host resolution to happen - // synchronously. Of course, even though QUIC *could* perform a 0-RTT - // connection to the the server, in this test we require confirmation - // before encrypting so the HTTP job will still start. - host_resolver_.set_synchronous_mode(true); - host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1", - ""); - - CreateSession(); - // Use a TestTaskRunner to avoid waiting in real time for timeouts. - QuicStreamFactoryPeer::SetAlarmFactory( - session_->quic_stream_factory(), - std::make_unique<QuicChromiumAlarmFactory>(quic_task_runner_.get(), - context_.clock())); - - AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); - - auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, - session_.get()); - TestCompletionCallback callback; - int rv = trans->Start(&request_, callback.callback(), net_log_.bound()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - - // Pump the message loop to get the request started. - base::RunLoop().RunUntilIdle(); - // Explicitly confirm the handshake. - crypto_client_stream_factory_.last_stream() - ->NotifySessionOneRttKeyAvailable(); - - // Now cancel the request. - trans.reset(); - - // Run the QUIC session to completion. - quic_task_runner_->RunUntilIdle(); - - ExpectQuicAlternateProtocolMapping(); - - ASSERT_TRUE(quic_data.AllWriteDataConsumed()); -} +// TODO(fayang): Add time driven TOO_MANY_RTOS test. // Verify that if a QUIC protocol error occurs after the handshake is confirmed // the request fails with QUIC_PROTOCOL_ERROR. @@ -7586,7 +7326,7 @@ class QuicNetworkTransactionWithDestinationTest uint64_t least_unacked, QuicTestPacketMaker* maker) { return maker->MakeAckPacket(packet_number, largest_received, - smallest_received, least_unacked, true); + smallest_received, least_unacked); } std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket( @@ -8674,7 +8414,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyConnectReuseQuicSession) { mock_quic_data.AddWrite( SYNCHRONOUS, ConstructClientDataPacket( packet_num++, GetQpackDecoderStreamId(), true, false, - StreamCancellationQpackDecoderInstruction(1))); + StreamCancellationQpackDecoderInstruction(1, false))); } mock_quic_data.AddWrite( @@ -8938,7 +8678,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyConnectBadCertificate) { mock_quic_data.AddWrite( SYNCHRONOUS, ConstructClientDataPacket( packet_num++, GetQpackDecoderStreamId(), true, false, - StreamCancellationQpackDecoderInstruction(1))); + StreamCancellationQpackDecoderInstruction(1, false))); } mock_quic_data.AddWrite( SYNCHRONOUS, @@ -9240,8 +8980,8 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyAuth) { } server_data_offset += 10; - mock_quic_data.AddWrite( - SYNCHRONOUS, client_maker.MakeAckPacket(packet_num++, 2, 1, 1, true)); + mock_quic_data.AddWrite(SYNCHRONOUS, + client_maker.MakeAckPacket(packet_num++, 2, 1, 1)); if (VersionUsesHttp3(version_.transport_version)) { mock_quic_data.AddWrite( @@ -9298,7 +9038,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyAuth) { SYNCHRONOUS, client_maker.MakeAckAndDataPacket( packet_num++, false, GetQpackDecoderStreamId(), 3, 3, 1, false, - StreamCancellationQpackDecoderInstruction(1))); + StreamCancellationQpackDecoderInstruction(1, false))); mock_quic_data.AddWrite(SYNCHRONOUS, client_maker.MakeRstPacket( packet_num++, false, @@ -9309,7 +9049,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyAuth) { client_maker.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(1), - quic::QUIC_STREAM_CANCELLED, 3, 3, 1, true)); + quic::QUIC_STREAM_CANCELLED, 3, 3, 1)); } mock_quic_data.AddSocketDataToFactory(&socket_factory_); @@ -9741,8 +9481,7 @@ TEST_P(QuicNetworkTransactionTest, NetworkIsolation) { 2, GetNthClientInitiatedBidirectionalStreamId(0), false, true, ConstructDataHeader(1) + "1")); partitioned_mock_quic_data1.AddWrite( - SYNCHRONOUS, - client_maker2.MakeAckPacket(packet_num2++, 2, 1, 1, true)); + SYNCHRONOUS, client_maker2.MakeAckPacket(packet_num2++, 2, 1, 1)); partitioned_mock_quic_data1.AddWrite( SYNCHRONOUS, @@ -9760,8 +9499,7 @@ TEST_P(QuicNetworkTransactionTest, NetworkIsolation) { 4, GetNthClientInitiatedBidirectionalStreamId(1), false, true, ConstructDataHeader(1) + "3")); partitioned_mock_quic_data1.AddWrite( - SYNCHRONOUS, - client_maker2.MakeAckPacket(packet_num2++, 4, 3, 1, true)); + SYNCHRONOUS, client_maker2.MakeAckPacket(packet_num2++, 4, 3, 1)); partitioned_mock_quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); @@ -9803,8 +9541,7 @@ TEST_P(QuicNetworkTransactionTest, NetworkIsolation) { 2, GetNthClientInitiatedBidirectionalStreamId(0), false, true, ConstructDataHeader(1) + "2")); partitioned_mock_quic_data2.AddWrite( - SYNCHRONOUS, - client_maker3.MakeAckPacket(packet_num3++, 2, 1, 1, true)); + SYNCHRONOUS, client_maker3.MakeAckPacket(packet_num3++, 2, 1, 1)); partitioned_mock_quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); @@ -9961,7 +9698,7 @@ TEST_P(QuicNetworkTransactionTest, NetworkIsolationTunnel) { 3, GetNthClientInitiatedBidirectionalStreamId(0), false, false, ConstructDataHeader(10) + std::string("0123456789"))); mock_quic_data[index]->AddWrite( - SYNCHRONOUS, client_maker.MakeAckPacket(packet_num++, 3, 2, 1, true)); + SYNCHRONOUS, client_maker.MakeAckPacket(packet_num++, 3, 2, 1)); mock_quic_data[index]->AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read diff --git a/chromium/net/quic/quic_proxy_client_socket_unittest.cc b/chromium/net/quic/quic_proxy_client_socket_unittest.cc index 8fc4d25b53d..045cfeec480 100644 --- a/chromium/net/quic/quic_proxy_client_socket_unittest.cc +++ b/chromium/net/quic/quic_proxy_client_socket_unittest.cc @@ -115,8 +115,6 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>, static const bool kFin = true; static const bool kIncludeVersion = true; static const bool kIncludeDiversificationNonce = true; - static const bool kIncludeCongestionFeedback = true; - static const bool kSendFeedback = true; static size_t GetStreamFrameDataLengthFromPacketLength( quic::QuicByteCount packet_length, @@ -340,7 +338,7 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>, uint64_t least_unacked) { return client_maker_.MakeAckAndRstPacket( packet_number, !kIncludeVersion, client_data_stream_id1_, error_code, - largest_received, smallest_received, least_unacked, kSendFeedback, + largest_received, smallest_received, least_unacked, /*include_stop_sending=*/false); } @@ -352,7 +350,7 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>, uint64_t least_unacked) { return client_maker_.MakeAckAndRstPacket( packet_number, !kIncludeVersion, client_data_stream_id1_, error_code, - largest_received, smallest_received, least_unacked, kSendFeedback, + largest_received, smallest_received, least_unacked, /*include_stop_sending_if_v99=*/true); } @@ -437,8 +435,7 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>, uint64_t smallest_received, uint64_t least_unacked) { return client_maker_.MakeAckPacket(packet_number, largest_received, - smallest_received, least_unacked, - kSendFeedback); + smallest_received, least_unacked); } // Helper functions for constructing packets sent by the server diff --git a/chromium/net/quic/quic_server_info.cc b/chromium/net/quic/quic_server_info.cc index cdf6e0bc4a2..4b49337536a 100644 --- a/chromium/net/quic/quic_server_info.cc +++ b/chromium/net/quic/quic_server_info.cc @@ -6,6 +6,7 @@ #include <limits> +#include "base/logging.h" #include "base/pickle.h" #include "base/stl_util.h" diff --git a/chromium/net/quic/quic_stream_factory.cc b/chromium/net/quic/quic_stream_factory.cc index f076703d26c..3358bd3d4be 100644 --- a/chromium/net/quic/quic_stream_factory.cc +++ b/chromium/net/quic/quic_stream_factory.cc @@ -45,7 +45,6 @@ #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" @@ -218,105 +217,6 @@ std::set<std::string> HostsFromOrigins(std::set<HostPortPair> origins) { } // namespace -// Responsible for verifying the certificates saved in -// quic::QuicCryptoClientConfig, and for notifying any associated requests when -// complete. Results from cert verification are ignored. -class QuicStreamFactory::CertVerifierJob { - public: - // ProofVerifierCallbackImpl is passed as the callback method to - // VerifyCertChain. The quic::ProofVerifier calls this class with the result - // of cert verification when verification is performed asynchronously. - class ProofVerifierCallbackImpl : public quic::ProofVerifierCallback { - public: - explicit ProofVerifierCallbackImpl(CertVerifierJob* job) : job_(job) {} - - ~ProofVerifierCallbackImpl() override {} - - void Run(bool ok, - const std::string& error_details, - std::unique_ptr<quic::ProofVerifyDetails>* details) override { - if (job_ == nullptr) - return; - job_->verify_callback_ = nullptr; - job_->OnComplete(); - } - - void Cancel() { job_ = nullptr; } - - private: - CertVerifierJob* job_; - }; - - CertVerifierJob( - std::unique_ptr<QuicCryptoClientConfigHandle> crypto_config_handle, - const quic::QuicServerId& server_id, - int cert_verify_flags, - const NetLogWithSource& net_log) - : crypto_config_handle_(std::move(crypto_config_handle)), - server_id_(server_id), - verify_callback_(nullptr), - verify_context_( - std::make_unique<ProofVerifyContextChromium>(cert_verify_flags, - net_log)), - start_time_(base::TimeTicks::Now()), - net_log_(net_log) {} - - ~CertVerifierJob() { - if (verify_callback_) - verify_callback_->Cancel(); - } - - // Starts verification of certs cached in the |crypto_config|. - quic::QuicAsyncStatus Run(CompletionOnceCallback callback) { - quic::QuicCryptoClientConfig* crypto_config = - crypto_config_handle_->GetConfig(); - quic::QuicCryptoClientConfig::CachedState* cached = - crypto_config->LookupOrCreate(server_id_); - auto verify_callback = std::make_unique<ProofVerifierCallbackImpl>(this); - auto* verify_callback_ptr = verify_callback.get(); - quic::QuicAsyncStatus status = - crypto_config->proof_verifier()->VerifyCertChain( - server_id_.host(), cached->certs(), - /*ocsp_response=*/std::string(), cached->cert_sct(), - verify_context_.get(), &verify_error_details_, &verify_details_, - std::move(verify_callback)); - if (status == quic::QUIC_PENDING) { - verify_callback_ = verify_callback_ptr; - callback_ = std::move(callback); - } - return status; - } - - void OnComplete() { - UMA_HISTOGRAM_TIMES("Net.QuicSession.CertVerifierJob.CompleteTime", - base::TimeTicks::Now() - start_time_); - if (!callback_.is_null()) - std::move(callback_).Run(OK); - } - - const quic::QuicServerId& server_id() const { return server_id_; } - - size_t EstimateMemoryUsage() const { - // TODO(xunjieli): crbug.com/669108. Track |verify_context_| and - // |verify_details_|. - return base::trace_event::EstimateMemoryUsage(verify_error_details_); - } - - private: - const std::unique_ptr<QuicCryptoClientConfigHandle> crypto_config_handle_; - const quic::QuicServerId server_id_; - ProofVerifierCallbackImpl* verify_callback_; - std::unique_ptr<quic::ProofVerifyContext> verify_context_; - std::unique_ptr<quic::ProofVerifyDetails> verify_details_; - std::string verify_error_details_; - const base::TimeTicks start_time_; - const NetLogWithSource net_log_; - CompletionOnceCallback callback_; - base::WeakPtrFactory<CertVerifierJob> weak_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(CertVerifierJob); -}; - // Refcounted class that owns quic::QuicCryptoClientConfig and tracks how many // consumers are using it currently. When the last reference is freed, the // QuicCryptoClientConfigHandle informs the owning QuicStreamFactory, moves it @@ -325,9 +225,8 @@ 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), std::move(session_cache)), + : config_(std::move(proof_verifier)), quic_stream_factory_(quic_stream_factory) { DCHECK(quic_stream_factory_); } @@ -1227,8 +1126,6 @@ QuicStreamFactory::~QuicStreamFactory() { all_sessions_.erase(all_sessions_.begin()); } active_jobs_.clear(); - while (!active_cert_verifier_jobs_.empty()) - active_cert_verifier_jobs_.erase(active_cert_verifier_jobs_.begin()); // This should have been moved to the recent map when all consumers of // QuicCryptoClientConfigs were deleted, in the above lines. @@ -1352,15 +1249,10 @@ int QuicStreamFactory::Create(const QuicSessionKey& session_key, if (!tick_clock_) tick_clock_ = base::DefaultTickClock::GetInstance(); - std::unique_ptr<CryptoClientConfigHandle> crypto_config_handle = - CreateCryptoConfigHandle(session_key.network_isolation_key()); - ignore_result(StartCertVerifyJob(*crypto_config_handle, - session_key.server_id(), cert_verify_flags, - net_log)); - QuicSessionAliasKey key(destination, session_key); std::unique_ptr<Job> job = std::make_unique<Job>( - this, quic_version, host_resolver_, key, std::move(crypto_config_handle), + this, quic_version, host_resolver_, key, + CreateCryptoConfigHandle(session_key.network_isolation_key()), WasQuicRecentlyBroken(session_key), params_.retry_on_alternate_network_before_handshake, params_.race_stale_dns_on_connection, priority, cert_verify_flags, @@ -1744,8 +1636,7 @@ void QuicStreamFactory::DumpMemoryStats( base::trace_event::EstimateMemoryUsage(ip_aliases_) + base::trace_event::EstimateMemoryUsage(session_peer_ip_) + base::trace_event::EstimateMemoryUsage(gone_away_aliases_) + - base::trace_event::EstimateMemoryUsage(active_jobs_) + - base::trace_event::EstimateMemoryUsage(active_cert_verifier_jobs_); + base::trace_event::EstimateMemoryUsage(active_jobs_); factory_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, base::trace_event::MemoryAllocatorDump::kUnitsBytes, memory_estimate); @@ -1755,9 +1646,6 @@ void QuicStreamFactory::DumpMemoryStats( factory_dump->AddScalar("active_jobs", base::trace_event::MemoryAllocatorDump::kUnitsObjects, active_jobs_.size()); - factory_dump->AddScalar("active_cert_jobs", - base::trace_event::MemoryAllocatorDump::kUnitsObjects, - active_cert_verifier_jobs_.size()); } bool QuicStreamFactory::HasMatchingIpSession(const QuicSessionAliasKey& key, @@ -1811,10 +1699,6 @@ void QuicStreamFactory::OnJobComplete(Job* job, int rv) { active_jobs_.erase(iter); } -void QuicStreamFactory::OnCertVerifyJobComplete(CertVerifierJob* job, int rv) { - active_cert_verifier_jobs_.erase(job->server_id()); -} - bool QuicStreamFactory::HasActiveSession( const QuicSessionKey& session_key) const { // TODO(rtenneti): crbug.com/498823 - delete active_sessions_.empty() check. @@ -1827,11 +1711,6 @@ bool QuicStreamFactory::HasActiveJob(const QuicSessionKey& session_key) const { return base::Contains(active_jobs_, session_key); } -bool QuicStreamFactory::HasActiveCertVerifierJob( - const quic::QuicServerId& server_id) const { - return base::Contains(active_cert_verifier_jobs_, server_id); -} - int QuicStreamFactory::CreateSession( const QuicSessionAliasKey& key, quic::ParsedQuicVersion quic_version, @@ -2048,30 +1927,6 @@ bool QuicStreamFactory::WasQuicRecentlyBroken( alternative_service, session_key.network_isolation_key()); } -quic::QuicAsyncStatus QuicStreamFactory::StartCertVerifyJob( - const CryptoClientConfigHandle& crypto_config_handle, - const quic::QuicServerId& server_id, - int cert_verify_flags, - const NetLogWithSource& net_log) { - if (!params_.race_cert_verification) - return quic::QUIC_FAILURE; - quic::QuicCryptoClientConfig::CachedState* cached = - crypto_config_handle.GetConfig()->LookupOrCreate(server_id); - if (!cached || cached->certs().empty() || - HasActiveCertVerifierJob(server_id)) { - return quic::QUIC_FAILURE; - } - std::unique_ptr<CertVerifierJob> cert_verifier_job(new CertVerifierJob( - std::make_unique<CryptoClientConfigHandle>(crypto_config_handle), - server_id, cert_verify_flags, net_log)); - quic::QuicAsyncStatus status = cert_verifier_job->Run( - base::BindOnce(&QuicStreamFactory::OnCertVerifyJobComplete, - base::Unretained(this), cert_verifier_job.get())); - if (status == quic::QUIC_PENDING) - active_cert_verifier_jobs_[server_id] = std::move(cert_verifier_job); - return status; -} - void QuicStreamFactory::InitializeMigrationOptions() { // The following list of options cannot be set immediately until // prerequisites are met. Cache the initial setting in local variables and @@ -2279,7 +2134,7 @@ QuicStreamFactory::CreateCryptoConfigHandle( cert_verifier_, ct_policy_enforcer_, transport_security_state_, cert_transparency_verifier_, HostsFromOrigins(params_.origins_to_force_quic_on)), - std::make_unique<QuicClientSessionCache>(), this); + this); quic::QuicCryptoClientConfig* crypto_config = crypto_config_owner->config(); crypto_config->set_user_agent_id(params_.user_agent_id); @@ -2316,17 +2171,6 @@ QuicStreamFactory::GetCryptoConfigForTesting( return CreateCryptoConfigHandle(network_isolation_key); } -quic::QuicAsyncStatus QuicStreamFactory::StartCertVerifyJobForTesting( - const quic::QuicServerId& server_id, - const NetworkIsolationKey& network_isolation_key, - int cert_verify_flags, - const NetLogWithSource& net_log) { - std::unique_ptr<QuicStreamFactory::CryptoClientConfigHandle> - crypto_config_handle = CreateCryptoConfigHandle(network_isolation_key); - return StartCertVerifyJob(*crypto_config_handle, server_id, cert_verify_flags, - net_log); -} - bool QuicStreamFactory::CryptoConfigCacheIsEmptyForTesting( const quic::QuicServerId& server_id, const NetworkIsolationKey& network_isolation_key) { diff --git a/chromium/net/quic/quic_stream_factory.h b/chromium/net/quic/quic_stream_factory.h index 4fd23ddec90..6e33a290557 100644 --- a/chromium/net/quic/quic_stream_factory.h +++ b/chromium/net/quic/quic_stream_factory.h @@ -362,7 +362,6 @@ class NET_EXPORT_PRIVATE QuicStreamFactory private: class Job; - class CertVerifierJob; class QuicCryptoClientConfigOwner; class CryptoClientConfigHandle; friend class test::QuicStreamFactoryPeer; @@ -376,8 +375,6 @@ class NET_EXPORT_PRIVATE QuicStreamFactory typedef std::map<IPEndPoint, SessionSet> IPAliasMap; typedef std::map<QuicChromiumClientSession*, IPEndPoint> SessionPeerIPMap; typedef std::map<QuicSessionKey, std::unique_ptr<Job>> JobMap; - typedef std::map<quic::QuicServerId, std::unique_ptr<CertVerifierJob>> - CertVerifierJobMap; using QuicCryptoClientConfigMap = std::map<NetworkIsolationKey, std::unique_ptr<QuicCryptoClientConfigOwner>>; @@ -385,10 +382,8 @@ class NET_EXPORT_PRIVATE QuicStreamFactory bool HasMatchingIpSession(const QuicSessionAliasKey& key, const AddressList& address_list); void OnJobComplete(Job* job, int rv); - void OnCertVerifyJobComplete(CertVerifierJob* job, int rv); bool HasActiveSession(const QuicSessionKey& session_key) const; bool HasActiveJob(const QuicSessionKey& session_key) const; - bool HasActiveCertVerifierJob(const quic::QuicServerId& server_id) const; int CreateSession(const QuicSessionAliasKey& key, quic::ParsedQuicVersion quic_version, int cert_verify_flags, @@ -425,20 +420,6 @@ class NET_EXPORT_PRIVATE QuicStreamFactory // Helper methods. bool WasQuicRecentlyBroken(const QuicSessionKey& session_key) const; - // Starts an asynchronous job for cert verification if - // |params_.race_cert_verification| is enabled and if there are cached certs - // for the given |server_id|. - // - // Takes a constant reference to a CryptoClientConfigHandle instead of a - // NetworkIsolationKey to force the caller to keep the corresponding - // QuicCryptoClientConfig alive. There's no guarantee it won't be garbage - // collected beyond when this method completes, otherwise. - quic::QuicAsyncStatus StartCertVerifyJob( - const CryptoClientConfigHandle& crypto_config_handle, - const quic::QuicServerId& server_id, - int cert_verify_flags, - const NetLogWithSource& net_log); - // Helper method to initialize the following migration options and check // pre-requisites: // - |params_.migrate_sessions_on_network_change_v2| @@ -479,12 +460,6 @@ class NET_EXPORT_PRIVATE QuicStreamFactory std::unique_ptr<QuicCryptoClientConfigHandle> GetCryptoConfigForTesting( const NetworkIsolationKey& network_isolation_key); - quic::QuicAsyncStatus StartCertVerifyJobForTesting( - const quic::QuicServerId& server_id, - const NetworkIsolationKey& network_isolation_key, - int cert_verify_flags, - const NetLogWithSource& net_log); - bool CryptoConfigCacheIsEmptyForTesting( const quic::QuicServerId& server_id, const NetworkIsolationKey& network_isolation_key); @@ -552,9 +527,6 @@ class NET_EXPORT_PRIVATE QuicStreamFactory JobMap active_jobs_; - // Map of quic::QuicServerId to owning CertVerifierJob. - CertVerifierJobMap active_cert_verifier_jobs_; - // PING timeout for connections. quic::QuicTime::Delta ping_timeout_; quic::QuicTime::Delta reduced_ping_timeout_; diff --git a/chromium/net/quic/quic_stream_factory_fuzzer.cc b/chromium/net/quic/quic_stream_factory_fuzzer.cc index 91083db5ea8..40aff46b5da 100644 --- a/chromium/net/quic/quic_stream_factory_fuzzer.cc +++ b/chromium/net/quic/quic_stream_factory_fuzzer.cc @@ -97,7 +97,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { data_provider.ConsumeBool() ? 1 : 0; params.close_sessions_on_ip_change = data_provider.ConsumeBool(); params.allow_server_migration = data_provider.ConsumeBool(); - params.race_cert_verification = data_provider.ConsumeBool(); params.estimate_initial_rtt = data_provider.ConsumeBool(); params.headers_include_h2_stream_dependency = data_provider.ConsumeBool(); params.enable_socket_recv_optimization = data_provider.ConsumeBool(); diff --git a/chromium/net/quic/quic_stream_factory_peer.cc b/chromium/net/quic/quic_stream_factory_peer.cc index fc68a8732f1..ac673b84b67 100644 --- a/chromium/net/quic/quic_stream_factory_peer.cc +++ b/chromium/net/quic/quic_stream_factory_peer.cc @@ -50,12 +50,6 @@ bool QuicStreamFactoryPeer::HasActiveJob(QuicStreamFactory* factory, false /* disable_secure_dns */)); } -bool QuicStreamFactoryPeer::HasActiveCertVerifierJob( - QuicStreamFactory* factory, - const quic::QuicServerId& server_id) { - return factory->HasActiveCertVerifierJob(server_id); -} - // static QuicChromiumClientSession* QuicStreamFactoryPeer::GetPendingSession( QuicStreamFactory* factory, @@ -123,27 +117,6 @@ quic::QuicTime::Delta QuicStreamFactoryPeer::GetPingTimeout( return factory->ping_timeout_; } -bool QuicStreamFactoryPeer::GetRaceCertVerification( - QuicStreamFactory* factory) { - return factory->params_.race_cert_verification; -} - -void QuicStreamFactoryPeer::SetRaceCertVerification( - QuicStreamFactory* factory, - bool race_cert_verification) { - factory->params_.race_cert_verification = race_cert_verification; -} - -quic::QuicAsyncStatus QuicStreamFactoryPeer::StartCertVerifyJob( - QuicStreamFactory* factory, - const quic::QuicServerId& server_id, - const NetworkIsolationKey& network_isolation_key, - int cert_verify_flags, - const NetLogWithSource& net_log) { - return factory->StartCertVerifyJobForTesting(server_id, network_isolation_key, - cert_verify_flags, net_log); -} - void QuicStreamFactoryPeer::SetYieldAfterPackets(QuicStreamFactory* factory, int yield_after_packets) { factory->yield_after_packets_ = yield_after_packets; diff --git a/chromium/net/quic/quic_stream_factory_peer.h b/chromium/net/quic/quic_stream_factory_peer.h index 60cc745903a..507aedda772 100644 --- a/chromium/net/quic/quic_stream_factory_peer.h +++ b/chromium/net/quic/quic_stream_factory_peer.h @@ -51,9 +51,6 @@ class QuicStreamFactoryPeer { static bool HasActiveJob(QuicStreamFactory* factory, const quic::QuicServerId& server_id); - static bool HasActiveCertVerifierJob(QuicStreamFactory* factory, - const quic::QuicServerId& server_id); - static QuicChromiumClientSession* GetPendingSession( QuicStreamFactory* factory, const quic::QuicServerId& server_id, @@ -79,21 +76,6 @@ class QuicStreamFactoryPeer { static quic::QuicTime::Delta GetPingTimeout(QuicStreamFactory* factory); - static bool GetRaceCertVerification(QuicStreamFactory* factory); - - static void SetRaceCertVerification(QuicStreamFactory* factory, - bool race_cert_verification); - - // When using this method, the caller should be holding onto a live - // NetworkIsolationKey, if it wants the results to stay alive in the - // per-NetworkIsolationKey cache. - static quic::QuicAsyncStatus StartCertVerifyJob( - QuicStreamFactory* factory, - const quic::QuicServerId& server_id, - const NetworkIsolationKey& network_isolation_key, - int cert_verify_flags, - const NetLogWithSource& net_log); - static void SetYieldAfterPackets(QuicStreamFactory* factory, int yield_after_packets); diff --git a/chromium/net/quic/quic_stream_factory_test.cc b/chromium/net/quic/quic_stream_factory_test.cc index bde0dd8bcb6..a4dd7ce26d3 100644 --- a/chromium/net/quic/quic_stream_factory_test.cc +++ b/chromium/net/quic/quic_stream_factory_test.cc @@ -312,11 +312,6 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment { return QuicStreamFactoryPeer::HasActiveJob(factory_.get(), server_id); } - bool HasActiveCertVerifierJob(const quic::QuicServerId& server_id) { - return QuicStreamFactoryPeer::HasActiveCertVerifierJob(factory_.get(), - server_id); - } - // Get the pending, not activated session, if there is only one session alive. QuicChromiumClientSession* GetPendingSession( const HostPortPair& host_port_pair) { @@ -819,12 +814,22 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment { } std::string StreamCancellationQpackDecoderInstruction(int n) const { + return StreamCancellationQpackDecoderInstruction(n, true); + } + + std::string StreamCancellationQpackDecoderInstruction( + int n, + bool create_stream) const { const quic::QuicStreamId cancelled_stream_id = GetNthClientInitiatedBidirectionalStreamId(n); EXPECT_LT(cancelled_stream_id, 63u); const unsigned char opcode = 0x40; - return {opcode | static_cast<unsigned char>(cancelled_stream_id)}; + if (create_stream) { + return {0x03, opcode | static_cast<unsigned char>(cancelled_stream_id)}; + } else { + return {opcode | static_cast<unsigned char>(cancelled_stream_id)}; + } } std::string ConstructDataHeader(size_t body_len) { @@ -1625,7 +1630,7 @@ TEST_P(QuicStreamFactoryTest, PoolingWithServerMigration) { "192.168.0.1", ""); IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 443); quic::QuicConfig config; - config.SetAlternateServerAddressToSend(ToQuicSocketAddress(alt_address)); + config.SetIPv4AlternateServerAddressToSend(ToQuicSocketAddress(alt_address)); VerifyServerMigration(config, alt_address); @@ -2699,7 +2704,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkMadeDefault( SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 2, 2, 1, true)); + quic::QUIC_STREAM_CANCELLED, 2, 2, 1)); } quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -2895,7 +2900,7 @@ TEST_P(QuicStreamFactoryTest, MigratedToBlockedSocketAfterProbing) { SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 2, 2, 1, true)); + quic::QUIC_STREAM_CANCELLED, 2, 2, 1)); } quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -3775,7 +3780,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkDisconnected( client_maker_.MakeAckAndRstPacket( packet_number++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -3919,7 +3924,7 @@ TEST_P(QuicStreamFactoryTest, NewNetworkConnectedAfterNoNetwork) { SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -4014,8 +4019,8 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) { server_maker_.MakeConnectivityProbingPacket(3, false)); quic_data2.AddRead(SYNCHRONOUS, server_maker_.MakeConnectivityProbingPacket(4, false)); - quic_data2.AddWrite( - ASYNC, client_maker_.MakeAckPacket(packet_number++, 1, 4, 1, 1, true)); + quic_data2.AddWrite(ASYNC, + client_maker_.MakeAckPacket(packet_number++, 1, 4, 1, 1)); quic_data2.AddRead( ASYNC, ConstructOkResponsePacket( @@ -4037,7 +4042,7 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) { client_maker_.MakeAckAndRstPacket( packet_number++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 5, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 5, 1, 1)); } quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -4148,7 +4153,7 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) { // This test verifies that the connection migrates to the alternate network // early when path degrading is detected with an ASYNCHRONOUS write before // migration. -TEST_P(QuicStreamFactoryTest, MigrateEarlyOnPathDegradingAysnc) { +TEST_P(QuicStreamFactoryTest, MigrateEarlyOnPathDegradingAsync) { TestMigrationOnPathDegrading(/*async_write_before_migration*/ true); } @@ -4226,7 +4231,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading( client_maker_.MakeAckAndRstPacket( packet_number++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 2, 2, 1, true)); + quic::QUIC_STREAM_CANCELLED, 2, 2, 1)); } quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -4446,7 +4451,7 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() { client_maker_.MakeAckAndRstPacket( packet_number++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 2, 2, 1, true)); + quic::QUIC_STREAM_CANCELLED, 2, 2, 1)); } quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -4627,7 +4632,7 @@ TEST_P(QuicStreamFactoryTest, MultiplePortMigrationsExceedsMaxLimit) { // ACK and PING post migration after successful probing. quic_data2.AddWrite( SYNCHRONOUS, client_maker_.MakeAckPacket(packet_number++, 1 + 2 * i, - 1 + 2 * i, 1, true)); + 1 + 2 * i, 1)); quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(packet_number++, false)); } @@ -4649,8 +4654,8 @@ TEST_P(QuicStreamFactoryTest, MultiplePortMigrationsExceedsMaxLimit) { // response. quic_data2.AddRead(ASYNC, server_maker_.MakeConnectivityProbingPacket( server_packet_num++, false)); - quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeAckPacket( - packet_number++, 9, 9, 1, true)); + quic_data2.AddWrite( + SYNCHRONOUS, client_maker_.MakeAckPacket(packet_number++, 9, 9, 1)); } quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // EOF. quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -4871,7 +4876,7 @@ TEST_P(QuicStreamFactoryTest, DoNotMigrateToBadSocketOnPathDegrading) { SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } quic_data.AddSocketDataToFactory(socket_factory_.get()); @@ -5004,9 +5009,8 @@ void QuicStreamFactoryTestBase::TestMigrateSessionWithDrainingStream( quic_data2.AddRead(ASYNC, server_maker_.MakeConnectivityProbingPacket(3, false)); // Ping packet to send after migration is completed. - quic_data2.AddWrite( - write_mode_for_queued_packet, - client_maker_.MakeAckPacket(packet_number++, 2, 3, 3, 1, true)); + quic_data2.AddWrite(write_mode_for_queued_packet, + client_maker_.MakeAckPacket(packet_number++, 2, 3, 3, 1)); if (write_mode_for_queued_packet == SYNCHRONOUS) { quic_data2.AddWrite(ASYNC, client_maker_.MakePingPacket(packet_number++, false)); @@ -5016,8 +5020,8 @@ void QuicStreamFactoryTestBase::TestMigrateSessionWithDrainingStream( ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false)); - quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeAckPacket( - packet_number++, 1, 3, 1, 1, true)); + quic_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeAckPacket(packet_number++, 1, 3, 1, 1)); quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -5192,7 +5196,7 @@ TEST_P(QuicStreamFactoryTest, MigrateOnNewNetworkConnectAfterPathDegrading) { SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 2, 2, 1, true)); + quic::QUIC_STREAM_CANCELLED, 2, 2, 1)); } quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -5479,7 +5483,7 @@ TEST_P(QuicStreamFactoryTest, MigrateOnPathDegradingWithNoNewNetwork) { SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } quic_data.AddSocketDataToFactory(socket_factory_.get()); @@ -5778,7 +5782,7 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyConnectionMigrationDisabled) { // asynchronous write error will be blocked during migration on write error. New // packets would not be written until the one with write error is rewritten on // the new network. -TEST_P(QuicStreamFactoryTest, MigrateSessionOnAysncWriteError) { +TEST_P(QuicStreamFactoryTest, MigrateSessionOnAsyncWriteError) { InitializeConnectionMigrationV2Test( {kDefaultNetworkForTests, kNewNetworkForTests}); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); @@ -5835,15 +5839,15 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionOnAysncWriteError) { SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } if (VersionUsesHttp3(version_.transport_version)) { socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /* should_include_version = */ true, - /* fin = */ false, StreamCancellationQpackDecoderInstruction(1))); + SYNCHRONOUS, client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /* should_include_version = */ true, + /* fin = */ false, + StreamCancellationQpackDecoderInstruction(1, false))); } socket_data1.AddWrite( SYNCHRONOUS, @@ -6065,8 +6069,8 @@ TEST_P(QuicStreamFactoryTest, MigrateBackToDefaultPostMigrationOnWriteError) { quic_data3.AddRead(ASYNC, server_maker_.MakeConnectivityProbingPacket(2, false)); quic_data3.AddRead(SYNCHRONOUS, ERR_IO_PENDING); - quic_data3.AddWrite( - ASYNC, client_maker_.MakeAckPacket(packet_num++, 1, 2, 1, 1, true)); + quic_data3.AddWrite(ASYNC, + client_maker_.MakeAckPacket(packet_num++, 1, 2, 1, 1)); if (VersionUsesHttp3(version_.transport_version)) { quic_data3.AddWrite( SYNCHRONOUS, client_maker_.MakeDataPacket( @@ -6319,7 +6323,7 @@ void QuicStreamFactoryTestBase:: SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -6559,7 +6563,7 @@ TEST_P(QuicStreamFactoryTest, SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -6693,7 +6697,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteError( SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -6895,14 +6899,14 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorWithMultipleRequests( SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } if (VersionUsesHttp3(version_.transport_version)) { socket_data1.AddWrite( SYNCHRONOUS, client_maker_.MakeDataPacket( packet_num++, GetQpackDecoderStreamId(), true, false, - StreamCancellationQpackDecoderInstruction(1))); + StreamCancellationQpackDecoderInstruction(1, false))); } socket_data1.AddWrite( SYNCHRONOUS, @@ -7059,7 +7063,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams( SYNCHRONOUS, client_maker_.MakeAckAndDataPacket( packet_number++, false, GetQpackDecoderStreamId(), 1, 1, 1, false, - StreamCancellationQpackDecoderInstruction(0))); + StreamCancellationQpackDecoderInstruction(0, false))); socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeRstPacket( packet_number++, false, @@ -7070,7 +7074,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams( client_maker_.MakeAckAndRstPacket( packet_number++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -7230,7 +7234,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams2( SYNCHRONOUS, client_maker_.MakeAckAndDataPacket( packet_number++, false, GetQpackDecoderStreamId(), 1, 1, 1, false, - StreamCancellationQpackDecoderInstruction(0))); + StreamCancellationQpackDecoderInstruction(0, false))); socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeRstPacket( packet_number++, false, @@ -7241,7 +7245,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams2( client_maker_.MakeAckAndRstPacket( packet_number++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -7623,7 +7627,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnMultipleWriteErrors( SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -7822,7 +7826,7 @@ void QuicStreamFactoryTestBase:: SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -7974,7 +7978,7 @@ void QuicStreamFactoryTestBase:: SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -8143,7 +8147,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorPauseBeforeConnected( SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -8282,7 +8286,7 @@ TEST_P(QuicStreamFactoryTest, IgnoreWriteErrorFromOldWriterAfterMigration) { SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -8410,7 +8414,7 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorFromOldReaderAfterMigration) { SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -8543,7 +8547,7 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorOnOldReaderDuringMigration) { SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -8642,10 +8646,9 @@ TEST_P(QuicStreamFactoryTest, DefaultRetransmittableOnWireTimeoutForMigration) { base::StringPiece("Hello World"))); // Read an ACK from server which acks all client data. - socket_data1.AddRead(SYNCHRONOUS, - server_maker_.MakeAckPacket(3, 3, 1, 1, false)); - socket_data1.AddWrite( - ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false)); + socket_data1.AddRead(SYNCHRONOUS, server_maker_.MakeAckPacket(3, 3, 1, 1)); + socket_data1.AddWrite(ASYNC, + client_maker_.MakeAckPacket(packet_num++, 2, 1, 1)); // The PING packet sent for retransmittable on wire. socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++, false)); @@ -8804,10 +8807,9 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeoutForMigration) { 2, GetNthClientInitiatedBidirectionalStreamId(0), false, false, base::StringPiece("Hello World"))); // Read an ACK from server which acks all client data. - socket_data1.AddRead(SYNCHRONOUS, - server_maker_.MakeAckPacket(3, 3, 1, 1, false)); - socket_data1.AddWrite( - ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false)); + socket_data1.AddRead(SYNCHRONOUS, server_maker_.MakeAckPacket(3, 3, 1, 1)); + socket_data1.AddWrite(ASYNC, + client_maker_.MakeAckPacket(packet_num++, 2, 1, 1)); // The PING packet sent for retransmittable on wire. socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++, false)); @@ -8954,10 +8956,9 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeout) { 2, GetNthClientInitiatedBidirectionalStreamId(0), false, false, base::StringPiece("Hello World"))); // Read an ACK from server which acks all client data. - socket_data1.AddRead(SYNCHRONOUS, - server_maker_.MakeAckPacket(3, 2, 1, 1, false)); - socket_data1.AddWrite( - ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false)); + socket_data1.AddRead(SYNCHRONOUS, server_maker_.MakeAckPacket(3, 2, 1, 1)); + socket_data1.AddWrite(ASYNC, + client_maker_.MakeAckPacket(packet_num++, 2, 1, 1)); // The PING packet sent for retransmittable on wire. socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++, false)); @@ -9102,10 +9103,9 @@ TEST_P(QuicStreamFactoryTest, NoRetransmittableOnWireTimeout) { 2, GetNthClientInitiatedBidirectionalStreamId(0), false, false, base::StringPiece("Hello World"))); // Read an ACK from server which acks all client data. - socket_data1.AddRead(SYNCHRONOUS, - server_maker_.MakeAckPacket(3, 2, 1, 1, false)); - socket_data1.AddWrite( - ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false)); + socket_data1.AddRead(SYNCHRONOUS, server_maker_.MakeAckPacket(3, 2, 1, 1)); + socket_data1.AddWrite(ASYNC, + client_maker_.MakeAckPacket(packet_num++, 2, 1, 1)); std::string header = ConstructDataHeader(6); socket_data1.AddRead( ASYNC, ConstructServerDataPacket( @@ -9241,10 +9241,9 @@ TEST_P(QuicStreamFactoryTest, 2, GetNthClientInitiatedBidirectionalStreamId(0), false, false, base::StringPiece("Hello World"))); // Read an ACK from server which acks all client data. - socket_data1.AddRead(SYNCHRONOUS, - server_maker_.MakeAckPacket(3, 2, 1, 1, false)); - socket_data1.AddWrite( - ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false)); + socket_data1.AddRead(SYNCHRONOUS, server_maker_.MakeAckPacket(3, 2, 1, 1)); + socket_data1.AddWrite(ASYNC, + client_maker_.MakeAckPacket(packet_num++, 2, 1, 1)); // The PING packet sent for retransmittable on wire. socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++, false)); @@ -9391,10 +9390,9 @@ TEST_P(QuicStreamFactoryTest, 2, GetNthClientInitiatedBidirectionalStreamId(0), false, false, base::StringPiece("Hello World"))); // Read an ACK from server which acks all client data. - socket_data1.AddRead(SYNCHRONOUS, - server_maker_.MakeAckPacket(3, 2, 1, 1, false)); - socket_data1.AddWrite( - ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false)); + socket_data1.AddRead(SYNCHRONOUS, server_maker_.MakeAckPacket(3, 2, 1, 1)); + socket_data1.AddWrite(ASYNC, + client_maker_.MakeAckPacket(packet_num++, 2, 1, 1)); std::string header = ConstructDataHeader(6); socket_data1.AddRead( ASYNC, ConstructServerDataPacket( @@ -9599,7 +9597,7 @@ TEST_P(QuicStreamFactoryTest, // Migrate on asynchronous write error, old network disconnects after alternate // network connects. TEST_P(QuicStreamFactoryTest, - MigrateSessionOnWriteErrorWithDisconnectAfterConnectAysnc) { + MigrateSessionOnWriteErrorWithDisconnectAfterConnectAsync) { TestMigrationOnWriteErrorWithMultipleNotifications( ASYNC, /*disconnect_before_connect*/ false); } @@ -9615,7 +9613,7 @@ TEST_P(QuicStreamFactoryTest, // Migrate on asynchronous write error, old network disconnects before alternate // network connects. TEST_P(QuicStreamFactoryTest, - MigrateSessionOnWriteErrorWithDisconnectBeforeConnectAysnc) { + MigrateSessionOnWriteErrorWithDisconnectBeforeConnectAsync) { TestMigrationOnWriteErrorWithMultipleNotifications( ASYNC, /*disconnect_before_connect*/ true); } @@ -9735,7 +9733,7 @@ void QuicStreamFactoryTestBase:: SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -10130,7 +10128,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigration) { SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + quic::QUIC_STREAM_CANCELLED, 1, 1, 1)); } socket_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -10170,7 +10168,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv4ToIPv4) { // Add alternate IPv4 server address to config. IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 123); quic::QuicConfig config; - config.SetAlternateServerAddressToSend(ToQuicSocketAddress(alt_address)); + config.SetIPv4AlternateServerAddressToSend(ToQuicSocketAddress(alt_address)); VerifyServerMigration(config, alt_address); } @@ -10182,7 +10180,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv6) { IPEndPoint alt_address = IPEndPoint( IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 123); quic::QuicConfig config; - config.SetAlternateServerAddressToSend(ToQuicSocketAddress(alt_address)); + config.SetIPv6AlternateServerAddressToSend(ToQuicSocketAddress(alt_address)); VerifyServerMigration(config, alt_address); } @@ -10193,7 +10191,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv4) { // Add alternate IPv4 server address to config. IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 123); quic::QuicConfig config; - config.SetAlternateServerAddressToSend(ToQuicSocketAddress(alt_address)); + config.SetIPv4AlternateServerAddressToSend(ToQuicSocketAddress(alt_address)); IPEndPoint expected_address( ConvertIPv4ToIPv4MappedIPv6(alt_address.address()), alt_address.port()); VerifyServerMigration(config, expected_address); @@ -10210,7 +10208,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv4ToIPv6Fails) { IPEndPoint alt_address = IPEndPoint( IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 123); quic::QuicConfig config; - config.SetAlternateServerAddressToSend(ToQuicSocketAddress(alt_address)); + config.SetIPv6AlternateServerAddressToSend(ToQuicSocketAddress(alt_address)); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); @@ -10969,78 +10967,6 @@ TEST_P(QuicStreamFactoryTest, } } -TEST_P(QuicStreamFactoryTest, StartCertVerifyJob) { - Initialize(); - - MockQuicData socket_data(version_); - socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); - if (VersionUsesHttp3(version_.transport_version)) - socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); - socket_data.AddSocketDataToFactory(socket_factory_.get()); - - // Save current state of |race_cert_verification|. - bool race_cert_verification = - QuicStreamFactoryPeer::GetRaceCertVerification(factory_.get()); - - // Need to hold onto this through the test, to keep the QuicCryptoClientConfig - // alive. - std::unique_ptr<QuicCryptoClientConfigHandle> crypto_config_handle = - QuicStreamFactoryPeer::GetCryptoConfig(factory_.get(), - NetworkIsolationKey()); - - // Load server config. - HostPortPair host_port_pair(kDefaultServerHostName, kDefaultServerPort); - quic::QuicServerId quic_server_id(host_port_pair_.host(), - host_port_pair_.port(), - privacy_mode_ == PRIVACY_MODE_ENABLED); - QuicStreamFactoryPeer::CacheDummyServerConfig(factory_.get(), quic_server_id, - NetworkIsolationKey()); - - QuicStreamFactoryPeer::SetRaceCertVerification(factory_.get(), true); - EXPECT_FALSE(HasActiveCertVerifierJob(quic_server_id)); - - // Start CertVerifyJob. - quic::QuicAsyncStatus status = QuicStreamFactoryPeer::StartCertVerifyJob( - factory_.get(), quic_server_id, NetworkIsolationKey(), - /*cert_verify_flags=*/0, net_log_); - if (status == quic::QUIC_PENDING) { - // Verify CertVerifierJob has started. - EXPECT_TRUE(HasActiveCertVerifierJob(quic_server_id)); - - while (HasActiveCertVerifierJob(quic_server_id)) { - base::RunLoop().RunUntilIdle(); - } - } - // Verify CertVerifierJob has finished. - EXPECT_FALSE(HasActiveCertVerifierJob(quic_server_id)); - - // Start a QUIC request. - 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()); - - // Restore |race_cert_verification|. - QuicStreamFactoryPeer::SetRaceCertVerification(factory_.get(), - race_cert_verification); - - EXPECT_TRUE(socket_data.AllReadDataConsumed()); - EXPECT_TRUE(socket_data.AllWriteDataConsumed()); - - // Verify there are no outstanding CertVerifierJobs after request has - // finished. - EXPECT_FALSE(HasActiveCertVerifierJob(quic_server_id)); -} - TEST_P(QuicStreamFactoryTest, YieldAfterPackets) { if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 && version_.HasIetfQuicFrames()) { diff --git a/chromium/net/quic/quic_test_packet_maker.cc b/chromium/net/quic/quic_test_packet_maker.cc index 10234cc17a7..db63151afa8 100644 --- a/chromium/net/quic/quic_test_packet_maker.cc +++ b/chromium/net/quic/quic_test_packet_maker.cc @@ -306,11 +306,9 @@ QuicTestPacketMaker::MakeAckAndRstPacket( quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received, - uint64_t least_unacked, - bool send_feedback) { + uint64_t least_unacked) { return MakeAckAndRstPacket(num, include_version, stream_id, error_code, largest_received, smallest_received, least_unacked, - send_feedback, /*include_stop_sending_if_v99=*/true); } @@ -323,7 +321,6 @@ QuicTestPacketMaker::MakeAckAndRstPacket( uint64_t largest_received, uint64_t smallest_received, uint64_t least_unacked, - bool send_feedback, bool include_stop_sending_if_v99) { InitializeHeader(num, include_version); @@ -479,10 +476,9 @@ std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket( uint64_t packet_number, uint64_t largest_received, uint64_t smallest_received, - uint64_t least_unacked, - bool send_feedback) { + uint64_t least_unacked) { return MakeAckPacket(packet_number, 1, largest_received, smallest_received, - least_unacked, send_feedback); + least_unacked); } std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket( @@ -490,8 +486,7 @@ std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket( uint64_t first_received, uint64_t largest_received, uint64_t smallest_received, - uint64_t least_unacked, - bool send_feedback) { + uint64_t least_unacked) { InitializeHeader(packet_number, /*include_version=*/false); AddQuicAckFrame(first_received, largest_received, smallest_received); return BuildPacket(); @@ -1353,8 +1348,6 @@ void QuicTestPacketMaker::MaybeAddHttp3SettingsFrames() { std::string data = type + settings_data + grease_data + max_push_id_data; AddQuicStreamFrame(stream_id, false, data); - AddQuicStreamFrame(stream_id + 4, false, "\x03"); - AddQuicStreamFrame(stream_id + 8, false, "\x02"); } } // namespace test diff --git a/chromium/net/quic/quic_test_packet_maker.h b/chromium/net/quic/quic_test_packet_maker.h index f153bbbce48..8df27cfbdb6 100644 --- a/chromium/net/quic/quic_test_packet_maker.h +++ b/chromium/net/quic/quic_test_packet_maker.h @@ -123,8 +123,7 @@ class QuicTestPacketMaker { quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received, - uint64_t least_unacked, - bool send_feedback); + uint64_t least_unacked); std::unique_ptr<quic::QuicReceivedPacket> MakeAckAndRstPacket( uint64_t num, @@ -134,7 +133,6 @@ class QuicTestPacketMaker { uint64_t largest_received, uint64_t smallest_received, uint64_t least_unacked, - bool send_feedback, bool include_stop_sending_if_v99); std::unique_ptr<quic::QuicReceivedPacket> MakeRstAckAndConnectionClosePacket( @@ -205,16 +203,14 @@ class QuicTestPacketMaker { uint64_t packet_number, uint64_t largest_received, uint64_t smallest_received, - uint64_t least_unacked, - bool send_feedback); + uint64_t least_unacked); std::unique_ptr<quic::QuicReceivedPacket> MakeAckPacket( uint64_t packet_number, uint64_t first_received, uint64_t largest_received, uint64_t smallest_received, - uint64_t least_unacked, - bool send_feedback); + uint64_t least_unacked); std::unique_ptr<quic::QuicReceivedPacket> MakeDataPacket( uint64_t packet_number, diff --git a/chromium/net/quic/quic_transport_client.cc b/chromium/net/quic/quic_transport_client.cc index 08aefc2994a..6da53b0ac2e 100644 --- a/chromium/net/quic/quic_transport_client.cc +++ b/chromium/net/quic/quic_transport_client.cc @@ -26,6 +26,9 @@ std::set<std::string> HostsFromOrigins(std::set<HostPortPair> origins) { } } // namespace +constexpr quic::ParsedQuicVersion + QuicTransportClient::kQuicVersionForOriginTrial; + QuicTransportClient::QuicTransportClient( const GURL& url, const url::Origin& origin, @@ -134,13 +137,16 @@ int QuicTransportClient::DoInit() { // TODO(vasilvv): check if QUIC is disabled by policy. + // Ensure that for the duration of the origin trial, a fixed QUIC transport + // version is available. + supported_versions_.push_back(kQuicVersionForOriginTrial); + // Add other supported versions if available. for (quic::ParsedQuicVersion& version : quic_context_->params()->supported_versions) { - // QuicTransport requires TLS-style ALPN. - if (version.handshake_protocol != quic::PROTOCOL_TLS1_3) - continue; - if (!quic::VersionSupportsMessageFrames(version.transport_version)) + if (!quic::IsVersionValidForQuicTransport(version)) continue; + if (version == kQuicVersionForOriginTrial) + continue; // Skip as we've already added it above. supported_versions_.push_back(version); } if (supported_versions_.empty()) { diff --git a/chromium/net/quic/quic_transport_client.h b/chromium/net/quic/quic_transport_client.h index 27e83d80171..4f0f58ff8c8 100644 --- a/chromium/net/quic/quic_transport_client.h +++ b/chromium/net/quic/quic_transport_client.h @@ -16,6 +16,7 @@ #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 "url/gurl.h" #include "url/origin.h" @@ -96,6 +97,11 @@ 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); + // |visitor| and |context| must outlive this object. QuicTransportClient(const GURL& url, const url::Origin& origin, 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 7f8c35f4ab9..9783a05ac60 100644 --- a/chromium/net/quic/quic_transport_end_to_end_test.cc +++ b/chromium/net/quic/quic_transport_end_to_end_test.cc @@ -40,7 +40,7 @@ class MockVisitor : public QuicTransportClient::Visitor { class QuicTransportEndToEndTest : public TestWithTaskEnvironment { public: QuicTransportEndToEndTest() { - quic::QuicEnableVersion(quic::DefaultVersionForQuicTransport()); + quic::QuicEnableVersion(QuicTransportClient::kQuicVersionForOriginTrial); origin_ = url::Origin::Create(GURL{"https://example.org"}); isolation_key_ = NetworkIsolationKey(origin_, origin_); @@ -57,8 +57,7 @@ class QuicTransportEndToEndTest : public TestWithTaskEnvironment { builder.set_host_resolver(std::move(host_resolver)); auto quic_context = std::make_unique<QuicContext>(); - quic_context->params()->supported_versions.push_back( - quic::DefaultVersionForQuicTransport()); + quic_context->params()->supported_versions.clear(); // This is required to bypass the check that only allows known certificate // roots in QUIC. quic_context->params()->origins_to_force_quic_on.insert( |