diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-05-12 15:59:20 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-05-25 06:57:22 +0000 |
commit | f7eaed5286974984ba5f9e3189d8f49d03e99f81 (patch) | |
tree | caed19b2af2024f35449fb0b781d0a25e09d4f8f /chromium/net/third_party/quiche/src/quic | |
parent | 9729c4479fe23554eae6e6dd1f30ff488f470c84 (diff) | |
download | qtwebengine-chromium-f7eaed5286974984ba5f9e3189d8f49d03e99f81.tar.gz |
BASELINE: Update Chromium to 100.0.4896.167
Change-Id: I98cbeb5d7543d966ffe04d8cefded0c493a11333
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/net/third_party/quiche/src/quic')
135 files changed, 3124 insertions, 2083 deletions
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc index fbf1343f58b..c634db5d4a3 100644 --- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc @@ -29,15 +29,14 @@ #include "quic/test_tools/simulator/simulator.h" #include "quic/test_tools/simulator/switch.h" #include "quic/test_tools/simulator/traffic_policer.h" +#include "common/platform/api/quiche_command_line_flags.h" using testing::AllOf; using testing::Ge; using testing::Le; -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - quic_bbr2_test_regression_mode, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, quic_bbr2_test_regression_mode, "", "One of a) 'record' to record test result (one file per test), or " "b) 'regress' to regress against recorded results, or " "c) <anything else> for non-regression mode."); diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc index 8973f94728a..caba9b1c7f4 100644 --- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc @@ -28,15 +28,14 @@ #include "quic/test_tools/simulator/quic_endpoint.h" #include "quic/test_tools/simulator/simulator.h" #include "quic/test_tools/simulator/switch.h" +#include "common/platform/api/quiche_command_line_flags.h" using testing::AllOf; using testing::Ge; using testing::Le; -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - quic_bbr_test_regression_mode, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, quic_bbr_test_regression_mode, "", "One of a) 'record' to record test result (one file per test), or " "b) 'regress' to regress against recorded results, or " "c) <anything else> for non-regression mode."); diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.h index d473a38cd91..b2401a2b6c7 100644 --- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.h +++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.h @@ -79,6 +79,8 @@ class QUIC_EXPORT_PRIVATE PacingSender { return {ideal_next_packet_send_time_, allow_burst}; } + uint32_t initial_burst_size() const { return initial_burst_size_; } + protected: uint32_t lumpy_tokens() const { return lumpy_tokens_; } diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h index 2fa1217a9ea..42716033c6d 100644 --- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h +++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h @@ -33,27 +33,28 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface { public: // Network Params for AdjustNetworkParameters. struct QUIC_NO_EXPORT NetworkParams { - NetworkParams() - : NetworkParams(QuicBandwidth::Zero(), QuicTime::Delta::Zero(), false) { - } + NetworkParams() = default; NetworkParams(const QuicBandwidth& bandwidth, const QuicTime::Delta& rtt, bool allow_cwnd_to_decrease) : bandwidth(bandwidth), rtt(rtt), allow_cwnd_to_decrease(allow_cwnd_to_decrease) {} + explicit NetworkParams(int burst_token) : burst_token(burst_token) {} bool operator==(const NetworkParams& other) const { return bandwidth == other.bandwidth && rtt == other.rtt && max_initial_congestion_window == other.max_initial_congestion_window && + burst_token == other.burst_token && allow_cwnd_to_decrease == other.allow_cwnd_to_decrease; } - QuicBandwidth bandwidth; - QuicTime::Delta rtt; + QuicBandwidth bandwidth = QuicBandwidth::Zero(); + QuicTime::Delta rtt = QuicTime::Delta::Zero(); int max_initial_congestion_window = 0; - bool allow_cwnd_to_decrease; + int burst_token = 0; + bool allow_cwnd_to_decrease = false; }; static SendAlgorithmInterface* Create( diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h index cf2a532e463..be4d2b2ad8d 100644 --- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h +++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h @@ -96,8 +96,7 @@ class QUIC_EXPORT_PRIVATE TcpCubicSenderBytes : public SendAlgorithmInterface { QuicTime::Delta rtt); void SetMinCongestionWindowInPackets(QuicPacketCount congestion_window); void ExitSlowstart(); - void OnPacketLost(QuicPacketNumber largest_loss, - QuicByteCount lost_bytes, + void OnPacketLost(QuicPacketNumber packet_number, QuicByteCount lost_bytes, QuicByteCount prior_in_flight); void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number, QuicByteCount acked_bytes, diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/boring_utils.h b/chromium/net/third_party/quiche/src/quic/core/crypto/boring_utils.h index 2927b891f98..d623fa25af5 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/boring_utils.h +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/boring_utils.h @@ -23,6 +23,12 @@ inline QUIC_EXPORT_PRIVATE CBS StringPieceToCbs(absl::string_view piece) { return result; } +inline QUIC_EXPORT_PRIVATE bool AddStringToCbb(CBB* cbb, + absl::string_view piece) { + return 1 == CBB_add_bytes(cbb, reinterpret_cast<const uint8_t*>(piece.data()), + piece.size()); +} + } // namespace quic #endif // QUICHE_QUIC_CORE_CRYPTO_BORING_UTILS_H_ diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_util.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_util.cc new file mode 100644 index 00000000000..550adffa582 --- /dev/null +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_util.cc @@ -0,0 +1,280 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "quic/core/crypto/certificate_util.h" + +#include "absl/strings/str_format.h" +#include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" +#include "third_party/boringssl/src/include/openssl/bn.h" +#include "third_party/boringssl/src/include/openssl/bytestring.h" +#include "third_party/boringssl/src/include/openssl/digest.h" +#include "third_party/boringssl/src/include/openssl/ec_key.h" +#include "third_party/boringssl/src/include/openssl/mem.h" +#include "third_party/boringssl/src/include/openssl/pkcs7.h" +#include "third_party/boringssl/src/include/openssl/pool.h" +#include "third_party/boringssl/src/include/openssl/rsa.h" +#include "third_party/boringssl/src/include/openssl/stack.h" +#include "quic/core/crypto/boring_utils.h" +#include "quic/platform/api/quic_logging.h" + +namespace quic { +namespace { +bool AddEcdsa256SignatureAlgorithm(CBB* cbb) { + // See RFC 5758. This is the encoding of OID 1.2.840.10045.4.3.2. + static const uint8_t kEcdsaWithSha256[] = {0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02}; + + // An AlgorithmIdentifier is described in RFC 5280, 4.1.1.2. + CBB sequence, oid; + if (!CBB_add_asn1(cbb, &sequence, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&sequence, &oid, CBS_ASN1_OBJECT)) { + return false; + } + + if (!CBB_add_bytes(&oid, kEcdsaWithSha256, sizeof(kEcdsaWithSha256))) { + return false; + } + + // RFC 5758, section 3.2: ecdsa-with-sha256 MUST omit the parameters field. + return CBB_flush(cbb); +} + +// Adds an X.509 Name with the specified distinguished name to |cbb|. +bool AddName(CBB* cbb, absl::string_view name) { + // See RFC 4519. + static const uint8_t kCommonName[] = {0x55, 0x04, 0x03}; + static const uint8_t kCountryName[] = {0x55, 0x04, 0x06}; + static const uint8_t kOrganizationName[] = {0x55, 0x04, 0x0a}; + static const uint8_t kOrganizationalUnitName[] = {0x55, 0x04, 0x0b}; + + std::vector<std::string> attributes = + absl::StrSplit(name, ',', absl::SkipEmpty()); + + if (attributes.empty()) { + QUIC_LOG(ERROR) << "Missing DN or wrong format"; + return false; + } + + // See RFC 5280, section 4.1.2.4. + CBB rdns; + if (!CBB_add_asn1(cbb, &rdns, CBS_ASN1_SEQUENCE)) { + return false; + } + + for (const std::string& attribute : attributes) { + std::vector<std::string> parts = + absl::StrSplit(absl::StripAsciiWhitespace(attribute), '='); + if (parts.size() != 2) { + QUIC_LOG(ERROR) << "Wrong DN format at " + attribute; + return false; + } + + const std::string& type_string = parts[0]; + const std::string& value_string = parts[1]; + absl::Span<const uint8_t> type_bytes; + if (type_string == "CN") { + type_bytes = kCommonName; + } else if (type_string == "C") { + type_bytes = kCountryName; + } else if (type_string == "O") { + type_bytes = kOrganizationName; + } else if (type_string == "OU") { + type_bytes = kOrganizationalUnitName; + } else { + QUIC_LOG(ERROR) << "Unrecognized type " + type_string; + return false; + } + + CBB rdn, attr, type, value; + if (!CBB_add_asn1(&rdns, &rdn, CBS_ASN1_SET) || + !CBB_add_asn1(&rdn, &attr, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&attr, &type, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&type, type_bytes.data(), type_bytes.size()) || + !CBB_add_asn1(&attr, &value, + type_string == "C" ? CBS_ASN1_PRINTABLESTRING + : CBS_ASN1_UTF8STRING) || + !AddStringToCbb(&value, value_string) || !CBB_flush(&rdns)) { + return false; + } + } + if (!CBB_flush(cbb)) { + return false; + } + return true; +} + +bool CBBAddTime(CBB* cbb, const CertificateTimestamp& timestamp) { + CBB child; + std::string formatted_time; + + // Per RFC 5280, 4.1.2.5, times which fit in UTCTime must be encoded as + // UTCTime rather than GeneralizedTime. + const bool is_utc_time = (1950 <= timestamp.year && timestamp.year < 2050); + if (is_utc_time) { + uint16_t year = timestamp.year - 1900; + if (year >= 100) { + year -= 100; + } + formatted_time = absl::StrFormat("%02d", year); + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_UTCTIME)) { + return false; + } + } else { + formatted_time = absl::StrFormat("%04d", timestamp.year); + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_GENERALIZEDTIME)) { + return false; + } + } + + absl::StrAppendFormat(&formatted_time, "%02d%02d%02d%02d%02dZ", + timestamp.month, timestamp.day, timestamp.hour, + timestamp.minute, timestamp.second); + + static const size_t kGeneralizedTimeLength = 15; + static const size_t kUTCTimeLength = 13; + QUICHE_DCHECK_EQ(formatted_time.size(), + is_utc_time ? kUTCTimeLength : kGeneralizedTimeLength); + + return AddStringToCbb(&child, formatted_time) && CBB_flush(cbb); +} + +bool CBBAddExtension(CBB* extensions, absl::Span<const uint8_t> oid, + bool critical, absl::Span<const uint8_t> contents) { + CBB extension, cbb_oid, cbb_contents; + if (!CBB_add_asn1(extensions, &extension, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&extension, &cbb_oid, CBS_ASN1_OBJECT) || + !CBB_add_bytes(&cbb_oid, oid.data(), oid.size()) || + (critical && !CBB_add_asn1_bool(&extension, 1)) || + !CBB_add_asn1(&extension, &cbb_contents, CBS_ASN1_OCTETSTRING) || + !CBB_add_bytes(&cbb_contents, contents.data(), contents.size()) || + !CBB_flush(extensions)) { + return false; + } + + return true; +} + +bool IsEcdsa256Key(const EVP_PKEY& evp_key) { + if (EVP_PKEY_id(&evp_key) != EVP_PKEY_EC) { + return false; + } + const EC_KEY* key = EVP_PKEY_get0_EC_KEY(&evp_key); + if (key == nullptr) { + return false; + } + const EC_GROUP* group = EC_KEY_get0_group(key); + if (group == nullptr) { + return false; + } + return EC_GROUP_get_curve_name(group) == NID_X9_62_prime256v1; +} + +} // namespace + +bssl::UniquePtr<EVP_PKEY> MakeKeyPairForSelfSignedCertificate() { + bssl::UniquePtr<EVP_PKEY_CTX> context( + EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr)); + if (!context) { + return nullptr; + } + if (EVP_PKEY_keygen_init(context.get()) != 1) { + return nullptr; + } + if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(context.get(), + NID_X9_62_prime256v1) != 1) { + return nullptr; + } + EVP_PKEY* raw_key = nullptr; + if (EVP_PKEY_keygen(context.get(), &raw_key) != 1) { + return nullptr; + } + return bssl::UniquePtr<EVP_PKEY>(raw_key); +} + +std::string CreateSelfSignedCertificate(EVP_PKEY& key, + const CertificateOptions& options) { + std::string error; + if (!IsEcdsa256Key(key)) { + QUIC_LOG(ERROR) << "CreateSelfSignedCert only accepts ECDSA P-256 keys"; + return error; + } + + // See RFC 5280, section 4.1. First, construct the TBSCertificate. + bssl::ScopedCBB cbb; + CBB tbs_cert, version, validity; + uint8_t* tbs_cert_bytes; + size_t tbs_cert_len; + + if (!CBB_init(cbb.get(), 64) || + !CBB_add_asn1(cbb.get(), &tbs_cert, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&tbs_cert, &version, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || + !CBB_add_asn1_uint64(&version, 2) || // X.509 version 3 + !CBB_add_asn1_uint64(&tbs_cert, options.serial_number) || + !AddEcdsa256SignatureAlgorithm(&tbs_cert) || // signature algorithm + !AddName(&tbs_cert, options.subject) || // issuer + !CBB_add_asn1(&tbs_cert, &validity, CBS_ASN1_SEQUENCE) || + !CBBAddTime(&validity, options.validity_start) || + !CBBAddTime(&validity, options.validity_end) || + !AddName(&tbs_cert, options.subject) || // subject + !EVP_marshal_public_key(&tbs_cert, &key)) { // subjectPublicKeyInfo + return error; + } + + CBB outer_extensions, extensions; + if (!CBB_add_asn1(&tbs_cert, &outer_extensions, + 3 | CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED) || + !CBB_add_asn1(&outer_extensions, &extensions, CBS_ASN1_SEQUENCE)) { + return error; + } + + // Key Usage + constexpr uint8_t kKeyUsageOid[] = {0x55, 0x1d, 0x0f}; + constexpr uint8_t kKeyUsageContent[] = { + 0x3, // BIT STRING + 0x2, // Length + 0x0, // Unused bits + 0x80, // bit(0): digitalSignature + }; + CBBAddExtension(&extensions, kKeyUsageOid, true, kKeyUsageContent); + + // TODO(wub): Add more extensions here if needed. + + if (!CBB_finish(cbb.get(), &tbs_cert_bytes, &tbs_cert_len)) { + return error; + } + + bssl::UniquePtr<uint8_t> delete_tbs_cert_bytes(tbs_cert_bytes); + + // Sign the TBSCertificate and write the entire certificate. + CBB cert, signature; + bssl::ScopedEVP_MD_CTX ctx; + uint8_t* sig_out; + size_t sig_len; + uint8_t* cert_bytes; + size_t cert_len; + if (!CBB_init(cbb.get(), tbs_cert_len) || + !CBB_add_asn1(cbb.get(), &cert, CBS_ASN1_SEQUENCE) || + !CBB_add_bytes(&cert, tbs_cert_bytes, tbs_cert_len) || + !AddEcdsa256SignatureAlgorithm(&cert) || + !CBB_add_asn1(&cert, &signature, CBS_ASN1_BITSTRING) || + !CBB_add_u8(&signature, 0 /* no unused bits */) || + !EVP_DigestSignInit(ctx.get(), nullptr, EVP_sha256(), nullptr, &key) || + // Compute the maximum signature length. + !EVP_DigestSign(ctx.get(), nullptr, &sig_len, tbs_cert_bytes, + tbs_cert_len) || + !CBB_reserve(&signature, &sig_out, sig_len) || + // Actually sign the TBSCertificate. + !EVP_DigestSign(ctx.get(), sig_out, &sig_len, tbs_cert_bytes, + tbs_cert_len) || + !CBB_did_write(&signature, sig_len) || + !CBB_finish(cbb.get(), &cert_bytes, &cert_len)) { + return error; + } + bssl::UniquePtr<uint8_t> delete_cert_bytes(cert_bytes); + return std::string(reinterpret_cast<char*>(cert_bytes), cert_len); +} + +} // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_util.h b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_util.h new file mode 100644 index 00000000000..ebc1cf48d6e --- /dev/null +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_util.h @@ -0,0 +1,46 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_QUIC_CORE_CRYPTO_CERTIFICATE_UTIL_H_ +#define QUICHE_QUIC_CORE_CRYPTO_CERTIFICATE_UTIL_H_ + +#include <string> + +#include "absl/strings/string_view.h" +#include "third_party/boringssl/src/include/openssl/evp.h" +#include "quic/core/quic_time.h" +#include "quic/platform/api/quic_export.h" + +namespace quic { + +struct QUIC_NO_EXPORT CertificateTimestamp { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; +}; + +struct QUIC_NO_EXPORT CertificateOptions { + absl::string_view subject; + uint64_t serial_number; + CertificateTimestamp validity_start; // a.k.a not_valid_before + CertificateTimestamp validity_end; // a.k.a not_valid_after +}; + +// Creates a ECDSA P-256 key pair. +QUIC_EXPORT_PRIVATE bssl::UniquePtr<EVP_PKEY> +MakeKeyPairForSelfSignedCertificate(); + +// Creates a self-signed, DER-encoded X.509 certificate. +// |key| must be a ECDSA P-256 key. +// This is mostly stolen from Chromium's net/cert/x509_util.h, with +// modifications to make it work in QUICHE. +QUIC_EXPORT_PRIVATE std::string CreateSelfSignedCertificate( + EVP_PKEY& key, const CertificateOptions& options); + +} // namespace quic + +#endif // QUICHE_QUIC_CORE_CRYPTO_CERTIFICATE_UTIL_H_ diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_util_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_util_test.cc new file mode 100644 index 00000000000..1ffe6f551ee --- /dev/null +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_util_test.cc @@ -0,0 +1,49 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "quic/core/crypto/certificate_util.h" + +#include "third_party/boringssl/src/include/openssl/ssl.h" +#include "quic/core/crypto/certificate_view.h" +#include "quic/platform/api/quic_test.h" +#include "quic/platform/api/quic_test_output.h" + +namespace quic { +namespace test { +namespace { + +TEST(CertificateUtilTest, CreateSelfSignedCertificate) { + bssl::UniquePtr<EVP_PKEY> key = MakeKeyPairForSelfSignedCertificate(); + ASSERT_NE(key, nullptr); + + CertificatePrivateKey cert_key(std::move(key)); + + CertificateOptions options; + options.subject = "CN=subject"; + options.serial_number = 0x12345678; + options.validity_start = {2020, 1, 1, 0, 0, 0}; + options.validity_end = {2049, 12, 31, 0, 0, 0}; + std::string der_cert = + CreateSelfSignedCertificate(*cert_key.private_key(), options); + ASSERT_FALSE(der_cert.empty()); + + QuicSaveTestOutput("CertificateUtilTest_CreateSelfSignedCert.crt", der_cert); + + std::unique_ptr<CertificateView> cert_view = + CertificateView::ParseSingleCertificate(der_cert); + ASSERT_NE(cert_view, nullptr); + EXPECT_EQ(cert_view->public_key_type(), PublicKeyType::kP256); + + absl::optional<std::string> subject = cert_view->GetHumanReadableSubject(); + ASSERT_TRUE(subject.has_value()); + EXPECT_EQ(*subject, options.subject); + + EXPECT_TRUE( + cert_key.ValidForSignatureAlgorithm(SSL_SIGN_ECDSA_SECP256R1_SHA256)); + EXPECT_TRUE(cert_key.MatchesPublicKey(*cert_view)); +} + +} // namespace +} // namespace test +} // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.cc index f0b1c18a195..12866670783 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.cc @@ -49,14 +49,6 @@ constexpr uint8_t kX509Version[] = {0x02, 0x01, 0x02}; // 2.5.29.17 constexpr uint8_t kSubjectAltNameOid[] = {0x55, 0x1d, 0x11}; -enum class PublicKeyType { - kRsa, - kP256, - kP384, - kEd25519, - kUnknown, -}; - PublicKeyType PublicKeyTypeFromKey(EVP_PKEY* public_key) { switch (EVP_PKEY_id(public_key)) { case EVP_PKEY_RSA: @@ -176,6 +168,22 @@ absl::optional<std::string> DistinguishedNameToString(CBS input) { } // namespace +std::string PublicKeyTypeToString(PublicKeyType type) { + switch (type) { + case PublicKeyType::kRsa: + return "RSA"; + case PublicKeyType::kP256: + return "ECDSA P-256"; + case PublicKeyType::kP384: + return "ECDSA P-384"; + case PublicKeyType::kEd25519: + return "Ed25519"; + case PublicKeyType::kUnknown: + return "unknown"; + } + return ""; +} + absl::optional<quic::QuicWallTime> ParseDerTime(unsigned tag, absl::string_view payload) { if (tag != CBS_ASN1_GENERALIZEDTIME && tag != CBS_ASN1_UTCTIME) { @@ -469,11 +477,13 @@ std::vector<std::string> CertificateView::LoadPemFromStream( } } +PublicKeyType CertificateView::public_key_type() const { + return PublicKeyTypeFromKey(public_key_.get()); +} + bool CertificateView::ValidatePublicKeyParameters() { - // The profile here affects what certificates can be used: - // (1) when QUIC is used as a server library without any custom certificate - // provider logic, - // (2) when QuicTransport is handling self-signed certificates. + // The profile here affects what certificates can be used when QUIC is used as + // a server library without any custom certificate provider logic. // The goal is to allow at minimum any certificate that would be allowed on a // regular Web session over TLS 1.3 while ensuring we do not expose any // algorithms we don't want to support long-term. diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.h b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.h index f2826cdd668..5b3c8c762c6 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.h +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.h @@ -34,6 +34,16 @@ struct QUIC_EXPORT_PRIVATE PemReadResult { // Reads |input| line-by-line and returns the next available PEM message. QUIC_EXPORT_PRIVATE PemReadResult ReadNextPemMessage(std::istream* input); +// Cryptograhpic algorithms recognized in X.509. +enum class PublicKeyType { + kRsa, + kP256, + kP384, + kEd25519, + kUnknown, +}; +QUIC_EXPORT_PRIVATE std::string PublicKeyTypeToString(PublicKeyType type); + // CertificateView represents a parsed version of a single X.509 certificate. As // the word "view" implies, it does not take ownership of the underlying strings // and consists primarily of pointers into the certificate that is passed into @@ -69,6 +79,9 @@ class QUIC_EXPORT_PRIVATE CertificateView { absl::string_view signature, uint16_t signature_algorithm) const; + // Returns the type of the key used in the certificate's SPKI. + PublicKeyType public_key_type() const; + private: CertificateView() = default; diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view_test.cc index 5d743b2114c..fbca9159c82 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view_test.cc @@ -58,6 +58,8 @@ TEST(CertificateViewTest, Parse) { const QuicWallTime validity_end = QuicWallTime::FromUNIXSeconds( *quiche::QuicheUtcDateTimeToUnixSeconds(2020, 2, 2, 18, 13, 59)); EXPECT_EQ(view->validity_end(), validity_end); + EXPECT_EQ(view->public_key_type(), PublicKeyType::kRsa); + EXPECT_EQ(PublicKeyTypeToString(view->public_key_type()), "RSA"); EXPECT_EQ("C=US,ST=California,L=Mountain View,O=QUIC Server,CN=127.0.0.1", view->GetHumanReadableSubject()); diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc index 68e3d9cbe19..0159e3004e5 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc @@ -13,6 +13,7 @@ #include "absl/strings/escaping.h" #include "quic/core/crypto/crypto_framer.h" #include "quic/core/quic_utils.h" +#include "common/platform/api/quiche_command_line_flags.h" using std::cerr; using std::cout; @@ -37,9 +38,9 @@ class CryptoMessagePrinter : public ::quic::CryptoFramerVisitorInterface { int main(int argc, char* argv[]) { const char* usage = "Usage: crypto_message_printer <hex>"; std::vector<std::string> messages = - quic::QuicParseCommandLineFlags(usage, argc, argv); + quiche::QuicheParseCommandLineFlags(usage, argc, argv); if (messages.size() != 1) { - quic::QuicPrintCommandLineFlagHelp(usage); + quiche::QuichePrintCommandLineFlagHelp(usage); exit(0); } diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h index 5a3003861e1..0ebe0e430b8 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h @@ -121,9 +121,9 @@ const QuicTag kBBQ7 = TAG('B', 'B', 'Q', '7'); // Reduce bw_lo by const QuicTag kBBQ8 = TAG('B', 'B', 'Q', '8'); // Reduce bw_lo by // bw_lo * bytes_lost/inflight const QuicTag kBBQ9 = TAG('B', 'B', 'Q', '9'); // Reduce bw_lo by + // bw_lo * bytes_lost/cwnd const QuicTag kBBQ0 = TAG('B', 'B', 'Q', '0'); // Increase bytes_acked in // PROBE_UP when app limited. - // bw_lo * bytes_lost/cwnd const QuicTag kRENO = TAG('R', 'E', 'N', 'O'); // Reno Congestion Control const QuicTag kTPCC = TAG('P', 'C', 'C', '\0'); // Performance-Oriented // Congestion Control @@ -434,6 +434,7 @@ const QuicTag kSRWP = TAG('S', 'R', 'W', 'P'); // Enable retransmittable on // Client Hints triggers. const QuicTag kGWCH = TAG('G', 'W', 'C', 'H'); const QuicTag kYTCH = TAG('Y', 'T', 'C', 'H'); +const QuicTag kACH0 = TAG('A', 'C', 'H', '0'); // Rejection tags const QuicTag kRREJ = TAG('R', 'R', 'E', 'J'); // Reasons for server sending diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc index 1826212d83c..a4a7a2a615d 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc @@ -44,8 +44,11 @@ size_t CryptoSecretBoxer::GetKeySize() { // kAEAD is the AEAD used for boxing: AES-256-GCM-SIV. static const EVP_AEAD* (*const kAEAD)() = EVP_aead_aes_256_gcm_siv; -void CryptoSecretBoxer::SetKeys(const std::vector<std::string>& keys) { - QUICHE_DCHECK(!keys.empty()); +bool CryptoSecretBoxer::SetKeys(const std::vector<std::string>& keys) { + if (keys.empty()) { + QUIC_LOG(DFATAL) << "No keys supplied!"; + return false; + } const EVP_AEAD* const aead = kAEAD(); std::unique_ptr<State> new_state(new State); @@ -57,7 +60,7 @@ void CryptoSecretBoxer::SetKeys(const std::vector<std::string>& keys) { if (!ctx) { ERR_clear_error(); QUIC_LOG(DFATAL) << "EVP_AEAD_CTX_init failed"; - return; + return false; } new_state->ctxs.push_back(std::move(ctx)); @@ -65,6 +68,7 @@ void CryptoSecretBoxer::SetKeys(const std::vector<std::string>& keys) { QuicWriterMutexLock l(&lock_); state_ = std::move(new_state); + return true; } std::string CryptoSecretBoxer::Box(QuicRandom* rand, diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.h index 5dd5cb24985..e2cd0377786 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.h +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.h @@ -34,13 +34,15 @@ class QUIC_EXPORT_PRIVATE CryptoSecretBoxer { // SetKeys sets a list of encryption keys. The first key in the list will be // used by |Box|, but all supplied keys will be tried by |Unbox|, to handle // key skew across the fleet. This must be called before |Box| or |Unbox|. - // Keys must be |GetKeySize()| bytes long. - void SetKeys(const std::vector<std::string>& keys); + // Keys must be |GetKeySize()| bytes long. No change is made if any key is + // invalid, or if there are no keys supplied. + bool SetKeys(const std::vector<std::string>& keys); // Box encrypts |plaintext| using a random nonce generated from |rand| and // returns the resulting ciphertext. Since an authenticator and nonce are // included, the result will be slightly larger than |plaintext|. The first - // key in the vector supplied to |SetKeys| will be used. + // key in the vector supplied to |SetKeys| will be used. |SetKeys| must be + // called before calling this method. std::string Box(QuicRandom* rand, absl::string_view plaintext) const; // Unbox takes the result of a previous call to |Box| in |ciphertext| and diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer_test.cc index 225bfc8b14e..7b07d96d11d 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer_test.cc @@ -56,9 +56,9 @@ TEST_F(CryptoSecretBoxerTest, MultipleKeys) { std::string key_12(CryptoSecretBoxer::GetKeySize(), 0x12); CryptoSecretBoxer boxer_11, boxer_12, boxer; - boxer_11.SetKeys({key_11}); - boxer_12.SetKeys({key_12}); - boxer.SetKeys({key_12, key_11}); + EXPECT_TRUE(boxer_11.SetKeys({key_11})); + EXPECT_TRUE(boxer_12.SetKeys({key_12})); + EXPECT_TRUE(boxer.SetKeys({key_12, key_11})); // Neither single-key boxer can decode the other's tokens. EXPECT_FALSE(CanDecode(boxer_11, boxer_12)); @@ -74,7 +74,7 @@ TEST_F(CryptoSecretBoxerTest, MultipleKeys) { // After we flush key_11 from |boxer|, it can no longer decode tokens from // |boxer_11|. - boxer.SetKeys({key_12}); + EXPECT_TRUE(boxer.SetKeys({key_12})); EXPECT_FALSE(CanDecode(boxer, boxer_11)); } diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc index 50bbfefa4dc..05bbdfe6321 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc @@ -57,8 +57,7 @@ namespace { // |out_len|, respectively. The resulting expanded secret is returned. std::vector<uint8_t> HkdfExpandLabel(const EVP_MD* prf, const std::vector<uint8_t>& secret, - const std::string& label, - size_t out_len) { + const std::string& label, size_t out_len) { bssl::ScopedCBB quic_hkdf_label; CBB inner_label; const char label_prefix[] = "tls13 "; @@ -91,13 +90,23 @@ std::vector<uint8_t> HkdfExpandLabel(const EVP_MD* prf, } // namespace +const std::string getLabelForVersion(const ParsedQuicVersion& version, + const absl::string_view& predicate) { + static_assert(SupportedVersions().size() == 6u, + "Supported versions out of sync with HKDF labels"); + if (version == ParsedQuicVersion::V2Draft01()) { + return absl::StrCat("quicv2 ", predicate); + } else { + return absl::StrCat("quic ", predicate); + } +} + void CryptoUtils::InitializeCrypterSecrets( - const EVP_MD* prf, - const std::vector<uint8_t>& pp_secret, - QuicCrypter* crypter) { - SetKeyAndIV(prf, pp_secret, crypter); - std::vector<uint8_t> header_protection_key = - GenerateHeaderProtectionKey(prf, pp_secret, crypter->GetKeySize()); + const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, QuicCrypter* crypter) { + SetKeyAndIV(prf, pp_secret, version, crypter); + std::vector<uint8_t> header_protection_key = GenerateHeaderProtectionKey( + prf, pp_secret, version, crypter->GetKeySize()); crypter->SetHeaderProtectionKey( absl::string_view(reinterpret_cast<char*>(header_protection_key.data()), header_protection_key.size())); @@ -105,11 +114,13 @@ void CryptoUtils::InitializeCrypterSecrets( void CryptoUtils::SetKeyAndIV(const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, QuicCrypter* crypter) { std::vector<uint8_t> key = - HkdfExpandLabel(prf, pp_secret, "quic key", crypter->GetKeySize()); - std::vector<uint8_t> iv = - HkdfExpandLabel(prf, pp_secret, "quic iv", crypter->GetIVSize()); + HkdfExpandLabel(prf, pp_secret, getLabelForVersion(version, "key"), + crypter->GetKeySize()); + std::vector<uint8_t> iv = HkdfExpandLabel( + prf, pp_secret, getLabelForVersion(version, "iv"), crypter->GetIVSize()); crypter->SetKey( absl::string_view(reinterpret_cast<char*>(key.data()), key.size())); crypter->SetIV( @@ -117,16 +128,17 @@ void CryptoUtils::SetKeyAndIV(const EVP_MD* prf, } std::vector<uint8_t> CryptoUtils::GenerateHeaderProtectionKey( - const EVP_MD* prf, - const std::vector<uint8_t>& pp_secret, - size_t out_len) { - return HkdfExpandLabel(prf, pp_secret, "quic hp", out_len); + const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, size_t out_len) { + return HkdfExpandLabel(prf, pp_secret, getLabelForVersion(version, "hp"), + out_len); } std::vector<uint8_t> CryptoUtils::GenerateNextKeyPhaseSecret( - const EVP_MD* prf, + const EVP_MD* prf, const ParsedQuicVersion& version, const std::vector<uint8_t>& current_secret) { - return HkdfExpandLabel(prf, current_secret, "quic ku", current_secret.size()); + return HkdfExpandLabel(prf, current_secret, getLabelForVersion(version, "ku"), + current_secret.size()); } namespace { @@ -138,6 +150,9 @@ const uint8_t kDraft29InitialSalt[] = {0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, const uint8_t kRFCv1InitialSalt[] = {0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a}; +const uint8_t kV2Draft01InitialSalt[] = { + 0xa7, 0x07, 0xc2, 0x03, 0xa5, 0x9b, 0x47, 0x18, 0x4a, 0x1d, + 0x62, 0xca, 0x57, 0x04, 0x06, 0xea, 0x7a, 0xe3, 0xe5, 0xd3}; // Salts used by deployed versions of QUIC. When introducing a new version, // generate a new salt by running `openssl rand -hex 20`. @@ -154,9 +169,12 @@ const uint8_t kReservedForNegotiationSalt[] = { const uint8_t* InitialSaltForVersion(const ParsedQuicVersion& version, size_t* out_len) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync with initial encryption salts"); - if (version == ParsedQuicVersion::RFCv1()) { + if (version == ParsedQuicVersion::V2Draft01()) { + *out_len = ABSL_ARRAYSIZE(kV2Draft01InitialSalt); + return kV2Draft01InitialSalt; + } else if (version == ParsedQuicVersion::RFCv1()) { *out_len = ABSL_ARRAYSIZE(kRFCv1InitialSalt); return kRFCv1InitialSalt; } else if (version == ParsedQuicVersion::Draft29()) { @@ -191,6 +209,11 @@ const uint8_t kRFCv1RetryIntegrityKey[] = {0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0xe3, 0x68, 0xc8, 0x4e}; const uint8_t kRFCv1RetryIntegrityNonce[] = { 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb}; +const uint8_t kV2Draft01RetryIntegrityKey[] = { + 0xba, 0x85, 0x8d, 0xc7, 0xb4, 0x3d, 0xe5, 0xdb, + 0xf8, 0x76, 0x17, 0xff, 0x4a, 0xb2, 0x53, 0xdb}; +const uint8_t kV2Draft01RetryIntegrityNonce[] = { + 0x14, 0x1b, 0x99, 0xc2, 0x39, 0xb0, 0x3e, 0x78, 0x5d, 0x6a, 0x2e, 0x9f}; // Retry integrity key used by ParsedQuicVersion::ReservedForNegotiation(). const uint8_t kReservedForNegotiationRetryIntegrityKey[] = { 0xf2, 0xcd, 0x8f, 0xe0, 0x36, 0xd0, 0x25, 0x35, @@ -204,13 +227,21 @@ const uint8_t kReservedForNegotiationRetryIntegrityNonce[] = { bool RetryIntegrityKeysForVersion(const ParsedQuicVersion& version, absl::string_view* key, absl::string_view* nonce) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync with retry integrity keys"); if (!version.UsesTls()) { QUIC_BUG(quic_bug_10699_2) << "Attempted to get retry integrity keys for invalid version " << version; return false; + } else if (version == ParsedQuicVersion::V2Draft01()) { + *key = absl::string_view( + reinterpret_cast<const char*>(kV2Draft01RetryIntegrityKey), + ABSL_ARRAYSIZE(kV2Draft01RetryIntegrityKey)); + *nonce = absl::string_view( + reinterpret_cast<const char*>(kV2Draft01RetryIntegrityNonce), + ABSL_ARRAYSIZE(kV2Draft01RetryIntegrityNonce)); + return true; } else if (version == ParsedQuicVersion::RFCv1()) { *key = absl::string_view( reinterpret_cast<const char*>(kRFCv1RetryIntegrityKey), @@ -291,20 +322,20 @@ void CryptoUtils::CreateInitialObfuscators(Perspective perspective, std::vector<uint8_t> encryption_secret = HkdfExpandLabel( hash, handshake_secret, encryption_label, EVP_MD_size(hash)); crypters->encrypter = std::make_unique<Aes128GcmEncrypter>(); - InitializeCrypterSecrets(hash, encryption_secret, crypters->encrypter.get()); + InitializeCrypterSecrets(hash, encryption_secret, version, + crypters->encrypter.get()); std::vector<uint8_t> decryption_secret = HkdfExpandLabel( hash, handshake_secret, decryption_label, EVP_MD_size(hash)); crypters->decrypter = std::make_unique<Aes128GcmDecrypter>(); - InitializeCrypterSecrets(hash, decryption_secret, crypters->decrypter.get()); + InitializeCrypterSecrets(hash, decryption_secret, version, + crypters->decrypter.get()); } // static bool CryptoUtils::ValidateRetryIntegrityTag( - ParsedQuicVersion version, - QuicConnectionId original_connection_id, - absl::string_view retry_without_tag, - absl::string_view integrity_tag) { + ParsedQuicVersion version, QuicConnectionId original_connection_id, + absl::string_view retry_without_tag, absl::string_view integrity_tag) { unsigned char computed_integrity_tag[kRetryIntegrityTagLength]; if (integrity_tag.length() != ABSL_ARRAYSIZE(computed_integrity_tag)) { QUIC_BUG(quic_bug_10699_4) @@ -348,10 +379,8 @@ bool CryptoUtils::ValidateRetryIntegrityTag( } // static -void CryptoUtils::GenerateNonce(QuicWallTime now, - QuicRandom* random_generator, - absl::string_view orbit, - std::string* nonce) { +void CryptoUtils::GenerateNonce(QuicWallTime now, QuicRandom* random_generator, + absl::string_view orbit, std::string* nonce) { // a 4-byte timestamp + 28 random bytes. nonce->reserve(kNonceSize); nonce->resize(kNonceSize); @@ -375,17 +404,13 @@ void CryptoUtils::GenerateNonce(QuicWallTime now, } // static -bool CryptoUtils::DeriveKeys(const ParsedQuicVersion& version, - absl::string_view premaster_secret, - QuicTag aead, - absl::string_view client_nonce, - absl::string_view server_nonce, - absl::string_view pre_shared_key, - const std::string& hkdf_input, - Perspective perspective, - Diversification diversification, - CrypterPair* crypters, - std::string* subkey_secret) { +bool CryptoUtils::DeriveKeys( + const ParsedQuicVersion& version, absl::string_view premaster_secret, + QuicTag aead, absl::string_view client_nonce, + absl::string_view server_nonce, absl::string_view pre_shared_key, + const std::string& hkdf_input, Perspective perspective, + Diversification diversification, CrypterPair* crypters, + std::string* subkey_secret) { // If the connection is using PSK, concatenate it with the pre-master secret. std::unique_ptr<char[]> psk_premaster_secret; if (!pre_shared_key.empty()) { @@ -573,8 +598,7 @@ QuicErrorCode CryptoUtils::ValidateServerHelloVersions( } QuicErrorCode CryptoUtils::ValidateClientHello( - const CryptoHandshakeMessage& client_hello, - ParsedQuicVersion version, + const CryptoHandshakeMessage& client_hello, ParsedQuicVersion version, const ParsedQuicVersionVector& supported_versions, std::string* error_details) { if (client_hello.tag() != kCHLO) { @@ -597,8 +621,7 @@ QuicErrorCode CryptoUtils::ValidateClientHello( } QuicErrorCode CryptoUtils::ValidateClientHelloVersion( - QuicVersionLabel client_version, - ParsedQuicVersion connection_version, + QuicVersionLabel client_version, ParsedQuicVersion connection_version, const ParsedQuicVersionVector& supported_versions, std::string* error_details) { if (client_version != CreateQuicVersionLabel(connection_version)) { @@ -736,8 +759,7 @@ std::string CryptoUtils::EarlyDataReasonToString( // static std::string CryptoUtils::HashHandshakeMessage( - const CryptoHandshakeMessage& message, - Perspective /*perspective*/) { + const CryptoHandshakeMessage& message, Perspective /*perspective*/) { std::string output; const QuicData& serialized = message.GetSerialized(); uint8_t digest[SHA256_DIGEST_LENGTH]; diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h index 8884f6fa096..fce62018823 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h @@ -79,9 +79,11 @@ class QUIC_EXPORT_PRIVATE CryptoUtils { // on the given QuicCrypter |*crypter|. // This follows the derivation described in section 7.3 of RFC 8446, except // with the label prefix in HKDF-Expand-Label changed from "tls13 " to "quic " - // as described in draft-ietf-quic-tls-14, section 5.1. + // as described in draft-ietf-quic-tls-14, section 5.1, or "quicv2 " as + // described in draft-ietf-quic-v2-01. static void InitializeCrypterSecrets(const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, QuicCrypter* crypter); // Derives the key and IV from the packet protection secret and sets those @@ -90,17 +92,17 @@ class QUIC_EXPORT_PRIVATE CryptoUtils { // called before using |crypter|. static void SetKeyAndIV(const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, QuicCrypter* crypter); // Derives the header protection key from the packet protection secret. static std::vector<uint8_t> GenerateHeaderProtectionKey( - const EVP_MD* prf, - const std::vector<uint8_t>& pp_secret, - size_t out_len); + const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, size_t out_len); // Given a secret for key phase n, return the secret for phase n+1. static std::vector<uint8_t> GenerateNextKeyPhaseSecret( - const EVP_MD* prf, + const EVP_MD* prf, const ParsedQuicVersion& version, const std::vector<uint8_t>& current_secret); // IETF QUIC encrypts ENCRYPTION_INITIAL messages with a version-specific key @@ -130,10 +132,8 @@ class QUIC_EXPORT_PRIVATE CryptoUtils { // <4 bytes> current time // <8 bytes> |orbit| (or random if |orbit| is empty) // <20 bytes> random - static void GenerateNonce(QuicWallTime now, - QuicRandom* random_generator, - absl::string_view orbit, - std::string* nonce); + static void GenerateNonce(QuicWallTime now, QuicRandom* random_generator, + absl::string_view orbit, std::string* nonce); // DeriveKeys populates |crypters->encrypter|, |crypters->decrypter|, and // |subkey_secret| (optional -- may be null) given the contents of @@ -155,15 +155,12 @@ class QUIC_EXPORT_PRIVATE CryptoUtils { // |SetDiversificationNonce| with a diversification nonce will be needed to // complete keying. static bool DeriveKeys(const ParsedQuicVersion& version, - absl::string_view premaster_secret, - QuicTag aead, + absl::string_view premaster_secret, QuicTag aead, absl::string_view client_nonce, absl::string_view server_nonce, absl::string_view pre_shared_key, - const std::string& hkdf_input, - Perspective perspective, - Diversification diversification, - CrypterPair* crypters, + const std::string& hkdf_input, Perspective perspective, + Diversification diversification, CrypterPair* crypters, std::string* subkey_secret); // Computes the FNV-1a hash of the provided DER-encoded cert for use in the @@ -199,8 +196,7 @@ class QUIC_EXPORT_PRIVATE CryptoUtils { // Returns QUIC_NO_ERROR if this is the case or returns the appropriate error // code and sets |error_details|. static QuicErrorCode ValidateClientHello( - const CryptoHandshakeMessage& client_hello, - ParsedQuicVersion version, + const CryptoHandshakeMessage& client_hello, ParsedQuicVersion version, const ParsedQuicVersionVector& supported_versions, std::string* error_details); @@ -212,8 +208,7 @@ class QUIC_EXPORT_PRIVATE CryptoUtils { // Returns QUIC_NO_ERROR if this is the case or returns the appropriate error // code and sets |error_details|. static QuicErrorCode ValidateClientHelloVersion( - QuicVersionLabel client_version, - ParsedQuicVersion connection_version, + QuicVersionLabel client_version, ParsedQuicVersion connection_version, const ParsedQuicVersionVector& supported_versions, std::string* error_details); diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils_test.cc index 251f136ec5d..f0d944b4fea 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils_test.cc @@ -8,6 +8,7 @@ #include "absl/base/macros.h" #include "absl/strings/escaping.h" +#include "absl/strings/string_view.h" #include "quic/core/quic_utils.h" #include "quic/platform/api/quic_test.h" #include "quic/test_tools/quic_test_utils.h" @@ -165,6 +166,97 @@ TEST_F(CryptoUtilsTest, ValidateServerVersionsWithDowngrade) { EXPECT_FALSE(error_details.empty()); } +// Test that the library is using the correct labels for each version, and +// therefore generating correct obfuscators, using the test vectors in appendix +// A of each RFC or internet-draft. +TEST_F(CryptoUtilsTest, ValidateCryptoLabels) { + // if the number of HTTP/3 QUIC versions has changed, we need to change the + // expected_keys hardcoded into this test. Regrettably, this is not a + // compile-time constant. + EXPECT_EQ(AllSupportedVersionsWithTls().size(), 3u); + const char draft_29_key[] = {// test vector from draft-ietf-quic-tls-29, A.1 + 0x14, + static_cast<char>(0x9d), + 0x0b, + 0x16, + 0x62, + static_cast<char>(0xab), + static_cast<char>(0x87), + 0x1f, + static_cast<char>(0xbe), + 0x63, + static_cast<char>(0xc4), + static_cast<char>(0x9b), + 0x5e, + 0x65, + 0x5a, + 0x5d}; + const char v1_key[] = {// test vector from RFC 9001, A.1 + static_cast<char>(0xcf), + 0x3a, + 0x53, + 0x31, + 0x65, + 0x3c, + 0x36, + 0x4c, + static_cast<char>(0x88), + static_cast<char>(0xf0), + static_cast<char>(0xf3), + 0x79, + static_cast<char>(0xb6), + 0x06, + 0x7e, + 0x37}; + const char v2_01_key[] = {// test vector from draft-ietf-quic-v2-01 + 0x15, + static_cast<char>(0xd5), + static_cast<char>(0xb4), + static_cast<char>(0xd9), + static_cast<char>(0xa2), + static_cast<char>(0xb8), + static_cast<char>(0x91), + 0x6a, + static_cast<char>(0xa3), + static_cast<char>(0x9b), + 0x1b, + static_cast<char>(0xfe), + 0x57, + 0x4d, + 0x2a, + static_cast<char>(0xad)}; + const char connection_id[] = // test vector from both docs + {static_cast<char>(0x83), + static_cast<char>(0x94), + static_cast<char>(0xc8), + static_cast<char>(0xf0), + 0x3e, + 0x51, + 0x57, + 0x08}; + const QuicConnectionId cid(connection_id, sizeof(connection_id)); + const char* key_str; + size_t key_size; + for (const ParsedQuicVersion& version : AllSupportedVersionsWithTls()) { + if (version == ParsedQuicVersion::Draft29()) { + key_str = draft_29_key; + key_size = sizeof(draft_29_key); + } else if (version == ParsedQuicVersion::RFCv1()) { + key_str = v1_key; + key_size = sizeof(v1_key); + } else { // draft-ietf-quic-v2-01 + key_str = v2_01_key; + key_size = sizeof(v2_01_key); + } + const absl::string_view expected_key{key_str, key_size}; + + CrypterPair crypters; + CryptoUtils::CreateInitialObfuscators(Perspective::IS_SERVER, version, cid, + &crypters); + EXPECT_EQ(crypters.encrypter->GetKey(), expected_key); + } +} + } // namespace } // namespace test } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc index e4989bc302a..1b1790adc75 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc @@ -834,9 +834,8 @@ void QuicCryptoClientConfig::AddCanonicalSuffix(const std::string& suffix) { } bool QuicCryptoClientConfig::PopulateFromCanonicalConfig( - const QuicServerId& server_id, - CachedState* server_state) { - QUICHE_DCHECK(server_state->IsEmpty()); + const QuicServerId& server_id, CachedState* cached) { + QUICHE_DCHECK(cached->IsEmpty()); size_t i = 0; for (; i < canonical_suffixes_.size(); ++i) { if (absl::EndsWithIgnoreCase(server_id.host(), canonical_suffixes_[i])) { @@ -867,7 +866,7 @@ bool QuicCryptoClientConfig::PopulateFromCanonicalConfig( // Update canonical version to point at the "most recent" entry. it->second = server_id; - server_state->InitializeFrom(*canonical_state); + cached->InitializeFrom(*canonical_state); return true; } diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h index 13517299087..9c71acafa08 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h @@ -332,16 +332,14 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig { QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params, std::string* error_details); - // Processes the message in |server_update|, updating the cached source + // Processes the message in |server_config_update|, updating the cached source // address token, and server config. - // If |server_update| is invalid then |error_details| will contain an error - // message, and an error code will be returned. If all has gone well + // If |server_config_update| is invalid then |error_details| will contain an + // error message, and an error code will be returned. If all has gone well // QUIC_NO_ERROR is returned. QuicErrorCode ProcessServerConfigUpdate( - const CryptoHandshakeMessage& server_update, - QuicWallTime now, - const QuicTransportVersion version, - absl::string_view chlo_hash, + const CryptoHandshakeMessage& server_config_update, QuicWallTime now, + const QuicTransportVersion version, absl::string_view chlo_hash, CachedState* cached, QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params, std::string* error_details); diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc index 16a53fa920c..71c177552a0 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc @@ -512,15 +512,17 @@ bool QuicCryptoServerConfig::SetConfigs( void QuicCryptoServerConfig::SetSourceAddressTokenKeys( const std::vector<std::string>& keys) { + // TODO(b/208866709) source_address_token_boxer_.SetKeys(keys); } -void QuicCryptoServerConfig::GetConfigIds( - std::vector<std::string>* scids) const { +std::vector<std::string> QuicCryptoServerConfig::GetConfigIds() const { QuicReaderMutexLock locked(&configs_lock_); + std::vector<std::string> scids; for (auto it = configs_.begin(); it != configs_.end(); ++it) { - scids->push_back(it->first); + scids.push_back(it->first); } + return scids; } void QuicCryptoServerConfig::ValidateClientHello( @@ -538,6 +540,10 @@ void QuicCryptoServerConfig::ValidateClientHello( client_hello, client_address.host(), now)); absl::string_view requested_scid; + // We ignore here the return value from GetStringPiece. If there is no SCID + // tag, EvaluateClientHello will discover that because GetCurrentConfigs will + // not have found the requested config (i.e. because none of the configs will + // have an empty string as its id). client_hello.GetStringPiece(kSCID, &requested_scid); Configs configs; if (!GetCurrentConfigs(now, requested_scid, @@ -1575,9 +1581,14 @@ QuicCryptoServerConfig::ParseConfigProtobuf( std::unique_ptr<CryptoHandshakeMessage> msg = CryptoFramer::ParseMessage(protobuf.config()); + if (!msg) { + QUIC_LOG(WARNING) << "Failed to parse server config message"; + return nullptr; + } + if (msg->tag() != kSCFG) { QUIC_LOG(WARNING) << "Server config message has tag " << msg->tag() - << " expected " << kSCFG; + << ", but expected " << kSCFG; return nullptr; } @@ -1597,6 +1608,7 @@ QuicCryptoServerConfig::ParseConfigProtobuf( QUIC_LOG(WARNING) << "Server config message is missing SCID"; return nullptr; } + QUICHE_DCHECK(!scid.empty()); config->id = std::string(scid); if (msg->GetTaglist(kAEAD, &config->aead) != QUIC_NO_ERROR) { diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h index ca6dbe5e32f..799058d70ff 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h @@ -200,7 +200,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { // p256 determines whether a P-256 public key will be included in the // server config. Note that this breaks deterministic server-config // generation since P-256 key generation doesn't use the QuicRandom given - // to DefaultConfig(). + // to GenerateConfig(). bool p256; }; @@ -238,8 +238,8 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { const QuicServerConfigProtobuf& protobuf, QuicWallTime now); - // AddDefaultConfig calls DefaultConfig to create a config and then calls - // AddConfig to add it. See the comment for |DefaultConfig| for details of + // AddDefaultConfig calls GenerateConfig to create a config and then calls + // AddConfig to add it. See the comment for |GenerateConfig| for details of // the arguments. std::unique_ptr<CryptoHandshakeMessage> AddDefaultConfig( QuicRandom* rand, @@ -264,7 +264,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { void SetSourceAddressTokenKeys(const std::vector<std::string>& keys); // Get the server config ids for all known configs. - void GetConfigIds(std::vector<std::string>* scids) const; + std::vector<std::string> GetConfigIds() const; // Checks |client_hello| for gross errors and determines whether it can be // shown to be fresh (i.e. not a replay). The result of the validation step @@ -282,9 +282,9 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { // port may be used for certificate selection. // version: protocol version used for this connection. // clock: used to validate client nonces and ephemeral keys. - // crypto_proof: in/out parameter to which will be written the crypto proof - // used in reply to a proof demand. The pointed-to-object must - // live until the callback is invoked. + // signed_config: in/out parameter to which will be written the crypto proof + // used in reply to a proof demand. The pointed-to-object must live until + // the callback is invoked. // done_cb: single-use callback that accepts an opaque // ValidatedClientHelloMsg token that holds information about // the client hello. The callback will always be called exactly @@ -293,10 +293,9 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { void ValidateClientHello( const CryptoHandshakeMessage& client_hello, const QuicSocketAddress& client_address, - const QuicSocketAddress& server_address, - QuicTransportVersion version, + const QuicSocketAddress& server_address, QuicTransportVersion version, const QuicClock* clock, - QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof, + QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config, std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const; // ProcessClientHello processes |client_hello| and decides whether to accept @@ -323,27 +322,22 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { // certs. Owned by QuicDispatcher. // params: the state of the handshake. This may be updated with a server // nonce when we send a rejection. - // crypto_proof: output structure containing the crypto proof used in reply to - // a proof demand. + // signed_config: output structure containing the crypto proof used in reply + // to a proof demand. // total_framing_overhead: the total per-packet overhead for a stream frame // chlo_packet_size: the size, in bytes, of the CHLO packet // done_cb: the callback invoked on completion void ProcessClientHello( QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> validate_chlo_result, - bool reject_only, - QuicConnectionId connection_id, + bool reject_only, QuicConnectionId connection_id, const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address, - ParsedQuicVersion version, - const ParsedQuicVersionVector& supported_versions, - const QuicClock* clock, - QuicRandom* rand, - QuicCompressedCertsCache* compressed_certs_cache, + const QuicSocketAddress& client_address, ParsedQuicVersion version, + const ParsedQuicVersionVector& supported_versions, const QuicClock* clock, + QuicRandom* rand, QuicCompressedCertsCache* compressed_certs_cache, QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params, - QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof, - QuicByteCount total_framing_overhead, - QuicByteCount chlo_packet_size, + QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config, + QuicByteCount total_framing_overhead, QuicByteCount chlo_packet_size, std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const; // BuildServerConfigUpdateMessage invokes |cb| with a SCUP message containing diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc index fa9be976f69..901ae66e3c1 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc @@ -106,8 +106,8 @@ TlsConnection::TlsConnection(SSL_CTX* ssl_ctx, ssl(), ssl_config_.signing_algorithm_prefs->data(), ssl_config_.signing_algorithm_prefs->size()); } - if (ssl_config.disable_ticket_support.has_value()) { - if (*ssl_config.disable_ticket_support) { + if (ssl_config_.disable_ticket_support.has_value()) { + if (*ssl_config_.disable_ticket_support) { SSL_set_options(ssl(), SSL_OP_NO_TICKET); } } diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc index 61e8f7c8720..0d828db2d2b 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc @@ -54,9 +54,9 @@ enum TransportParameters::TransportParameterId : uint64_t { kInitialRoundTripTime = 0x3127, kGoogleConnectionOptions = 0x3128, - kGoogleUserAgentId = 0x3129, + // 0x3129 was used to convey the user agent string. // 0x312A was used only in T050 to indicate support for HANDSHAKE_DONE. - kGoogleKeyUpdateNotYetSupported = 0x312B, + // 0x312B was used to indicate that QUIC+TLS key updates were not supported. // 0x4751 was used for non-standard Google-specific parameters encoded as a // Google QUIC_CRYPTO CHLO, it has been replaced by individual parameters. kGoogleQuicVersion = @@ -122,10 +122,6 @@ std::string TransportParameterIdToString( return "initial_round_trip_time"; case TransportParameters::kGoogleConnectionOptions: return "google_connection_options"; - case TransportParameters::kGoogleUserAgentId: - return "user_agent_id"; - case TransportParameters::kGoogleKeyUpdateNotYetSupported: - return "key_update_not_yet_supported"; case TransportParameters::kGoogleQuicVersion: return "google-version"; case TransportParameters::kMinAckDelay: @@ -164,10 +160,6 @@ bool TransportParameterIdIsKnown( return true; case TransportParameters::kVersionInformation: return GetQuicReloadableFlag(quic_version_information); - case TransportParameters::kGoogleUserAgentId: - return !GetQuicReloadableFlag(quic_ignore_user_agent_transport_parameter); - case TransportParameters::kGoogleKeyUpdateNotYetSupported: - return !GetQuicReloadableFlag(quic_ignore_key_update_not_yet_supported); } return false; } @@ -447,13 +439,6 @@ std::string TransportParameters::ToString() const { rv += QuicTagToString(connection_option); } } - if (user_agent_id.has_value()) { - rv += " " + TransportParameterIdToString(kGoogleUserAgentId) + " \"" + - user_agent_id.value() + "\""; - } - if (key_update_not_yet_supported) { - rv += " " + TransportParameterIdToString(kGoogleKeyUpdateNotYetSupported); - } for (const auto& kv : custom_parameters) { absl::StrAppend(&rv, " 0x", absl::Hex(static_cast<uint32_t>(kv.first)), "="); @@ -493,8 +478,7 @@ TransportParameters::TransportParameters() kMinActiveConnectionIdLimitTransportParam, kVarInt62MaxValue), max_datagram_frame_size(kMaxDatagramFrameSize), - initial_round_trip_time_us(kInitialRoundTripTime), - key_update_not_yet_supported(false) + initial_round_trip_time_us(kInitialRoundTripTime) // Important note: any new transport parameters must be added // to TransportParameters::AreValid, SerializeTransportParameters and // ParseTransportParameters, TransportParameters's custom copy constructor, the @@ -528,8 +512,6 @@ TransportParameters::TransportParameters(const TransportParameters& other) max_datagram_frame_size(other.max_datagram_frame_size), initial_round_trip_time_us(other.initial_round_trip_time_us), google_connection_options(other.google_connection_options), - user_agent_id(other.user_agent_id), - key_update_not_yet_supported(other.key_update_not_yet_supported), custom_parameters(other.custom_parameters) { if (other.preferred_address) { preferred_address = std::make_unique<TransportParameters::PreferredAddress>( @@ -570,8 +552,6 @@ bool TransportParameters::operator==(const TransportParameters& rhs) const { initial_round_trip_time_us.value() == rhs.initial_round_trip_time_us.value() && google_connection_options == rhs.google_connection_options && - user_agent_id == rhs.user_agent_id && - key_update_not_yet_supported == rhs.key_update_not_yet_supported && custom_parameters == rhs.custom_parameters)) { return false; } @@ -646,10 +626,6 @@ bool TransportParameters::AreValid(std::string* error_details) const { *error_details = "Server cannot send initial round trip time"; return false; } - if (perspective == Perspective::IS_SERVER && user_agent_id.has_value()) { - *error_details = "Server cannot send user agent ID"; - return false; - } if (version_information.has_value()) { const QuicVersionLabel& chosen_version = version_information.value().chosen_version; @@ -758,8 +734,6 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/, kIntegerParameterLength + // max_datagram_frame_size kIntegerParameterLength + // initial_round_trip_time_us kTypeAndValueLength + // google_connection_options - kTypeAndValueLength + // user_agent_id - kTypeAndValueLength + // key_update_not_yet_supported kTypeAndValueLength; // google-version std::vector<TransportParameters::TransportParameterId> parameter_ids = { @@ -784,8 +758,6 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/, TransportParameters::kInitialSourceConnectionId, TransportParameters::kRetrySourceConnectionId, TransportParameters::kGoogleConnectionOptions, - TransportParameters::kGoogleUserAgentId, - TransportParameters::kGoogleKeyUpdateNotYetSupported, TransportParameters::kGoogleQuicVersion, TransportParameters::kVersionInformation, }; @@ -796,10 +768,6 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/, max_transport_param_length += in.google_connection_options.value().size() * sizeof(QuicTag); } - // user_agent_id. - if (in.user_agent_id.has_value()) { - max_transport_param_length += in.user_agent_id.value().length(); - } // Google-specific version extension. if (in.legacy_version_information.has_value()) { max_transport_param_length += @@ -1124,30 +1092,6 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/, } } } break; - // Google-specific user agent identifier. - case TransportParameters::kGoogleUserAgentId: { - if (in.user_agent_id.has_value()) { - if (!writer.WriteVarInt62(TransportParameters::kGoogleUserAgentId) || - !writer.WriteStringPieceVarInt62(in.user_agent_id.value())) { - QUIC_BUG(Failed to write Google user agent ID) - << "Failed to write Google user agent ID \"" - << in.user_agent_id.value() << "\" for " << in; - return false; - } - } - } break; - // Google-specific indicator for key update not yet supported. - case TransportParameters::kGoogleKeyUpdateNotYetSupported: { - if (in.key_update_not_yet_supported) { - if (!writer.WriteVarInt62( - TransportParameters::kGoogleKeyUpdateNotYetSupported) || - !writer.WriteVarInt62(/* transport parameter length */ 0)) { - QUIC_BUG(Failed to write key_update_not_yet_supported) - << "Failed to write key_update_not_yet_supported for " << in; - return false; - } - } - } break; // Google-specific version extension. case TransportParameters::kGoogleQuicVersion: { if (!in.legacy_version_information.has_value()) { @@ -1470,54 +1414,6 @@ bool ParseTransportParameters(ParsedQuicVersion version, out->google_connection_options.value().push_back(connection_option); } } break; - case TransportParameters::kGoogleUserAgentId: - if (GetQuicReloadableFlag(quic_ignore_user_agent_transport_parameter)) { - QUIC_RELOADABLE_FLAG_COUNT( - quic_ignore_user_agent_transport_parameter); - // This is a copy of the default switch statement below. - // TODO(dschinazi) remove this case entirely when deprecating the - // quic_ignore_user_agent_transport_parameter flag. - if (out->custom_parameters.find(param_id) != - out->custom_parameters.end()) { - *error_details = "Received a second unknown parameter" + - TransportParameterIdToString(param_id); - return false; - } - out->custom_parameters[param_id] = - std::string(value_reader.ReadRemainingPayload()); - break; - } - if (out->user_agent_id.has_value()) { - *error_details = "Received a second user_agent_id"; - return false; - } - out->user_agent_id = std::string(value_reader.ReadRemainingPayload()); - break; - case TransportParameters::kGoogleKeyUpdateNotYetSupported: - if (GetQuicReloadableFlag(quic_ignore_key_update_not_yet_supported)) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_ignore_key_update_not_yet_supported, - 1, 2); - QUIC_CODE_COUNT(quic_ignore_key_update_not_yet_supported_ignored); - // This is a copy of the default switch statement below. - // TODO(dschinazi) remove this case entirely when deprecating the - // quic_ignore_key_update_not_yet_supported flag. - if (out->custom_parameters.find(param_id) != - out->custom_parameters.end()) { - *error_details = "Received a second unknown parameter" + - TransportParameterIdToString(param_id); - return false; - } - out->custom_parameters[param_id] = - std::string(value_reader.ReadRemainingPayload()); - break; - } - QUIC_CODE_COUNT(quic_ignore_key_update_not_yet_supported_received); - if (out->key_update_not_yet_supported) { - *error_details = "Received a second key_update_not_yet_supported"; - return false; - } - out->key_update_not_yet_supported = true; - break; case TransportParameters::kGoogleQuicVersion: { if (!out->legacy_version_information.has_value()) { out->legacy_version_information = diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h index fa349359571..1b6f51684fa 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h @@ -260,13 +260,6 @@ struct QUIC_EXPORT_PRIVATE TransportParameters { // Google-specific connection options. absl::optional<QuicTagVector> google_connection_options; - // Google-specific user agent identifier. - absl::optional<std::string> user_agent_id; - - // Google-specific mechanism to indicate that IETF QUIC Key Update has not - // yet been implemented. This will be removed once we implement it. - bool key_update_not_yet_supported; - // Validates whether transport parameters are valid according to // the specification. If the transport parameters are not valid, this method // will write a human-readable error message to |error_details|. diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc index d9b55730454..c9df18a3d8a 100644 --- a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc @@ -37,7 +37,6 @@ const uint64_t kFakeInitialRoundTripTime = 53; const uint8_t kFakePreferredStatelessResetTokenData[16] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F}; -const bool kFakeKeyUpdateNotYetSupported = true; const auto kCustomParameter1 = static_cast<TransportParameters::TransportParameterId>(0xffcd); @@ -128,10 +127,6 @@ QuicTagVector CreateFakeGoogleConnectionOptions() { MakeQuicTag('H', 'I', 'J', 0xff)}; } -std::string CreateFakeUserAgentId() { - return "FakeUAID"; -} - void RemoveGreaseParameters(TransportParameters* params) { std::vector<TransportParameters::TransportParameterId> grease_params; for (const auto& kv : params->custom_parameters) { @@ -291,8 +286,6 @@ TEST_P(TransportParametersTest, CopyConstructor) { orig_params.retry_source_connection_id = CreateFakeRetrySourceConnectionId(); orig_params.initial_round_trip_time_us.set_value(kFakeInitialRoundTripTime); orig_params.google_connection_options = CreateFakeGoogleConnectionOptions(); - orig_params.user_agent_id = CreateFakeUserAgentId(); - orig_params.key_update_not_yet_supported = kFakeKeyUpdateNotYetSupported; orig_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value; orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value; @@ -329,12 +322,6 @@ TEST_P(TransportParametersTest, RoundTripClient) { CreateFakeInitialSourceConnectionId(); orig_params.initial_round_trip_time_us.set_value(kFakeInitialRoundTripTime); orig_params.google_connection_options = CreateFakeGoogleConnectionOptions(); - if (!GetQuicReloadableFlag(quic_ignore_user_agent_transport_parameter)) { - orig_params.user_agent_id = CreateFakeUserAgentId(); - } - if (!GetQuicReloadableFlag(quic_ignore_key_update_not_yet_supported)) { - orig_params.key_update_not_yet_supported = kFakeKeyUpdateNotYetSupported; - } orig_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value; orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value; @@ -578,13 +565,6 @@ TEST_P(TransportParametersTest, ParseClientParams) { 'A', 'L', 'P', 'N', // value 'E', 'F', 'G', 0x00, 'H', 'I', 'J', 0xff, - // user_agent_id - 0x71, 0x29, // parameter id - 0x08, // length - 'F', 'a', 'k', 'e', 'U', 'A', 'I', 'D', // value - // key_update_not_yet_supported - 0x71, 0x2B, // parameter id - 0x00, // length // Google version extension 0x80, 0x00, 0x47, 0x52, // parameter id 0x04, // length @@ -649,15 +629,6 @@ TEST_P(TransportParametersTest, ParseClientParams) { ASSERT_TRUE(new_params.google_connection_options.has_value()); EXPECT_EQ(CreateFakeGoogleConnectionOptions(), new_params.google_connection_options.value()); - if (!GetQuicReloadableFlag(quic_ignore_user_agent_transport_parameter)) { - ASSERT_TRUE(new_params.user_agent_id.has_value()); - EXPECT_EQ(CreateFakeUserAgentId(), new_params.user_agent_id.value()); - } else { - EXPECT_FALSE(new_params.user_agent_id.has_value()); - } - if (!GetQuicReloadableFlag(quic_ignore_key_update_not_yet_supported)) { - EXPECT_TRUE(new_params.key_update_not_yet_supported); - } } TEST_P(TransportParametersTest, @@ -844,9 +815,6 @@ TEST_P(TransportParametersTest, ParseServerParams) { 'A', 'L', 'P', 'N', // value 'E', 'F', 'G', 0x00, 'H', 'I', 'J', 0xff, - // key_update_not_yet_supported - 0x71, 0x2B, // parameter id - 0x00, // length // Google version extension 0x80, 0x00, 0x47, 0x52, // parameter id 0x0d, // length @@ -933,10 +901,6 @@ TEST_P(TransportParametersTest, ParseServerParams) { ASSERT_TRUE(new_params.google_connection_options.has_value()); EXPECT_EQ(CreateFakeGoogleConnectionOptions(), new_params.google_connection_options.value()); - EXPECT_FALSE(new_params.user_agent_id.has_value()); - if (!GetQuicReloadableFlag(quic_ignore_key_update_not_yet_supported)) { - EXPECT_TRUE(new_params.key_update_not_yet_supported); - } } TEST_P(TransportParametersTest, ParseServerParametersRepeated) { @@ -1054,8 +1018,6 @@ TEST_P(TransportParametersTest, SerializationOrderIsRandom) { CreateFakeInitialSourceConnectionId(); orig_params.initial_round_trip_time_us.set_value(kFakeInitialRoundTripTime); orig_params.google_connection_options = CreateFakeGoogleConnectionOptions(); - orig_params.user_agent_id = CreateFakeUserAgentId(); - orig_params.key_update_not_yet_supported = kFakeKeyUpdateNotYetSupported; orig_params.custom_parameters[kCustomParameter1] = kCustomParameter1Value; orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value; diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h index 8a5c7e6e12e..c9c46d41d3c 100644 --- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h +++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h @@ -111,6 +111,8 @@ struct QUIC_EXPORT_PRIVATE QuicAckFrame { QuicTime::Delta ack_delay_time = QuicTime::Delta::Infinite(); // Vector of <packet_number, time> for when packets arrived. + // For IETF versions, packet numbers and timestamps in this vector are both in + // ascending orders. Packets received out of order are not saved here. PacketTimeVector received_packet_times; // Set of packets. diff --git a/chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h b/chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h index 1e47d16a5f1..7fbc5ae33db 100644 --- a/chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h +++ b/chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h @@ -7,6 +7,7 @@ #include "quic/core/crypto/transport_parameters.h" #include "quic/core/quic_types.h" +#include "quic/core/quic_versions.h" namespace quic { @@ -21,15 +22,12 @@ class QUIC_EXPORT_PRIVATE HandshakerDelegateInterface { // Called when new decryption key of |level| is available. Returns true if // decrypter is set successfully, otherwise, returns false. virtual bool OnNewDecryptionKeyAvailable( - EncryptionLevel level, - std::unique_ptr<QuicDecrypter> decrypter, - bool set_alternative_decrypter, - bool latch_once_used) = 0; + EncryptionLevel level, std::unique_ptr<QuicDecrypter> decrypter, + bool set_alternative_decrypter, bool latch_once_used) = 0; // Called when new encryption key of |level| is available. virtual void OnNewEncryptionKeyAvailable( - EncryptionLevel level, - std::unique_ptr<QuicEncrypter> encrypter) = 0; + EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter) = 0; // Called to set default encryption level to |level|. Only used in QUIC // crypto. @@ -68,8 +66,7 @@ class QUIC_EXPORT_PRIVATE HandshakerDelegateInterface { // On failure, returns a QuicErrorCode and saves a detailed error in // |error_details|. virtual QuicErrorCode ProcessTransportParameters( - const TransportParameters& params, - bool is_resumption, + const TransportParameters& params, bool is_resumption, std::string* error_details) = 0; // Called at the end of an handshake operation callback. @@ -77,6 +74,10 @@ class QUIC_EXPORT_PRIVATE HandshakerDelegateInterface { // Whether a packet flusher is currently attached. virtual bool PacketFlusherAttached() const = 0; + + // Get the QUIC version currently in use. tls_handshaker needs this to pass + // to crypto_utils to apply version-dependent HKDF labels. + virtual ParsedQuicVersion parsed_version() const = 0; }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc index 29e6377280b..cad9cacb022 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc @@ -485,8 +485,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { } } - void AddToCache(absl::string_view path, - int response_code, + void AddToCache(absl::string_view path, int response_code, absl::string_view body) { memory_cache_backend_.AddSimpleResponse(server_hostname_, path, response_code, body); @@ -553,12 +552,6 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { EXPECT_EQ(0u, server_stats.packets_lost); } EXPECT_EQ(0u, server_stats.packets_discarded); - if (!GetQuicReloadableFlag( - quic_ignore_user_agent_transport_parameter)) { - EXPECT_EQ( - server_session->user_agent_id().value_or("MissingUserAgent"), - kTestUserAgentId); - } } else { ADD_FAILURE() << "Missing server connection"; } @@ -657,16 +650,14 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { } bool SendSynchronousRequestAndCheckResponse( - QuicTestClient* client, - const std::string& request, + QuicTestClient* client, const std::string& request, const std::string& expected_response) { std::string received_response = client->SendSynchronousRequest(request); return CheckResponse(client, received_response, expected_response); } bool SendSynchronousRequestAndCheckResponse( - const std::string& request, - const std::string& expected_response) { + const std::string& request, const std::string& expected_response) { return SendSynchronousRequestAndCheckResponse(client_.get(), request, expected_response); } @@ -844,8 +835,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { }; // Run all end to end tests with all supported versions. -INSTANTIATE_TEST_SUITE_P(EndToEndTests, - EndToEndTest, +INSTANTIATE_TEST_SUITE_P(EndToEndTests, EndToEndTest, ::testing::ValuesIn(GetTestParams()), ::testing::PrintToStringParamName()); @@ -3210,8 +3200,7 @@ TEST_P(EndToEndTest, ConnectionMigrationNewTokenForNewIp) { class DuplicatePacketWithSpoofedSelfAddressWriter : public QuicPacketWriterWrapper { public: - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, PerPacketOptions* options) override { @@ -3246,7 +3235,8 @@ TEST_P(EndToEndTest, ClientAddressSpoofedForSomePeriod) { ASSERT_TRUE(QuicConnectionPeer::HasUnusedPeerIssuedConnectionId( GetClientConnection())); - QuicIpAddress real_host = TestLoopback(1); + QuicIpAddress real_host = + client_->client()->session()->connection()->self_address().host(); ASSERT_TRUE(client_->MigrateSocket(real_host)); SendSynchronousFooRequestAndCheckResponse(); EXPECT_EQ( @@ -4384,13 +4374,10 @@ TEST_P(EndToEndTest, CanceledStreamDoesNotBecomeZombie) { class ServerStreamWithErrorResponseBody : public QuicSimpleServerStream { public: ServerStreamWithErrorResponseBody( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend, std::string response_body) - : QuicSimpleServerStream(id, - session, - BIDIRECTIONAL, + : QuicSimpleServerStream(id, session, BIDIRECTIONAL, quic_simple_server_backend), response_body_(std::move(response_body)) {} @@ -4419,8 +4406,7 @@ class StreamWithErrorFactory : public QuicTestServer::StreamFactory { ~StreamWithErrorFactory() override = default; QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) override { return new ServerStreamWithErrorResponseBody( id, session, quic_simple_server_backend, response_body_); @@ -4433,12 +4419,9 @@ class StreamWithErrorFactory : public QuicTestServer::StreamFactory { // A test server stream that drops all received body. class ServerStreamThatDropsBody : public QuicSimpleServerStream { public: - ServerStreamThatDropsBody(QuicStreamId id, - QuicSpdySession* session, + ServerStreamThatDropsBody(QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) - : QuicSimpleServerStream(id, - session, - BIDIRECTIONAL, + : QuicSimpleServerStream(id, session, BIDIRECTIONAL, quic_simple_server_backend) {} ~ServerStreamThatDropsBody() override = default; @@ -4480,8 +4463,7 @@ class ServerStreamThatDropsBodyFactory : public QuicTestServer::StreamFactory { ~ServerStreamThatDropsBodyFactory() override = default; QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) override { return new ServerStreamThatDropsBody(id, session, quic_simple_server_backend); @@ -4492,13 +4474,9 @@ class ServerStreamThatDropsBodyFactory : public QuicTestServer::StreamFactory { class ServerStreamThatSendsHugeResponse : public QuicSimpleServerStream { public: ServerStreamThatSendsHugeResponse( - QuicStreamId id, - QuicSpdySession* session, - QuicSimpleServerBackend* quic_simple_server_backend, - int64_t body_bytes) - : QuicSimpleServerStream(id, - session, - BIDIRECTIONAL, + QuicStreamId id, QuicSpdySession* session, + QuicSimpleServerBackend* quic_simple_server_backend, int64_t body_bytes) + : QuicSimpleServerStream(id, session, BIDIRECTIONAL, quic_simple_server_backend), body_bytes_(body_bytes) {} @@ -4528,8 +4506,7 @@ class ServerStreamThatSendsHugeResponseFactory ~ServerStreamThatSendsHugeResponseFactory() override = default; QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) override { return new ServerStreamThatSendsHugeResponse( id, session, quic_simple_server_backend, body_bytes_); @@ -5254,8 +5231,7 @@ TEST_P(EndToEndPacketReorderingTest, ReorderedConnectivityProbing) { // called. class PacketHoldingWriter : public QuicPacketWriterWrapper { public: - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, PerPacketOptions* options) override { @@ -5533,11 +5509,13 @@ TEST_P(EndToEndPacketReorderingTest, MigrateAgainAfterPathValidationFailure) { } TEST_P(EndToEndPacketReorderingTest, - MigrateAgainAfterPathValidationFailureWithNonZeroClientConnectionId) { + MigrateAgainAfterPathValidationFailureWithNonZeroClientCid) { if (!version_.SupportsClientConnectionIds()) { ASSERT_TRUE(Initialize()); return; } + SetQuicReloadableFlag(quic_retire_cid_on_reverse_path_validation_failure, + true); override_client_connection_id_length_ = kQuicDefaultConnectionIdLength; ASSERT_TRUE(Initialize()); if (!GetClientConnection()->connection_migration_use_new_cid()) { @@ -5707,8 +5685,7 @@ class BadShloPacketWriter : public QuicPacketWriterWrapper { : error_returned_(false), version_(version) {} ~BadShloPacketWriter() override {} - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, quic::PerPacketOptions* options) override { @@ -5725,6 +5702,9 @@ class BadShloPacketWriter : public QuicPacketWriterWrapper { } bool TypeByteIsServerHello(uint8_t type_byte) { + if (version_.UsesV2PacketTypes()) { + return ((type_byte & 0x30) >> 4) == 3; + } if (version_.UsesQuicCrypto()) { // ENCRYPTION_ZERO_RTT packet. return ((type_byte & 0x30) >> 4) == 1; @@ -5781,21 +5761,23 @@ TEST_P(EndToEndTest, ConnectionCloseBeforeHandshakeComplete) { class BadShloPacketWriter2 : public QuicPacketWriterWrapper { public: - BadShloPacketWriter2() : error_returned_(false) {} + BadShloPacketWriter2(ParsedQuicVersion version) + : error_returned_(false), version_(version) {} ~BadShloPacketWriter2() override {} - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, quic::PerPacketOptions* options) override { const uint8_t type_byte = buffer[0]; - if ((type_byte & FLAGS_LONG_HEADER) && - (((type_byte & 0x30) >> 4) == 1 || (type_byte & 0x7F) == 0x7C)) { - QUIC_DVLOG(1) << "Dropping ZERO_RTT_PACKET packet"; - return WriteResult(WRITE_STATUS_OK, buf_len); - } - if (!error_returned_ && !(type_byte & FLAGS_LONG_HEADER)) { + + if (type_byte & FLAGS_LONG_HEADER) { + if (((type_byte & 0x30 >> 4) == (version_.UsesV2PacketTypes() ? 2 : 1)) || + ((type_byte & 0x7F) == 0x7C)) { + QUIC_DVLOG(1) << "Dropping ZERO_RTT_PACKET packet"; + return WriteResult(WRITE_STATUS_OK, buf_len); + } + } else if (!error_returned_) { QUIC_DVLOG(1) << "Return write error for short header packet"; error_returned_ = true; return WriteResult(WRITE_STATUS_ERROR, QUIC_EMSGSIZE); @@ -5806,6 +5788,7 @@ class BadShloPacketWriter2 : public QuicPacketWriterWrapper { private: bool error_returned_; + ParsedQuicVersion version_; }; TEST_P(EndToEndTest, ForwardSecureConnectionClose) { @@ -5836,7 +5819,7 @@ TEST_P(EndToEndTest, ForwardSecureConnectionClose) { dispatcher, // This causes the all server sent ZERO_RTT_PROTECTED packets to be // dropped, and first short header packet causes write error. - new BadShloPacketWriter2()); + new BadShloPacketWriter2(version_)); server_thread_->Resume(); client_.reset(CreateQuicClient(client_writer_)); EXPECT_EQ("", client_->SendSynchronousRequest("/foo")); @@ -5913,10 +5896,6 @@ TEST_P(EndToEndTest, CustomTransportParameters) { QuicConfig* server_config = nullptr; if (server_session != nullptr) { server_config = server_session->config(); - if (!GetQuicReloadableFlag(quic_ignore_user_agent_transport_parameter)) { - EXPECT_EQ(server_session->user_agent_id().value_or("MissingUserAgent"), - kTestUserAgentId); - } } else { ADD_FAILURE() << "Missing server session"; } @@ -6025,8 +6004,7 @@ class CopyingPacketWriter : public PacketDroppingTestWriter { public: explicit CopyingPacketWriter(int num_packets_to_copy) : num_packets_to_copy_(num_packets_to_copy) {} - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, PerPacketOptions* options) override { diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc index 42fef63c978..3a44f79a1d1 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc @@ -50,7 +50,6 @@ using spdy::SpdyGoAwayIR; using spdy::SpdyHeaderBlock; using spdy::SpdyHeadersHandlerInterface; using spdy::SpdyHeadersIR; -using spdy::SpdyKnownSettingsId; using spdy::SpdyPingId; using spdy::SpdyPingIR; using spdy::SpdyPriority; diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc index 30c4178feca..2d144d2465c 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc @@ -45,7 +45,6 @@ using testing::_; using testing::StrictMock; using testing::AtLeast; -using testing::Return; namespace quic { namespace test { diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc index 5a859271e6e..cfc47296417 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc @@ -43,7 +43,6 @@ using spdy::SpdyFrameType; using spdy::SpdyHeaderBlock; using spdy::SpdyHeadersHandlerInterface; using spdy::SpdyHeadersIR; -using spdy::SpdyKnownSettingsId; using spdy::SpdyPingId; using spdy::SpdyPriority; using spdy::SpdyPriorityIR; diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc index 5db1aab4e91..45506211f9d 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc @@ -153,7 +153,6 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker { } void SetServerApplicationStateForResumption( std::unique_ptr<ApplicationState> /*application_state*/) override {} - bool KeyUpdateSupportedLocally() const override { return false; } std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() override { return nullptr; diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc index 8147ce00dcc..5317137d7e0 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc @@ -185,6 +185,8 @@ QuicSpdyStream::QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session, headers_payload_length_(0), trailers_decompressed_(false), trailers_consumed_(false), + qpack_decoded_headers_accumulator_reset_reason_( + QpackDecodedHeadersAccumulatorResetReason::kUnSet), http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)), decoder_(http_decoder_visitor_.get(), HttpDecoderOptionsForBidiStream(spdy_session)), @@ -225,6 +227,8 @@ QuicSpdyStream::QuicSpdyStream(PendingStream* pending, headers_payload_length_(0), trailers_decompressed_(false), trailers_consumed_(false), + qpack_decoded_headers_accumulator_reset_reason_( + QpackDecodedHeadersAccumulatorResetReason::kUnSet), http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)), decoder_(http_decoder_visitor_.get()), sequencer_offset_(sequencer()->NumBytesConsumed()), @@ -563,6 +567,8 @@ void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers, bool header_list_size_limit_exceeded) { header_list_size_limit_exceeded_ = header_list_size_limit_exceeded; qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInOnHeadersDecoded; QuicSpdySession::LogHeaderCompressionRatioHistogram( /* using_qpack = */ true, @@ -592,6 +598,8 @@ void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers, void QuicSpdyStream::OnHeaderDecodingError(QuicErrorCode error_code, absl::string_view error_message) { qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInOnHeaderDecodingError; std::string connection_close_error_message = absl::StrCat( "Error decoding ", headers_decompressed_ ? "trailers" : "headers", @@ -756,6 +764,8 @@ void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) { if (GetQuicReloadableFlag(quic_abort_qpack_on_stream_reset)) { QUIC_RELOADABLE_FLAG_COUNT_N(quic_abort_qpack_on_stream_reset, 1, 2); qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInOnStreamReset1; } } @@ -769,6 +779,8 @@ void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) { if (!fin_received() && spdy_session_->qpack_decoder()) { spdy_session_->qpack_decoder()->OnStreamReset(id()); qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInOnStreamReset2; } QuicStream::OnStreamReset(frame); @@ -791,6 +803,8 @@ void QuicSpdyStream::ResetWithError(QuicResetStreamError error) { if (GetQuicReloadableFlag(quic_abort_qpack_on_stream_reset)) { QUIC_RELOADABLE_FLAG_COUNT_N(quic_abort_qpack_on_stream_reset, 2, 2); qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInResetWithError; } } @@ -893,6 +907,8 @@ void QuicSpdyStream::OnClose() { QuicStream::OnClose(); qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInOnClose; if (visitor_) { Visitor* visitor = visitor_; @@ -1088,7 +1104,14 @@ bool QuicSpdyStream::OnHeadersFrameStart(QuicByteCount header_length, bool QuicSpdyStream::OnHeadersFramePayload(absl::string_view payload) { QUICHE_DCHECK(VersionUsesHttp3(transport_version())); - QUICHE_DCHECK(qpack_decoded_headers_accumulator_); + + if (!qpack_decoded_headers_accumulator_) { + QUIC_BUG(b215142466_OnHeadersFramePayload) + << static_cast<int>(qpack_decoded_headers_accumulator_reset_reason_); + OnHeaderDecodingError(QUIC_INTERNAL_ERROR, + "qpack_decoded_headers_accumulator_ is nullptr"); + return false; + } qpack_decoded_headers_accumulator_->Decode(payload); @@ -1103,7 +1126,14 @@ bool QuicSpdyStream::OnHeadersFramePayload(absl::string_view payload) { bool QuicSpdyStream::OnHeadersFrameEnd() { QUICHE_DCHECK(VersionUsesHttp3(transport_version())); - QUICHE_DCHECK(qpack_decoded_headers_accumulator_); + + if (!qpack_decoded_headers_accumulator_) { + QUIC_BUG(b215142466_OnHeadersFrameEnd) + << static_cast<int>(qpack_decoded_headers_accumulator_reset_reason_); + OnHeaderDecodingError(QUIC_INTERNAL_ERROR, + "qpack_decoded_headers_accumulator_ is nullptr"); + return false; + } qpack_decoded_headers_accumulator_->EndHeaderBlock(); @@ -1244,9 +1274,7 @@ void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() { std::string protocol; absl::optional<QuicDatagramStreamId> flow_id; bool version_indicated = false; - for (const auto& header : header_list_) { - const std::string& header_name = header.first; - const std::string& header_value = header.second; + for (const auto& [header_name, header_value] : header_list_) { if (header_name == ":method") { if (!method.empty() || header_value.empty()) { return; diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h index 8ec56d58f06..14ac2f2f585 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h @@ -391,6 +391,20 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream WebTransportStreamAdapter adapter; }; + // Reason codes for `qpack_decoded_headers_accumulator_` being nullptr. + enum class QpackDecodedHeadersAccumulatorResetReason { + // `qpack_decoded_headers_accumulator_` was default constructed to nullptr. + kUnSet = 0, + // `qpack_decoded_headers_accumulator_` was reset in the corresponding + // method. + kResetInOnHeadersDecoded = 1, + kResetInOnHeaderDecodingError = 2, + kResetInOnStreamReset1 = 3, + kResetInOnStreamReset2 = 4, + kResetInResetWithError = 5, + kResetInOnClose = 6, + }; + // Called by HttpDecoderVisitor. bool OnDataFrameStart(QuicByteCount header_length, QuicByteCount payload_length); @@ -462,6 +476,9 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream // Headers accumulator for decoding HEADERS frame payload. std::unique_ptr<QpackDecodedHeadersAccumulator> qpack_decoded_headers_accumulator_; + // Reason for `qpack_decoded_headers_accumulator_` being nullptr. + QpackDecodedHeadersAccumulatorResetReason + qpack_decoded_headers_accumulator_reset_reason_; // Visitor of the HttpDecoder. std::unique_ptr<HttpDecoderVisitor> http_decoder_visitor_; // HttpDecoder for processing raw incoming stream frames. diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc index 3bad6efe6ee..c8146e1c5a1 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc @@ -136,7 +136,6 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker { } void SetServerApplicationStateForResumption( std::unique_ptr<ApplicationState> /*application_state*/) override {} - bool KeyUpdateSupportedLocally() const override { return true; } std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() override { return nullptr; @@ -3424,6 +3423,32 @@ TEST_P(QuicSpdyStreamTest, GetMaxDatagramSize) { EXPECT_EQ(size - 1, size_with_context); } +TEST_P(QuicSpdyStreamTest, + QUIC_TEST_DISABLED_IN_CHROME(HeadersAccumulatorNullptr)) { + if (!UsesHttp3()) { + return; + } + + Initialize(kShouldProcessData); + + // Creates QpackDecodedHeadersAccumulator in + // `qpack_decoded_headers_accumulator_`. + std::string headers = HeadersFrame({std::make_pair("foo", "bar")}); + stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers)); + + // Resets `qpack_decoded_headers_accumulator_`. + stream_->OnHeadersDecoded({}, false); + + // This private method should never be called when + // `qpack_decoded_headers_accumulator_` is nullptr. The number 1 identifies + // the site where `qpack_decoded_headers_accumulator_` was last reset. + EXPECT_CALL(*connection_, CloseConnection(_, _, _)); + bool result = true; + EXPECT_QUIC_BUG(result = QuicSpdyStreamPeer::OnHeadersFrameEnd(stream_), + "b215142466_OnHeadersFrameEnd.: 1$"); + EXPECT_FALSE(result); +} + } // namespace } // namespace test } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc index 74c9c53a72d..5b744077402 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc @@ -13,6 +13,7 @@ #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" +#include "quic/core/quic_versions.h" #include "quic/platform/api/quic_flag_utils.h" #include "quic/platform/api/quic_flags.h" #include "quic/platform/api/quic_logging.h" @@ -194,4 +195,23 @@ void SpdyUtils::AddDatagramFlowIdHeader(spdy::SpdyHeaderBlock* headers, (*headers)["datagram-flow-id"] = absl::StrCat(flow_id); } +// static +ParsedQuicVersion SpdyUtils::ExtractQuicVersionFromAltSvcEntry( + const spdy::SpdyAltSvcWireFormat::AlternativeService& + alternative_service_entry, + const ParsedQuicVersionVector& supported_versions) { + for (const ParsedQuicVersion& version : supported_versions) { + if (version.AlpnDeferToRFCv1()) { + // Versions with share an ALPN with v1 are currently unable to be + // advertised with Alt-Svc. + continue; + } + if (AlpnForVersion(version) == alternative_service_entry.protocol_id) { + return version; + } + } + + return ParsedQuicVersion::Unsupported(); +} + } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h index 01fae4f17a7..85099ab15e7 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h +++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h @@ -14,6 +14,7 @@ #include "quic/core/http/quic_header_list.h" #include "quic/core/quic_packets.h" #include "quic/platform/api/quic_export.h" +#include "spdy/core/spdy_alt_svc_wire_format.h" #include "spdy/core/spdy_header_block.h" namespace quic { @@ -61,6 +62,14 @@ class QUIC_EXPORT_PRIVATE SpdyUtils { // Adds the "datagram-flow-id" header. static void AddDatagramFlowIdHeader(spdy::SpdyHeaderBlock* headers, QuicDatagramStreamId flow_id); + + // Returns the advertised QUIC version from the specified alternative service + // advertisement, or ParsedQuicVersion::Unsupported() if no supported version + // is advertised. + static ParsedQuicVersion ExtractQuicVersionFromAltSvcEntry( + const spdy::SpdyAltSvcWireFormat::AlternativeService& + alternative_service_entry, + const ParsedQuicVersionVector& supported_versions); }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc index 918739d6f90..85c5ceccd57 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc @@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "quic/core/http/spdy_utils.h" + #include <memory> #include <string> #include "absl/base/macros.h" #include "absl/strings/string_view.h" -#include "quic/core/http/spdy_utils.h" +#include "quic/core/quic_versions.h" #include "quic/platform/api/quic_test.h" using spdy::SpdyHeaderBlock; @@ -408,5 +410,33 @@ TEST_F(DatagramFlowIdTest, DatagramFlowId) { ValidateDatagramFlowId("44; ecn-ect0, 42, 48; ecn-ce, 46; ecn-ect1", 42); } +using ExtractQuicVersionFromAltSvcEntry = QuicTest; + +TEST_F(ExtractQuicVersionFromAltSvcEntry, SupportedVersion) { + ParsedQuicVersionVector supported_versions = AllSupportedVersions(); + spdy::SpdyAltSvcWireFormat::AlternativeService entry; + for (const ParsedQuicVersion& version : supported_versions) { + entry.protocol_id = AlpnForVersion(version); + ParsedQuicVersion expected_version = version; + // Versions with share an ALPN with v1 are currently unable to be + // advertised with Alt-Svc. + if (entry.protocol_id == AlpnForVersion(ParsedQuicVersion::RFCv1()) && + version != ParsedQuicVersion::RFCv1()) { + expected_version = ParsedQuicVersion::RFCv1(); + } + EXPECT_EQ(expected_version, SpdyUtils::ExtractQuicVersionFromAltSvcEntry( + entry, supported_versions)) + << "version: " << version; + } +} + +TEST_F(ExtractQuicVersionFromAltSvcEntry, UnsupportedVersion) { + spdy::SpdyAltSvcWireFormat::AlternativeService entry; + entry.protocol_id = "quic"; + EXPECT_EQ(ParsedQuicVersion::Unsupported(), + SpdyUtils::ExtractQuicVersionFromAltSvcEntry( + entry, AllSupportedVersions())); +} + } // namespace test } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc index 4e50e728ee4..934cc5f0d4d 100644 --- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc +++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc @@ -7,6 +7,7 @@ #include "absl/strings/string_view.h" #include "quic/core/qpack/qpack_decoder.h" #include "quic/core/qpack/qpack_header_table.h" +#include "quic/platform/api/quic_bug_tracker.h" namespace quic { @@ -88,6 +89,11 @@ void QpackDecodedHeadersAccumulator::EndHeaderBlock() { QUICHE_DCHECK(!error_detected_); QUICHE_DCHECK(!headers_decoded_); + if (!decoder_) { + QUIC_BUG(b215142466_EndHeaderBlock); + return; + } + // Might destroy |this|. decoder_->EndHeaderBlock(); } diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc index 3ae944152c0..974f7b2274f 100644 --- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc +++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc @@ -87,6 +87,12 @@ QpackEncoder::Representations QpackEncoder::FirstPassEncode( const QuicByteCount initial_encoder_stream_buffered_byte_count = encoder_stream_sender_.BufferedByteCount(); + bool can_write_to_encoder_stream = true; + if (GetQuicReloadableFlag(quic_limit_encoder_stream_buffering)) { + QUIC_RELOADABLE_FLAG_COUNT(quic_limit_encoder_stream_buffering); + can_write_to_encoder_stream = encoder_stream_sender_.CanWrite(); + } + Representations representations; representations.reserve(header_list.size()); @@ -152,17 +158,20 @@ QpackEncoder::Representations QpackEncoder::FirstPassEncode( std::min(smallest_blocking_index, index))) { dynamic_table_insertion_blocked = true; } else { - // If allowed, duplicate entry and refer to it. - encoder_stream_sender_.SendDuplicate( - QpackAbsoluteIndexToEncoderStreamRelativeIndex( - index, header_table_.inserted_entry_count())); - uint64_t new_index = header_table_.InsertEntry(name, value); - representations.push_back(EncodeIndexedHeaderField( - is_static, new_index, referred_indices)); - smallest_blocking_index = std::min(smallest_blocking_index, index); - header_table_.set_dynamic_table_entry_referenced(); - - break; + if (can_write_to_encoder_stream) { + // If allowed, duplicate entry and refer to it. + encoder_stream_sender_.SendDuplicate( + QpackAbsoluteIndexToEncoderStreamRelativeIndex( + index, header_table_.inserted_entry_count())); + uint64_t new_index = header_table_.InsertEntry(name, value); + representations.push_back(EncodeIndexedHeaderField( + is_static, new_index, referred_indices)); + smallest_blocking_index = + std::min(smallest_blocking_index, index); + header_table_.set_dynamic_table_entry_referenced(); + + break; + } } } @@ -182,15 +191,17 @@ QpackEncoder::Representations QpackEncoder::FirstPassEncode( header_table_.MaxInsertSizeWithoutEvictingGivenEntry( smallest_blocking_index)) { // If allowed, insert entry into dynamic table and refer to it. - encoder_stream_sender_.SendInsertWithNameReference(is_static, index, - value); - uint64_t new_index = header_table_.InsertEntry(name, value); - representations.push_back(EncodeIndexedHeaderField( - /* is_static = */ false, new_index, referred_indices)); - smallest_blocking_index = - std::min<uint64_t>(smallest_blocking_index, new_index); - - break; + if (can_write_to_encoder_stream) { + encoder_stream_sender_.SendInsertWithNameReference(is_static, + index, value); + uint64_t new_index = header_table_.InsertEntry(name, value); + representations.push_back(EncodeIndexedHeaderField( + /* is_static = */ false, new_index, referred_indices)); + smallest_blocking_index = + std::min<uint64_t>(smallest_blocking_index, new_index); + + break; + } } // Emit literal field with name reference. @@ -208,18 +219,20 @@ QpackEncoder::Representations QpackEncoder::FirstPassEncode( dynamic_table_insertion_blocked = true; } else { // If allowed, insert entry with name reference and refer to it. - encoder_stream_sender_.SendInsertWithNameReference( - is_static, - QpackAbsoluteIndexToEncoderStreamRelativeIndex( - index, header_table_.inserted_entry_count()), - value); - uint64_t new_index = header_table_.InsertEntry(name, value); - representations.push_back( - EncodeIndexedHeaderField(is_static, new_index, referred_indices)); - smallest_blocking_index = std::min(smallest_blocking_index, index); - header_table_.set_dynamic_table_entry_referenced(); + if (can_write_to_encoder_stream) { + encoder_stream_sender_.SendInsertWithNameReference( + is_static, + QpackAbsoluteIndexToEncoderStreamRelativeIndex( + index, header_table_.inserted_entry_count()), + value); + uint64_t new_index = header_table_.InsertEntry(name, value); + representations.push_back(EncodeIndexedHeaderField( + is_static, new_index, referred_indices)); + smallest_blocking_index = std::min(smallest_blocking_index, index); + header_table_.set_dynamic_table_entry_referenced(); - break; + break; + } } if ((blocking_allowed || index < known_received_count) && @@ -251,14 +264,16 @@ QpackEncoder::Representations QpackEncoder::FirstPassEncode( smallest_blocking_index)) { dynamic_table_insertion_blocked = true; } else { - encoder_stream_sender_.SendInsertWithoutNameReference(name, value); - uint64_t new_index = header_table_.InsertEntry(name, value); - representations.push_back(EncodeIndexedHeaderField( - /* is_static = */ false, new_index, referred_indices)); - smallest_blocking_index = - std::min<uint64_t>(smallest_blocking_index, new_index); + if (can_write_to_encoder_stream) { + encoder_stream_sender_.SendInsertWithoutNameReference(name, value); + uint64_t new_index = header_table_.InsertEntry(name, value); + representations.push_back(EncodeIndexedHeaderField( + /* is_static = */ false, new_index, referred_indices)); + smallest_blocking_index = + std::min<uint64_t>(smallest_blocking_index, new_index); - break; + break; + } } // Encode entry as string literals. @@ -275,12 +290,18 @@ QpackEncoder::Representations QpackEncoder::FirstPassEncode( encoder_stream_sender_.BufferedByteCount(); QUICHE_DCHECK_GE(encoder_stream_buffered_byte_count, initial_encoder_stream_buffered_byte_count); + if (encoder_stream_sent_byte_count) { *encoder_stream_sent_byte_count = encoder_stream_buffered_byte_count - initial_encoder_stream_buffered_byte_count; } - encoder_stream_sender_.Flush(); + if (can_write_to_encoder_stream) { + encoder_stream_sender_.Flush(); + } else { + QUICHE_DCHECK_EQ(encoder_stream_buffered_byte_count, + initial_encoder_stream_buffered_byte_count); + } ++header_list_count_; diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc index 4079ba45a85..8b6f887cf3c 100644 --- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc +++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc @@ -14,6 +14,14 @@ namespace quic { +namespace { + +// If QUIC stream bufferes more that this number of bytes, +// CanWrite() will return false. +constexpr uint64_t kMaxBytesBufferedByStream = 64 * 1024; + +} // anonymous namespace + QpackEncoderStreamSender::QpackEncoderStreamSender() : delegate_(nullptr) {} void QpackEncoderStreamSender::SendInsertWithNameReference( @@ -44,6 +52,11 @@ void QpackEncoderStreamSender::SendSetDynamicTableCapacity(uint64_t capacity) { QpackInstructionWithValues::SetDynamicTableCapacity(capacity), &buffer_); } +bool QpackEncoderStreamSender::CanWrite() const { + return delegate_ && delegate_->NumBytesBuffered() + buffer_.size() <= + kMaxBytesBufferedByStream; +} + void QpackEncoderStreamSender::Flush() { if (buffer_.empty()) { return; diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h index 44d777d8d90..d8c64306a78 100644 --- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h +++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h @@ -38,9 +38,18 @@ class QUIC_EXPORT_PRIVATE QpackEncoderStreamSender { // 5.2.4. Set Dynamic Table Capacity void SendSetDynamicTableCapacity(uint64_t capacity); - // Returns number of buffered bytes. + // Returns number of bytes buffered by this object. + // There is no limit on how much data this object is willing to buffer. QuicByteCount BufferedByteCount() const { return buffer_.size(); } + // Returns whether writing to the encoder stream is allowed. Writing is + // disallowed if the amount of data buffered by the underlying stream exceeds + // a hardcoded limit, in order to limit memory consumption in case the encoder + // stream is blocked. CanWrite() returning true does not mean that the + // encoder stream is not blocked, it just means the blocked data does not + // exceed the threshold. + bool CanWrite() const; + // Writes all buffered instructions on the encoder stream. void Flush(); diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc index 21397ed8571..30f578e9378 100644 --- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc @@ -18,12 +18,19 @@ using ::testing::_; using ::testing::Eq; +using ::testing::Return; using ::testing::StrictMock; namespace quic { namespace test { namespace { +// A number larger than kMaxBytesBufferedByStream in +// qpack_encoder_stream_sender.cc. Returning this value from NumBytesBuffered() +// will instruct QpackEncoder not to generate any instructions for the encoder +// stream. +constexpr uint64_t kTooManyBytesBuffered = 1024 * 1024; + class QpackEncoderTest : public QuicTest { protected: QpackEncoderTest() @@ -47,6 +54,8 @@ class QpackEncoderTest : public QuicTest { }; TEST_F(QpackEncoderTest, Empty) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; std::string output = Encode(header_list); @@ -54,6 +63,8 @@ TEST_F(QpackEncoderTest, Empty) { } TEST_F(QpackEncoderTest, EmptyName) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list[""] = "foo"; std::string output = Encode(header_list); @@ -62,6 +73,8 @@ TEST_F(QpackEncoderTest, EmptyName) { } TEST_F(QpackEncoderTest, EmptyValue) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list["foo"] = ""; std::string output = Encode(header_list); @@ -70,6 +83,8 @@ TEST_F(QpackEncoderTest, EmptyValue) { } TEST_F(QpackEncoderTest, EmptyNameAndValue) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list[""] = ""; std::string output = Encode(header_list); @@ -78,6 +93,8 @@ TEST_F(QpackEncoderTest, EmptyNameAndValue) { } TEST_F(QpackEncoderTest, Simple) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list["foo"] = "bar"; std::string output = Encode(header_list); @@ -86,6 +103,8 @@ TEST_F(QpackEncoderTest, Simple) { } TEST_F(QpackEncoderTest, Multiple) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list["foo"] = "bar"; // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. @@ -108,6 +127,8 @@ TEST_F(QpackEncoderTest, Multiple) { } TEST_F(QpackEncoderTest, StaticTable) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); { spdy::Http2HeaderBlock header_list; header_list[":method"] = "GET"; @@ -149,6 +170,8 @@ TEST_F(QpackEncoderTest, DecoderStreamError) { } TEST_F(QpackEncoderTest, SplitAlongNullCharacter) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list["foo"] = absl::string_view("bar\0bar\0baz", 11); std::string output = Encode(header_list); @@ -217,6 +240,8 @@ TEST_F(QpackEncoderTest, InvalidHeaderAcknowledgement) { } TEST_F(QpackEncoderTest, DynamicTable) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); encoder_.SetMaximumBlockedStreams(1); encoder_.SetMaximumDynamicTableCapacity(4096); encoder_.SetDynamicTableCapacity(4096); @@ -252,6 +277,8 @@ TEST_F(QpackEncoderTest, DynamicTable) { // There is no room in the dynamic table after inserting the first entry. TEST_F(QpackEncoderTest, SmallDynamicTable) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); encoder_.SetMaximumBlockedStreams(1); encoder_.SetMaximumDynamicTableCapacity(QpackEntry::Size("foo", "bar")); encoder_.SetDynamicTableCapacity(QpackEntry::Size("foo", "bar")); @@ -288,6 +315,8 @@ TEST_F(QpackEncoderTest, SmallDynamicTable) { } TEST_F(QpackEncoderTest, BlockedStream) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); encoder_.SetMaximumBlockedStreams(1); encoder_.SetMaximumDynamicTableCapacity(4096); encoder_.SetDynamicTableCapacity(4096); @@ -395,6 +424,8 @@ TEST_F(QpackEncoderTest, BlockedStream) { } TEST_F(QpackEncoderTest, Draining) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list1; header_list1["one"] = "foo"; header_list1["two"] = "foo"; @@ -467,6 +498,135 @@ TEST_F(QpackEncoderTest, DynamicTableCapacityLessThanMaximum) { EXPECT_EQ(30u, header_table->dynamic_table_capacity()); } +TEST_F(QpackEncoderTest, EncoderStreamWritesDisallowedThenAllowed) { + if (!GetQuicReloadableFlag(quic_limit_encoder_stream_buffering)) { + return; + } + + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(kTooManyBytesBuffered)); + encoder_.SetMaximumBlockedStreams(1); + encoder_.SetMaximumDynamicTableCapacity(4096); + encoder_.SetDynamicTableCapacity(4096); + + spdy::Http2HeaderBlock header_list1; + header_list1["foo"] = "bar"; + header_list1.AppendValueOrAddHeader("foo", "baz"); + header_list1["cookie"] = "baz"; // name matches static entry + + // Encoder is not allowed to write on the encoder stream. + // No Set Dynamic Table Capacity or Insert instructions are sent. + // Headers are encoded as string literals. + EXPECT_EQ(absl::HexStringToBytes("0000" // prefix + "2a94e7" // literal name "foo" + "03626172" // with literal value "bar" + "2a94e7" // literal name "foo" + "0362617a" // with literal value "baz" + "55" // name of static entry 5 + "0362617a"), // with literal value "baz" + Encode(header_list1)); + + EXPECT_EQ(0u, encoder_stream_sent_byte_count_); + + // If number of bytes buffered by encoder stream goes under the threshold, + // then QpackEncoder will resume emitting encoder stream instructions. + ::testing::Mock::VerifyAndClearExpectations(&encoder_stream_sender_delegate_); + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); + + spdy::Http2HeaderBlock header_list2; + header_list2["foo"] = "bar"; + header_list2.AppendValueOrAddHeader("foo", + "baz"); // name matches dynamic entry + header_list2["cookie"] = "baz"; // name matches static entry + + // Set Dynamic Table Capacity instruction. + std::string set_dyanamic_table_capacity = absl::HexStringToBytes("3fe11f"); + // Insert three entries into the dynamic table. + std::string insert_entries = absl::HexStringToBytes( + "62" // insert without name reference + "94e7" // Huffman-encoded name "foo" + "03626172" // value "bar" + "80" // insert with name reference, dynamic index 0 + "0362617a" // value "baz" + "c5" // insert with name reference, static index 5 + "0362617a"); // value "baz" + EXPECT_CALL(encoder_stream_sender_delegate_, + WriteStreamData(Eq( + absl::StrCat(set_dyanamic_table_capacity, insert_entries)))); + + EXPECT_EQ(absl::HexStringToBytes( + "0400" // prefix + "828180"), // dynamic entries with relative index 0, 1, and 2 + Encode(header_list2)); + + EXPECT_EQ(insert_entries.size(), encoder_stream_sent_byte_count_); +} + +TEST_F(QpackEncoderTest, EncoderStreamWritesAllowedThenDisallowed) { + if (!GetQuicReloadableFlag(quic_limit_encoder_stream_buffering)) { + return; + } + + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); + encoder_.SetMaximumBlockedStreams(1); + encoder_.SetMaximumDynamicTableCapacity(4096); + encoder_.SetDynamicTableCapacity(4096); + + spdy::Http2HeaderBlock header_list1; + header_list1["foo"] = "bar"; + header_list1.AppendValueOrAddHeader("foo", + "baz"); // name matches dynamic entry + header_list1["cookie"] = "baz"; // name matches static entry + + // Set Dynamic Table Capacity instruction. + std::string set_dyanamic_table_capacity = absl::HexStringToBytes("3fe11f"); + // Insert three entries into the dynamic table. + std::string insert_entries = absl::HexStringToBytes( + "62" // insert without name reference + "94e7" // Huffman-encoded name "foo" + "03626172" // value "bar" + "80" // insert with name reference, dynamic index 0 + "0362617a" // value "baz" + "c5" // insert with name reference, static index 5 + "0362617a"); // value "baz" + EXPECT_CALL(encoder_stream_sender_delegate_, + WriteStreamData(Eq( + absl::StrCat(set_dyanamic_table_capacity, insert_entries)))); + + EXPECT_EQ(absl::HexStringToBytes( + "0400" // prefix + "828180"), // dynamic entries with relative index 0, 1, and 2 + Encode(header_list1)); + + EXPECT_EQ(insert_entries.size(), encoder_stream_sent_byte_count_); + + // If number of bytes buffered by encoder stream goes over the threshold, + // then QpackEncoder will stop emitting encoder stream instructions. + ::testing::Mock::VerifyAndClearExpectations(&encoder_stream_sender_delegate_); + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(kTooManyBytesBuffered)); + + spdy::Http2HeaderBlock header_list2; + header_list2["foo"] = "bar"; // matches previously inserted dynamic entry + header_list2["bar"] = "baz"; + header_list2["cookie"] = "baz"; // name matches static entry + + // Encoder is not allowed to write on the encoder stream. + // No Set Dynamic Table Capacity or Insert instructions are sent. + // Headers are encoded as string literals. + EXPECT_EQ( + absl::HexStringToBytes("0400" // prefix + "82" // dynamic entry with relative index 0 + "23626172" // literal name "bar" + "0362617a" // with literal value "baz" + "80"), // dynamic entry with relative index 2 + Encode(header_list2)); + + EXPECT_EQ(0u, encoder_stream_sent_byte_count_); +} + } // namespace } // namespace test } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc index 8cd1108a458..20f7a62731b 100644 --- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc +++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc @@ -9,16 +9,17 @@ #include "quic/platform/api/quic_flags.h" #include "quic/platform/api/quic_logging.h" #include "quic/test_tools/qpack/qpack_offline_decoder.h" +#include "common/platform/api/quiche_command_line_flags.h" int main(int argc, char* argv[]) { const char* usage = "Usage: qpack_offline_decoder input_filename expected_headers_filename " "...."; std::vector<std::string> args = - quic::QuicParseCommandLineFlags(usage, argc, argv); + quiche::QuicheParseCommandLineFlags(usage, argc, argv); if (args.size() < 2 || args.size() % 2 != 0) { - quic::QuicPrintCommandLineFlagHelp(usage); + quiche::QuichePrintCommandLineFlagHelp(usage); return 1; } diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc index 626d0639bf5..3e921d860f6 100644 --- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc +++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc @@ -34,6 +34,10 @@ void QpackSendStream::WriteStreamData(absl::string_view data) { WriteOrBufferData(data, false, nullptr); } +uint64_t QpackSendStream::NumBytesBuffered() const { + return QuicStream::BufferedDataBytes(); +} + void QpackSendStream::MaybeSendStreamType() { if (!stream_type_sent_) { char type[sizeof(http3_stream_type_)]; diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h index 086ad638d46..72dc677ecc7 100644 --- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h +++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h @@ -43,6 +43,9 @@ class QUIC_EXPORT_PRIVATE QpackSendStream : public QuicStream, // before the first instruction so that the peer can open an qpack stream. void WriteStreamData(absl::string_view data) override; + // Return the number of bytes buffered due to underlying stream being blocked. + uint64_t NumBytesBuffered() const override; + // TODO(b/112770235): Remove this method once QuicStreamIdManager supports // creating HTTP/3 unidirectional streams dynamically. void MaybeSendStreamType(); diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h index 4bd1a3ae72d..04f533d3084 100644 --- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h +++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h @@ -17,6 +17,9 @@ class QUIC_EXPORT_PRIVATE QpackStreamSenderDelegate { // Write data on the unidirectional stream. virtual void WriteStreamData(absl::string_view data) = 0; + + // Return the number of bytes buffered due to underlying stream being blocked. + virtual uint64_t NumBytesBuffered() const = 0; }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h index 3206b373dd7..9607054bd38 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h @@ -90,8 +90,7 @@ class QUIC_NO_EXPORT QuicBufferedPacketStore { BufferedPacketList early_arrived_packets) = 0; }; - QuicBufferedPacketStore(VisitorInterface* vistor, - const QuicClock* clock, + QuicBufferedPacketStore(VisitorInterface* visitor, const QuicClock* clock, QuicAlarmFactory* alarm_factory); QuicBufferedPacketStore(const QuicBufferedPacketStore&) = delete; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_config.cc b/chromium/net/third_party/quiche/src/quic/core/quic_config.cc index 796c641051b..8313ef76fbd 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_config.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_config.cc @@ -456,8 +456,6 @@ QuicConfig::QuicConfig() initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL), initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL), connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL), - key_update_supported_remotely_(false), - key_update_supported_locally_(false), alternate_server_address_ipv6_(kASAD, PRESENCE_OPTIONAL), alternate_server_address_ipv4_(kASAD, PRESENCE_OPTIONAL), stateless_reset_token_(kSRST, PRESENCE_OPTIONAL), @@ -863,22 +861,6 @@ bool QuicConfig::DisableConnectionMigration() const { return connection_migration_disabled_.HasReceivedValue(); } -void QuicConfig::SetKeyUpdateSupportedLocally() { - key_update_supported_locally_ = true; -} - -bool QuicConfig::KeyUpdateSupportedForConnection() const { - return KeyUpdateSupportedRemotely() && KeyUpdateSupportedLocally(); -} - -bool QuicConfig::KeyUpdateSupportedLocally() const { - return key_update_supported_locally_; -} - -bool QuicConfig::KeyUpdateSupportedRemotely() const { - return key_update_supported_remotely_; -} - void QuicConfig::SetIPv6AlternateServerAddressToSend( const QuicSocketAddress& alternate_server_address_ipv6) { if (!alternate_server_address_ipv6.host().IsIPv6()) { @@ -1297,10 +1279,6 @@ bool QuicConfig::FillTransportParameters(TransportParameters* params) const { params->google_connection_options = connection_options_.GetSendValues(); } - if (!KeyUpdateSupportedLocally()) { - params->key_update_not_yet_supported = true; - } - params->custom_parameters = custom_transport_parameters_to_send_; return true; @@ -1410,9 +1388,6 @@ QuicErrorCode QuicConfig::ProcessTransportParameters( if (params.disable_active_migration) { connection_migration_disabled_.SetReceivedValue(1u); } - if (!is_resumption && !params.key_update_not_yet_supported) { - key_update_supported_remotely_ = true; - } active_connection_id_limit_.SetReceivedValue( params.active_connection_id_limit.value()); diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_config.h b/chromium/net/third_party/quiche/src/quic/core/quic_config.h index d122be7ff29..cb8b4ecdf1e 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_config.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_config.h @@ -67,7 +67,7 @@ class QUIC_EXPORT_PRIVATE QuicConfigValue { // Stores uint32_t from CHLO or SHLO messages that are not negotiated. class QUIC_EXPORT_PRIVATE QuicFixedUint32 : public QuicConfigValue { public: - QuicFixedUint32(QuicTag name, QuicConfigPresence presence); + QuicFixedUint32(QuicTag tag, QuicConfigPresence presence); ~QuicFixedUint32() override; bool HasSendValue() const; @@ -384,12 +384,6 @@ class QUIC_EXPORT_PRIVATE QuicConfig { void SetDisableConnectionMigration(); bool DisableConnectionMigration() const; - // Key update support. - void SetKeyUpdateSupportedLocally(); - bool KeyUpdateSupportedForConnection() const; - bool KeyUpdateSupportedLocally() const; - bool KeyUpdateSupportedRemotely() const; - // IPv6 alternate server address. void SetIPv6AlternateServerAddressToSend( const QuicSocketAddress& alternate_server_address_ipv6); @@ -593,13 +587,6 @@ class QUIC_EXPORT_PRIVATE QuicConfig { // Uses the disable_active_migration transport parameter in IETF QUIC. QuicFixedUint32 connection_migration_disabled_; - // Whether key update is supported by the peer. Uses key_update_not_yet - // supported transport parameter in IETF QUIC. - bool key_update_supported_remotely_; - - // Whether key update is supported locally. - bool key_update_supported_locally_; - // Alternate server addresses the client could connect to. // Uses the preferred_address transport parameter in IETF QUIC. // Note that when QUIC_CRYPTO is in use, only one of the addresses is sent. diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_config_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_config_test.cc index 5124a975bf8..e53d429030e 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_config_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_config_test.cc @@ -56,9 +56,6 @@ TEST_P(QuicConfigTest, SetDefaults) { EXPECT_FALSE(config_.HasReceivedInitialMaxStreamDataBytesUnidirectional()); EXPECT_EQ(kMaxIncomingPacketSize, config_.GetMaxPacketSizeToSend()); EXPECT_FALSE(config_.HasReceivedMaxPacketSize()); - EXPECT_FALSE(config_.KeyUpdateSupportedForConnection()); - EXPECT_FALSE(config_.KeyUpdateSupportedLocally()); - EXPECT_FALSE(config_.KeyUpdateSupportedRemotely()); } TEST_P(QuicConfigTest, AutoSetIetfFlowControl) { @@ -519,7 +516,6 @@ TEST_P(QuicConfigTest, FillTransportParams) { EXPECT_EQ( static_cast<uint64_t>(kDefaultMinAckDelayTimeMs) * kNumMicrosPerMilli, params.min_ack_delay_us.value()); - EXPECT_TRUE(params.key_update_not_yet_supported); EXPECT_EQ(params.preferred_address->ipv4_socket_address, kTestServerAddress); EXPECT_EQ(*reinterpret_cast<StatelessResetToken*>( @@ -685,83 +681,6 @@ TEST_P(QuicConfigTest, DisableMigrationTransportParameter) { EXPECT_TRUE(config_.DisableConnectionMigration()); } -TEST_P(QuicConfigTest, KeyUpdateNotYetSupportedTransportParameterNorLocally) { - if (!version_.UsesTls()) { - // TransportParameters are only used for QUIC+TLS. - return; - } - EXPECT_FALSE(config_.KeyUpdateSupportedForConnection()); - EXPECT_FALSE(config_.KeyUpdateSupportedLocally()); - EXPECT_FALSE(config_.KeyUpdateSupportedRemotely()); - TransportParameters params; - params.key_update_not_yet_supported = true; - std::string error_details; - EXPECT_THAT(config_.ProcessTransportParameters( - params, /* is_resumption = */ false, &error_details), - IsQuicNoError()); - EXPECT_FALSE(config_.KeyUpdateSupportedForConnection()); - EXPECT_FALSE(config_.KeyUpdateSupportedLocally()); - EXPECT_FALSE(config_.KeyUpdateSupportedRemotely()); -} - -TEST_P(QuicConfigTest, KeyUpdateNotYetSupportedTransportParameter) { - if (!version_.UsesTls()) { - // TransportParameters are only used for QUIC+TLS. - return; - } - config_.SetKeyUpdateSupportedLocally(); - EXPECT_FALSE(config_.KeyUpdateSupportedForConnection()); - EXPECT_TRUE(config_.KeyUpdateSupportedLocally()); - - TransportParameters params; - params.key_update_not_yet_supported = true; - std::string error_details; - EXPECT_THAT(config_.ProcessTransportParameters( - params, /* is_resumption = */ false, &error_details), - IsQuicNoError()); - EXPECT_FALSE(config_.KeyUpdateSupportedForConnection()); - EXPECT_TRUE(config_.KeyUpdateSupportedLocally()); -} - -TEST_P(QuicConfigTest, KeyUpdateSupportedRemotelyButNotLocally) { - if (!version_.UsesTls()) { - // TransportParameters are only used for QUIC+TLS. - return; - } - EXPECT_FALSE(config_.KeyUpdateSupportedLocally()); - EXPECT_FALSE(config_.KeyUpdateSupportedForConnection()); - - TransportParameters params; - params.key_update_not_yet_supported = false; - std::string error_details; - EXPECT_THAT(config_.ProcessTransportParameters( - params, /* is_resumption = */ false, &error_details), - IsQuicNoError()); - EXPECT_FALSE(config_.KeyUpdateSupportedForConnection()); - EXPECT_FALSE(config_.KeyUpdateSupportedLocally()); - EXPECT_TRUE(config_.KeyUpdateSupportedRemotely()); -} - -TEST_P(QuicConfigTest, KeyUpdateSupported) { - if (!version_.UsesTls()) { - // TransportParameters are only used for QUIC+TLS. - return; - } - config_.SetKeyUpdateSupportedLocally(); - EXPECT_TRUE(config_.KeyUpdateSupportedLocally()); - EXPECT_FALSE(config_.KeyUpdateSupportedForConnection()); - - TransportParameters params; - params.key_update_not_yet_supported = false; - std::string error_details; - EXPECT_THAT(config_.ProcessTransportParameters( - params, /* is_resumption = */ false, &error_details), - IsQuicNoError()); - EXPECT_TRUE(config_.KeyUpdateSupportedForConnection()); - EXPECT_TRUE(config_.KeyUpdateSupportedLocally()); - EXPECT_TRUE(config_.KeyUpdateSupportedRemotely()); -} - TEST_P(QuicConfigTest, SendPreferredIPv4Address) { if (!version_.UsesTls()) { // TransportParameters are only used for QUIC+TLS. diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc index e31408a3116..2fe7af38717 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc @@ -505,8 +505,7 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) { if (!ValidateConfigConnectionIds(config)) { return; } - support_key_update_for_connection_ = - config.KeyUpdateSupportedForConnection(); + support_key_update_for_connection_ = version().UsesTls(); framer_.SetKeyUpdateSupportForConnection( support_key_update_for_connection_); } else { @@ -641,7 +640,6 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) { // 2) Client side's rollout can be protected by the same connection option. connection_migration_use_new_cid_ = validate_client_addresses_ && - GetQuicReloadableFlag(quic_drop_unsent_path_response) && GetQuicReloadableFlag(quic_connection_migration_use_new_cid_v2); if (config.HasReceivedMaxPacketSize()) { peer_max_packet_size_ = config.ReceivedMaxPacketSize(); @@ -1742,19 +1740,10 @@ bool QuicConnection::OnPathChallengeFrameInternal( // Queue or send PATH_RESPONSE. Send PATH_RESPONSE to the source address of // the current incoming packet, even if it's not the default path or the // alternative path. - const bool success = SendPathResponse( - frame.data_buffer, last_received_packet_info_.source_address, - current_effective_peer_address); - if (GetQuicReloadableFlag(quic_drop_unsent_path_response)) { - QUIC_RELOADABLE_FLAG_COUNT(quic_drop_unsent_path_response); - } - if (!success) { + if (!SendPathResponse(frame.data_buffer, + last_received_packet_info_.source_address, + current_effective_peer_address)) { QUIC_CODE_COUNT(quic_failed_to_send_path_response); - if (!GetQuicReloadableFlag(quic_drop_unsent_path_response)) { - // Queue the payloads to re-try later. - pending_path_challenge_payloads_.push_back( - {frame.data_buffer, last_received_packet_info_.source_address}); - } } // TODO(b/150095588): change the stats to // num_valid_path_challenge_received. @@ -2870,23 +2859,6 @@ void QuicConnection::OnCanWrite() { } } - // TODO(danzh) PATH_RESPONSE is of more interest to the peer than ACK, - // evaluate if it's worth to send them before sending ACKs. - while (!pending_path_challenge_payloads_.empty()) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_send_path_response2, 4, 5); - const PendingPathChallenge& pending_path_challenge = - pending_path_challenge_payloads_.front(); - // Note connection_migration_use_cid_ will depends on - // quic_drop_unsent_path_response flag eventually, and hence the empty - // effective_peer_address here will not be used. - if (!SendPathResponse(pending_path_challenge.received_path_challenge, - pending_path_challenge.peer_address, - /*effective_peer_address=*/QuicSocketAddress())) { - break; - } - pending_path_challenge_payloads_.pop_front(); - } - // Sending queued packets may have caused the socket to become write blocked, // or the congestion manager to prohibit sending. if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) { @@ -3273,11 +3245,9 @@ bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) { return false; } - if (GetQuicReloadableFlag(quic_suppress_write_mid_packet_processing) && - version().CanSendCoalescedPackets() && + if (version().CanSendCoalescedPackets() && framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_INITIAL) && framer_.is_processing_packet()) { - QUIC_RELOADABLE_FLAG_COUNT(quic_suppress_write_mid_packet_processing); // While we still have initial keys, suppress sending in mid of packet // processing. // TODO(fayang): always suppress sending while in the mid of packet @@ -3726,15 +3696,8 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) { return true; } } - if (GetQuicReloadableFlag( - quic_donot_rearm_pto_on_application_data_during_handshake)) { - QUIC_RELOADABLE_FLAG_COUNT( - quic_donot_rearm_pto_on_application_data_during_handshake); - if (ShouldSetRetransmissionAlarmOnPacketSent(in_flight, - packet->encryption_level)) { - SetRetransmissionAlarm(); - } - } else if (in_flight || !retransmission_alarm_->IsSet()) { + if (ShouldSetRetransmissionAlarmOnPacketSent(in_flight, + packet->encryption_level)) { SetRetransmissionAlarm(); } SetPingAlarm(); @@ -6765,6 +6728,21 @@ void QuicConnection::RetirePeerIssuedConnectionIdsNoLongerOnPath() { } } +void QuicConnection::RetirePeerIssuedConnectionIdsOnPathValidationFailure() { + // The alarm to retire connection IDs no longer on paths is scheduled at the + // end of writing and reading packet. On path validation failure, there could + // be no packet to write or read. Hence the retirement alarm for the + // connection ID associated with the failed path needs to be proactively + // scheduled here. + if (GetQuicReloadableFlag( + quic_retire_cid_on_reverse_path_validation_failure) || + perspective_ == Perspective::IS_CLIENT) { + QUIC_RELOADABLE_FLAG_COUNT( + quic_retire_cid_on_reverse_path_validation_failure); + RetirePeerIssuedConnectionIdsNoLongerOnPath(); + } +} + bool QuicConnection::MigratePath(const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address, QuicPacketWriter* writer, @@ -6816,12 +6794,7 @@ void QuicConnection::OnPathValidationFailureAtClient() { QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT); alternative_path_.Clear(); } - // The alarm to retire connection IDs no longer on paths is scheduled at the - // end of writing and reading packet. On path validation failure, there could - // be no packet to write or read. Hence the retirement alarm for the - // connection ID associated with the failed path needs to be proactively - // scheduled here. - RetirePeerIssuedConnectionIdsNoLongerOnPath(); + RetirePeerIssuedConnectionIdsOnPathValidationFailure(); } QuicConnectionId QuicConnection::GetOneActiveServerConnectionId() const { @@ -7075,6 +7048,7 @@ void QuicConnection::ReversePathValidationResultDelegate:: QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 6, 6); connection_->alternative_path_.Clear(); } + connection_->RetirePeerIssuedConnectionIdsOnPathValidationFailure(); } QuicConnection::ScopedRetransmissionTimeoutIndicator:: diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection.h b/chromium/net/third_party/quiche/src/quic/core/quic_connection.h index 3b310c8f838..954eb6a6d0f 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_connection.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection.h @@ -1564,6 +1564,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection // any path. void RetirePeerIssuedConnectionIdsNoLongerOnPath(); + // When path validation fails, proactively retire peer issued connection IDs + // no longer used on any path. + void RetirePeerIssuedConnectionIdsOnPathValidationFailure(); + // Writes the given packet to socket, encrypted with packet's // encryption_level. Returns true on successful write, and false if the writer // was blocked and the write needs to be tried again. Notifies the @@ -2165,13 +2169,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection quiche::QuicheCircularDeque<QuicPathFrameBuffer> received_path_challenge_payloads_; - // Buffer outstanding PATH_CHALLENGEs if socket write is blocked, future - // OnCanWrite will attempt to respond with PATH_RESPONSEs using the retained - // payload and peer addresses. - // TODO(fayang): remove this when deprecating quic_drop_unsent_path_response. - quiche::QuicheCircularDeque<PendingPathChallenge> - pending_path_challenge_payloads_; - // When we receive a RETRY packet or some INITIAL packets, we replace // |server_connection_id_| with the value from that packet and save off the // original value of |server_connection_id_| into diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc index 89fb70bacb1..fba066caf68 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc @@ -184,19 +184,12 @@ class TestConnection : public QuicConnection { TestConnection(QuicConnectionId connection_id, QuicSocketAddress initial_self_address, QuicSocketAddress initial_peer_address, - TestConnectionHelper* helper, - TestAlarmFactory* alarm_factory, - TestPacketWriter* writer, - Perspective perspective, + TestConnectionHelper* helper, TestAlarmFactory* alarm_factory, + TestPacketWriter* writer, Perspective perspective, ParsedQuicVersion version) - : QuicConnection(connection_id, - initial_self_address, - initial_peer_address, - helper, - alarm_factory, - writer, - /* owns_writer= */ false, - perspective, + : QuicConnection(connection_id, initial_self_address, + initial_peer_address, helper, alarm_factory, writer, + /* owns_writer= */ false, perspective, SupportedVersions(version)), notifier_(nullptr) { writer->set_perspective(perspective); @@ -215,11 +208,9 @@ class TestConnection : public QuicConnection { QuicConnectionPeer::SetLossAlgorithm(this, loss_algorithm); } - void SendPacket(EncryptionLevel /*level*/, - uint64_t packet_number, + void SendPacket(EncryptionLevel /*level*/, uint64_t packet_number, std::unique_ptr<QuicPacket> packet, - HasRetransmittableData retransmittable, - bool has_ack, + HasRetransmittableData retransmittable, bool has_ack, bool has_pending_frames) { ScopedPacketFlusher flusher(this); char buffer[kMaxOutgoingPacketSize]; @@ -239,8 +230,7 @@ class TestConnection : public QuicConnection { } QuicConsumedData SaveAndSendStreamData(QuicStreamId id, - const struct iovec* iov, - int iov_count, + const struct iovec* iov, int iov_count, size_t total_length, QuicStreamOffset offset, StreamSendingState state) { @@ -555,8 +545,7 @@ enum class AckResponse { kDefer, kImmediate }; // Run tests with combinations of {ParsedQuicVersion, AckResponse}. struct TestParams { - TestParams(ParsedQuicVersion version, - AckResponse ack_response, + TestParams(ParsedQuicVersion version, AckResponse ack_response, bool no_stop_waiting) : version(version), ack_response(ack_response), @@ -609,30 +598,20 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> { protected: QuicConnectionTest() : connection_id_(TestConnectionId()), - framer_(SupportedVersions(version()), - QuicTime::Zero(), - Perspective::IS_CLIENT, - connection_id_.length()), + framer_(SupportedVersions(version()), QuicTime::Zero(), + Perspective::IS_CLIENT, connection_id_.length()), send_algorithm_(new StrictMock<MockSendAlgorithm>), loss_algorithm_(new MockLossAlgorithm()), helper_(new TestConnectionHelper(&clock_, &random_generator_)), alarm_factory_(new TestAlarmFactory()), - peer_framer_(SupportedVersions(version()), - QuicTime::Zero(), - Perspective::IS_SERVER, - connection_id_.length()), - peer_creator_(connection_id_, - &peer_framer_, + peer_framer_(SupportedVersions(version()), QuicTime::Zero(), + Perspective::IS_SERVER, connection_id_.length()), + peer_creator_(connection_id_, &peer_framer_, /*delegate=*/nullptr), writer_( new TestPacketWriter(version(), &clock_, Perspective::IS_CLIENT)), - connection_(connection_id_, - kSelfAddress, - kPeerAddress, - helper_.get(), - alarm_factory_.get(), - writer_.get(), - Perspective::IS_CLIENT, + connection_(connection_id_, kSelfAddress, kPeerAddress, helper_.get(), + alarm_factory_.get(), writer_.get(), Perspective::IS_CLIENT, version()), creator_(QuicConnectionPeer::GetPacketCreator(&connection_)), manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)), @@ -872,16 +851,14 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> { QuicReceivedPacket(encrypted_buffer, encrypted_length, clock_.Now())); } - size_t ProcessFramePacketAtLevel(uint64_t number, - QuicFrame frame, + size_t ProcessFramePacketAtLevel(uint64_t number, QuicFrame frame, EncryptionLevel level) { QuicFrames frames; frames.push_back(frame); return ProcessFramesPacketAtLevel(number, frames, level); } - size_t ProcessFramesPacketAtLevel(uint64_t number, - const QuicFrames& frames, + size_t ProcessFramesPacketAtLevel(uint64_t number, const QuicFrames& frames, EncryptionLevel level) { QuicPacketHeader header = ConstructPacketHeader(number, level); // Set the correct encryption level and encrypter on peer_creator and @@ -1025,8 +1002,7 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> { return encrypted_length; } - size_t ProcessDataPacketAtLevel(uint64_t number, - bool has_stop_waiting, + size_t ProcessDataPacketAtLevel(uint64_t number, bool has_stop_waiting, EncryptionLevel level) { std::unique_ptr<QuicPacket> packet( ConstructDataPacket(number, has_stop_waiting, level)); @@ -1055,8 +1031,7 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> { QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false)); } - QuicByteCount SendStreamDataToPeer(QuicStreamId id, - absl::string_view data, + QuicByteCount SendStreamDataToPeer(QuicStreamId id, absl::string_view data, QuicStreamOffset offset, StreamSendingState state, QuicPacketNumber* last_packet) { @@ -1084,8 +1059,7 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> { .Times(AnyNumber()); } - void SendRstStream(QuicStreamId id, - QuicRstStreamErrorCode error, + void SendRstStream(QuicStreamId id, QuicRstStreamErrorCode error, QuicStreamOffset bytes_written) { notifier_.WriteOrBufferRstStream(id, error, bytes_written); connection_.OnStreamReset(id, error); @@ -4543,179 +4517,6 @@ TEST_P(QuicConnectionTest, TLP) { EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked); } -TEST_P(QuicConnectionTest, TailLossProbeDelayForStreamDataInTLPR) { - if (connection_.PtoEnabled() || GetQuicReloadableFlag(quic_deprecate_tlpr)) { - return; - } - - // Set TLPR from QuicConfig. - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - QuicConfig config; - QuicTagVector options; - options.push_back(kTLPR); - config.SetConnectionOptionsToSend(options); - connection_.SetFromConfig(config); - connection_.SetMaxTailLossProbes(1); - - SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr); - EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked); - - QuicTime retransmission_time = - connection_.GetRetransmissionAlarm()->deadline(); - EXPECT_NE(QuicTime::Zero(), retransmission_time); - QuicTime::Delta expected_tlp_delay = - 0.5 * manager_->GetRttStats()->SmoothedOrInitialRtt(); - EXPECT_EQ(expected_tlp_delay, retransmission_time - clock_.Now()); - - EXPECT_EQ(QuicPacketNumber(1u), writer_->header().packet_number); - // Simulate firing of the retransmission alarm and retransmit the packet. - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2), _, _)); - clock_.AdvanceTime(retransmission_time - clock_.Now()); - connection_.GetRetransmissionAlarm()->Fire(); - EXPECT_EQ(QuicPacketNumber(2u), writer_->header().packet_number); - - // We do not raise the high water mark yet. - EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked); -} - -TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) { - if (connection_.PtoEnabled() || GetQuicReloadableFlag(quic_deprecate_tlpr)) { - return; - } - - // Set TLPR from QuicConfig. - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - QuicConfig config; - QuicTagVector options; - options.push_back(kTLPR); - config.SetConnectionOptionsToSend(options); - QuicConfigPeer::SetNegotiated(&config, true); - if (connection_.version().UsesTls()) { - QuicConfigPeer::SetReceivedOriginalConnectionId( - &config, connection_.connection_id()); - QuicConfigPeer::SetReceivedInitialSourceConnectionId( - &config, connection_.connection_id()); - } - connection_.SetFromConfig(config); - connection_.SetMaxTailLossProbes(1); - - // Sets retransmittable on wire. - const QuicTime::Delta retransmittable_on_wire_timeout = - QuicTime::Delta::FromMilliseconds(50); - connection_.set_initial_retransmittable_on_wire_timeout( - retransmittable_on_wire_timeout); - - EXPECT_TRUE(connection_.connected()); - EXPECT_CALL(visitor_, ShouldKeepConnectionAlive()) - .WillRepeatedly(Return(true)); - EXPECT_FALSE(connection_.PathDegradingDetectionInProgress()); - EXPECT_FALSE(connection_.IsPathDegrading()); - EXPECT_FALSE(connection_.GetPingAlarm()->IsSet()); - - const char data[] = "data"; - size_t data_size = strlen(data); - QuicStreamOffset offset = 0; - - // Send a data packet. - connection_.SendStreamDataWithString(1, data, offset, NO_FIN); - offset += data_size; - - // Path degrading alarm should be set when there is a retransmittable packet - // on the wire. - EXPECT_TRUE(connection_.PathDegradingDetectionInProgress()); - - // Verify the path degrading delay. - // First TLP with stream data. - QuicTime::Delta srtt = manager_->GetRttStats()->SmoothedOrInitialRtt(); - QuicTime::Delta expected_delay = 0.5 * srtt; - // Add 1st RTO. - QuicTime::Delta retransmission_delay = - QuicTime::Delta::FromMilliseconds(kDefaultRetransmissionTimeMs); - expected_delay = expected_delay + retransmission_delay; - // Add 2nd RTO. - expected_delay = expected_delay + retransmission_delay * 2; - EXPECT_EQ(expected_delay, - QuicConnectionPeer::GetSentPacketManager(&connection_) - ->GetPathDegradingDelay()); - ASSERT_TRUE(connection_.sent_packet_manager().HasInFlightPackets()); - - // The ping alarm is set for the ping timeout, not the shorter - // retransmittable_on_wire_timeout. - EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); - EXPECT_EQ(connection_.ping_timeout(), - connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); - - // Receive an ACK for the data packet. - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame = - InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}}); - ProcessAckPacket(&frame); - - // Path degrading alarm should be cancelled as there is no more - // reretransmittable packets on the wire. - EXPECT_FALSE(connection_.PathDegradingDetectionInProgress()); - // The ping alarm should be set to the retransmittable_on_wire_timeout. - EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); - EXPECT_EQ(retransmittable_on_wire_timeout, - connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); - - // Simulate firing of the retransmittable on wire and send a PING. - clock_.AdvanceTime(retransmittable_on_wire_timeout); - connection_.GetPingAlarm()->Fire(); - - // The retransmission alarm and the path degrading alarm should be set as - // there is a retransmittable packet (PING) on the wire, - EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); - EXPECT_TRUE(connection_.PathDegradingDetectionInProgress()); - - // Verify the retransmission delay. - QuicTime::Delta min_rto_timeout = - QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs); - srtt = manager_->GetRttStats()->SmoothedOrInitialRtt(); - - // Arm RTO mode since there is only PING in flight. - expected_delay = manager_->GetPtoDelay(); - EXPECT_EQ(expected_delay, - connection_.GetRetransmissionAlarm()->deadline() - clock_.Now()); - - // Verify the path degrading delay = TLP delay + 1st RTO + 2nd RTO. - // Add 1st RTO. - expected_delay = std::max(2 * srtt, 1.5 * srtt + 0.5 * min_rto_timeout); - retransmission_delay = - std::max(manager_->GetRttStats()->smoothed_rtt() + - 4 * manager_->GetRttStats()->mean_deviation(), - min_rto_timeout); - expected_delay = expected_delay + retransmission_delay; - // Add 2nd RTO. - expected_delay = expected_delay + retransmission_delay * 2; - EXPECT_EQ(expected_delay, - QuicConnectionPeer::GetSentPacketManager(&connection_) - ->GetPathDegradingDelay()); - - // The ping alarm is set for the ping timeout, not the shorter - // retransmittable_on_wire_timeout. - EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); - EXPECT_EQ(connection_.ping_timeout(), - connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); - - // Advance a small period of time: 5ms. And receive a retransmitted ACK. - // This will update the retransmission alarm, verify the retransmission delay - // is correct. - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); - QuicAckFrame ack = InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}}); - ProcessAckPacket(&ack); - - // Verify the retransmission delay. - // First TLP without unacked stream data will no longer use TLPR. - // Arm RTO mode since there is only PING in flight. - expected_delay = manager_->GetPtoDelay(); - expected_delay = expected_delay - QuicTime::Delta::FromMilliseconds(5); - EXPECT_EQ(expected_delay, - connection_.GetRetransmissionAlarm()->deadline() - clock_.Now()); -} - TEST_P(QuicConnectionTest, RTO) { if (connection_.PtoEnabled()) { return; @@ -10672,7 +10473,12 @@ void QuicConnectionTest::TestClientRetryHandling( return; } - // These values come from draft-ietf-quic-tls Appendix A.4. + // These values come from draft-ietf-quic-v2 Appendix A.4. + uint8_t retry_packet_rfcv2[] = { + 0xcf, 0x70, 0x9a, 0x50, 0xc4, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, + 0x42, 0x62, 0xb5, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x1d, 0xc7, 0x11, 0x30, + 0xcd, 0x1e, 0xd3, 0x9d, 0x6e, 0xfc, 0xee, 0x5c, 0x85, 0x80, 0x65, 0x01}; + // These values come from RFC9001 Appendix A.4. uint8_t retry_packet_rfcv1[] = { 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x04, 0xa2, 0x65, 0xba, @@ -10684,7 +10490,10 @@ void QuicConnectionTest::TestClientRetryHandling( uint8_t* retry_packet; size_t retry_packet_length; - if (version() == ParsedQuicVersion::RFCv1()) { + if (version() == ParsedQuicVersion::V2Draft01()) { + retry_packet = retry_packet_rfcv2; + retry_packet_length = ABSL_ARRAYSIZE(retry_packet_rfcv2); + } else if (version() == ParsedQuicVersion::RFCv1()) { retry_packet = retry_packet_rfcv1; retry_packet_length = ABSL_ARRAYSIZE(retry_packet_rfcv1); } else if (version() == ParsedQuicVersion::Draft29()) { @@ -12719,30 +12528,6 @@ TEST_P(QuicConnectionTest, FailToWritePathResponse) { writer_->SetWriteBlocked(); ProcessFramesPacketWithAddresses(frames, kSelfAddress, kNewPeerAddress, ENCRYPTION_FORWARD_SECURE); - - if (GetQuicReloadableFlag(quic_drop_unsent_path_response)) { - EXPECT_EQ(0u, QuicConnectionPeer::NumPendingPathChallengesToResponse( - &connection_)); - return; - } - ASSERT_EQ( - 1u, QuicConnectionPeer::NumPendingPathChallengesToResponse(&connection_)); - - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1)); - writer_->SetWritable(); - connection_.OnCanWrite(); - EXPECT_EQ(1u, writer_->path_response_frames().size()); - // The final check is to ensure that the random data in the response - // matches the random data from the challenge. - EXPECT_EQ(0, memcmp(path_frame_buffer.data(), - &(writer_->path_response_frames().front().data_buffer), - sizeof(path_frame_buffer))); - EXPECT_EQ(1u, writer_->padding_frames().size()); - // PATH_RESPONSE should be sent in another packet to a different peer - // address. - EXPECT_EQ(kNewPeerAddress, writer_->last_write_peer_address()); - EXPECT_EQ( - 0u, QuicConnectionPeer::NumPendingPathChallengesToResponse(&connection_)); } // Regression test for b/168101557. @@ -12949,13 +12734,11 @@ TEST_P(QuicConnectionTest, InitiateKeyUpdate) { } TransportParameters params; - params.key_update_not_yet_supported = false; QuicConfig config; std::string error_details; EXPECT_THAT(config.ProcessTransportParameters( params, /* is_resumption = */ false, &error_details), IsQuicNoError()); - config.SetKeyUpdateSupportedLocally(); QuicConfigPeer::SetNegotiated(&config, true); if (connection_.version().UsesTls()) { QuicConfigPeer::SetReceivedOriginalConnectionId( @@ -13111,12 +12894,10 @@ TEST_P(QuicConnectionTest, InitiateKeyUpdateApproachingConfidentialityLimit) { std::string error_details; TransportParameters params; // Key update is enabled. - params.key_update_not_yet_supported = false; QuicConfig config; EXPECT_THAT(config.ProcessTransportParameters( params, /* is_resumption = */ false, &error_details), IsQuicNoError()); - config.SetKeyUpdateSupportedLocally(); QuicConfigPeer::SetNegotiated(&config, true); if (connection_.version().UsesTls()) { QuicConfigPeer::SetReceivedOriginalConnectionId( @@ -13209,12 +12990,10 @@ TEST_P(QuicConnectionTest, std::string error_details; TransportParameters params; // Key update is enabled. - params.key_update_not_yet_supported = false; QuicConfig config; EXPECT_THAT(config.ProcessTransportParameters( params, /* is_resumption = */ false, &error_details), IsQuicNoError()); - config.SetKeyUpdateSupportedLocally(); QuicConfigPeer::SetNegotiated(&config, true); if (connection_.version().UsesTls()) { QuicConfigPeer::SetReceivedOriginalConnectionId( @@ -13250,137 +13029,6 @@ TEST_P(QuicConnectionTest, TestConnectionCloseQuicErrorCode(QUIC_AEAD_LIMIT_REACHED); } -TEST_P(QuicConnectionTest, - CloseConnectionOnConfidentialityLimitKeyUpdateNotSupportedByPeer) { - if (!connection_.version().UsesTls()) { - return; - } - - // Set key update confidentiality limit to 1 packet. - SetQuicFlag(FLAGS_quic_key_update_confidentiality_limit, 1U); - // Use confidentiality limit for connection close of 3 packets. - constexpr size_t kConfidentialityLimit = 3U; - - std::string error_details; - TransportParameters params; - // Key update not enabled for this connection as peer doesn't support it. - params.key_update_not_yet_supported = true; - QuicConfig config; - EXPECT_THAT(config.ProcessTransportParameters( - params, /* is_resumption = */ false, &error_details), - IsQuicNoError()); - // Key update is supported locally. - config.SetKeyUpdateSupportedLocally(); - QuicConfigPeer::SetNegotiated(&config, true); - if (connection_.version().UsesTls()) { - QuicConfigPeer::SetReceivedOriginalConnectionId( - &config, connection_.connection_id()); - QuicConfigPeer::SetReceivedInitialSourceConnectionId( - &config, connection_.connection_id()); - } - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - connection_.SetFromConfig(config); - - connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); - connection_.SetEncrypter( - ENCRYPTION_FORWARD_SECURE, - std::make_unique<NullEncrypterWithConfidentialityLimit>( - Perspective::IS_CLIENT, kConfidentialityLimit)); - EXPECT_CALL(visitor_, GetHandshakeState()) - .WillRepeatedly(Return(HANDSHAKE_CONFIRMED)); - connection_.OnHandshakeComplete(); - - QuicPacketNumber last_packet; - // Send 3 packets and receive acks for them. Since key update is not enabled - // the confidentiality limit should be reached, forcing the connection to be - // closed. - SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); - EXPECT_TRUE(connection_.connected()); - // Receive ack for packet. - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame1 = InitAckFrame(1); - ProcessAckPacket(&frame1); - - SendStreamDataToPeer(2, "foo", 0, NO_FIN, &last_packet); - EXPECT_TRUE(connection_.connected()); - // Receive ack for packet. - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame2 = InitAckFrame(2); - ProcessAckPacket(&frame2); - - EXPECT_CALL(visitor_, OnConnectionClosed(_, _)); - SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet); - EXPECT_FALSE(connection_.connected()); - const QuicConnectionStats& stats = connection_.GetStats(); - EXPECT_EQ(0U, stats.key_update_count); - TestConnectionCloseQuicErrorCode(QUIC_AEAD_LIMIT_REACHED); -} - -TEST_P(QuicConnectionTest, - CloseConnectionOnConfidentialityLimitKeyUpdateNotEnabledLocally) { - if (!connection_.version().UsesTls()) { - return; - } - - // Set key update confidentiality limit to 1 packet. - SetQuicFlag(FLAGS_quic_key_update_confidentiality_limit, 1U); - // Use confidentiality limit for connection close of 3 packets. - constexpr size_t kConfidentialityLimit = 3U; - - std::string error_details; - TransportParameters params; - // Key update is supported by peer but not locally - // (config.SetKeyUpdateSupportedLocally is not called.) - params.key_update_not_yet_supported = false; - QuicConfig config; - EXPECT_THAT(config.ProcessTransportParameters( - params, /* is_resumption = */ false, &error_details), - IsQuicNoError()); - QuicConfigPeer::SetNegotiated(&config, true); - if (connection_.version().UsesTls()) { - QuicConfigPeer::SetReceivedOriginalConnectionId( - &config, connection_.connection_id()); - QuicConfigPeer::SetReceivedInitialSourceConnectionId( - &config, connection_.connection_id()); - } - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - connection_.SetFromConfig(config); - - connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); - connection_.SetEncrypter( - ENCRYPTION_FORWARD_SECURE, - std::make_unique<NullEncrypterWithConfidentialityLimit>( - Perspective::IS_CLIENT, kConfidentialityLimit)); - EXPECT_CALL(visitor_, GetHandshakeState()) - .WillRepeatedly(Return(HANDSHAKE_CONFIRMED)); - connection_.OnHandshakeComplete(); - - QuicPacketNumber last_packet; - // Send 3 packets and receive acks for them. Since key update is not enabled - // the confidentiality limit should be reached, forcing the connection to be - // closed. - SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); - EXPECT_TRUE(connection_.connected()); - // Receive ack for packet. - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame1 = InitAckFrame(1); - ProcessAckPacket(&frame1); - - SendStreamDataToPeer(2, "foo", 0, NO_FIN, &last_packet); - EXPECT_TRUE(connection_.connected()); - // Receive ack for packet. - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame2 = InitAckFrame(2); - ProcessAckPacket(&frame2); - - EXPECT_CALL(visitor_, OnConnectionClosed(_, _)); - SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet); - EXPECT_FALSE(connection_.connected()); - const QuicConnectionStats& stats = connection_.GetStats(); - EXPECT_EQ(0U, stats.key_update_count); - TestConnectionCloseQuicErrorCode(QUIC_AEAD_LIMIT_REACHED); -} - TEST_P(QuicConnectionTest, CloseConnectionOnIntegrityLimitDuringHandshake) { if (!connection_.version().UsesTls()) { return; @@ -13536,13 +13184,11 @@ TEST_P(QuicConnectionTest, CloseConnectionOnIntegrityLimitAcrossKeyPhases) { constexpr QuicPacketCount kIntegrityLimit = 4; TransportParameters params; - params.key_update_not_yet_supported = false; QuicConfig config; std::string error_details; EXPECT_THAT(config.ProcessTransportParameters( params, /* is_resumption = */ false, &error_details), IsQuicNoError()); - config.SetKeyUpdateSupportedLocally(); QuicConfigPeer::SetNegotiated(&config, true); if (connection_.version().UsesTls()) { QuicConfigPeer::SetReceivedOriginalConnectionId( @@ -13987,12 +13633,10 @@ TEST_P(QuicConnectionTest, // kept for key update, so enable key update for the test. std::string error_details; TransportParameters params; - params.key_update_not_yet_supported = false; QuicConfig config; EXPECT_THAT(config.ProcessTransportParameters( params, /* is_resumption = */ false, &error_details), IsQuicNoError()); - config.SetKeyUpdateSupportedLocally(); QuicConfigPeer::SetNegotiated(&config, true); QuicConfigPeer::SetReceivedOriginalConnectionId(&config, connection_.connection_id()); @@ -15265,14 +14909,8 @@ TEST_P(QuicConnectionTest, SendingZeroRttPacketsDoesNotPostponePTO) { connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT); connection_.SendStreamDataWithString(2, "foo", 0, NO_FIN); ASSERT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); - if (GetQuicReloadableFlag( - quic_donot_rearm_pto_on_application_data_during_handshake)) { - // PTO deadline should be unchanged. - EXPECT_EQ(pto_deadline, connection_.GetRetransmissionAlarm()->deadline()); - } else { - // PTO gets re-armed. - EXPECT_NE(pto_deadline, connection_.GetRetransmissionAlarm()->deadline()); - } + // PTO deadline should be unchanged. + EXPECT_EQ(pto_deadline, connection_.GetRetransmissionAlarm()->deadline()); } TEST_P(QuicConnectionTest, QueueingUndecryptablePacketsDoesntPostponePTO) { @@ -15547,6 +15185,25 @@ TEST_P(QuicConnectionTest, AckElicitingFrames) { } } +TEST_P(QuicConnectionTest, ReceivedChloAndAck) { + if (!version().HasIetfQuicFrames()) { + return; + } + set_perspective(Perspective::IS_SERVER); + QuicFrames frames; + QuicAckFrame ack_frame = InitAckFrame(1); + frames.push_back(MakeCryptoFrame()); + frames.push_back(QuicFrame(&ack_frame)); + + EXPECT_CALL(visitor_, OnCryptoFrame(_)) + .WillOnce(IgnoreResult(InvokeWithoutArgs( + &connection_, &TestConnection::SendCryptoStreamData))); + EXPECT_CALL(visitor_, BeforeConnectionCloseSent()); + EXPECT_CALL(visitor_, OnConnectionClosed(_, _)); + ProcessFramesPacketWithAddresses(frames, kSelfAddress, kPeerAddress, + ENCRYPTION_INITIAL); +} + // Regression test for b/201643321. TEST_P(QuicConnectionTest, FailedToRetransmitShlo) { if (!version().HasIetfQuicFrames()) { diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc index e9a99167f46..872b050bf9c 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc @@ -180,10 +180,6 @@ size_t QuicCryptoClientHandshaker::BufferSizeLimitForLevel( return QuicCryptoHandshaker::BufferSizeLimitForLevel(level); } -bool QuicCryptoClientHandshaker::KeyUpdateSupportedLocally() const { - return false; -} - std::unique_ptr<QuicDecrypter> QuicCryptoClientHandshaker::AdvanceKeysAndCreateCurrentOneRttDecrypter() { // Key update is only defined in QUIC+TLS. diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h index d9f10350553..c0c94b94cd8 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h @@ -51,7 +51,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker CryptoMessageParser* crypto_message_parser() override; HandshakeState GetHandshakeState() const override; size_t BufferSizeLimitForLevel(EncryptionLevel level) const override; - bool KeyUpdateSupportedLocally() const override; std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() override; std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc index 31d96a37794..27a2a469ace 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc @@ -114,10 +114,6 @@ size_t QuicCryptoClientStream::BufferSizeLimitForLevel( return handshaker_->BufferSizeLimitForLevel(level); } -bool QuicCryptoClientStream::KeyUpdateSupportedLocally() const { - return handshaker_->KeyUpdateSupportedLocally(); -} - std::unique_ptr<QuicDecrypter> QuicCryptoClientStream::AdvanceKeysAndCreateCurrentOneRttDecrypter() { return handshaker_->AdvanceKeysAndCreateCurrentOneRttDecrypter(); diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h index e37a5707ba5..34928b61f81 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h @@ -183,9 +183,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream // buffered at each encryption level. virtual size_t BufferSizeLimitForLevel(EncryptionLevel level) const = 0; - // Returns whether the implementation supports key update. - virtual bool KeyUpdateSupportedLocally() const = 0; - // Called to generate a decrypter for the next key phase. Each call should // generate the key for phase n+1. virtual std::unique_ptr<QuicDecrypter> @@ -283,7 +280,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream void SetServerApplicationStateForResumption( std::unique_ptr<ApplicationState> application_state) override; size_t BufferSizeLimitForLevel(EncryptionLevel level) const override; - bool KeyUpdateSupportedLocally() const override; std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() override; std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc index 28bfe4add34..55b7bf1a703 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc @@ -435,10 +435,6 @@ size_t QuicCryptoServerStream::BufferSizeLimitForLevel( return QuicCryptoHandshaker::BufferSizeLimitForLevel(level); } -bool QuicCryptoServerStream::KeyUpdateSupportedLocally() const { - return false; -} - std::unique_ptr<QuicDecrypter> QuicCryptoServerStream::AdvanceKeysAndCreateCurrentOneRttDecrypter() { // Key update is only defined in QUIC+TLS. diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h index cf4f6e00489..aca9e9a1170 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h @@ -66,7 +66,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream void SetServerApplicationStateForResumption( std::unique_ptr<ApplicationState> state) override; size_t BufferSizeLimitForLevel(EncryptionLevel level) const override; - bool KeyUpdateSupportedLocally() const override; std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() override; std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h index 86b691309bc..8197a5f4d75 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h @@ -149,9 +149,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream { // encryption level |level|. virtual size_t BufferSizeLimitForLevel(EncryptionLevel level) const; - // Returns whether the implementation supports key update. - virtual bool KeyUpdateSupportedLocally() const = 0; - // Called to generate a decrypter for the next key phase. Each call should // generate the key for phase n+1. virtual std::unique_ptr<QuicDecrypter> @@ -245,6 +242,10 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream { virtual void OnDataAvailableInSequencer(QuicStreamSequencer* sequencer, EncryptionLevel level); + QuicStreamSequencer* GetStreamSequencerForLevel(EncryptionLevel level) { + return &substreams_[level].sequencer; + } + private: // Data sent and received in CRYPTO frames is sent at multiple encryption // levels. Some of the state for the single logical crypto stream is split diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc index 1c18c7b7886..2c9ec0db082 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc @@ -80,7 +80,6 @@ class MockQuicCryptoStream : public QuicCryptoStream, HandshakeState GetHandshakeState() const override { return HANDSHAKE_START; } void SetServerApplicationStateForResumption( std::unique_ptr<ApplicationState> /*application_state*/) override {} - bool KeyUpdateSupportedLocally() const override { return false; } std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() override { return nullptr; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc index 4221d4fd9d0..0da608c6900 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc @@ -367,7 +367,7 @@ QuicDispatcher::~QuicDispatcher() { clear_stateless_reset_addresses_alarm_->PermanentCancel(); } reference_counted_session_map_.clear(); - closed_ref_counted_session_list_.clear(); + closed_session_list_.clear(); num_sessions_in_session_map_ = 0; } @@ -968,7 +968,7 @@ std::unique_ptr<QuicPerPacketContext> QuicDispatcher::GetPerPacketContext() void QuicDispatcher::DeleteSessions() { if (!write_blocked_list_.empty()) { - for (const auto& session : closed_ref_counted_session_list_) { + for (const auto& session : closed_session_list_) { if (write_blocked_list_.erase(session->connection()) != 0) { QUIC_BUG(quic_bug_12724_2) << "QuicConnection was in WriteBlockedList before destruction " @@ -976,7 +976,7 @@ void QuicDispatcher::DeleteSessions() { } } } - closed_ref_counted_session_list_.clear(); + closed_session_list_.clear(); } void QuicDispatcher::ClearStatelessResetAddresses() { @@ -1051,11 +1051,11 @@ void QuicDispatcher::OnConnectionClosed(QuicConnectionId server_connection_id, if (ShouldDestroySessionAsynchronously()) { // Set up alarm to fire immediately to bring destruction of this session // out of current call stack. - if (closed_ref_counted_session_list_.empty()) { + if (closed_session_list_.empty()) { delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(), QuicTime::Delta::Zero()); } - closed_ref_counted_session_list_.push_back(std::move(it->second)); + closed_session_list_.push_back(std::move(it->second)); } CleanUpSession(it->first, connection, error, error_details, source); for (const QuicConnectionId& cid : @@ -1377,11 +1377,6 @@ const ParsedQuicVersionVector& QuicDispatcher::GetSupportedVersions() { return version_manager_->GetSupportedVersions(); } -const ParsedQuicVersionVector& -QuicDispatcher::GetSupportedVersionsWithQuicCrypto() { - return version_manager_->GetSupportedVersionsWithQuicCrypto(); -} - void QuicDispatcher::DeliverPacketsToSession( const std::list<BufferedPacket>& packets, QuicSession* session) { diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h index eab326a9679..f22d58aa4c9 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h @@ -256,8 +256,6 @@ class QUIC_NO_EXPORT QuicDispatcher const ParsedQuicVersionVector& GetSupportedVersions(); - const ParsedQuicVersionVector& GetSupportedVersionsWithQuicCrypto(); - const QuicConfig& config() const { return *config_; } const QuicCryptoServerConfig* crypto_config() const { return crypto_config_; } @@ -414,8 +412,7 @@ class QUIC_NO_EXPORT QuicDispatcher std::unique_ptr<QuicTimeWaitListManager> time_wait_list_manager_; // The list of closed but not-yet-deleted sessions. - std::vector<std::unique_ptr<QuicSession>> closed_session_list_; - std::vector<std::shared_ptr<QuicSession>> closed_ref_counted_session_list_; + std::vector<std::shared_ptr<QuicSession>> closed_session_list_; // The helper used for all connections. std::unique_ptr<QuicConnectionHelperInterface> helper_; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc index ca4ae483af8..add5164d674 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc @@ -1521,7 +1521,7 @@ TEST_P(QuicDispatcherTestOneVersion, dispatcher_->ProcessPacket(server_address_, client_address, received_packet); } -static_assert(quic::SupportedVersions().size() == 5u, +static_assert(quic::SupportedVersions().size() == 6u, "Please add new RejectDeprecatedVersion tests above this assert " "when deprecating versions"); diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h index 6fb1e02ed4e..986b842ae8d 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h @@ -15,7 +15,7 @@ namespace quic { // Creates alarms that use the supplied EpollServer for timing and firing. class QUIC_EXPORT_PRIVATE QuicEpollAlarmFactory : public QuicAlarmFactory { public: - explicit QuicEpollAlarmFactory(QuicEpollServer* eps); + explicit QuicEpollAlarmFactory(QuicEpollServer* epoll_server); QuicEpollAlarmFactory(const QuicEpollAlarmFactory&) = delete; QuicEpollAlarmFactory& operator=(const QuicEpollAlarmFactory&) = delete; ~QuicEpollAlarmFactory() override; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.cc b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.cc index 8f532562aee..42d2e0230cc 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.cc @@ -12,11 +12,10 @@ namespace quic { QuicEpollConnectionHelper::QuicEpollConnectionHelper( - QuicEpollServer* epoll_server, - QuicAllocator type) + QuicEpollServer* epoll_server, QuicAllocator allocator_type) : clock_(epoll_server), random_generator_(QuicRandom::GetInstance()), - allocator_type_(type) {} + allocator_type_(allocator_type) {} QuicEpollConnectionHelper::~QuicEpollConnectionHelper() = default; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h index 0db6ed2cd0a..d363d6bc97f 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h @@ -30,7 +30,8 @@ enum class QuicAllocator { SIMPLE, BUFFER_POOL }; class QUIC_EXPORT_PRIVATE QuicEpollConnectionHelper : public QuicConnectionHelperInterface { public: - QuicEpollConnectionHelper(QuicEpollServer* eps, QuicAllocator allocator); + QuicEpollConnectionHelper(QuicEpollServer* epoll_server, + QuicAllocator allocator_type); QuicEpollConnectionHelper(const QuicEpollConnectionHelper&) = delete; QuicEpollConnectionHelper& operator=(const QuicEpollConnectionHelper&) = delete; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc index 74922c37721..c7da0ae17ba 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc @@ -279,6 +279,7 @@ const char* QuicErrorCodeToString(QuicErrorCode error) { RETURN_STRING_LITERAL(QUIC_TLS_UNEXPECTED_KEYING_MATERIAL_EXPORT_LABEL); RETURN_STRING_LITERAL(QUIC_TLS_KEYING_MATERIAL_EXPORTS_MISMATCH); RETURN_STRING_LITERAL(QUIC_TLS_KEYING_MATERIAL_EXPORT_NOT_AVAILABLE); + RETURN_STRING_LITERAL(QUIC_UNEXPECTED_DATA_BEFORE_ENCRYPTION_ESTABLISHED); RETURN_STRING_LITERAL(QUIC_LAST_ERROR); // Intentionally have no default case, so we'll break the build @@ -784,6 +785,8 @@ QuicErrorCodeToIetfMapping QuicErrorCodeToTransportErrorCode( return {true, static_cast<uint64_t>(PROTOCOL_VIOLATION)}; case QUIC_TLS_KEYING_MATERIAL_EXPORT_NOT_AVAILABLE: return {true, static_cast<uint64_t>(PROTOCOL_VIOLATION)}; + case QUIC_UNEXPECTED_DATA_BEFORE_ENCRYPTION_ESTABLISHED: + return {true, static_cast<uint64_t>(PROTOCOL_VIOLATION)}; case QUIC_LAST_ERROR: return {false, static_cast<uint64_t>(QUIC_LAST_ERROR)}; } diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h index 218b12ff1ea..0ecef013ff9 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h @@ -608,9 +608,10 @@ enum QuicErrorCode { QUIC_TLS_UNEXPECTED_KEYING_MATERIAL_EXPORT_LABEL = 208, QUIC_TLS_KEYING_MATERIAL_EXPORTS_MISMATCH = 209, QUIC_TLS_KEYING_MATERIAL_EXPORT_NOT_AVAILABLE = 210, + QUIC_UNEXPECTED_DATA_BEFORE_ENCRYPTION_ESTABLISHED = 211, // No error. Used as bound while iterating. - QUIC_LAST_ERROR = 211, + QUIC_LAST_ERROR = 212, }; // QuicErrorCodes is encoded as four octets on-the-wire when doing Google QUIC, // or a varint62 when doing IETF QUIC. Ensure that its value does not exceed diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h b/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h index b7b7f155cb4..069ba10b822 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h @@ -1,4 +1,4 @@ -// Copyright (c) 2021 The Chromium Authors. All rights reserved. +// Copyright (c) 2022 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,8 @@ #ifdef QUIC_FLAG +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_set_burst_token, false) + QUIC_FLAG(FLAGS_quic_restart_flag_quic_offload_pacing_to_usps2, false) // A testonly reloadable flag that will always default to false. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_testonly_default_false, false) @@ -16,15 +18,15 @@ QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_false, false) // A testonly restart flag that will always default to true. QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_true, true) // Donot check amplification limit if there is available pending_timer_transmission_count. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_check_amplification_limit_with_pending_timer_credit, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_check_amplification_limit_with_pending_timer_credit, true) // If bytes in flight has dipped below 1.25*MaxBW in the last round, do not exit PROBE_UP due to excess queue buildup. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_no_probe_up_exit_if_no_queue, true) // If true, 1) NEW_TOKENs sent from a IETF QUIC session will include the cached network parameters proto, 2) A min_rtt received from a validated token will be used to set the initial rtt, 3) Enable bandwidth resumption for IETF QUIC when connection options BWRE or BWMX exists. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_cached_network_parameters_to_address_token2, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_cached_network_parameters_to_address_token2, true) // If true, QUIC will default enable MTU discovery at server, with a target of 1450 bytes. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false) -// If true, QUIC won\'t honor the connection option TLPR -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_deprecate_tlpr, true) +// If true, QpackEncoder will stop emitting instructions on the encoder stream if amount of buffered data exceeds a hardcoded limit. +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_limit_encoder_stream_buffering, true) // If true, QuicGsoBatchWriter will support release time if it is available and the process has the permission to do so. QUIC_FLAG(FLAGS_quic_restart_flag_quic_support_release_time_for_gso, false) // If true, TlsServerHandshaker will be able to 1) request client cert, and 2) verify the client cert in the virtual method TlsServerHandshaker::VerifyCertChain. @@ -32,7 +34,7 @@ QUIC_FLAG(FLAGS_quic_restart_flag_quic_tls_server_support_client_cert, true) // If true, abort async QPACK header decompression in QuicSpdyStream::Reset() and in QuicSpdyStream::OnStreamReset(). QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_abort_qpack_on_stream_reset, true) // If true, accept empty crypto frame. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_accept_empty_crypto_frame, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_accept_empty_crypto_frame, true) // If true, ack frequency frame can be sent from server to client. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_can_send_ack_frequency, true) // If true, allow client to enable BBRv2 on server via connection option \'B2ON\'. @@ -69,12 +71,8 @@ QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_single_ack_in_packet2, false) QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_no_select_cert_if_disconnected, true) // If true, do not count bytes sent/received on the alternative path into the bytes sent/received on the default path. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_count_bytes_on_alternative_path_seperately, true) -// If true, do not re-arm PTO while sending application data during handshake. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_rearm_pto_on_application_data_during_handshake, true) // If true, do not use the gQUIC common certificate set for certificate compression. QUIC_FLAG(FLAGS_quic_restart_flag_quic_no_common_cert_set, true) -// If true, drop unsent PATH_RESPONSEs and rely on peer\'s retry. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_drop_unsent_path_response, true) // If true, enable server retransmittable on wire PING. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_server_on_wire_ping, true) // If true, flush pending frames as well as pending padding bytes on connection migration. @@ -99,12 +97,12 @@ QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_require_handshake_confirmation, false) QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_reset_per_packet_state_for_undecryptable_packets, true) // If true, send PATH_RESPONSE upon receiving PATH_CHALLENGE regardless of perspective. --gfe2_reloadable_flag_quic_start_peer_migration_earlier has to be true before turn on this flag. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_path_response2, true) +// If true, server proactively retires client issued connection ID on reverse path validation failure. +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_retire_cid_on_reverse_path_validation_failure, false) // If true, set burst token to 2 in cwnd bootstrapping experiment. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_bursts, false) // If true, stop resetting ideal_next_packet_send_time_ in pacing sender. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time, false) -// If true, suppress crypto data write in mid of packet processing. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_suppress_write_mid_packet_processing, true) // If true, use BBRv2 as the default congestion controller. Takes precedence over --quic_default_to_bbr. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr_v2, false) // If true, use max(max_bw, send_rate) as the estimated bandwidth in QUIC\'s MaxAckHeightTracker. @@ -117,22 +115,18 @@ QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, fa QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path3, true) // If true, when client attempts TLS resumption, use token in session_cache_ instead of cached_states_ in QuicCryptoClientConfig. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_use_token_in_session_cache, true) -// When receiving STOP_SENDING, send a RESET_STREAM with a matching error code. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_match_ietf_reset_code, true) // When the flag is true, exit STARTUP after the same number of loss events as PROBE_UP. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_startup_probe_up_loss_events, true) -// When true, QUIC server will ignore received key_update_not_yet_supported transport parameter. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ignore_key_update_not_yet_supported, true) -// When true, QUIC server will ignore received user agent transport parameter and rely on getting that information from HTTP headers. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ignore_user_agent_transport_parameter, true) // When true, QUIC will both send and validate the version_information transport parameter. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_version_information, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_version_information, true) // When true, defaults to BBR congestion control instead of Cubic. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr, false) // When true, prevents QUIC\'s PacingSender from generating bursts when the congestion controller is CWND limited and not pacing limited. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_pacing_sender_bursts, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_pacing_sender_bursts, true) // When true, set the initial congestion control window from connection options in QuicSentPacketManager rather than TcpCubicSenderBytes. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_unified_iw_options, true) +// When true, support draft-ietf-quic-v2-01 +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_version_2_draft_01, false) // When true, the B203 connection option causes the Bbr2Sender to ignore inflight_hi during PROBE_UP and increase it when the bytes delivered without loss are higher. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_ignore_inflight_hi_in_probe_up, true) // When true, the B205 connection option enables extra acked in STARTUP, and B204 adds new logic to decrease it whenever max bandwidth increases. diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc index 79ace5a642d..da28e4c5b5c 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc @@ -170,8 +170,7 @@ QuicPacketNumberLength ReadSequenceNumberLength(uint8_t flags) { } } -QuicPacketNumberLength ReadAckPacketNumberLength( - uint8_t flags) { +QuicPacketNumberLength ReadAckPacketNumberLength(uint8_t flags) { switch (flags & PACKET_FLAGS_8BYTE_PACKET) { case PACKET_FLAGS_8BYTE_PACKET: return PACKET_6BYTE_PACKET_NUMBER; @@ -197,16 +196,17 @@ QuicPacketNumberLength GetShortHeaderPacketNumberLength(uint8_t type) { return static_cast<QuicPacketNumberLength>((type & 0x03) + 1); } -uint8_t LongHeaderTypeToOnWireValue(QuicLongHeaderType type) { +uint8_t LongHeaderTypeToOnWireValue(QuicLongHeaderType type, + const ParsedQuicVersion& version) { switch (type) { case INITIAL: - return 0; + return version.UsesV2PacketTypes() ? (1 << 4) : 0; case ZERO_RTT_PROTECTED: - return 1 << 4; + return version.UsesV2PacketTypes() ? (2 << 4) : (1 << 4); case HANDSHAKE: - return 2 << 4; + return version.UsesV2PacketTypes() ? (3 << 4) : (2 << 4); case RETRY: - return 3 << 4; + return version.UsesV2PacketTypes() ? 0 : (3 << 4); case VERSION_NEGOTIATION: return 0xF0; // Value does not matter default: @@ -215,27 +215,22 @@ uint8_t LongHeaderTypeToOnWireValue(QuicLongHeaderType type) { } } -bool GetLongHeaderType(uint8_t type, QuicLongHeaderType* long_header_type) { +QuicLongHeaderType GetLongHeaderType(uint8_t type, + const ParsedQuicVersion& version) { QUICHE_DCHECK((type & FLAGS_LONG_HEADER)); switch ((type & 0x30) >> 4) { case 0: - *long_header_type = INITIAL; - break; + return version.UsesV2PacketTypes() ? RETRY : INITIAL; case 1: - *long_header_type = ZERO_RTT_PROTECTED; - break; + return version.UsesV2PacketTypes() ? INITIAL : ZERO_RTT_PROTECTED; case 2: - *long_header_type = HANDSHAKE; - break; + return version.UsesV2PacketTypes() ? ZERO_RTT_PROTECTED : HANDSHAKE; case 3: - *long_header_type = RETRY; - break; + return version.UsesV2PacketTypes() ? HANDSHAKE : RETRY; default: QUIC_BUG(quic_bug_10850_4) << "Unreachable statement"; - *long_header_type = INVALID_PACKET_TYPE; - return false; + return INVALID_PACKET_TYPE; } - return true; } QuicPacketNumberLength GetLongHeaderPacketNumberLength(uint8_t type) { @@ -331,8 +326,7 @@ bool IsValidFullPacketNumber(uint64_t full_packet_number, return full_packet_number > 0 || version.HasIetfQuicFrames(); } -bool AppendIetfConnectionIds(bool version_flag, - bool use_length_prefix, +bool AppendIetfConnectionIds(bool version_flag, bool use_length_prefix, QuicConnectionId destination_connection_id, QuicConnectionId source_connection_id, QuicDataWriter* writer) { @@ -412,6 +406,7 @@ QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions, perspective_(perspective), validate_flags_(true), process_timestamps_(false), + max_receive_timestamps_per_ack_(std::numeric_limits<uint32_t>::max()), receive_timestamps_exponent_(0), creation_time_(creation_time), last_timestamp_(QuicTime::Delta::Zero()), @@ -476,13 +471,14 @@ size_t QuicFramer::GetMessageFrameSize(QuicTransportVersion version, } // static -size_t QuicFramer::GetMinAckFrameSize(QuicTransportVersion version, - const QuicAckFrame& ack_frame, - uint32_t local_ack_delay_exponent) { +size_t QuicFramer::GetMinAckFrameSize( + QuicTransportVersion version, const QuicAckFrame& ack_frame, + uint32_t local_ack_delay_exponent, + bool use_ietf_ack_with_receive_timestamp) { if (VersionHasIetfQuicFrames(version)) { // The minimal ack frame consists of the following fields: Largest - // Acknowledged, ACK Delay, 0 ACK Block Count, First ACK Block and ECN - // counts. + // Acknowledged, ACK Delay, 0 ACK Block Count, First ACK Block and either 0 + // Timestamp Range Count or ECN counts. // Type byte + largest acked. size_t min_size = kQuicFrameTypeSize + @@ -496,10 +492,14 @@ size_t QuicFramer::GetMinAckFrameSize(QuicTransportVersion version, min_size += QuicDataWriter::GetVarInt62Len( ack_frame.packets.Empty() ? 0 : ack_frame.packets.rbegin()->Length() - 1); - // ECN counts. - if (ack_frame.ecn_counters_populated && - (ack_frame.ect_0_count || ack_frame.ect_1_count || - ack_frame.ecn_ce_count)) { + + if (use_ietf_ack_with_receive_timestamp) { + // 0 Timestamp Range Count. + min_size += QuicDataWriter::GetVarInt62Len(0); + } else if (ack_frame.ecn_counters_populated && + (ack_frame.ect_0_count || ack_frame.ect_1_count || + ack_frame.ecn_ce_count)) { + // ECN counts. min_size += (QuicDataWriter::GetVarInt62Len(ack_frame.ect_0_count) + QuicDataWriter::GetVarInt62Len(ack_frame.ect_1_count) + QuicDataWriter::GetVarInt62Len(ack_frame.ecn_ce_count)); @@ -533,8 +533,7 @@ size_t QuicFramer::GetRstStreamFrameSize(QuicTransportVersion version, // static size_t QuicFramer::GetConnectionCloseFrameSize( - QuicTransportVersion version, - const QuicConnectionCloseFrame& frame) { + QuicTransportVersion version, const QuicConnectionCloseFrame& frame) { if (!VersionHasIetfQuicFrames(version)) { // Not IETF QUIC, return Google QUIC CONNECTION CLOSE frame size. return kQuicFrameTypeSize + kQuicErrorCodeSize + @@ -569,8 +568,7 @@ size_t QuicFramer::GetMinGoAwayFrameSize() { // static size_t QuicFramer::GetWindowUpdateFrameSize( - QuicTransportVersion version, - const QuicWindowUpdateFrame& frame) { + QuicTransportVersion version, const QuicWindowUpdateFrame& frame) { if (!VersionHasIetfQuicFrames(version)) { return kQuicFrameTypeSize + kQuicMaxStreamIdSize + kQuicMaxStreamOffsetSize; } @@ -599,8 +597,7 @@ size_t QuicFramer::GetMaxStreamsFrameSize(QuicTransportVersion version, // static size_t QuicFramer::GetStreamsBlockedFrameSize( - QuicTransportVersion version, - const QuicStreamsBlockedFrame& frame) { + QuicTransportVersion version, const QuicStreamsBlockedFrame& frame) { if (!VersionHasIetfQuicFrames(version)) { QUIC_BUG(quic_bug_10850_10) << "In version " << version @@ -658,8 +655,7 @@ size_t QuicFramer::GetPathResponseFrameSize( // static size_t QuicFramer::GetRetransmittableControlFrameSize( - QuicTransportVersion version, - const QuicFrame& frame) { + QuicTransportVersion version, const QuicFrame& frame) { switch (frame.type) { case PING_FRAME: // Ping has no payload. @@ -793,11 +789,8 @@ bool QuicFramer::IsSupportedVersion(const ParsedQuicVersion version) const { } size_t QuicFramer::GetSerializedFrameLength( - const QuicFrame& frame, - size_t free_bytes, - bool first_frame, - bool last_frame, - QuicPacketNumberLength packet_number_length) { + const QuicFrame& frame, size_t free_bytes, bool first_frame, + bool last_frame, QuicPacketNumberLength packet_number_length) { // Prevent a rare crash reported in b/19458523. if (frame.type == ACK_FRAME && frame.ack_frame == nullptr) { QUIC_BUG(quic_bug_10850_13) @@ -835,9 +828,10 @@ size_t QuicFramer::GetSerializedFrameLength( } bool can_truncate = frame.type == ACK_FRAME && - free_bytes >= GetMinAckFrameSize(version_.transport_version, - *frame.ack_frame, - local_ack_delay_exponent_); + free_bytes >= + GetMinAckFrameSize(version_.transport_version, *frame.ack_frame, + local_ack_delay_exponent_, + UseIetfAckWithReceiveTimestamp(*frame.ack_frame)); if (can_truncate) { // Truncate the frame so the packet will not exceed kMaxOutgoingPacketSize. // Note that we may not use every byte of the writer in this case. @@ -887,8 +881,7 @@ bool QuicFramer::WriteIetfLongHeaderLength(const QuicPacketHeader& header, } size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header, - const QuicFrames& frames, - char* buffer, + const QuicFrames& frames, char* buffer, size_t packet_length, EncryptionLevel level) { QUIC_BUG_IF(quic_bug_12975_2, @@ -1345,10 +1338,8 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildIetfStatelessResetPacket( // static std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket( QuicConnectionId server_connection_id, - QuicConnectionId client_connection_id, - bool ietf_quic, - bool use_length_prefix, - const ParsedQuicVersionVector& versions) { + QuicConnectionId client_connection_id, bool ietf_quic, + bool use_length_prefix, const ParsedQuicVersionVector& versions) { QUIC_CODE_COUNT(quic_build_version_negotiation); if (use_length_prefix) { QUICHE_DCHECK(ietf_quic); @@ -1420,8 +1411,7 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket( // static std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildIetfVersionNegotiationPacket( - bool use_length_prefix, - QuicConnectionId server_connection_id, + bool use_length_prefix, QuicConnectionId server_connection_id, QuicConnectionId client_connection_id, const ParsedQuicVersionVector& versions) { QUIC_DVLOG(1) << "Building IETF version negotiation packet with" @@ -1566,8 +1556,7 @@ bool QuicFramer::ProcessPacketInternal(const QuicEncryptedPacket& packet) { } bool QuicFramer::ProcessVersionNegotiationPacket( - QuicDataReader* reader, - const QuicPacketHeader& header) { + QuicDataReader* reader, const QuicPacketHeader& header) { QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective_); QuicVersionNegotiationPacket packet( @@ -1667,8 +1656,7 @@ bool QuicFramer::ProcessRetryPacket(QuicDataReader* reader, // If the IETF length field only spans part of the outer packet, // then there is a coalesced packet after this one. void QuicFramer::MaybeProcessCoalescedPacket( - const QuicDataReader& encrypted_reader, - uint64_t remaining_bytes_length, + const QuicDataReader& encrypted_reader, uint64_t remaining_bytes_length, const QuicPacketHeader& header) { if (header.remaining_packet_length >= remaining_bytes_length) { // There is no coalesced packet. @@ -2221,7 +2209,7 @@ bool QuicFramer::AppendIetfHeaderTypeByte(const QuicPacketHeader& header, if (header.version_flag) { type = static_cast<uint8_t>( FLAGS_LONG_HEADER | FLAGS_FIXED_BIT | - LongHeaderTypeToOnWireValue(header.long_packet_type) | + LongHeaderTypeToOnWireValue(header.long_packet_type, version_) | PacketNumberLengthToOnWireValue(header.packet_number_length)); } else { type = static_cast<uint8_t>( @@ -2357,8 +2345,7 @@ const QuicTime::Delta QuicFramer::CalculateTimestampFromWire( uint64_t QuicFramer::CalculatePacketNumberFromWire( QuicPacketNumberLength packet_number_length, - QuicPacketNumber base_packet_number, - uint64_t packet_number) const { + QuicPacketNumber base_packet_number, uint64_t packet_number) const { // The new packet number might have wrapped to the next epoch, or // it might have reverse wrapped to the previous epoch, or it might // remain in the same epoch. Select the packet number closest to the @@ -2632,21 +2619,27 @@ bool QuicFramer::ProcessIetfHeaderTypeByte(QuicDataReader* reader, set_detailed_error("Fixed bit is 0 in long header."); return false; } - if (!GetLongHeaderType(type, &header->long_packet_type)) { - set_detailed_error("Illegal long header type value."); - return false; - } - if (header->long_packet_type == RETRY) { - if (!version().SupportsRetry()) { - set_detailed_error("RETRY not supported in this version."); + header->long_packet_type = GetLongHeaderType(type, header->version); + switch (header->long_packet_type) { + case INVALID_PACKET_TYPE: + set_detailed_error("Illegal long header type value."); return false; - } - if (perspective_ == Perspective::IS_SERVER) { - set_detailed_error("Client-initiated RETRY is invalid."); - return false; - } - } else if (!header->version.HasHeaderProtection()) { - header->packet_number_length = GetLongHeaderPacketNumberLength(type); + case RETRY: + if (!version().SupportsRetry()) { + set_detailed_error("RETRY not supported in this version."); + return false; + } + if (perspective_ == Perspective::IS_SERVER) { + set_detailed_error("Client-initiated RETRY is invalid."); + return false; + } + break; + default: + if (!header->version.HasHeaderProtection()) { + header->packet_number_length = + GetLongHeaderPacketNumberLength(type); + } + break; } } } @@ -2690,14 +2683,11 @@ bool QuicFramer::ProcessVersionLabel(QuicDataReader* reader, // static bool QuicFramer::ProcessAndValidateIetfConnectionIdLength( - QuicDataReader* reader, - ParsedQuicVersion version, - Perspective perspective, + QuicDataReader* reader, ParsedQuicVersion version, Perspective perspective, bool should_update_expected_server_connection_id_length, uint8_t* expected_server_connection_id_length, uint8_t* destination_connection_id_length, - uint8_t* source_connection_id_length, - std::string* detailed_error) { + uint8_t* source_connection_id_length, std::string* detailed_error) { uint8_t connection_id_lengths_byte; if (!reader->ReadBytes(&connection_id_lengths_byte, 1)) { *detailed_error = "Unable to read ConnectionId length."; @@ -2880,10 +2870,8 @@ bool QuicFramer::ProcessIetfPacketHeader(QuicDataReader* reader, } bool QuicFramer::ProcessAndCalculatePacketNumber( - QuicDataReader* reader, - QuicPacketNumberLength packet_number_length, - QuicPacketNumber base_packet_number, - uint64_t* packet_number) { + QuicDataReader* reader, QuicPacketNumberLength packet_number_length, + QuicPacketNumber base_packet_number, uint64_t* packet_number) { uint64_t wire_packet_number; if (!reader->ReadBytesToUInt64(packet_number_length, &wire_packet_number)) { return false; @@ -3131,8 +3119,7 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader, // static bool QuicFramer::IsIetfFrameTypeExpectedForEncryptionLevel( - uint64_t frame_type, - EncryptionLevel level) { + uint64_t frame_type, EncryptionLevel level) { switch (level) { case ENCRYPTION_INITIAL: case ENCRYPTION_HANDSHAKE: @@ -3560,8 +3547,7 @@ void SetBit(uint8_t* flags, bool val, uint8_t offset) { } } // namespace -bool QuicFramer::ProcessStreamFrame(QuicDataReader* reader, - uint8_t frame_type, +bool QuicFramer::ProcessStreamFrame(QuicDataReader* reader, uint8_t frame_type, QuicStreamFrame* frame) { uint8_t stream_flags = frame_type; @@ -3748,12 +3734,12 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, uint8_t frame_type) { // Determine the two lengths from the frame type: largest acked length, // ack block length. - const QuicPacketNumberLength ack_block_length = ReadAckPacketNumberLength( - ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits, - kActBlockLengthOffset)); - const QuicPacketNumberLength largest_acked_length = ReadAckPacketNumberLength( - ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits, - kLargestAckedOffset)); + const QuicPacketNumberLength ack_block_length = + ReadAckPacketNumberLength(ExtractBits( + frame_type, kQuicSequenceNumberLengthNumBits, kActBlockLengthOffset)); + const QuicPacketNumberLength largest_acked_length = + ReadAckPacketNumberLength(ExtractBits( + frame_type, kQuicSequenceNumberLengthNumBits, kLargestAckedOffset)); uint64_t largest_acked; if (!reader->ReadBytesToUInt64(largest_acked_length, &largest_acked)) { @@ -4179,7 +4165,7 @@ bool QuicFramer::ProcessIetfTimestampsInAckFrame(QuicPacketNumber largest_acked, // packet order. timestamp_delta = timestamp_delta << receive_timestamps_exponent_; if (i == 0 && j == 0) { - last_timestamp_ = CalculateTimestampFromWire(timestamp_delta); + last_timestamp_ = QuicTime::Delta::FromMicroseconds(timestamp_delta); } else { last_timestamp_ = last_timestamp_ - QuicTime::Delta::FromMicroseconds(timestamp_delta); @@ -4188,10 +4174,10 @@ bool QuicFramer::ProcessIetfTimestampsInAckFrame(QuicPacketNumber largest_acked, return false; } } - visitor_->OnAckTimestamp(packet_number - j, - creation_time_ + last_timestamp_); + visitor_->OnAckTimestamp(packet_number, creation_time_ + last_timestamp_); + packet_number--; } - packet_number = packet_number - (timestamp_count - 1); + packet_number--; } return true; } @@ -4364,11 +4350,9 @@ bool QuicFramer::ProcessMessageFrame(QuicDataReader* reader, // static absl::string_view QuicFramer::GetAssociatedDataFromEncryptedPacket( - QuicTransportVersion version, - const QuicEncryptedPacket& encrypted, + QuicTransportVersion version, const QuicEncryptedPacket& encrypted, QuicConnectionIdLength destination_connection_id_length, - QuicConnectionIdLength source_connection_id_length, - bool includes_version, + QuicConnectionIdLength source_connection_id_length, bool includes_version, bool includes_diversification_nonce, QuicPacketNumberLength packet_number_length, QuicVariableLengthIntegerLength retry_token_length_length, @@ -4397,8 +4381,7 @@ void QuicFramer::SetDecrypter(EncryptionLevel level, } void QuicFramer::SetAlternativeDecrypter( - EncryptionLevel level, - std::unique_ptr<QuicDecrypter> decrypter, + EncryptionLevel level, std::unique_ptr<QuicDecrypter> decrypter, bool latch_once_used) { QUICHE_DCHECK_NE(level, decrypter_level_); QUICHE_DCHECK(!version_.KnowsWhichDecrypterToUse()); @@ -4523,10 +4506,8 @@ void QuicFramer::SetInitialObfuscators(QuicConnectionId connection_id) { } size_t QuicFramer::EncryptInPlace(EncryptionLevel level, - QuicPacketNumber packet_number, - size_t ad_len, - size_t total_len, - size_t buffer_len, + QuicPacketNumber packet_number, size_t ad_len, + size_t total_len, size_t buffer_len, char* buffer) { QUICHE_DCHECK(packet_number.IsInitialized()); if (encrypter_[level] == nullptr) { @@ -4568,10 +4549,8 @@ constexpr bool IsLongHeader(uint8_t type_byte) { } // namespace -bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level, - char* buffer, - size_t buffer_len, - size_t ad_len) { +bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level, char* buffer, + size_t buffer_len, size_t ad_len) { QuicDataReader buffer_reader(buffer, buffer_len); QuicDataWriter buffer_writer(buffer_len, buffer); // The sample starts 4 bytes after the start of the packet number. @@ -4615,7 +4594,8 @@ bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level, QuicLongHeaderType header_type; if (IsLongHeader(type_byte)) { bitmask = 0x0f; - if (!GetLongHeaderType(type_byte, &header_type)) { + header_type = GetLongHeaderType(type_byte, version_); + if (header_type == INVALID_PACKET_TYPE) { return false; } } @@ -4781,8 +4761,7 @@ bool QuicFramer::RemoveHeaderProtection(QuicDataReader* reader, size_t QuicFramer::EncryptPayload(EncryptionLevel level, QuicPacketNumber packet_number, - const QuicPacket& packet, - char* buffer, + const QuicPacket& packet, char* buffer, size_t buffer_len) { QUICHE_DCHECK(packet_number.IsInitialized()); if (encrypter_[level] == nullptr) { @@ -4867,8 +4846,7 @@ bool QuicFramer::DecryptPayload(size_t udp_packet_length, absl::string_view encrypted, absl::string_view associated_data, const QuicPacketHeader& header, - char* decrypted_buffer, - size_t buffer_length, + char* decrypted_buffer, size_t buffer_length, size_t* decrypted_length, EncryptionLevel* decrypted_level) { if (!EncryptionLevelIsValid(decrypter_level_)) { @@ -5088,9 +5066,11 @@ size_t QuicFramer::GetIetfAckFrameSize(const QuicAckFrame& frame) { previous_smallest = iter->min(); } - // ECN counts. - if (frame.ecn_counters_populated && - (frame.ect_0_count || frame.ect_1_count || frame.ecn_ce_count)) { + if (UseIetfAckWithReceiveTimestamp(frame)) { + ack_frame_size += GetIetfAckFrameTimestampSize(frame); + } else if (frame.ecn_counters_populated && + (frame.ect_0_count || frame.ect_1_count || frame.ecn_ce_count)) { + // ECN counts. ack_frame_size += QuicDataWriter::GetVarInt62Len(frame.ect_0_count); ack_frame_size += QuicDataWriter::GetVarInt62Len(frame.ect_1_count); ack_frame_size += QuicDataWriter::GetVarInt62Len(frame.ecn_ce_count); @@ -5099,9 +5079,22 @@ size_t QuicFramer::GetIetfAckFrameSize(const QuicAckFrame& frame) { return ack_frame_size; } +size_t QuicFramer::GetIetfAckFrameTimestampSize(const QuicAckFrame& ack) { + QUICHE_DCHECK(!ack.received_packet_times.empty()); + std::string detailed_error; + absl::InlinedVector<AckTimestampRange, 2> timestamp_ranges = + GetAckTimestampRanges(ack, detailed_error); + if (!detailed_error.empty()) { + return 0; + } + + int64_t size = + FrameAckTimestampRanges(ack, timestamp_ranges, /*writer=*/nullptr); + return std::max<int64_t>(0, size); +} + size_t QuicFramer::GetAckFrameSize( - const QuicAckFrame& ack, - QuicPacketNumberLength /*packet_number_length*/) { + const QuicAckFrame& ack, QuicPacketNumberLength /*packet_number_length*/) { QUICHE_DCHECK(!ack.packets.Empty()); size_t ack_size = 0; @@ -5113,7 +5106,8 @@ size_t QuicFramer::GetAckFrameSize( GetMinPacketNumberLength(QuicPacketNumber(ack_info.max_block_length)); ack_size = GetMinAckFrameSize(version_.transport_version, ack, - local_ack_delay_exponent_); + local_ack_delay_exponent_, + UseIetfAckWithReceiveTimestamp(ack)); // First ack block length. ack_size += ack_block_length; if (ack_info.num_ack_blocks != 0) { @@ -5141,8 +5135,7 @@ size_t QuicFramer::GetAckFrameTimeStampSize(const QuicAckFrame& ack) { } size_t QuicFramer::ComputeFrameLength( - const QuicFrame& frame, - bool last_frame_in_packet, + const QuicFrame& frame, bool last_frame_in_packet, QuicPacketNumberLength packet_number_length) { switch (frame.type) { case STREAM_FRAME: @@ -5370,8 +5363,7 @@ bool QuicFramer::AppendPacketNumber(QuicPacketNumberLength packet_number_length, } // static -bool QuicFramer::AppendStreamId(size_t stream_id_length, - QuicStreamId stream_id, +bool QuicFramer::AppendStreamId(size_t stream_id_length, QuicStreamId stream_id, QuicDataWriter* writer) { if (stream_id_length == 0 || stream_id_length > 4) { QUIC_BUG(quic_bug_10850_77) @@ -5397,8 +5389,7 @@ bool QuicFramer::AppendStreamOffset(size_t offset_length, // static bool QuicFramer::AppendAckBlock(uint8_t gap, QuicPacketNumberLength length_length, - uint64_t length, - QuicDataWriter* writer) { + uint64_t length, QuicDataWriter* writer) { if (length == 0) { if (!IsValidPacketNumberLength(length_length)) { QUIC_BUG(quic_bug_10850_79) @@ -5613,7 +5604,8 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame, int32_t available_timestamp_and_ack_block_bytes = writer->capacity() - writer->length() - ack_block_length - GetMinAckFrameSize(version_.transport_version, frame, - local_ack_delay_exponent_) - + local_ack_delay_exponent_, + UseIetfAckWithReceiveTimestamp(frame)) - (new_ack_info.num_ack_blocks != 0 ? kNumberOfAckBlocksSize : 0); QUICHE_DCHECK_LE(0, available_timestamp_and_ack_block_bytes); @@ -5808,6 +5800,172 @@ bool QuicFramer::AppendTimestampsToAckFrame(const QuicAckFrame& frame, return true; } +absl::InlinedVector<QuicFramer::AckTimestampRange, 2> +QuicFramer::GetAckTimestampRanges(const QuicAckFrame& frame, + std::string& detailed_error) const { + detailed_error = ""; + if (frame.received_packet_times.empty()) { + return {}; + } + + absl::InlinedVector<AckTimestampRange, 2> timestamp_ranges; + + for (size_t r = 0; r < std::min<size_t>(max_receive_timestamps_per_ack_, + frame.received_packet_times.size()); + ++r) { + const size_t i = frame.received_packet_times.size() - 1 - r; + const QuicPacketNumber packet_number = frame.received_packet_times[i].first; + const QuicTime receive_timestamp = frame.received_packet_times[i].second; + + if (timestamp_ranges.empty()) { + if (receive_timestamp < creation_time_ || + LargestAcked(frame) < packet_number) { + detailed_error = + "The first packet is either received earlier than framer creation " + "time, or larger than largest acked packet."; + QUIC_BUG(quic_framer_ack_ts_first_packet_bad) + << detailed_error << " receive_timestamp:" << receive_timestamp + << ", framer_creation_time:" << creation_time_ + << ", packet_number:" << packet_number + << ", largest_acked:" << LargestAcked(frame); + return {}; + } + timestamp_ranges.push_back(AckTimestampRange()); + timestamp_ranges.back().gap = LargestAcked(frame) - packet_number; + timestamp_ranges.back().range_begin = i; + timestamp_ranges.back().range_end = i; + continue; + } + + const size_t prev_i = timestamp_ranges.back().range_end; + const QuicPacketNumber prev_packet_number = + frame.received_packet_times[prev_i].first; + const QuicTime prev_receive_timestamp = + frame.received_packet_times[prev_i].second; + + QUIC_DVLOG(3) << "prev_packet_number:" << prev_packet_number + << ", packet_number:" << packet_number; + if (prev_receive_timestamp < receive_timestamp || + prev_packet_number <= packet_number) { + detailed_error = "Packet number and/or receive time not in order."; + QUIC_BUG(quic_framer_ack_ts_packet_out_of_order) + << detailed_error << " packet_number:" << packet_number + << ", receive_timestamp:" << receive_timestamp + << ", prev_packet_number:" << prev_packet_number + << ", prev_receive_timestamp:" << prev_receive_timestamp; + return {}; + } + + if (prev_packet_number == packet_number + 1) { + timestamp_ranges.back().range_end = i; + } else { + timestamp_ranges.push_back(AckTimestampRange()); + timestamp_ranges.back().gap = prev_packet_number - 2 - packet_number; + timestamp_ranges.back().range_begin = i; + timestamp_ranges.back().range_end = i; + } + } + + return timestamp_ranges; +} + +int64_t QuicFramer::FrameAckTimestampRanges( + const QuicAckFrame& frame, + const absl::InlinedVector<AckTimestampRange, 2>& timestamp_ranges, + QuicDataWriter* writer) const { + int64_t size = 0; + auto maybe_write_var_int62 = [&](uint64_t value) { + size += QuicDataWriter::GetVarInt62Len(value); + if (writer != nullptr && !writer->WriteVarInt62(value)) { + return false; + } + return true; + }; + + if (!maybe_write_var_int62(timestamp_ranges.size())) { + return -1; + } + + // |effective_prev_time| is the exponent-encoded timestamp of the previous + // packet. + absl::optional<QuicTime> effective_prev_time; + for (const AckTimestampRange& range : timestamp_ranges) { + QUIC_DVLOG(3) << "Range: gap:" << range.gap << ", beg:" << range.range_begin + << ", end:" << range.range_end; + if (!maybe_write_var_int62(range.gap)) { + return -1; + } + + if (!maybe_write_var_int62(range.range_begin - range.range_end + 1)) { + return -1; + } + + for (int64_t i = range.range_begin; i >= range.range_end; --i) { + const QuicTime receive_timestamp = frame.received_packet_times[i].second; + uint64_t time_delta; + if (effective_prev_time.has_value()) { + time_delta = + (*effective_prev_time - receive_timestamp).ToMicroseconds(); + QUIC_DVLOG(3) << "time_delta:" << time_delta + << ", exponent:" << receive_timestamps_exponent_ + << ", effective_prev_time:" << *effective_prev_time + << ", recv_time:" << receive_timestamp; + time_delta = time_delta >> receive_timestamps_exponent_; + effective_prev_time = effective_prev_time.value() - + QuicTime::Delta::FromMicroseconds( + time_delta << receive_timestamps_exponent_); + } else { + // The first delta is from framer creation to the current receive + // timestamp (forward in time), whereas in the common case subsequent + // deltas move backwards in time. + time_delta = (receive_timestamp - creation_time_).ToMicroseconds(); + QUIC_DVLOG(3) << "First time_delta:" << time_delta + << ", exponent:" << receive_timestamps_exponent_ + << ", recv_time:" << receive_timestamp + << ", creation_time:" << creation_time_; + // Round up the first exponent-encoded time delta so that the next + // receive timestamp is guaranteed to be decreasing. + time_delta = ((time_delta - 1) >> receive_timestamps_exponent_) + 1; + effective_prev_time = + creation_time_ + QuicTime::Delta::FromMicroseconds( + time_delta << receive_timestamps_exponent_); + } + + if (!maybe_write_var_int62(time_delta)) { + return -1; + } + } + } + + return size; +} + +bool QuicFramer::AppendIetfTimestampsToAckFrame(const QuicAckFrame& frame, + QuicDataWriter* writer) { + QUICHE_DCHECK(!frame.received_packet_times.empty()); + std::string detailed_error; + const absl::InlinedVector<AckTimestampRange, 2> timestamp_ranges = + GetAckTimestampRanges(frame, detailed_error); + if (!detailed_error.empty()) { + set_detailed_error(std::move(detailed_error)); + return false; + } + + // Compute the size first using a null writer. + int64_t size = + FrameAckTimestampRanges(frame, timestamp_ranges, /*writer=*/nullptr); + if (size > static_cast<int64_t>(writer->capacity() - writer->length())) { + QUIC_DVLOG(1) << "Insufficient room to write IETF ack receive timestamps. " + "size_remain:" + << (writer->capacity() - writer->length()) + << ", size_needed:" << size; + // Write a Timestamp Range Count of 0. + return writer->WriteVarInt62(0); + } + + return FrameAckTimestampRanges(frame, timestamp_ranges, writer) > 0; +} + bool QuicFramer::AppendStopWaitingFrame(const QuicPacketHeader& header, const QuicStopWaitingFrame& frame, QuicDataWriter* writer) { @@ -5845,8 +6003,10 @@ bool QuicFramer::AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame, QuicDataWriter* writer) { uint8_t type = IETF_ACK; uint64_t ecn_size = 0; - if (frame.ecn_counters_populated && - (frame.ect_0_count || frame.ect_1_count || frame.ecn_ce_count)) { + if (UseIetfAckWithReceiveTimestamp(frame)) { + type = IETF_ACK_RECEIVE_TIMESTAMPS; + } else if (frame.ecn_counters_populated && + (frame.ect_0_count || frame.ect_1_count || frame.ecn_ce_count)) { // Change frame type to ACK_ECN if any ECN count is available. type = IETF_ACK_ECN; ecn_size = (QuicDataWriter::GetVarInt62Len(frame.ect_0_count) + @@ -5904,10 +6064,19 @@ bool QuicFramer::AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame, const uint64_t gap = previous_smallest - iter->max() - 1; const uint64_t ack_range = iter->Length() - 1; - if (writer->remaining() < ecn_size || - writer->remaining() - ecn_size < + if (type == IETF_ACK_RECEIVE_TIMESTAMPS && + writer->remaining() < static_cast<size_t>(QuicDataWriter::GetVarInt62Len(gap) + - QuicDataWriter::GetVarInt62Len(ack_range))) { + QuicDataWriter::GetVarInt62Len(ack_range) + + QuicDataWriter::GetVarInt62Len(0))) { + // If we write this ACK range we won't have space for a timestamp range + // count of 0. + break; + } else if (writer->remaining() < ecn_size || + writer->remaining() - ecn_size < + static_cast<size_t>( + QuicDataWriter::GetVarInt62Len(gap) + + QuicDataWriter::GetVarInt62Len(ack_range))) { // ACK range does not fit, truncate it. break; } @@ -5951,6 +6120,12 @@ bool QuicFramer::AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame, } } + if (type == IETF_ACK_RECEIVE_TIMESTAMPS) { + if (!AppendIetfTimestampsToAckFrame(frame, writer)) { + return false; + } + } + return true; } @@ -5976,8 +6151,7 @@ bool QuicFramer::AppendRstStreamFrame(const QuicRstStreamFrame& frame, } bool QuicFramer::AppendConnectionCloseFrame( - const QuicConnectionCloseFrame& frame, - QuicDataWriter* writer) { + const QuicConnectionCloseFrame& frame, QuicDataWriter* writer) { if (VersionHasIetfQuicFrames(version_.transport_version)) { return AppendIetfConnectionCloseFrame(frame, writer); } @@ -6084,8 +6258,7 @@ bool QuicFramer::RaiseError(QuicErrorCode error) { } bool QuicFramer::IsVersionNegotiation( - const QuicPacketHeader& header, - bool packet_has_ietf_packet_header) const { + const QuicPacketHeader& header, bool packet_has_ietf_packet_header) const { if (!packet_has_ietf_packet_header && perspective_ == Perspective::IS_CLIENT) { return header.version_flag; @@ -6097,8 +6270,7 @@ bool QuicFramer::IsVersionNegotiation( } bool QuicFramer::AppendIetfConnectionCloseFrame( - const QuicConnectionCloseFrame& frame, - QuicDataWriter* writer) { + const QuicConnectionCloseFrame& frame, QuicDataWriter* writer) { if (frame.close_type != IETF_QUIC_TRANSPORT_CONNECTION_CLOSE && frame.close_type != IETF_QUIC_APPLICATION_CONNECTION_CLOSE) { QUIC_BUG(quic_bug_10850_90) @@ -6135,8 +6307,7 @@ bool QuicFramer::AppendIetfConnectionCloseFrame( } bool QuicFramer::ProcessIetfConnectionCloseFrame( - QuicDataReader* reader, - QuicConnectionCloseType type, + QuicDataReader* reader, QuicConnectionCloseType type, QuicConnectionCloseFrame* frame) { frame->close_type = type; @@ -6263,8 +6434,7 @@ bool QuicFramer::ProcessIetfResetStreamFrame(QuicDataReader* reader, } bool QuicFramer::ProcessStopSendingFrame( - QuicDataReader* reader, - QuicStopSendingFrame* stop_sending_frame) { + QuicDataReader* reader, QuicStopSendingFrame* stop_sending_frame) { if (!ReadUint32FromVarint62(reader, IETF_STOP_SENDING, &stop_sending_frame->stream_id)) { return false; @@ -6281,8 +6451,7 @@ bool QuicFramer::ProcessStopSendingFrame( } bool QuicFramer::AppendStopSendingFrame( - const QuicStopSendingFrame& stop_sending_frame, - QuicDataWriter* writer) { + const QuicStopSendingFrame& stop_sending_frame, QuicDataWriter* writer) { if (!writer->WriteVarInt62(stop_sending_frame.stream_id)) { set_detailed_error("Can not write stop sending stream id"); return false; @@ -6438,8 +6607,7 @@ bool QuicFramer::ProcessStreamsBlockedFrame(QuicDataReader* reader, } bool QuicFramer::AppendNewConnectionIdFrame( - const QuicNewConnectionIdFrame& frame, - QuicDataWriter* writer) { + const QuicNewConnectionIdFrame& frame, QuicDataWriter* writer) { if (!writer->WriteVarInt62(frame.sequence_number)) { set_detailed_error("Can not write New Connection ID sequence number"); return false; @@ -6500,8 +6668,7 @@ bool QuicFramer::ProcessNewConnectionIdFrame(QuicDataReader* reader, } bool QuicFramer::AppendRetireConnectionIdFrame( - const QuicRetireConnectionIdFrame& frame, - QuicDataWriter* writer) { + const QuicRetireConnectionIdFrame& frame, QuicDataWriter* writer) { if (!writer->WriteVarInt62(frame.sequence_number)) { set_detailed_error("Can not write Retire Connection ID sequence number"); return false; @@ -6510,8 +6677,7 @@ bool QuicFramer::AppendRetireConnectionIdFrame( } bool QuicFramer::ProcessRetireConnectionIdFrame( - QuicDataReader* reader, - QuicRetireConnectionIdFrame* frame) { + QuicDataReader* reader, QuicRetireConnectionIdFrame* frame) { if (!reader->ReadVarInt62(&frame->sequence_number)) { set_detailed_error( "Unable to read retire connection ID frame sequence number."); @@ -6567,8 +6733,7 @@ uint8_t QuicFramer::GetStreamFrameTypeByte(const QuicStreamFrame& frame, } uint8_t QuicFramer::GetIetfStreamFrameTypeByte( - const QuicStreamFrame& frame, - bool last_frame_in_packet) const { + const QuicStreamFrame& frame, bool last_frame_in_packet) const { QUICHE_DCHECK(VersionHasIetfQuicFrames(version_.transport_version)); uint8_t type_byte = IETF_STREAM; if (!last_frame_in_packet) { @@ -6662,14 +6827,10 @@ QuicErrorCode QuicFramer::ParsePublicHeaderDispatcher( // static QuicErrorCode QuicFramer::ParsePublicHeaderGoogleQuic( - QuicDataReader* reader, - uint8_t* first_byte, - PacketHeaderFormat* format, - bool* version_present, - QuicVersionLabel* version_label, + QuicDataReader* reader, uint8_t* first_byte, PacketHeaderFormat* format, + bool* version_present, QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version, - QuicConnectionId* destination_connection_id, - std::string* detailed_error) { + QuicConnectionId* destination_connection_id, std::string* detailed_error) { *format = GOOGLE_QUIC_PACKET; *version_present = (*first_byte & PACKET_PUBLIC_FLAGS_VERSION) != 0; uint8_t destination_connection_id_length = 0; @@ -6696,10 +6857,8 @@ namespace { const QuicVersionLabel kProxVersionLabel = 0x50524F58; // "PROX" inline bool PacketHasLengthPrefixedConnectionIds( - const QuicDataReader& reader, - ParsedQuicVersion parsed_version, - QuicVersionLabel version_label, - uint8_t first_byte) { + const QuicDataReader& reader, ParsedQuicVersion parsed_version, + QuicVersionLabel version_label, uint8_t first_byte) { if (parsed_version.IsKnown()) { return parsed_version.HasLengthPrefixedConnectionIds(); } @@ -6733,18 +6892,15 @@ inline bool PacketHasLengthPrefixedConnectionIds( } inline bool ParseLongHeaderConnectionIds( - QuicDataReader* reader, - bool has_length_prefix, - QuicVersionLabel version_label, - QuicConnectionId* destination_connection_id, - QuicConnectionId* source_connection_id, - std::string* detailed_error) { + QuicDataReader& reader, bool has_length_prefix, + QuicVersionLabel version_label, QuicConnectionId& destination_connection_id, + QuicConnectionId& source_connection_id, std::string& detailed_error) { if (has_length_prefix) { - if (!reader->ReadLengthPrefixedConnectionId(destination_connection_id)) { - *detailed_error = "Unable to read destination connection ID."; + if (!reader.ReadLengthPrefixedConnectionId(&destination_connection_id)) { + detailed_error = "Unable to read destination connection ID."; return false; } - if (!reader->ReadLengthPrefixedConnectionId(source_connection_id)) { + if (!reader.ReadLengthPrefixedConnectionId(&source_connection_id)) { if (version_label == kProxVersionLabel) { // The "PROX" version does not follow the length-prefixed invariants, // and can therefore attempt to read a payload byte and interpret it @@ -6753,14 +6909,14 @@ inline bool ParseLongHeaderConnectionIds( // parsing as successful. return true; } - *detailed_error = "Unable to read source connection ID."; + detailed_error = "Unable to read source connection ID."; return false; } } else { // Parse connection ID lengths. uint8_t connection_id_lengths_byte; - if (!reader->ReadUInt8(&connection_id_lengths_byte)) { - *detailed_error = "Unable to read connection ID lengths."; + if (!reader.ReadUInt8(&connection_id_lengths_byte)) { + detailed_error = "Unable to read connection ID lengths."; return false; } uint8_t destination_connection_id_length = @@ -6775,16 +6931,16 @@ inline bool ParseLongHeaderConnectionIds( } // Read destination connection ID. - if (!reader->ReadConnectionId(destination_connection_id, - destination_connection_id_length)) { - *detailed_error = "Unable to read destination connection ID."; + if (!reader.ReadConnectionId(&destination_connection_id, + destination_connection_id_length)) { + detailed_error = "Unable to read destination connection ID."; return false; } // Read source connection ID. - if (!reader->ReadConnectionId(source_connection_id, - source_connection_id_length)) { - *detailed_error = "Unable to read source connection ID."; + if (!reader.ReadConnectionId(&source_connection_id, + source_connection_id_length)) { + detailed_error = "Unable to read source connection ID."; return false; } } @@ -6795,21 +6951,15 @@ inline bool ParseLongHeaderConnectionIds( // static QuicErrorCode QuicFramer::ParsePublicHeader( - QuicDataReader* reader, - uint8_t expected_destination_connection_id_length, - bool ietf_format, - uint8_t* first_byte, - PacketHeaderFormat* format, - bool* version_present, - bool* has_length_prefix, - QuicVersionLabel* version_label, - ParsedQuicVersion* parsed_version, + QuicDataReader* reader, uint8_t expected_destination_connection_id_length, + bool ietf_format, uint8_t* first_byte, PacketHeaderFormat* format, + bool* version_present, bool* has_length_prefix, + QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version, QuicConnectionId* destination_connection_id, QuicConnectionId* source_connection_id, QuicLongHeaderType* long_packet_type, QuicVariableLengthIntegerLength* retry_token_length_length, - absl::string_view* retry_token, - std::string* detailed_error) { + absl::string_view* retry_token, std::string* detailed_error) { *version_present = false; *has_length_prefix = false; *version_label = 0; @@ -6863,9 +7013,9 @@ QuicErrorCode QuicFramer::ParsePublicHeader( *reader, *parsed_version, *version_label, *first_byte); // Parse connection IDs. - if (!ParseLongHeaderConnectionIds(reader, *has_length_prefix, *version_label, - destination_connection_id, - source_connection_id, detailed_error)) { + if (!ParseLongHeaderConnectionIds(*reader, *has_length_prefix, *version_label, + *destination_connection_id, + *source_connection_id, *detailed_error)) { return QUIC_INVALID_PACKET_HEADER; } @@ -6875,14 +7025,20 @@ QuicErrorCode QuicFramer::ParsePublicHeader( } // Parse long packet type. - if (!GetLongHeaderType(*first_byte, long_packet_type)) { - *detailed_error = "Unable to parse long packet type."; - return QUIC_INVALID_PACKET_HEADER; - } + *long_packet_type = GetLongHeaderType(*first_byte, *parsed_version); - if (!parsed_version->SupportsRetry() || *long_packet_type != INITIAL) { - // Retry token is only present on initial packets for some versions. - return QUIC_NO_ERROR; + switch (*long_packet_type) { + case INVALID_PACKET_TYPE: + *detailed_error = "Unable to parse long packet type."; + return QUIC_INVALID_PACKET_HEADER; + case INITIAL: + if (!parsed_version->SupportsRetry()) { + // Retry token is only present on initial packets for some versions. + return QUIC_NO_ERROR; + } + break; + default: + return QUIC_NO_ERROR; } *retry_token_length_length = reader->PeekVarInt62Length(); @@ -6903,8 +7059,7 @@ QuicErrorCode QuicFramer::ParsePublicHeader( // static bool QuicFramer::WriteClientVersionNegotiationProbePacket( - char* packet_bytes, - QuicByteCount packet_length, + char* packet_bytes, QuicByteCount packet_length, const char* destination_connection_id_bytes, uint8_t destination_connection_id_length) { if (packet_bytes == nullptr) { @@ -6981,10 +7136,8 @@ bool QuicFramer::WriteClientVersionNegotiationProbePacket( // static bool QuicFramer::ParseServerVersionNegotiationProbeResponse( - const char* packet_bytes, - QuicByteCount packet_length, - char* source_connection_id_bytes, - uint8_t* source_connection_id_length_out, + const char* packet_bytes, QuicByteCount packet_length, + char* source_connection_id_bytes, uint8_t* source_connection_id_length_out, std::string* detailed_error) { if (detailed_error == nullptr) { QUIC_BUG(quic_bug_10850_101) << "Invalid error_details"; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_framer.h b/chromium/net/third_party/quiche/src/quic/core/quic_framer.h index 287888850b4..306f0491d58 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_framer.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_framer.h @@ -315,8 +315,15 @@ class QUIC_EXPORT_PRIVATE QuicFramer { process_timestamps_ = process_timestamps; } + // Sets the max number of receive timestamps to send per ACK frame. + // TODO(wub): Remove the const once timestamps are negotiated via + // transport params. + void set_max_receive_timestamps_per_ack(uint32_t max_timestamps) const { + max_receive_timestamps_per_ack_ = max_timestamps; + } + // Sets the exponent to use when writing/reading ACK receive timestamps. - void set_receive_timestamps_exponent(uint32_t exponent) { + void set_receive_timestamps_exponent(uint32_t exponent) const { receive_timestamps_exponent_ = exponent; } @@ -347,7 +354,8 @@ class QUIC_EXPORT_PRIVATE QuicFramer { // blocks. static size_t GetMinAckFrameSize(QuicTransportVersion version, const QuicAckFrame& ack_frame, - uint32_t local_ack_delay_exponent); + uint32_t local_ack_delay_exponent, + bool use_ietf_ack_with_receive_timestamp); // Size in bytes of a stop waiting frame. static size_t GetStopWaitingFrameSize( QuicPacketNumberLength packet_number_length); @@ -521,8 +529,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer { QuicDataWriter* writer); size_t AppendIetfFrames(const QuicFrames& frames, QuicDataWriter* writer); bool AppendStreamFrame(const QuicStreamFrame& frame, - bool last_frame_in_packet, - QuicDataWriter* writer); + bool no_stream_frame_length, QuicDataWriter* writer); bool AppendCryptoFrame(const QuicCryptoFrame& frame, QuicDataWriter* writer); bool AppendAckFrequencyFrame(const QuicAckFrequencyFrame& frame, QuicDataWriter* writer); @@ -728,6 +735,23 @@ class QUIC_EXPORT_PRIVATE QuicFramer { using NackRangeMap = std::map<QuicPacketNumber, uint8_t>; + // AckTimestampRange is a data structure derived from a QuicAckFrame. It is + // used to serialize timestamps in a IETF_ACK_RECEIVE_TIMESTAMPS frame. + struct QUIC_EXPORT_PRIVATE AckTimestampRange { + QuicPacketCount gap; + // |range_begin| and |range_end| are index(es) in + // QuicAckFrame.received_packet_times, representing a continuous range of + // packet numbers in descending order. |range_begin| >= |range_end|. + int64_t range_begin; // Inclusive + int64_t range_end; // Inclusive + }; + absl::InlinedVector<AckTimestampRange, 2> GetAckTimestampRanges( + const QuicAckFrame& frame, std::string& detailed_error) const; + int64_t FrameAckTimestampRanges( + const QuicAckFrame& frame, + const absl::InlinedVector<AckTimestampRange, 2>& timestamp_ranges, + QuicDataWriter* writer) const; + struct QUIC_EXPORT_PRIVATE AckFrameInfo { AckFrameInfo(); AckFrameInfo(const AckFrameInfo& other); @@ -896,6 +920,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer { // Computes the wire size in bytes of time stamps in |ack|. size_t GetAckFrameTimeStampSize(const QuicAckFrame& ack); + size_t GetIetfAckFrameTimestampSize(const QuicAckFrame& ack); // Computes the wire size in bytes of the |ack| frame. size_t GetAckFrameSize(const QuicAckFrame& ack, @@ -949,7 +974,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer { // |writer|, and return true if successful. bool AppendAckFrameAndTypeByte(const QuicAckFrame& frame, - QuicDataWriter* builder); + QuicDataWriter* writer); bool AppendTimestampsToAckFrame(const QuicAckFrame& frame, QuicDataWriter* writer); @@ -959,14 +984,16 @@ class QUIC_EXPORT_PRIVATE QuicFramer { // of the frame. bool AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame, QuicDataWriter* writer); + bool AppendIetfTimestampsToAckFrame(const QuicAckFrame& frame, + QuicDataWriter* writer); bool AppendStopWaitingFrame(const QuicPacketHeader& header, const QuicStopWaitingFrame& frame, - QuicDataWriter* builder); + QuicDataWriter* writer); bool AppendRstStreamFrame(const QuicRstStreamFrame& frame, - QuicDataWriter* builder); + QuicDataWriter* writer); bool AppendConnectionCloseFrame(const QuicConnectionCloseFrame& frame, - QuicDataWriter* builder); + QuicDataWriter* writer); bool AppendGoAwayFrame(const QuicGoAwayFrame& frame, QuicDataWriter* writer); bool AppendWindowUpdateFrame(const QuicWindowUpdateFrame& frame, QuicDataWriter* writer); @@ -1081,6 +1108,15 @@ class QUIC_EXPORT_PRIVATE QuicFramer { bool ProcessPacketInternal(const QuicEncryptedPacket& packet); + // Determine whether the given QuicAckFrame should be serialized with a + // IETF_ACK_RECEIVE_TIMESTAMPS frame type. + bool UseIetfAckWithReceiveTimestamp(const QuicAckFrame& frame) const { + return VersionHasIetfQuicFrames(version_.transport_version) && + process_timestamps_ && + std::min<uint64_t>(max_receive_timestamps_per_ack_, + frame.received_packet_times.size()) > 0; + } + std::string detailed_error_; QuicFramerVisitorInterface* visitor_; QuicErrorCode error_; @@ -1122,10 +1158,13 @@ class QUIC_EXPORT_PRIVATE QuicFramer { // The diversification nonce from the last received packet. DiversificationNonce last_nonce_; // If true, send and process timestamps in the ACK frame. - // TODO(ianswett): Remove the mutable once set_process_timestamps isn't const. + // TODO(ianswett): Remove the mutables once set_process_timestamps and + // set_receive_timestamp_exponent_ aren't const. mutable bool process_timestamps_; + // The max number of receive timestamps to send per ACK frame. + mutable uint32_t max_receive_timestamps_per_ack_; // The exponent to use when writing/reading ACK receive timestamps. - uint32_t receive_timestamps_exponent_; + mutable uint32_t receive_timestamps_exponent_; // The creation time of the connection, used to calculate timestamps. QuicTime creation_time_; // The last timestamp received if process_timestamps_ is true. diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc index 28b7c20345a..d24664dbded 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc @@ -38,6 +38,8 @@ using testing::_; using testing::ContainerEq; +using testing::Eq; +using testing::IsNull; using testing::Return; namespace quic { @@ -105,10 +107,8 @@ class TestEncrypter : public QuicEncrypter { bool SetHeaderProtectionKey(absl::string_view /*key*/) override { return true; } - bool EncryptPacket(uint64_t packet_number, - absl::string_view associated_data, - absl::string_view plaintext, - char* output, + bool EncryptPacket(uint64_t packet_number, absl::string_view associated_data, + absl::string_view plaintext, char* output, size_t* output_length, size_t /*max_output_length*/) override { packet_number_ = QuicPacketNumber(packet_number); @@ -162,10 +162,8 @@ class TestDecrypter : public QuicDecrypter { bool SetDiversificationNonce(const DiversificationNonce& /*key*/) override { return true; } - bool DecryptPacket(uint64_t packet_number, - absl::string_view associated_data, - absl::string_view ciphertext, - char* output, + bool DecryptPacket(uint64_t packet_number, absl::string_view associated_data, + absl::string_view ciphertext, char* output, size_t* output_length, size_t /*max_output_length*/) override { packet_number_ = QuicPacketNumber(packet_number); @@ -197,9 +195,7 @@ class TestDecrypter : public QuicDecrypter { }; std::unique_ptr<QuicEncryptedPacket> EncryptPacketWithTagAndPhase( - const QuicPacket& packet, - uint8_t tag, - bool phase) { + const QuicPacket& packet, uint8_t tag, bool phase) { std::string packet_data = std::string(packet.AsStringPiece()); if (phase) { packet_data[0] |= FLAGS_KEY_PHASE_BIT; @@ -692,9 +688,7 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> { decrypter_(new test::TestDecrypter()), version_(GetParam()), start_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(0x10)), - framer_(AllSupportedVersions(), - start_, - Perspective::IS_SERVER, + framer_(AllSupportedVersions(), start_, Perspective::IS_SERVER, kQuicDefaultConnectionIdLength) { framer_.set_version(version_); if (framer_.version().KnowsWhichDecrypterToUse()) { @@ -726,6 +720,19 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> { return (CreateQuicVersionLabel(version_) >> 8 * (3 - pos)) & 0xff; } + // Helper functions to take a v1 long header packet and make it v2. These are + // not needed for short header packets, but if sent, this function will exit + // cleanly. It needs to be called twice for coalesced packets (see references + // to length_of_first_coalesced_packet below for examples of how to do this). + inline void ReviseFirstByteByVersion(unsigned char packet_ietf[]) { + if (version_.UsesV2PacketTypes() && (packet_ietf[0] >= 0x80)) { + packet_ietf[0] = (packet_ietf[0] + 0x10) | 0xc0; + } + } + inline void ReviseFirstByteByVersion(PacketFragments& packet_ietf) { + ReviseFirstByteByVersion(&packet_ietf[0].fragment[0]); + } + bool CheckEncryption(QuicPacketNumber packet_number, QuicPacket* packet) { if (packet_number != encrypter_->packet_number_) { QUIC_LOG(ERROR) << "Encrypted incorrect packet number. expected " @@ -762,8 +769,7 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> { } bool CheckDecryption( - const QuicEncryptedPacket& encrypted, - bool includes_version, + const QuicEncryptedPacket& encrypted, bool includes_version, bool includes_diversification_nonce, QuicConnectionIdLength destination_connection_id_length, QuicConnectionIdLength source_connection_id_length, @@ -838,15 +844,13 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> { } } - if (expected_error.empty()) - continue; + if (expected_error.empty()) continue; CheckProcessingFails(*packet, i, expected_error, error_code); } } - void CheckProcessingFails(const QuicEncryptedPacket& packet, - size_t len, + void CheckProcessingFails(const QuicEncryptedPacket& packet, size_t len, std::string expected_error, QuicErrorCode error_code) { QuicEncryptedPacket encrypted(packet.data(), len, false); @@ -855,8 +859,7 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> { EXPECT_EQ(error_code, framer_.error()) << "len: " << len; } - void CheckProcessingFails(unsigned char* packet, - size_t len, + void CheckProcessingFails(unsigned char* packet, size_t len, std::string expected_error, QuicErrorCode error_code) { QuicEncryptedPacket encrypted(AsChars(packet), len, false); @@ -894,8 +897,7 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> { // N starts at 1. QuicStreamId GetNthStreamid(QuicTransportVersion transport_version, - Perspective perspective, - bool bidirectional, + Perspective perspective, bool bidirectional, int n) { if (bidirectional) { return QuicUtils::GetFirstBidirectionalStreamId(transport_version, @@ -931,8 +933,7 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> { GetQuicVersionByte(3) // Run all framer tests with all supported versions of QUIC. -INSTANTIATE_TEST_SUITE_P(QuicFramerTests, - QuicFramerTest, +INSTANTIATE_TEST_SUITE_P(QuicFramerTests, QuicFramerTest, ::testing::ValuesIn(AllSupportedVersions()), ::testing::PrintToStringParamName()); @@ -1273,6 +1274,7 @@ TEST_P(QuicFramerTest, LongPacketHeaderWithBothConnectionIds) { unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } @@ -1379,6 +1381,7 @@ TEST_P(QuicFramerTest, ParsePublicHeader) { unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } else if (framer_.version().HasIetfInvariantHeader()) { @@ -1669,6 +1672,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) { }; // clang-format on + ReviseFirstByteByVersion(packet49); PacketFragments& fragments = framer_.version().HasLongHeaderLengths() ? packet49 @@ -2970,6 +2974,7 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) { ? VARIABLE_LENGTH_INTEGER_LENGTH_1 : VARIABLE_LENGTH_INTEGER_LENGTH_0; + ReviseFirstByteByVersion(packet_ietf); PacketFragments& fragments = VersionHasIetfQuicFrames(framer_.transport_version()) ? packet_ietf @@ -4113,7 +4118,7 @@ TEST_P(QuicFramerTest, AckFrameMultipleReceiveTimestampRanges) { // Timestamp range 2 (one packet). { "Unable to read receive timestamp gap.", - { kVarInt62OneByte + 0x07 }}, + { kVarInt62OneByte + 0x05 }}, { "Unable to read receive timestamp count.", { kVarInt62OneByte + 0x01 }}, { "Unable to read receive timestamp delta.", @@ -4121,7 +4126,7 @@ TEST_P(QuicFramerTest, AckFrameMultipleReceiveTimestampRanges) { // Timestamp range 3 (two packets). { "Unable to read receive timestamp gap.", - { kVarInt62OneByte + 0x0a }}, + { kVarInt62OneByte + 0x08 }}, { "Unable to read receive timestamp count.", { kVarInt62OneByte + 0x02 }}, { "Unable to read receive timestamp delta.", @@ -6420,6 +6425,7 @@ TEST_P(QuicFramerTest, ParseIetfRetryPacket) { unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().UsesTls()) { + ReviseFirstByteByVersion(packet_with_tag); p = packet_with_tag; p_length = ABSL_ARRAYSIZE(packet_with_tag); } else if (framer_.version().HasLongHeaderLengths()) { @@ -7115,6 +7121,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) { unsigned char* p = packet; size_t p_size = ABSL_ARRAYSIZE(packet); if (VersionHasIetfQuicFrames(framer_.transport_version())) { + ReviseFirstByteByVersion(packet_ietf); p = packet_ietf; p_size = ABSL_ARRAYSIZE(packet_ietf); } else if (framer_.version().HasLongHeaderLengths()) { @@ -7483,6 +7490,706 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) { "constructed packet", data->data(), data->length(), AsChars(p), p_size); } +TEST_P(QuicFramerTest, BuildAckReceiveTimestampsFrameMultipleRanges) { + if (!VersionHasIetfQuicFrames(framer_.transport_version())) { + return; + } + + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + QuicAckFrame ack_frame = InitAckFrame(kSmallLargestObserved); + ack_frame.received_packet_times = PacketTimeVector{ + // Timestamp Range 3. + {kSmallLargestObserved - 22, CreationTimePlus(0x29ffdddd)}, + {kSmallLargestObserved - 21, CreationTimePlus(0x29ffdedd)}, + // Timestamp Range 2. + {kSmallLargestObserved - 11, CreationTimePlus(0x29ffdeed)}, + // Timestamp Range 1. + {kSmallLargestObserved - 4, CreationTimePlus(0x29ffeeed)}, + {kSmallLargestObserved - 3, CreationTimePlus(0x29ffeeee)}, + {kSmallLargestObserved - 2, CreationTimePlus(0x29ffffff)}, + }; + ack_frame.ack_delay_time = QuicTime::Delta::Zero(); + QuicFrames frames = {QuicFrame(&ack_frame)}; + + unsigned char packet_ietf[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, + 0xDC, + 0xBA, + 0x98, + 0x76, + 0x54, + 0x32, + 0x10, + // packet number + 0x12, + 0x34, + 0x56, + 0x78, + + // frame type (IETF_ACK_RECEIVE_TIMESTAMPS frame) + 0x22, + // largest acked + kVarInt62TwoBytes + 0x12, + 0x34, // = 4660 + // Zero delta time. + kVarInt62OneByte + 0x00, + // number of additional ack blocks + kVarInt62OneByte + 0x00, + // first ack block length. + kVarInt62TwoBytes + 0x12, + 0x33, + + // Receive Timestamps. + + // Timestamp Range Count + kVarInt62OneByte + 0x03, + + // Timestamp range 1 (three packets). + // Gap + kVarInt62OneByte + 0x02, + // Timestamp Range Count + kVarInt62OneByte + 0x03, + // Timestamp Delta + kVarInt62FourBytes + 0x29, + 0xff, + 0xff, + 0xff, + // Timestamp Delta + kVarInt62TwoBytes + 0x11, + 0x11, + // Timestamp Delta + kVarInt62OneByte + 0x01, + + // Timestamp range 2 (one packet). + // Gap + kVarInt62OneByte + 0x05, + // Timestamp Range Count + kVarInt62OneByte + 0x01, + // Timestamp Delta + kVarInt62TwoBytes + 0x10, + 0x00, + + // Timestamp range 3 (two packets). + // Gap + kVarInt62OneByte + 0x08, + // Timestamp Range Count + kVarInt62OneByte + 0x02, + // Timestamp Delta + kVarInt62OneByte + 0x10, + // Timestamp Delta + kVarInt62TwoBytes + 0x01, + 0x00, + }; + // clang-format on + + framer_.set_process_timestamps(true); + framer_.set_max_receive_timestamps_per_ack(8); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + quiche::test::CompareCharArraysWithHexError( + "constructed packet", data->data(), data->length(), AsChars(packet_ietf), + ABSL_ARRAYSIZE(packet_ietf)); +} + +TEST_P(QuicFramerTest, BuildAckReceiveTimestampsFrameExceedsMaxTimestamps) { + if (!VersionHasIetfQuicFrames(framer_.transport_version())) { + return; + } + + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + QuicAckFrame ack_frame = InitAckFrame(kSmallLargestObserved); + ack_frame.received_packet_times = PacketTimeVector{ + // Timestamp Range 3 (not included because max receive timestamps = 4). + {kSmallLargestObserved - 20, CreationTimePlus(0x29ffdddd)}, + // Timestamp Range 2. + {kSmallLargestObserved - 10, CreationTimePlus(0x29ffdedd)}, + {kSmallLargestObserved - 9, CreationTimePlus(0x29ffdeed)}, + // Timestamp Range 1. + {kSmallLargestObserved - 2, CreationTimePlus(0x29ffeeed)}, + {kSmallLargestObserved - 1, CreationTimePlus(0x29ffeeee)}, + {kSmallLargestObserved, CreationTimePlus(0x29ffffff)}, + }; + ack_frame.ack_delay_time = QuicTime::Delta::Zero(); + QuicFrames frames = {QuicFrame(&ack_frame)}; + + unsigned char packet_ietf[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, + 0xDC, + 0xBA, + 0x98, + 0x76, + 0x54, + 0x32, + 0x10, + // packet number + 0x12, + 0x34, + 0x56, + 0x78, + + // frame type (IETF_ACK_RECEIVE_TIMESTAMPS frame) + 0x22, + // largest acked + kVarInt62TwoBytes + 0x12, + 0x34, // = 4660 + // Zero delta time. + kVarInt62OneByte + 0x00, + // number of additional ack blocks + kVarInt62OneByte + 0x00, + // first ack block length. + kVarInt62TwoBytes + 0x12, + 0x33, + + // Receive Timestamps. + + // Timestamp Range Count + kVarInt62OneByte + 0x02, + + // Timestamp range 1 (three packets). + // Gap + kVarInt62OneByte + 0x00, + // Timestamp Range Count + kVarInt62OneByte + 0x03, + // Timestamp Delta + kVarInt62FourBytes + 0x29, + 0xff, + 0xff, + 0xff, + // Timestamp Delta + kVarInt62TwoBytes + 0x11, + 0x11, + // Timestamp Delta + kVarInt62OneByte + 0x01, + + // Timestamp range 2 (one packet). + // Gap + kVarInt62OneByte + 0x05, + // Timestamp Range Count + kVarInt62OneByte + 0x01, + // Timestamp Delta + kVarInt62TwoBytes + 0x10, + 0x00, + }; + // clang-format on + + framer_.set_process_timestamps(true); + framer_.set_max_receive_timestamps_per_ack(4); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + quiche::test::CompareCharArraysWithHexError( + "constructed packet", data->data(), data->length(), AsChars(packet_ietf), + ABSL_ARRAYSIZE(packet_ietf)); +} + +TEST_P(QuicFramerTest, BuildAckReceiveTimestampsFrameWithExponentEncoding) { + if (!VersionHasIetfQuicFrames(framer_.transport_version())) { + return; + } + + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + QuicAckFrame ack_frame = InitAckFrame(kSmallLargestObserved); + ack_frame.received_packet_times = PacketTimeVector{ + // Timestamp Range 2. + {kSmallLargestObserved - 12, CreationTimePlus((0x06c00 << 3) + 0x03)}, + {kSmallLargestObserved - 11, CreationTimePlus((0x28e00 << 3) + 0x00)}, + // Timestamp Range 1. + {kSmallLargestObserved - 5, CreationTimePlus((0x29f00 << 3) + 0x00)}, + {kSmallLargestObserved - 4, CreationTimePlus((0x29f00 << 3) + 0x01)}, + {kSmallLargestObserved - 3, CreationTimePlus((0x29f00 << 3) + 0x02)}, + {kSmallLargestObserved - 2, CreationTimePlus((0x29f00 << 3) + 0x03)}, + }; + ack_frame.ack_delay_time = QuicTime::Delta::Zero(); + + QuicFrames frames = {QuicFrame(&ack_frame)}; + + unsigned char packet_ietf[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, + 0xDC, + 0xBA, + 0x98, + 0x76, + 0x54, + 0x32, + 0x10, + // packet number + 0x12, + 0x34, + 0x56, + 0x78, + + // frame type (IETF_ACK_RECEIVE_TIMESTAMPS frame) + 0x22, + // largest acked + kVarInt62TwoBytes + 0x12, + 0x34, // = 4660 + // Zero delta time. + kVarInt62OneByte + 0x00, + // number of additional ack blocks + kVarInt62OneByte + 0x00, + // first ack block length. + kVarInt62TwoBytes + 0x12, + 0x33, + + // Receive Timestamps. + + // Timestamp Range Count + kVarInt62OneByte + 0x02, + + // Timestamp range 1 (three packets). + // Gap + kVarInt62OneByte + 0x02, + // Timestamp Range Count + kVarInt62OneByte + 0x04, + // Timestamp Delta + kVarInt62FourBytes + 0x00, + 0x02, + 0x9f, + 0x01, // round up + // Timestamp Delta + kVarInt62OneByte + 0x00, + // Timestamp Delta + kVarInt62OneByte + 0x00, + // Timestamp Delta + kVarInt62OneByte + 0x01, + + // Timestamp range 2 (one packet). + // Gap + kVarInt62OneByte + 0x04, + // Timestamp Range Count + kVarInt62OneByte + 0x02, + // Timestamp Delta + kVarInt62TwoBytes + 0x11, + 0x00, + // Timestamp Delta + kVarInt62FourBytes + 0x00, + 0x02, + 0x21, + 0xff, + }; + // clang-format on + + framer_.set_process_timestamps(true); + framer_.set_max_receive_timestamps_per_ack(8); + framer_.set_receive_timestamps_exponent(3); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + quiche::test::CompareCharArraysWithHexError( + "constructed packet", data->data(), data->length(), AsChars(packet_ietf), + ABSL_ARRAYSIZE(packet_ietf)); +} + +TEST_P(QuicFramerTest, BuildAndProcessAckReceiveTimestampsWithMultipleRanges) { + if (!VersionHasIetfQuicFrames(framer_.transport_version())) { + return; + } + framer_.InstallDecrypter(ENCRYPTION_FORWARD_SECURE, + std::make_unique<StrictTaggingDecrypter>(/*key=*/0)); + framer_.SetKeyUpdateSupportForConnection(true); + framer_.set_process_timestamps(true); + framer_.set_max_receive_timestamps_per_ack(8); + + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + QuicAckFrame ack_frame = InitAckFrame(kSmallLargestObserved); + ack_frame.received_packet_times = PacketTimeVector{ + {kSmallLargestObserved - 1201, CreationTimePlus(0x8bcaef234)}, + {kSmallLargestObserved - 1200, CreationTimePlus(0x8bcdef123)}, + {kSmallLargestObserved - 1000, CreationTimePlus(0xaacdef123)}, + {kSmallLargestObserved - 4, CreationTimePlus(0xabcdea125)}, + {kSmallLargestObserved - 2, CreationTimePlus(0xabcdee124)}, + {kSmallLargestObserved - 1, CreationTimePlus(0xabcdef123)}, + {kSmallLargestObserved, CreationTimePlus(0xabcdef123)}, + }; + ack_frame.ack_delay_time = QuicTime::Delta::Zero(); + QuicFrames frames = {QuicFrame(&ack_frame)}; + + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + std::unique_ptr<QuicEncryptedPacket> encrypted( + EncryptPacketWithTagAndPhase(*data, 0, false)); + ASSERT_TRUE(encrypted); + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER); + EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); + EXPECT_THAT(framer_.error(), IsQuicNoError()); + + const QuicAckFrame& frame = *visitor_.ack_frames_[0]; + EXPECT_THAT(frame.received_packet_times, + ContainerEq(PacketTimeVector{ + {kSmallLargestObserved, CreationTimePlus(0xabcdef123)}, + {kSmallLargestObserved - 1, CreationTimePlus(0xabcdef123)}, + {kSmallLargestObserved - 2, CreationTimePlus(0xabcdee124)}, + {kSmallLargestObserved - 4, CreationTimePlus(0xabcdea125)}, + {kSmallLargestObserved - 1000, CreationTimePlus(0xaacdef123)}, + {kSmallLargestObserved - 1200, CreationTimePlus(0x8bcdef123)}, + {kSmallLargestObserved - 1201, CreationTimePlus(0x8bcaef234)}, + })); +} + +TEST_P(QuicFramerTest, + BuildAndProcessAckReceiveTimestampsExceedsMaxTimestamps) { + if (!VersionHasIetfQuicFrames(framer_.transport_version())) { + return; + } + framer_.InstallDecrypter(ENCRYPTION_FORWARD_SECURE, + std::make_unique<StrictTaggingDecrypter>(/*key=*/0)); + framer_.SetKeyUpdateSupportForConnection(true); + framer_.set_process_timestamps(true); + framer_.set_max_receive_timestamps_per_ack(2); + + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + QuicAckFrame ack_frame = InitAckFrame(kSmallLargestObserved); + ack_frame.received_packet_times = PacketTimeVector{ + {kSmallLargestObserved - 1201, CreationTimePlus(0x8bcaef234)}, + {kSmallLargestObserved - 1200, CreationTimePlus(0x8bcdef123)}, + {kSmallLargestObserved - 1000, CreationTimePlus(0xaacdef123)}, + {kSmallLargestObserved - 5, CreationTimePlus(0xabcdea125)}, + {kSmallLargestObserved - 3, CreationTimePlus(0xabcded124)}, + {kSmallLargestObserved - 2, CreationTimePlus(0xabcdee124)}, + {kSmallLargestObserved - 1, CreationTimePlus(0xabcdef123)}, + }; + ack_frame.ack_delay_time = QuicTime::Delta::Zero(); + QuicFrames frames = {QuicFrame(&ack_frame)}; + + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + std::unique_ptr<QuicEncryptedPacket> encrypted( + EncryptPacketWithTagAndPhase(*data, 0, false)); + ASSERT_TRUE(encrypted); + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER); + EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); + EXPECT_THAT(framer_.error(), IsQuicNoError()); + + const QuicAckFrame& frame = *visitor_.ack_frames_[0]; + EXPECT_THAT(frame.received_packet_times, + ContainerEq(PacketTimeVector{ + {kSmallLargestObserved - 1, CreationTimePlus(0xabcdef123)}, + {kSmallLargestObserved - 2, CreationTimePlus(0xabcdee124)}, + })); +} + +TEST_P(QuicFramerTest, + BuildAndProcessAckReceiveTimestampsWithExponentNoTruncation) { + if (!VersionHasIetfQuicFrames(framer_.transport_version())) { + return; + } + framer_.InstallDecrypter(ENCRYPTION_FORWARD_SECURE, + std::make_unique<StrictTaggingDecrypter>(/*key=*/0)); + framer_.SetKeyUpdateSupportForConnection(true); + framer_.set_process_timestamps(true); + framer_.set_max_receive_timestamps_per_ack(8); + framer_.set_receive_timestamps_exponent(3); + + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + QuicAckFrame ack_frame = InitAckFrame(kSmallLargestObserved); + ack_frame.received_packet_times = PacketTimeVector{ + {kSmallLargestObserved - 8, CreationTimePlus(0x1add << 3)}, + {kSmallLargestObserved - 7, CreationTimePlus(0x29ed << 3)}, + {kSmallLargestObserved - 3, CreationTimePlus(0x29fe << 3)}, + {kSmallLargestObserved - 2, CreationTimePlus(0x29ff << 3)}, + }; + ack_frame.ack_delay_time = QuicTime::Delta::Zero(); + QuicFrames frames = {QuicFrame(&ack_frame)}; + + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + std::unique_ptr<QuicEncryptedPacket> encrypted( + EncryptPacketWithTagAndPhase(*data, 0, false)); + ASSERT_TRUE(encrypted); + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER); + EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); + EXPECT_THAT(framer_.error(), IsQuicNoError()); + + const QuicAckFrame& frame = *visitor_.ack_frames_[0]; + EXPECT_THAT(frame.received_packet_times, + ContainerEq(PacketTimeVector{ + {kSmallLargestObserved - 2, CreationTimePlus(0x29ff << 3)}, + {kSmallLargestObserved - 3, CreationTimePlus(0x29fe << 3)}, + {kSmallLargestObserved - 7, CreationTimePlus(0x29ed << 3)}, + {kSmallLargestObserved - 8, CreationTimePlus(0x1add << 3)}, + })); +} + +TEST_P(QuicFramerTest, + BuildAndProcessAckReceiveTimestampsWithExponentTruncation) { + if (!VersionHasIetfQuicFrames(framer_.transport_version())) { + return; + } + framer_.InstallDecrypter(ENCRYPTION_FORWARD_SECURE, + std::make_unique<StrictTaggingDecrypter>(/*key=*/0)); + framer_.SetKeyUpdateSupportForConnection(true); + framer_.set_process_timestamps(true); + framer_.set_max_receive_timestamps_per_ack(8); + framer_.set_receive_timestamps_exponent(3); + + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + QuicAckFrame ack_frame = InitAckFrame(kSmallLargestObserved); + ack_frame.received_packet_times = PacketTimeVector{ + {kSmallLargestObserved - 10, CreationTimePlus((0x1001 << 3) + 1)}, + {kSmallLargestObserved - 9, CreationTimePlus((0x2995 << 3) - 1)}, + {kSmallLargestObserved - 8, CreationTimePlus((0x2995 << 3) + 0)}, + {kSmallLargestObserved - 7, CreationTimePlus((0x2995 << 3) + 1)}, + {kSmallLargestObserved - 6, CreationTimePlus((0x2995 << 3) + 2)}, + {kSmallLargestObserved - 3, CreationTimePlus((0x2995 << 3) + 3)}, + {kSmallLargestObserved - 2, CreationTimePlus((0x2995 << 3) + 4)}, + }; + ack_frame.ack_delay_time = QuicTime::Delta::Zero(); + QuicFrames frames = {QuicFrame(&ack_frame)}; + + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + std::unique_ptr<QuicEncryptedPacket> encrypted( + EncryptPacketWithTagAndPhase(*data, 0, false)); + ASSERT_TRUE(encrypted); + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER); + EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); + EXPECT_THAT(framer_.error(), IsQuicNoError()); + + const QuicAckFrame& frame = *visitor_.ack_frames_[0]; + EXPECT_THAT(frame.received_packet_times, + ContainerEq(PacketTimeVector{ + {kSmallLargestObserved - 2, CreationTimePlus(0x2996 << 3)}, + {kSmallLargestObserved - 3, CreationTimePlus(0x2996 << 3)}, + {kSmallLargestObserved - 6, CreationTimePlus(0x2996 << 3)}, + {kSmallLargestObserved - 7, CreationTimePlus(0x2996 << 3)}, + {kSmallLargestObserved - 8, CreationTimePlus(0x2995 << 3)}, + {kSmallLargestObserved - 9, CreationTimePlus(0x2995 << 3)}, + {kSmallLargestObserved - 10, CreationTimePlus(0x1002 << 3)}, + })); +} + +TEST_P(QuicFramerTest, AckReceiveTimestamps) { + if (!VersionHasIetfQuicFrames(framer_.transport_version())) { + return; + } + framer_.InstallDecrypter(ENCRYPTION_FORWARD_SECURE, + std::make_unique<StrictTaggingDecrypter>(/*key=*/0)); + framer_.SetKeyUpdateSupportForConnection(true); + framer_.set_process_timestamps(true); + framer_.set_max_receive_timestamps_per_ack(8); + framer_.set_receive_timestamps_exponent(3); + + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + // Use kSmallLargestObserved to make this test finished in a short time. + QuicAckFrame ack_frame = InitAckFrame(kSmallLargestObserved); + ack_frame.received_packet_times = PacketTimeVector{ + {kSmallLargestObserved - 5, CreationTimePlus((0x29ff << 3))}, + {kSmallLargestObserved - 4, CreationTimePlus((0x29ff << 3))}, + {kSmallLargestObserved - 3, CreationTimePlus((0x29ff << 3))}, + {kSmallLargestObserved - 2, CreationTimePlus((0x29ff << 3))}, + }; + ack_frame.ack_delay_time = QuicTime::Delta::Zero(); + QuicFrames frames = {QuicFrame(&ack_frame)}; + + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + std::unique_ptr<QuicEncryptedPacket> encrypted( + EncryptPacketWithTagAndPhase(*data, 0, false)); + ASSERT_TRUE(encrypted); + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER); + EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); + EXPECT_THAT(framer_.error(), IsQuicNoError()); + + const QuicAckFrame& frame = *visitor_.ack_frames_[0]; + EXPECT_THAT(frame.received_packet_times, + ContainerEq(PacketTimeVector{ + {kSmallLargestObserved - 2, CreationTimePlus(0x29ff << 3)}, + {kSmallLargestObserved - 3, CreationTimePlus(0x29ff << 3)}, + {kSmallLargestObserved - 4, CreationTimePlus(0x29ff << 3)}, + {kSmallLargestObserved - 5, CreationTimePlus(0x29ff << 3)}, + })); +} + +TEST_P(QuicFramerTest, AckReceiveTimestampsPacketOutOfOrder) { + if (!VersionHasIetfQuicFrames(framer_.transport_version())) { + return; + } + framer_.InstallDecrypter(ENCRYPTION_FORWARD_SECURE, + std::make_unique<StrictTaggingDecrypter>(/*key=*/0)); + framer_.SetKeyUpdateSupportForConnection(true); + framer_.set_process_timestamps(true); + framer_.set_max_receive_timestamps_per_ack(8); + framer_.set_receive_timestamps_exponent(3); + + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + // Use kSmallLargestObserved to make this test finished in a short time. + QuicAckFrame ack_frame = InitAckFrame(kSmallLargestObserved); + + // The packet numbers below are out of order, this is impossible because we + // don't record out of order packets in received_packet_times. The test is + // intended to ensure this error is raised when it happens. + ack_frame.received_packet_times = PacketTimeVector{ + {kSmallLargestObserved - 5, CreationTimePlus((0x29ff << 3))}, + {kSmallLargestObserved - 2, CreationTimePlus((0x29ff << 3))}, + {kSmallLargestObserved - 4, CreationTimePlus((0x29ff << 3))}, + {kSmallLargestObserved - 3, CreationTimePlus((0x29ff << 3))}, + }; + ack_frame.ack_delay_time = QuicTime::Delta::Zero(); + QuicFrames frames = {QuicFrame(&ack_frame)}; + + EXPECT_QUIC_BUG(BuildDataPacket(header, frames), + "Packet number and/or receive time not in order."); +} + +// If there's insufficient room for IETF ack receive timestamps, don't write any +// timestamp ranges. +TEST_P(QuicFramerTest, IetfAckReceiveTimestampsTruncate) { + if (!VersionHasIetfQuicFrames(framer_.transport_version())) { + return; + } + framer_.InstallDecrypter(ENCRYPTION_FORWARD_SECURE, + std::make_unique<StrictTaggingDecrypter>(/*key=*/0)); + framer_.SetKeyUpdateSupportForConnection(true); + framer_.set_process_timestamps(true); + framer_.set_max_receive_timestamps_per_ack(8192); + framer_.set_receive_timestamps_exponent(3); + + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + // Use kSmallLargestObserved to make this test finished in a short time. + QuicAckFrame ack_frame = InitAckFrame(kSmallLargestObserved); + for (QuicPacketNumber i(1); i <= kSmallLargestObserved; i += 2) { + ack_frame.received_packet_times.push_back( + {i, CreationTimePlus((0x29ff << 3))}); + } + + ack_frame.ack_delay_time = QuicTime::Delta::Zero(); + QuicFrames frames = {QuicFrame(&ack_frame)}; + + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + std::unique_ptr<QuicEncryptedPacket> encrypted( + EncryptPacketWithTagAndPhase(*data, 0, false)); + ASSERT_TRUE(encrypted); + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER); + EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); + EXPECT_THAT(framer_.error(), IsQuicNoError()); + + const QuicAckFrame& frame = *visitor_.ack_frames_[0]; + EXPECT_TRUE(frame.received_packet_times.empty()); +} + +// If there are too many ack ranges, they will be truncated to make room for a +// timestamp range count of 0. +TEST_P(QuicFramerTest, IetfAckReceiveTimestampsAckRangeTruncation) { + if (!VersionHasIetfQuicFrames(framer_.transport_version())) { + return; + } + SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE); + framer_.set_process_timestamps(true); + framer_.set_max_receive_timestamps_per_ack(8); + framer_.set_receive_timestamps_exponent(3); + + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + QuicAckFrame ack_frame; + // Create a packet with just the ack. + ack_frame = MakeAckFrameWithGaps(/*gap_size=*/0xffffffff, + /*max_num_gaps=*/200, + /*largest_acked=*/kMaxIetfVarInt); + ack_frame.received_packet_times = PacketTimeVector{ + {QuicPacketNumber(kMaxIetfVarInt) - 2, CreationTimePlus((0x29ff << 3))}, + }; + QuicFrames frames = {QuicFrame(&ack_frame)}; + // Build an ACK packet. + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + std::unique_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames)); + ASSERT_TRUE(raw_ack_packet != nullptr); + char buffer[kMaxOutgoingPacketSize]; + size_t encrypted_length = + framer_.EncryptPayload(ENCRYPTION_INITIAL, header.packet_number, + *raw_ack_packet, buffer, kMaxOutgoingPacketSize); + ASSERT_NE(0u, encrypted_length); + // Now make sure we can turn our ack packet back into an ack frame. + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER); + ASSERT_TRUE(framer_.ProcessPacket( + QuicEncryptedPacket(buffer, encrypted_length, false))); + ASSERT_EQ(1u, visitor_.ack_frames_.size()); + QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0]; + EXPECT_EQ(QuicPacketNumber(kMaxIetfVarInt), + LargestAcked(processed_ack_frame)); + // Verify ACK ranges in the frame gets truncated. + ASSERT_LT(processed_ack_frame.packets.NumPacketsSlow(), + ack_frame.packets.NumIntervals()); + EXPECT_EQ(158u, processed_ack_frame.packets.NumPacketsSlow()); + EXPECT_LT(processed_ack_frame.packets.NumIntervals(), + ack_frame.packets.NumIntervals()); + EXPECT_EQ(QuicPacketNumber(kMaxIetfVarInt), + processed_ack_frame.packets.Max()); + // But the receive timestamps are not truncated because they are small. + EXPECT_FALSE(processed_ack_frame.received_packet_times.empty()); +} + TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlockMaxLength) { QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); QuicPacketHeader header; @@ -13034,10 +13741,16 @@ TEST_P(QuicFramerTest, CoalescedPacket) { 'R', 'L', 'D', '?', }; // clang-format on + const size_t first_packet_ietf_size = 46; + // If the first packet changes, the attempt to fix the first byte of the + // second packet will fail. + EXPECT_EQ(packet_ietf[first_packet_ietf_size], 0xD3); unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); + ReviseFirstByteByVersion(&packet_ietf[first_packet_ietf_size]); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -13157,6 +13870,7 @@ TEST_P(QuicFramerTest, CoalescedPacketWithUdpPadding) { unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -13304,10 +14018,16 @@ TEST_P(QuicFramerTest, CoalescedPacketWithDifferentVersion) { 'R', 'L', 'D', '?', }; // clang-format on + const size_t first_packet_ietf_size = 46; + // If the first packet changes, the attempt to fix the first byte of the + // second packet will fail. + EXPECT_EQ(packet_ietf[first_packet_ietf_size], 0xD3); unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); + ReviseFirstByteByVersion(&packet_ietf[first_packet_ietf_size]); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -13415,6 +14135,7 @@ TEST_P(QuicFramerTest, UndecryptablePacketWithoutDecrypter) { unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } else if (framer_.version().HasIetfInvariantHeader()) { @@ -13517,6 +14238,7 @@ TEST_P(QuicFramerTest, UndecryptablePacketWithDecrypter) { unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } else if (framer_.version().HasIetfInvariantHeader()) { @@ -13677,10 +14399,15 @@ TEST_P(QuicFramerTest, UndecryptableCoalescedPacket) { }; // clang-format on const size_t length_of_first_coalesced_packet = 46; + // If the first packet changes, the attempt to fix the first byte of the + // second packet will fail. + EXPECT_EQ(packet_ietf[length_of_first_coalesced_packet], 0xD3); unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); + ReviseFirstByteByVersion(&packet_ietf[length_of_first_coalesced_packet]); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -13844,10 +14571,16 @@ TEST_P(QuicFramerTest, MismatchedCoalescedPacket) { 'R', 'L', 'D', '?', }; // clang-format on + const size_t length_of_first_coalesced_packet = 46; + // If the first packet changes, the attempt to fix the first byte of the + // second packet will fail. + EXPECT_EQ(packet_ietf[length_of_first_coalesced_packet], 0xD3); unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); + ReviseFirstByteByVersion(&packet_ietf[length_of_first_coalesced_packet]); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -13949,10 +14682,16 @@ TEST_P(QuicFramerTest, InvalidCoalescedPacket) { // version would be here but we cut off the invalid coalesced header. }; // clang-format on + const size_t length_of_first_coalesced_packet = 46; + // If the first packet changes, the attempt to fix the first byte of the + // second packet will fail. + EXPECT_EQ(packet_ietf[length_of_first_coalesced_packet], 0xD3); unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); + ReviseFirstByteByVersion(&packet_ietf[length_of_first_coalesced_packet]); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -14180,6 +14919,7 @@ TEST_P(QuicFramerTest, MultiplePacketNumberSpaces) { QuicEncryptedPacket(AsChars(long_header_packet), ABSL_ARRAYSIZE(long_header_packet), false))); } else { + ReviseFirstByteByVersion(long_header_packet_ietf); EXPECT_TRUE(framer_.ProcessPacket( QuicEncryptedPacket(AsChars(long_header_packet_ietf), ABSL_ARRAYSIZE(long_header_packet_ietf), false))); @@ -14708,9 +15448,11 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromLongHeaderToClient) { 0x00, }; // clang-format on + unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } @@ -14776,6 +15518,7 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromLongHeaderToServer) { unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } @@ -15615,6 +16358,7 @@ TEST_P(QuicFramerTest, ErrorWhenUnexpectedFrameTypeEncountered) { }; // clang-format on + ReviseFirstByteByVersion(packet); QuicEncryptedPacket encrypted(AsChars(packet), ABSL_ARRAYSIZE(packet), false); EXPECT_FALSE(framer_.ProcessPacket(encrypted)); diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc index 079778cd5d8..d0f1578fa79 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc @@ -38,6 +38,7 @@ QuicReceivedPacketManager::QuicReceivedPacketManager(QuicConnectionStats* stats) max_ack_ranges_(0), time_largest_observed_(QuicTime::Zero()), save_timestamps_(false), + save_timestamps_for_in_order_packets_(false), stats_(stats), num_retransmittable_packets_received_since_last_ack_sent_(0), min_received_before_ack_decimation_(kMinReceivedBeforeAckDecimation), @@ -80,9 +81,12 @@ void QuicReceivedPacketManager::RecordPacketReceived( } ack_frame_updated_ = true; + // Whether |packet_number| is received out of order. + bool packet_reordered = false; if (LargestAcked(ack_frame_).IsInitialized() && LargestAcked(ack_frame_) > packet_number) { // Record how out of order stats. + packet_reordered = true; ++stats_->packets_reordered; stats_->max_sequence_reordering = std::max(stats_->max_sequence_reordering, @@ -101,8 +105,11 @@ void QuicReceivedPacketManager::RecordPacketReceived( if (save_timestamps_) { // The timestamp format only handles packets in time order. - if (!ack_frame_.received_packet_times.empty() && - ack_frame_.received_packet_times.back().second > receipt_time) { + if (save_timestamps_for_in_order_packets_ && packet_reordered) { + QUIC_DLOG(WARNING) << "Not saving receive timestamp for packet " + << packet_number; + } else if (!ack_frame_.received_packet_times.empty() && + ack_frame_.received_packet_times.back().second > receipt_time) { QUIC_LOG(WARNING) << "Receive time went backwards from: " << ack_frame_.received_packet_times.back().second.ToDebuggingValue() diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.h index 822725db6aa..21f7f045d4a 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.h @@ -103,8 +103,9 @@ class QUIC_EXPORT_PRIVATE QuicReceivedPacketManager { max_ack_ranges_ = max_ack_ranges; } - void set_save_timestamps(bool save_timestamps) { + void set_save_timestamps(bool save_timestamps, bool in_order_packets_only) { save_timestamps_ = save_timestamps; + save_timestamps_for_in_order_packets_ = in_order_packets_only; } size_t min_received_before_ack_decimation() const { @@ -167,6 +168,10 @@ class QUIC_EXPORT_PRIVATE QuicReceivedPacketManager { // If true, save timestamps in the ack_frame_. bool save_timestamps_; + // If true and |save_timestamps_|, only save timestamps for packets that are + // received in order. + bool save_timestamps_for_in_order_packets_; + // Least packet number received from peer. QuicPacketNumber least_received_packet_number_; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager_test.cc index 9d6b6644421..cc0438140fe 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager_test.cc @@ -46,7 +46,7 @@ class QuicReceivedPacketManagerTest : public QuicTest { QuicReceivedPacketManagerTest() : received_manager_(&stats_) { clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); rtt_stats_.UpdateRtt(kMinRttMs, QuicTime::Delta::Zero(), QuicTime::Zero()); - received_manager_.set_save_timestamps(true); + received_manager_.set_save_timestamps(true, false); } void RecordPacketReceipt(uint64_t packet_number) { @@ -189,6 +189,21 @@ TEST_F(QuicReceivedPacketManagerTest, IgnoreOutOfOrderTimestamps) { EXPECT_EQ(2u, received_manager_.ack_frame().received_packet_times.size()); } +TEST_F(QuicReceivedPacketManagerTest, IgnoreOutOfOrderPackets) { + received_manager_.set_save_timestamps(true, true); + EXPECT_FALSE(received_manager_.ack_frame_updated()); + RecordPacketReceipt(1, QuicTime::Zero()); + EXPECT_TRUE(received_manager_.ack_frame_updated()); + EXPECT_EQ(1u, received_manager_.ack_frame().received_packet_times.size()); + RecordPacketReceipt(4, + QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1)); + EXPECT_EQ(2u, received_manager_.ack_frame().received_packet_times.size()); + + RecordPacketReceipt(3, + QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(3)); + EXPECT_EQ(2u, received_manager_.ack_frame().received_packet_times.size()); +} + TEST_F(QuicReceivedPacketManagerTest, HasMissingPackets) { EXPECT_QUIC_BUG(received_manager_.PeerFirstSendingPacketNumber(), "No packets have been received yet"); diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc index 4c5026ca974..55dbe057887 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc @@ -87,7 +87,6 @@ QuicSentPacketManager::QuicSentPacketManager( pending_timer_transmission_count_(0), max_tail_loss_probes_(kDefaultMaxTailLossProbes), max_rto_packets_(kMaxRetransmissionsOnTimeout), - enable_half_rtt_tail_loss_probe_(false), using_pacing_(false), use_new_rto_(false), conservative_handshake_retransmits_(false), @@ -209,12 +208,7 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) { QUIC_CODE_COUNT(two_aggressive_ptos); num_tlp_timeout_ptos_ = 2; } - if (GetQuicReloadableFlag(quic_deprecate_tlpr)) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_deprecate_tlpr, 2, 2); - } - if (config.HasClientSentConnectionOption(kPLE1, perspective) || - (config.HasClientSentConnectionOption(kTLPR, perspective) && - !GetQuicReloadableFlag(quic_deprecate_tlpr))) { + if (config.HasClientSentConnectionOption(kPLE1, perspective)) { first_pto_srtt_multiplier_ = 0.5; } else if (config.HasClientSentConnectionOption(kPLE2, perspective)) { first_pto_srtt_multiplier_ = 1.5; @@ -304,17 +298,6 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) { if (config.HasClientSentConnectionOption(k1RTO, perspective)) { max_rto_packets_ = 1; } - if (GetQuicReloadableFlag(quic_deprecate_tlpr)) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_deprecate_tlpr, 1, 2); - } - if (config.HasClientSentConnectionOption(kTLPR, perspective) && - !GetQuicReloadableFlag(quic_deprecate_tlpr)) { - enable_half_rtt_tail_loss_probe_ = true; - } - if (config.HasClientRequestedIndependentOption(kTLPR, perspective) && - !GetQuicReloadableFlag(quic_deprecate_tlpr)) { - enable_half_rtt_tail_loss_probe_ = true; - } if (config.HasClientSentConnectionOption(kNRTO, perspective)) { use_new_rto_ = true; } @@ -352,6 +335,15 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) { if (network_change_visitor_ != nullptr) { network_change_visitor_->OnCongestionChange(); } + + if (debug_delegate_ != nullptr) { + DebugDelegate::SendParameters parameters; + parameters.congestion_control_type = + send_algorithm_->GetCongestionControlType(); + parameters.use_pacing = using_pacing_; + parameters.initial_congestion_window = initial_congestion_window_; + debug_delegate_->OnConfigProcessed(parameters); + } } void QuicSentPacketManager::ApplyConnectionOptions( @@ -392,6 +384,18 @@ void QuicSentPacketManager::ResumeConnectionState( void QuicSentPacketManager::AdjustNetworkParameters( const SendAlgorithmInterface::NetworkParams& params) { + if (params.burst_token != 0) { + if (using_pacing_) { + QUIC_RELOADABLE_FLAG_COUNT(quic_set_burst_token); + int old_burst_size = pacing_sender_.initial_burst_size(); + pacing_sender_.SetBurstTokens(params.burst_token); + if (debug_delegate_ != nullptr) { + debug_delegate_->OnAdjustBurstSize(old_burst_size, + pacing_sender_.initial_burst_size()); + } + } + return; + } const QuicBandwidth& bandwidth = params.bandwidth; const QuicTime::Delta& rtt = params.rtt; if (!rtt.IsZero()) { @@ -1393,12 +1397,6 @@ const QuicTime::Delta QuicSentPacketManager::GetCryptoRetransmissionDelay() const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const { QuicTime::Delta srtt = rtt_stats_.SmoothedOrInitialRtt(); - if (enable_half_rtt_tail_loss_probe_ && consecutive_tlp_count_ == 0u) { - if (unacked_packets().HasUnackedStreamData()) { - // Enable TLPR if there are pending data packets. - return std::max(min_tlp_timeout_, srtt * 0.5); - } - } if (!unacked_packets_.HasMultipleInFlightPackets()) { // This expression really should be using the delayed ack time, but in TCP // MinRTO was traditionally set to 2x the delayed ack timer and this @@ -1444,10 +1442,6 @@ const QuicTime::Delta QuicSentPacketManager::GetProbeTimeoutDelay( QuicTime::Delta::FromMilliseconds(kMinHandshakeTimeoutMs)) * (1 << consecutive_pto_count_); } - if (enable_half_rtt_tail_loss_probe_ && consecutive_pto_count_ == 0 && - handshake_finished_) { - return std::max(min_tlp_timeout_, rtt_stats_.smoothed_rtt() * 0.5); - } const QuicTime::Delta rtt_var = use_standard_deviation_for_pto_ ? rtt_stats_.GetStandardOrMeanDeviation() : rtt_stats_.mean_deviation(); @@ -1769,18 +1763,11 @@ QuicSentPacketManager::GetNConsecutiveRetransmissionTimeoutDelay( std::min(num_timeouts, static_cast<int>(max_tail_loss_probes_)); num_timeouts -= num_tlps; if (num_tlps > 0) { - if (enable_half_rtt_tail_loss_probe_ && - unacked_packets().HasUnackedStreamData()) { - total_delay = total_delay + std::max(min_tlp_timeout_, srtt * 0.5); - --num_tlps; - } - if (num_tlps > 0) { - const QuicTime::Delta tlp_delay = - std::max(2 * srtt, unacked_packets_.HasMultipleInFlightPackets() - ? min_tlp_timeout_ - : (1.5 * srtt + (min_rto_timeout_ * 0.5))); - total_delay = total_delay + num_tlps * tlp_delay; - } + const QuicTime::Delta tlp_delay = + std::max(2 * srtt, unacked_packets_.HasMultipleInFlightPackets() + ? min_tlp_timeout_ + : (1.5 * srtt + (min_rto_timeout_ * 0.5))); + total_delay = total_delay + num_tlps * tlp_delay; } if (num_timeouts == 0) { return total_delay; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h index e4a7036e432..dac8ccf08d8 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h @@ -52,6 +52,12 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { // the packet manager or connection as a result of these callbacks. class QUIC_EXPORT_PRIVATE DebugDelegate { public: + struct QUIC_EXPORT_PRIVATE SendParameters { + CongestionControlType congestion_control_type; + bool use_pacing; + QuicPacketCount initial_congestion_window; + }; + virtual ~DebugDelegate() {} // Called when a spurious retransmission is detected. @@ -80,7 +86,12 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { QuicByteCount /*old_cwnd*/, QuicByteCount /*new_cwnd*/) {} + virtual void OnAdjustBurstSize(int /*old_burst_size*/, + int /*new_burst_size*/) {} + virtual void OnOvershootingDetected() {} + + virtual void OnConfigProcessed(const SendParameters& /*parameters*/) {} }; // Interface which gets callbacks from the QuicSentPacketManager when @@ -622,8 +633,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { // Maximum number of packets to send upon RTO. QuicPacketCount max_rto_packets_; // If true, send the TLP at 0.5 RTT. - // TODO(renjietang): remove it once quic_deprecate_tlpr flag is deprecated. - bool enable_half_rtt_tail_loss_probe_; bool using_pacing_; // If true, use the new RTO with loss based CWND reduction instead of the send // algorithms's OnRetransmissionTimeout to reduce the congestion window. diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc index a09afc6b7b8..1ce3da8e396 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc @@ -1463,112 +1463,6 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeTailLossProbe) { EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); } -TEST_F(QuicSentPacketManagerTest, TLPRWithPendingStreamData) { - if (GetQuicReloadableFlag(quic_default_on_pto) || - GetQuicReloadableFlag(quic_deprecate_tlpr)) { - return; - } - QuicConfig config; - QuicTagVector options; - - options.push_back(kTLPR); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*send_algorithm_, PacingRate(_)) - .WillRepeatedly(Return(QuicBandwidth::Zero())); - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillOnce(Return(10 * kDefaultTCPMSS)); - manager_.SetFromConfig(config); - EXPECT_TRUE( - QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_)); - - QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2); - - SendDataPacket(1); - SendDataPacket(2); - - // Test with a standard smoothed RTT. - RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); - rtt_stats->set_initial_rtt(QuicTime::Delta::FromMilliseconds(100)); - QuicTime::Delta srtt = rtt_stats->initial_rtt(); - // With pending stream data, TLPR is used. - QuicTime::Delta expected_tlp_delay = 0.5 * srtt; - EXPECT_CALL(notifier_, HasUnackedStreamData()).WillRepeatedly(Return(true)); - - EXPECT_EQ(expected_tlp_delay, - manager_.GetRetransmissionTime() - clock_.Now()); - - // Retransmit the packet by invoking the retransmission timeout. - clock_.AdvanceTime(expected_tlp_delay); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke( - [this](TransmissionType type) { RetransmitDataPacket(3, type); }))); - EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe()); - - EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false)); - EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now())); - - // 2nd TLP. - expected_tlp_delay = 2 * srtt; - EXPECT_EQ(expected_tlp_delay, - manager_.GetRetransmissionTime() - clock_.Now()); -} - -TEST_F(QuicSentPacketManagerTest, TLPRWithoutPendingStreamData) { - if (GetQuicReloadableFlag(quic_default_on_pto) || - GetQuicReloadableFlag(quic_deprecate_tlpr)) { - return; - } - QuicConfig config; - QuicTagVector options; - - options.push_back(kTLPR); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*send_algorithm_, PacingRate(_)) - .WillRepeatedly(Return(QuicBandwidth::Zero())); - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillOnce(Return(10 * kDefaultTCPMSS)); - manager_.SetFromConfig(config); - EXPECT_TRUE( - QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_)); - QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2); - - SendPingPacket(1, ENCRYPTION_INITIAL); - SendPingPacket(2, ENCRYPTION_INITIAL); - - // Test with a standard smoothed RTT. - RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); - rtt_stats->set_initial_rtt(QuicTime::Delta::FromMilliseconds(100)); - QuicTime::Delta srtt = rtt_stats->initial_rtt(); - QuicTime::Delta expected_tlp_delay = 0.5 * srtt; - // With no pending stream data, TLPR is ignored. - expected_tlp_delay = 2 * srtt; - EXPECT_CALL(notifier_, HasUnackedStreamData()).WillRepeatedly(Return(false)); - EXPECT_EQ(expected_tlp_delay, - manager_.GetRetransmissionTime() - clock_.Now()); - - // Retransmit the packet by invoking the retransmission timeout. - clock_.AdvanceTime(expected_tlp_delay); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke( - [this](TransmissionType type) { RetransmitDataPacket(3, type); }))); - EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe()); - EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false)); - EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now())); - - // 2nd TLP. - expected_tlp_delay = 2 * srtt; - EXPECT_EQ(expected_tlp_delay, - manager_.GetRetransmissionTime() - clock_.Now()); -} - TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) { if (GetQuicReloadableFlag(quic_default_on_pto)) { return; @@ -2125,41 +2019,6 @@ TEST_F(QuicSentPacketManagerTest, Negotiate1TLPFromOptionsAtClient) { EXPECT_EQ(1u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_)); } -TEST_F(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtServer) { - if (GetQuicReloadableFlag(quic_default_on_pto) || - GetQuicReloadableFlag(quic_deprecate_tlpr)) { - return; - } - QuicConfig config; - QuicTagVector options; - - options.push_back(kTLPR); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - manager_.SetFromConfig(config); - EXPECT_TRUE( - QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtClient) { - if (GetQuicReloadableFlag(quic_default_on_pto) || - GetQuicReloadableFlag(quic_deprecate_tlpr)) { - return; - } - QuicConfig client_config; - QuicTagVector options; - - options.push_back(kTLPR); - QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); - client_config.SetConnectionOptionsToSend(options); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - manager_.SetFromConfig(client_config); - EXPECT_TRUE( - QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_)); -} - TEST_F(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtServer) { if (GetQuicReloadableFlag(quic_default_on_pto)) { return; @@ -4371,90 +4230,6 @@ TEST_F(QuicSentPacketManagerTest, manager_.GetRetransmissionTime()); } -TEST_F(QuicSentPacketManagerTest, ClientOnlyTLPRServer) { - if (GetQuicReloadableFlag(quic_deprecate_tlpr)) { - return; - } - QuicConfig config; - QuicTagVector options; - - options.push_back(kTLPR); - config.SetClientConnectionOptions(options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - // No change if the server receives client options. - EXPECT_FALSE( - QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, ClientOnlyTLPR) { - if (GetQuicReloadableFlag(quic_deprecate_tlpr)) { - return; - } - QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); - QuicConfig config; - QuicTagVector options; - - options.push_back(kTLPR); - config.SetClientConnectionOptions(options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - EXPECT_TRUE( - QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, PtoWithTlpr) { - if (GetQuicReloadableFlag(quic_deprecate_tlpr)) { - return; - } - QuicConfig config; - QuicTagVector options; - - options.push_back(kTLPR); - options.push_back(k1PTO); - options.push_back(kPTOS); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*send_algorithm_, PacingRate(_)) - .WillRepeatedly(Return(QuicBandwidth::Zero())); - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillOnce(Return(10 * kDefaultTCPMSS)); - manager_.SetFromConfig(config); - EXPECT_TRUE( - QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_)); - RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); - rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100), - QuicTime::Delta::Zero(), QuicTime::Zero()); - QuicTime::Delta srtt = rtt_stats->smoothed_rtt(); - manager_.SetHandshakeConfirmed(); - - SendDataPacket(1, ENCRYPTION_FORWARD_SECURE); - // Verify PTO is correctly set. - QuicTime::Delta expected_pto_delay = 0.5 * srtt; - QuicTime deadline = clock_.Now() + expected_pto_delay; - EXPECT_EQ(deadline, manager_.GetRetransmissionTime()); - - // Invoke PTO. - clock_.AdvanceTime(deadline - clock_.Now()); - manager_.OnRetransmissionTimeout(); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeSendProbePackets(); - - // Verify PTO period gets set correctly. - expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + - QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); - QuicTime sent_time = clock_.Now(); - EXPECT_EQ(sent_time + expected_pto_delay * 2, - manager_.GetRetransmissionTime()); -} - TEST_F(QuicSentPacketManagerTest, SendPathChallengeAndGetAck) { QuicPacketNumber packet_number(1); EXPECT_CALL(*send_algorithm_, diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session.cc b/chromium/net/third_party/quiche/src/quic/core/quic_session.cc index 14d549a3888..202bff43e1f 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_session.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_session.cc @@ -147,10 +147,6 @@ void QuicSession::Initialize() { connection_->OnSuccessfulVersionNegotiation(); } - if (GetMutableCryptoStream()->KeyUpdateSupportedLocally()) { - config_.SetKeyUpdateSupportedLocally(); - } - if (QuicVersionUsesCryptoFrames(transport_version())) { return; } diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session.h b/chromium/net/third_party/quiche/src/quic/core/quic_session.h index d06e1fe43a4..88ae992880d 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_session.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_session.h @@ -312,6 +312,7 @@ class QUIC_EXPORT_PRIVATE QuicSession std::string* error_details) override; void OnHandshakeCallbackDone() override; bool PacketFlusherAttached() const override; + ParsedQuicVersion parsed_version() const override { return version(); } // Implement StreamDelegateInterface. void OnStreamError(QuicErrorCode error_code, diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc index 8d5e477237a..256865d9e7b 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc @@ -159,7 +159,6 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker { } void SetServerApplicationStateForResumption( std::unique_ptr<ApplicationState> /*application_state*/) override {} - MOCK_METHOD(bool, KeyUpdateSupportedLocally, (), (const, override)); MOCK_METHOD(std::unique_ptr<QuicDecrypter>, AdvanceKeysAndCreateCurrentOneRttDecrypter, (), @@ -235,8 +234,6 @@ class TestSession : public QuicSession { writev_consumes_all_data_(false), uses_pending_streams_(false), num_incoming_streams_created_(0) { - EXPECT_CALL(*GetMutableCryptoStream(), KeyUpdateSupportedLocally()) - .WillRepeatedly(Return(false)); Initialize(); this->connection()->SetEncrypter( ENCRYPTION_FORWARD_SECURE, @@ -2294,20 +2291,6 @@ TEST_P(QuicSessionTestClient, MinAckDelaySetOnTheClientQuicConfig) { ASSERT_TRUE(session_.connection()->can_receive_ack_frequency_frame()); } -TEST_P(QuicSessionTestClient, KeyUpdateNotSupportedLocally) { - EXPECT_CALL(*session_.GetMutableCryptoStream(), KeyUpdateSupportedLocally()) - .WillOnce(Return(false)); - session_.Initialize(); - EXPECT_FALSE(session_.config()->KeyUpdateSupportedLocally()); -} - -TEST_P(QuicSessionTestClient, KeyUpdateSupportedLocally) { - EXPECT_CALL(*session_.GetMutableCryptoStream(), KeyUpdateSupportedLocally()) - .WillOnce(Return(true)); - session_.Initialize(); - EXPECT_TRUE(session_.config()->KeyUpdateSupportedLocally()); -} - TEST_P(QuicSessionTestClient, FailedToCreateStreamIfTooCloseToIdleTimeout) { connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); EXPECT_TRUE(session_.CanOpenNextOutgoingBidirectionalStream()); diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc index f055bdf2e9f..6237dae2f62 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc @@ -506,13 +506,7 @@ bool QuicStream::OnStopSending(QuicResetStreamError error) { } stream_error_ = error; - if (GetQuicReloadableFlag(quic_match_ietf_reset_code)) { - QUIC_RELOADABLE_FLAG_COUNT(quic_match_ietf_reset_code); - MaybeSendRstStream(error); - } else { - MaybeSendRstStream( - QuicResetStreamError::FromInternal(error.internal_code())); - } + MaybeSendRstStream(error); return true; } diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_tag.cc b/chromium/net/third_party/quiche/src/quic/core/quic_tag.cc index 32b7bf9cd76..b5f64f1a775 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_tag.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_tag.cc @@ -66,7 +66,7 @@ std::string QuicTagToString(QuicTag tag) { reinterpret_cast<const char*>(&orig_tag), sizeof(orig_tag))); } -uint32_t MakeQuicTag(char a, char b, char c, char d) { +uint32_t MakeQuicTag(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { return static_cast<uint32_t>(a) | static_cast<uint32_t>(b) << 8 | static_cast<uint32_t>(c) << 16 | static_cast<uint32_t>(d) << 24; } diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_tag.h b/chromium/net/third_party/quiche/src/quic/core/quic_tag.h index c77219eb321..1dfc754f870 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_tag.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_tag.h @@ -5,6 +5,7 @@ #ifndef QUICHE_QUIC_CORE_QUIC_TAG_H_ #define QUICHE_QUIC_CORE_QUIC_TAG_H_ +#include <cstdint> #include <map> #include <string> #include <vector> @@ -28,7 +29,8 @@ using QuicTagVector = std::vector<QuicTag>; // MakeQuicTag returns a value given the four bytes. For example: // MakeQuicTag('C', 'H', 'L', 'O'); -QUIC_EXPORT_PRIVATE QuicTag MakeQuicTag(char a, char b, char c, char d); +QUIC_EXPORT_PRIVATE QuicTag MakeQuicTag(uint8_t a, uint8_t b, uint8_t c, + uint8_t d); // Returns true if |tag_vector| contains |tag|. QUIC_EXPORT_PRIVATE bool ContainsQuicTag(const QuicTagVector& tag_vector, diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_types.h b/chromium/net/third_party/quiche/src/quic/core/quic_types.h index 200e843f826..a437c9ae731 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_types.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_types.h @@ -13,11 +13,12 @@ #include <vector> #include "absl/container/inlined_vector.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" #include "quic/core/quic_connection_id.h" #include "quic/core/quic_error_codes.h" #include "quic/core/quic_packet_number.h" #include "quic/core/quic_time.h" -#include "quic/platform/api/quic_containers.h" #include "quic/platform/api/quic_export.h" #include "quic/platform/api/quic_flags.h" diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc index 3aa821c1cd4..13094564258 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc @@ -30,21 +30,17 @@ QuicVersionManager::GetSupportedVersionsWithOnlyHttp3() { return filtered_supported_versions_with_http3_; } -const ParsedQuicVersionVector& -QuicVersionManager::GetSupportedVersionsWithQuicCrypto() { - MaybeRefilterSupportedVersions(); - return filtered_supported_versions_with_quic_crypto_; -} - const std::vector<std::string>& QuicVersionManager::GetSupportedAlpns() { MaybeRefilterSupportedVersions(); return filtered_supported_alpns_; } void QuicVersionManager::MaybeRefilterSupportedVersions() { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); - if (disable_version_rfcv1_ != + if (enable_version_2_draft_01_ != + GetQuicReloadableFlag(quic_enable_version_2_draft_01) || + disable_version_rfcv1_ != GetQuicReloadableFlag(quic_disable_version_rfcv1) || disable_version_draft_29_ != GetQuicReloadableFlag(quic_disable_version_draft_29) || @@ -54,6 +50,8 @@ void QuicVersionManager::MaybeRefilterSupportedVersions() { GetQuicReloadableFlag(quic_disable_version_q046) || disable_version_q043_ != GetQuicReloadableFlag(quic_disable_version_q043)) { + enable_version_2_draft_01_ = + GetQuicReloadableFlag(quic_enable_version_2_draft_01); disable_version_rfcv1_ = GetQuicReloadableFlag(quic_disable_version_rfcv1); disable_version_draft_29_ = GetQuicReloadableFlag(quic_disable_version_draft_29); @@ -69,7 +67,6 @@ void QuicVersionManager::RefilterSupportedVersions() { filtered_supported_versions_ = FilterSupportedVersions(allowed_supported_versions_); filtered_supported_versions_with_http3_.clear(); - filtered_supported_versions_with_quic_crypto_.clear(); filtered_transport_versions_.clear(); filtered_supported_alpns_.clear(); for (const ParsedQuicVersion& version : filtered_supported_versions_) { @@ -82,10 +79,11 @@ void QuicVersionManager::RefilterSupportedVersions() { if (version.UsesHttp3()) { filtered_supported_versions_with_http3_.push_back(version); } - if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) { - filtered_supported_versions_with_quic_crypto_.push_back(version); + if (std::find(filtered_supported_alpns_.begin(), + filtered_supported_alpns_.end(), + AlpnForVersion(version)) == filtered_supported_alpns_.end()) { + filtered_supported_alpns_.emplace_back(AlpnForVersion(version)); } - filtered_supported_alpns_.emplace_back(AlpnForVersion(version)); } } diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h index a3ae7194ad4..44e134ac363 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h @@ -25,9 +25,6 @@ class QUIC_EXPORT_PRIVATE QuicVersionManager { // Returns currently supported versions using HTTP/3. const ParsedQuicVersionVector& GetSupportedVersionsWithOnlyHttp3(); - // Returns currently supported versions using QUIC crypto. - const ParsedQuicVersionVector& GetSupportedVersionsWithQuicCrypto(); - // Returns the list of supported ALPNs, based on the current supported // versions and any custom additions by subclasses. const std::vector<std::string>& GetSupportedAlpns(); @@ -58,6 +55,8 @@ class QUIC_EXPORT_PRIVATE QuicVersionManager { private: // Cached value of reloadable flags. + // quic_enable_version_2_draft_01 flag + bool enable_version_2_draft_01_ = false; // quic_disable_version_rfcv1 flag bool disable_version_rfcv1_ = true; // quic_disable_version_draft_29 flag @@ -82,8 +81,6 @@ class QUIC_EXPORT_PRIVATE QuicVersionManager { ParsedQuicVersionVector filtered_supported_versions_; // Currently supported versions using HTTP/3. ParsedQuicVersionVector filtered_supported_versions_with_http3_; - // Currently supported versions using QUIC crypto. - ParsedQuicVersionVector filtered_supported_versions_with_quic_crypto_; // This vector contains the transport versions from // |filtered_supported_versions_|. No guarantees are made that the same // transport version isn't repeated. diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc index 8960bced5c0..da87c4a1d53 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc @@ -18,11 +18,12 @@ namespace { class QuicVersionManagerTest : public QuicTest {}; TEST_F(QuicVersionManagerTest, QuicVersionManager) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); for (const ParsedQuicVersion& version : AllSupportedVersions()) { QuicEnableVersion(version); } + QuicDisableVersion(ParsedQuicVersion::V2Draft01()); QuicDisableVersion(ParsedQuicVersion::RFCv1()); QuicDisableVersion(ParsedQuicVersion::Draft29()); QuicVersionManager manager(AllSupportedVersions()); @@ -37,8 +38,6 @@ TEST_F(QuicVersionManagerTest, QuicVersionManager) { EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), manager.GetSupportedVersions()); EXPECT_TRUE(manager.GetSupportedVersionsWithOnlyHttp3().empty()); - EXPECT_EQ(CurrentSupportedVersionsWithQuicCrypto(), - manager.GetSupportedVersionsWithQuicCrypto()); EXPECT_THAT(manager.GetSupportedAlpns(), ElementsAre("h3-Q050", "h3-Q046", "h3-Q043")); @@ -47,15 +46,11 @@ TEST_F(QuicVersionManagerTest, QuicVersionManager) { expected_parsed_versions.insert(expected_parsed_versions.begin(), ParsedQuicVersion::Draft29()); EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions()); - EXPECT_EQ(expected_parsed_versions.size() - 1 - offset, - manager.GetSupportedVersionsWithQuicCrypto().size()); EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), manager.GetSupportedVersions()); EXPECT_EQ(1u, manager.GetSupportedVersionsWithOnlyHttp3().size()); EXPECT_EQ(CurrentSupportedHttp3Versions(), manager.GetSupportedVersionsWithOnlyHttp3()); - EXPECT_EQ(CurrentSupportedVersionsWithQuicCrypto(), - manager.GetSupportedVersionsWithQuicCrypto()); EXPECT_THAT(manager.GetSupportedAlpns(), ElementsAre("h3-29", "h3-Q050", "h3-Q046", "h3-Q043")); @@ -64,17 +59,27 @@ TEST_F(QuicVersionManagerTest, QuicVersionManager) { expected_parsed_versions.insert(expected_parsed_versions.begin(), ParsedQuicVersion::RFCv1()); EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions()); - EXPECT_EQ(expected_parsed_versions.size() - 1 - offset, - manager.GetSupportedVersionsWithQuicCrypto().size()); EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), manager.GetSupportedVersions()); EXPECT_EQ(2u, manager.GetSupportedVersionsWithOnlyHttp3().size()); EXPECT_EQ(CurrentSupportedHttp3Versions(), manager.GetSupportedVersionsWithOnlyHttp3()); - EXPECT_EQ(CurrentSupportedVersionsWithQuicCrypto(), - manager.GetSupportedVersionsWithQuicCrypto()); EXPECT_THAT(manager.GetSupportedAlpns(), ElementsAre("h3", "h3-29", "h3-Q050", "h3-Q046", "h3-Q043")); + + offset++; + QuicEnableVersion(ParsedQuicVersion::V2Draft01()); + expected_parsed_versions.insert(expected_parsed_versions.begin(), + ParsedQuicVersion::V2Draft01()); + EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions()); + EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), + manager.GetSupportedVersions()); + EXPECT_EQ(3u, manager.GetSupportedVersionsWithOnlyHttp3().size()); + EXPECT_EQ(CurrentSupportedHttp3Versions(), + manager.GetSupportedVersionsWithOnlyHttp3()); + EXPECT_THAT( + manager.GetSupportedAlpns(), + ElementsAre("h3", "h3-29", "h3-Q050", "h3-Q046", "h3-Q043")); } } // namespace diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc b/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc index 4c9e661fa41..21ec163807c 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc @@ -23,12 +23,6 @@ namespace quic { namespace { -// Constructs a version label from the 4 bytes such that the on-the-wire -// order will be: d, c, b, a. -QuicVersionLabel MakeVersionLabel(char a, char b, char c, char d) { - return MakeQuicTag(d, c, b, a); -} - QuicVersionLabel CreateRandomVersionLabelForNegotiation() { QuicVersionLabel result; if (!GetQuicFlag(FLAGS_quic_disable_version_negotiation_grease_randomness)) { @@ -42,11 +36,13 @@ QuicVersionLabel CreateRandomVersionLabelForNegotiation() { } void SetVersionFlag(const ParsedQuicVersion& version, bool should_enable) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); const bool enable = should_enable; const bool disable = !should_enable; - if (version == ParsedQuicVersion::RFCv1()) { + if (version == ParsedQuicVersion::V2Draft01()) { + SetQuicReloadableFlag(quic_enable_version_2_draft_01, enable); + } else if (version == ParsedQuicVersion::RFCv1()) { SetQuicReloadableFlag(quic_disable_version_rfcv1, disable); } else if (version == ParsedQuicVersion::Draft29()) { SetQuicReloadableFlag(quic_disable_version_draft_29, disable); @@ -182,6 +178,16 @@ bool ParsedQuicVersion::UsesQuicCrypto() const { return handshake_protocol == PROTOCOL_QUIC_CRYPTO; } +bool ParsedQuicVersion::UsesV2PacketTypes() const { + QUICHE_DCHECK(IsKnown()); + return transport_version == QUIC_VERSION_IETF_2_DRAFT_01; +} + +bool ParsedQuicVersion::AlpnDeferToRFCv1() const { + QUICHE_DCHECK(IsKnown()); + return transport_version == QUIC_VERSION_IETF_2_DRAFT_01; +} + bool VersionHasLengthPrefixedConnectionIds( QuicTransportVersion transport_version) { QUICHE_DCHECK(transport_version != QUIC_VERSION_UNSUPPORTED); @@ -200,6 +206,10 @@ std::ostream& operator<<(std::ostream& os, return os; } +QuicVersionLabel MakeVersionLabel(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { + return MakeQuicTag(d, c, b, a); +} + std::ostream& operator<<(std::ostream& os, const QuicVersionLabelVector& version_labels) { os << QuicVersionLabelVectorToString(version_labels); @@ -213,9 +223,11 @@ std::ostream& operator<<(std::ostream& os, } QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); - if (parsed_version == ParsedQuicVersion::RFCv1()) { + if (parsed_version == ParsedQuicVersion::V2Draft01()) { + return MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4); + } else if (parsed_version == ParsedQuicVersion::RFCv1()) { return MakeVersionLabel(0x00, 0x00, 0x00, 0x01); } else if (parsed_version == ParsedQuicVersion::Draft29()) { return MakeVersionLabel(0xff, 0x00, 0x00, 29); @@ -333,25 +345,11 @@ ParsedQuicVersion ParseQuicVersionString(absl::string_view version_string) { if (version_string.empty()) { return UnsupportedQuicVersion(); } - int quic_version_number = 0; const ParsedQuicVersionVector supported_versions = AllSupportedVersions(); - if (absl::SimpleAtoi(version_string, &quic_version_number) && - quic_version_number > 0) { - QuicTransportVersion transport_version = - static_cast<QuicTransportVersion>(quic_version_number); - if (!ParsedQuicVersionIsValid(PROTOCOL_QUIC_CRYPTO, transport_version)) { - return UnsupportedQuicVersion(); - } - ParsedQuicVersion version(PROTOCOL_QUIC_CRYPTO, transport_version); - if (std::find(supported_versions.begin(), supported_versions.end(), - version) != supported_versions.end()) { - return version; - } - return UnsupportedQuicVersion(); - } for (const ParsedQuicVersion& version : supported_versions) { if (version_string == ParsedQuicVersionToString(version) || - version_string == AlpnForVersion(version) || + (version_string == AlpnForVersion(version) && + !version.AlpnDeferToRFCv1()) || (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO && version_string == QuicVersionToString(version.transport_version))) { return version; @@ -364,6 +362,21 @@ ParsedQuicVersion ParseQuicVersionString(absl::string_view version_string) { return version; } } + int quic_version_number = 0; + if (absl::SimpleAtoi(version_string, &quic_version_number) && + quic_version_number > 0) { + QuicTransportVersion transport_version = + static_cast<QuicTransportVersion>(quic_version_number); + if (!ParsedQuicVersionIsValid(PROTOCOL_QUIC_CRYPTO, transport_version)) { + return UnsupportedQuicVersion(); + } + ParsedQuicVersion version(PROTOCOL_QUIC_CRYPTO, transport_version); + if (std::find(supported_versions.begin(), supported_versions.end(), + version) != supported_versions.end()) { + return version; + } + return UnsupportedQuicVersion(); + } // Reading from the client so this should not be considered an ERROR. QUIC_DLOG(INFO) << "Unsupported QUIC version string: \"" << version_string << "\"."; @@ -411,10 +424,16 @@ ParsedQuicVersionVector CurrentSupportedVersions() { ParsedQuicVersionVector FilterSupportedVersions( ParsedQuicVersionVector versions) { + static_assert(SupportedVersions().size() == 6u, + "Supported versions out of sync"); ParsedQuicVersionVector filtered_versions; filtered_versions.reserve(versions.size()); for (const ParsedQuicVersion& version : versions) { - if (version == ParsedQuicVersion::RFCv1()) { + if (version == ParsedQuicVersion::V2Draft01()) { + if (GetQuicReloadableFlag(quic_enable_version_2_draft_01)) { + filtered_versions.push_back(version); + } + } else if (version == ParsedQuicVersion::RFCv1()) { if (!GetQuicReloadableFlag(quic_disable_version_rfcv1)) { filtered_versions.push_back(version); } @@ -444,8 +463,7 @@ ParsedQuicVersionVector FilterSupportedVersions( } ParsedQuicVersionVector ParsedVersionOfIndex( - const ParsedQuicVersionVector& versions, - int index) { + const ParsedQuicVersionVector& versions, int index) { ParsedQuicVersionVector version; int version_count = versions.size(); if (index >= 0 && index < version_count) { @@ -460,9 +478,20 @@ std::string QuicVersionLabelToString(QuicVersionLabel version_label) { return QuicTagToString(quiche::QuicheEndian::HostToNet32(version_label)); } +ParsedQuicVersion ParseQuicVersionLabelString( + absl::string_view version_label_string) { + const ParsedQuicVersionVector supported_versions = AllSupportedVersions(); + for (const ParsedQuicVersion& version : supported_versions) { + if (version_label_string == + QuicVersionLabelToString(CreateQuicVersionLabel(version))) { + return version; + } + } + return UnsupportedQuicVersion(); +} + std::string QuicVersionLabelVectorToString( - const QuicVersionLabelVector& version_labels, - const std::string& separator, + const QuicVersionLabelVector& version_labels, const std::string& separator, size_t skip_after_nth_version) { std::string result; for (size_t i = 0; i < version_labels.size(); ++i) { @@ -490,6 +519,7 @@ std::string QuicVersionToString(QuicTransportVersion transport_version) { RETURN_STRING_LITERAL(QUIC_VERSION_50); RETURN_STRING_LITERAL(QUIC_VERSION_IETF_DRAFT_29); RETURN_STRING_LITERAL(QUIC_VERSION_IETF_RFC_V1); + RETURN_STRING_LITERAL(QUIC_VERSION_IETF_2_DRAFT_01); RETURN_STRING_LITERAL(QUIC_VERSION_UNSUPPORTED); RETURN_STRING_LITERAL(QUIC_VERSION_RESERVED_FOR_NEGOTIATION); } @@ -508,10 +538,13 @@ std::string HandshakeProtocolToString(HandshakeProtocol handshake_protocol) { } std::string ParsedQuicVersionToString(ParsedQuicVersion version) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); if (version == UnsupportedQuicVersion()) { return "0"; + } else if (version == ParsedQuicVersion::V2Draft01()) { + QUICHE_DCHECK(version.UsesHttp3()); + return "v2draft01"; } else if (version == ParsedQuicVersion::RFCv1()) { QUICHE_DCHECK(version.UsesHttp3()); return "RFCv1"; @@ -536,8 +569,7 @@ std::string QuicTransportVersionVectorToString( } std::string ParsedQuicVersionVectorToString( - const ParsedQuicVersionVector& versions, - const std::string& separator, + const ParsedQuicVersionVector& versions, const std::string& separator, size_t skip_after_nth_version) { std::string result; for (size_t i = 0; i < versions.size(); ++i) { @@ -604,7 +636,9 @@ ParsedQuicVersion LegacyVersionForEncapsulation() { } std::string AlpnForVersion(ParsedQuicVersion parsed_version) { - if (parsed_version == ParsedQuicVersion::RFCv1()) { + if (parsed_version == ParsedQuicVersion::V2Draft01()) { + return "h3"; + } else if (parsed_version == ParsedQuicVersion::RFCv1()) { return "h3"; } else if (parsed_version == ParsedQuicVersion::Draft29()) { return "h3-29"; diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_versions.h b/chromium/net/third_party/quiche/src/quic/core/quic_versions.h index 331a99c9759..59bf7532f3a 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_versions.h +++ b/chromium/net/third_party/quiche/src/quic/core/quic_versions.h @@ -23,6 +23,7 @@ #ifndef QUICHE_QUIC_CORE_QUIC_VERSIONS_H_ #define QUICHE_QUIC_CORE_QUIC_VERSIONS_H_ +#include <cstdint> #include <string> #include <vector> @@ -122,8 +123,9 @@ enum QuicTransportVersion { // Number 70 used to represent draft-ietf-quic-transport-25. // Number 71 used to represent draft-ietf-quic-transport-27. // Number 72 used to represent draft-ietf-quic-transport-28. - QUIC_VERSION_IETF_DRAFT_29 = 73, // draft-ietf-quic-transport-29. - QUIC_VERSION_IETF_RFC_V1 = 80, // RFC 9000. + QUIC_VERSION_IETF_DRAFT_29 = 73, // draft-ietf-quic-transport-29. + QUIC_VERSION_IETF_RFC_V1 = 80, // RFC 9000. + QUIC_VERSION_IETF_2_DRAFT_01 = 81, // draft-ietf-quic-v2-01. // Version 99 was a dumping ground for IETF QUIC changes which were not yet // ready for production between 2018-02 and 2020-02. @@ -171,6 +173,7 @@ QUIC_EXPORT_PRIVATE constexpr bool ParsedQuicVersionIsValid( QuicTransportVersion transport_version) { bool transport_version_is_valid = false; constexpr QuicTransportVersion valid_transport_versions[] = { + QUIC_VERSION_IETF_2_DRAFT_01, QUIC_VERSION_IETF_RFC_V1, QUIC_VERSION_IETF_DRAFT_29, QUIC_VERSION_50, @@ -195,7 +198,8 @@ QUIC_EXPORT_PRIVATE constexpr bool ParsedQuicVersionIsValid( return transport_version != QUIC_VERSION_UNSUPPORTED && transport_version != QUIC_VERSION_RESERVED_FOR_NEGOTIATION && transport_version != QUIC_VERSION_IETF_DRAFT_29 && - transport_version != QUIC_VERSION_IETF_RFC_V1; + transport_version != QUIC_VERSION_IETF_RFC_V1 && + transport_version != QUIC_VERSION_IETF_2_DRAFT_01; case PROTOCOL_TLS1_3: return transport_version != QUIC_VERSION_UNSUPPORTED && transport_version != QUIC_VERSION_50 && @@ -245,6 +249,10 @@ struct QUIC_EXPORT_PRIVATE ParsedQuicVersion { transport_version != other.transport_version; } + static constexpr ParsedQuicVersion V2Draft01() { + return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_2_DRAFT_01); + } + static constexpr ParsedQuicVersion RFCv1() { return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_RFC_V1); } @@ -361,6 +369,14 @@ struct QUIC_EXPORT_PRIVATE ParsedQuicVersion { // Returns whether this version uses PROTOCOL_QUIC_CRYPTO. bool UsesQuicCrypto() const; + + // Returns whether this version uses the QUICv2 Long Header Packet Types. + bool UsesV2PacketTypes() const; + + // Returns true if this shares ALPN codes with RFCv1, and endpoints should + // choose RFCv1 when presented with a v1 ALPN. Note that this is false for + // RFCv1. + bool AlpnDeferToRFCv1() const; }; QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion(); @@ -377,36 +393,38 @@ QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, using ParsedQuicVersionVector = std::vector<ParsedQuicVersion>; QUIC_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& os, - const ParsedQuicVersionVector& versions); + std::ostream& os, const ParsedQuicVersionVector& versions); // Representation of the on-the-wire QUIC version number. Will be written/read // to the wire in network-byte-order. using QuicVersionLabel = uint32_t; using QuicVersionLabelVector = std::vector<QuicVersionLabel>; +// Constructs a version label from the 4 bytes such that the on-the-wire +// order will be: d, c, b, a. +QUIC_EXPORT_PRIVATE QuicVersionLabel MakeVersionLabel(uint8_t a, uint8_t b, + uint8_t c, uint8_t d); + QUIC_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& os, - const QuicVersionLabelVector& version_labels); + std::ostream& os, const QuicVersionLabelVector& version_labels); // This vector contains all crypto handshake protocols that are supported. constexpr std::array<HandshakeProtocol, 2> SupportedHandshakeProtocols() { return {PROTOCOL_TLS1_3, PROTOCOL_QUIC_CRYPTO}; } -constexpr std::array<ParsedQuicVersion, 5> SupportedVersions() { +constexpr std::array<ParsedQuicVersion, 6> SupportedVersions() { return { - ParsedQuicVersion::RFCv1(), ParsedQuicVersion::Draft29(), - ParsedQuicVersion::Q050(), ParsedQuicVersion::Q046(), - ParsedQuicVersion::Q043(), + ParsedQuicVersion::V2Draft01(), ParsedQuicVersion::RFCv1(), + ParsedQuicVersion::Draft29(), ParsedQuicVersion::Q050(), + ParsedQuicVersion::Q046(), ParsedQuicVersion::Q043(), }; } using QuicTransportVersionVector = std::vector<QuicTransportVersion>; QUIC_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& os, - const QuicTransportVersionVector& transport_versions); + std::ostream& os, const QuicTransportVersionVector& transport_versions); // Returns a vector of supported QUIC versions. QUIC_EXPORT_PRIVATE ParsedQuicVersionVector AllSupportedVersions(); @@ -490,12 +508,20 @@ CreateQuicVersionLabelVector(const ParsedQuicVersionVector& versions); QUIC_EXPORT_PRIVATE std::string QuicVersionLabelToString( QuicVersionLabel version_label); +// Helper function which translates from a QuicVersionLabel string to a +// ParsedQuicVersion. The version label string must be of the form returned +// by QuicVersionLabelToString, for example, "00000001" or "Q046", but not +// "51303433" (the hex encoding of the Q064 version label). Returns +// the ParsedQuicVersion which matches the label or UnsupportedQuicVersion() +// otherwise. +QUIC_EXPORT_PRIVATE ParsedQuicVersion +ParseQuicVersionLabelString(absl::string_view version_label_string); + // Returns |separator|-separated list of string representations of // QuicVersionLabel values in the supplied |version_labels| vector. The values // after the (0-based) |skip_after_nth_version|'th are skipped. QUIC_EXPORT_PRIVATE std::string QuicVersionLabelVectorToString( - const QuicVersionLabelVector& version_labels, - const std::string& separator, + const QuicVersionLabelVector& version_labels, const std::string& separator, size_t skip_after_nth_version); // Returns comma separated list of string representations of QuicVersionLabel @@ -529,8 +555,7 @@ QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionVectorToString( // ParsedQuicVersion values in the supplied |versions| vector. The values after // the (0-based) |skip_after_nth_version|'th are skipped. QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionVectorToString( - const ParsedQuicVersionVector& versions, - const std::string& separator, + const ParsedQuicVersionVector& versions, const std::string& separator, size_t skip_after_nth_version); // Returns comma separated list of string representations of ParsedQuicVersion diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc index 60790d61ece..8d420acaf3d 100644 --- a/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc @@ -15,24 +15,16 @@ namespace quic { namespace test { namespace { -using ::testing::_; using ::testing::ElementsAre; using ::testing::IsEmpty; -class QuicVersionsTest : public QuicTest { - protected: - QuicVersionLabel MakeVersionLabel(char a, char b, char c, char d) { - return MakeQuicTag(d, c, b, a); - } -}; - -TEST_F(QuicVersionsTest, CreateQuicVersionLabelUnsupported) { +TEST(QuicVersionsTest, CreateQuicVersionLabelUnsupported) { EXPECT_QUIC_BUG( CreateQuicVersionLabel(UnsupportedQuicVersion()), "Unsupported version QUIC_VERSION_UNSUPPORTED PROTOCOL_UNSUPPORTED"); } -TEST_F(QuicVersionsTest, KnownAndValid) { +TEST(QuicVersionsTest, KnownAndValid) { for (const ParsedQuicVersion& version : AllSupportedVersions()) { EXPECT_TRUE(version.IsKnown()); EXPECT_TRUE(ParsedQuicVersionIsValid(version.handshake_protocol, @@ -59,7 +51,7 @@ TEST_F(QuicVersionsTest, KnownAndValid) { static_cast<QuicTransportVersion>(99))); } -TEST_F(QuicVersionsTest, Features) { +TEST(QuicVersionsTest, Features) { ParsedQuicVersion parsed_version_q043 = ParsedQuicVersion::Q043(); ParsedQuicVersion parsed_version_draft_29 = ParsedQuicVersion::Draft29(); @@ -110,7 +102,9 @@ TEST_F(QuicVersionsTest, Features) { EXPECT_FALSE(parsed_version_draft_29.UsesQuicCrypto()); } -TEST_F(QuicVersionsTest, ParseQuicVersionLabel) { +TEST(QuicVersionsTest, ParseQuicVersionLabel) { + static_assert(SupportedVersions().size() == 6u, + "Supported versions out of sync"); EXPECT_EQ(ParsedQuicVersion::Q043(), ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '3'))); EXPECT_EQ(ParsedQuicVersion::Q046(), @@ -121,15 +115,25 @@ TEST_F(QuicVersionsTest, ParseQuicVersionLabel) { ParseQuicVersionLabel(MakeVersionLabel(0xff, 0x00, 0x00, 0x1d))); EXPECT_EQ(ParsedQuicVersion::RFCv1(), ParseQuicVersionLabel(MakeVersionLabel(0x00, 0x00, 0x00, 0x01))); - EXPECT_EQ((ParsedQuicVersionVector{ParsedQuicVersion::RFCv1(), + EXPECT_EQ(ParsedQuicVersion::V2Draft01(), + ParseQuicVersionLabel(MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4))); + EXPECT_EQ((ParsedQuicVersionVector{ParsedQuicVersion::V2Draft01(), + ParsedQuicVersion::RFCv1(), ParsedQuicVersion::Draft29()}), ParseQuicVersionLabelVector(QuicVersionLabelVector{ + MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4), MakeVersionLabel(0x00, 0x00, 0x00, 0x01), MakeVersionLabel(0xaa, 0xaa, 0xaa, 0xaa), MakeVersionLabel(0xff, 0x00, 0x00, 0x1d)})); + + for (const ParsedQuicVersion& version : AllSupportedVersions()) { + EXPECT_EQ(version, ParseQuicVersionLabel(CreateQuicVersionLabel(version))); + } } -TEST_F(QuicVersionsTest, ParseQuicVersionString) { +TEST(QuicVersionsTest, ParseQuicVersionString) { + static_assert(SupportedVersions().size() == 6u, + "Supported versions out of sync"); EXPECT_EQ(ParsedQuicVersion::Q043(), ParseQuicVersionString("Q043")); EXPECT_EQ(ParsedQuicVersion::Q046(), ParseQuicVersionString("QUIC_VERSION_46")); @@ -149,13 +153,23 @@ TEST_F(QuicVersionsTest, ParseQuicVersionString) { EXPECT_EQ(ParsedQuicVersion::Draft29(), ParseQuicVersionString("draft29")); EXPECT_EQ(ParsedQuicVersion::Draft29(), ParseQuicVersionString("h3-29")); + EXPECT_EQ(ParsedQuicVersion::RFCv1(), ParseQuicVersionString("00000001")); + EXPECT_EQ(ParsedQuicVersion::RFCv1(), ParseQuicVersionString("h3")); + + // QUICv2 will never be the result for "h3". + for (const ParsedQuicVersion& version : AllSupportedVersions()) { EXPECT_EQ(version, ParseQuicVersionString(ParsedQuicVersionToString(version))); + EXPECT_EQ(version, ParseQuicVersionString(QuicVersionLabelToString( + CreateQuicVersionLabel(version)))); + if (!version.AlpnDeferToRFCv1()) { + EXPECT_EQ(version, ParseQuicVersionString(AlpnForVersion(version))); + } } } -TEST_F(QuicVersionsTest, ParseQuicVersionVectorString) { +TEST(QuicVersionsTest, ParseQuicVersionVectorString) { ParsedQuicVersion version_q046 = ParsedQuicVersion::Q046(); ParsedQuicVersion version_q050 = ParsedQuicVersion::Q050(); ParsedQuicVersion version_draft_29 = ParsedQuicVersion::Draft29(); @@ -207,53 +221,101 @@ TEST_F(QuicVersionsTest, ParseQuicVersionVectorString) { ElementsAre(version_draft_29)); } -TEST_F(QuicVersionsTest, CreateQuicVersionLabel) { - EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '3'), - CreateQuicVersionLabel(ParsedQuicVersion::Q043())); - EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '6'), - CreateQuicVersionLabel(ParsedQuicVersion::Q046())); - EXPECT_EQ(MakeVersionLabel('Q', '0', '5', '0'), - CreateQuicVersionLabel(ParsedQuicVersion::Q050())); - EXPECT_EQ(MakeVersionLabel(0xff, 0x00, 0x00, 0x1d), - CreateQuicVersionLabel(ParsedQuicVersion::Draft29())); - EXPECT_EQ(MakeVersionLabel(0x00, 0x00, 0x00, 0x01), - CreateQuicVersionLabel(ParsedQuicVersion::RFCv1())); +// Do not use MakeVersionLabel() to generate expectations, because +// CreateQuicVersionLabel() uses MakeVersionLabel() internally, +// in case it has a bug. +TEST(QuicVersionsTest, CreateQuicVersionLabel) { + static_assert(SupportedVersions().size() == 6u, + "Supported versions out of sync"); + EXPECT_EQ(0x51303433u, CreateQuicVersionLabel(ParsedQuicVersion::Q043())); + EXPECT_EQ(0x51303436u, CreateQuicVersionLabel(ParsedQuicVersion::Q046())); + EXPECT_EQ(0x51303530u, CreateQuicVersionLabel(ParsedQuicVersion::Q050())); + EXPECT_EQ(0xff00001du, CreateQuicVersionLabel(ParsedQuicVersion::Draft29())); + EXPECT_EQ(0x00000001u, CreateQuicVersionLabel(ParsedQuicVersion::RFCv1())); + EXPECT_EQ(0x709a50c4u, + CreateQuicVersionLabel(ParsedQuicVersion::V2Draft01())); // Make sure the negotiation reserved version is in the IETF reserved space. EXPECT_EQ( - MakeVersionLabel(0xda, 0x5a, 0x3a, 0x3a) & 0x0f0f0f0f, + 0xda5a3a3au & 0x0f0f0f0f, CreateQuicVersionLabel(ParsedQuicVersion::ReservedForNegotiation()) & 0x0f0f0f0f); // Make sure that disabling randomness works. SetQuicFlag(FLAGS_quic_disable_version_negotiation_grease_randomness, true); - EXPECT_EQ( - MakeVersionLabel(0xda, 0x5a, 0x3a, 0x3a), - CreateQuicVersionLabel(ParsedQuicVersion::ReservedForNegotiation())); + EXPECT_EQ(0xda5a3a3au, CreateQuicVersionLabel( + ParsedQuicVersion::ReservedForNegotiation())); } -TEST_F(QuicVersionsTest, QuicVersionLabelToString) { +TEST(QuicVersionsTest, QuicVersionLabelToString) { + static_assert(SupportedVersions().size() == 6u, + "Supported versions out of sync"); + EXPECT_EQ("Q043", QuicVersionLabelToString( + CreateQuicVersionLabel(ParsedQuicVersion::Q043()))); + EXPECT_EQ("Q046", QuicVersionLabelToString( + CreateQuicVersionLabel(ParsedQuicVersion::Q046()))); + EXPECT_EQ("Q050", QuicVersionLabelToString( + CreateQuicVersionLabel(ParsedQuicVersion::Q050()))); + EXPECT_EQ("ff00001d", QuicVersionLabelToString(CreateQuicVersionLabel( + ParsedQuicVersion::Draft29()))); + EXPECT_EQ("00000001", QuicVersionLabelToString(CreateQuicVersionLabel( + ParsedQuicVersion::RFCv1()))); + EXPECT_EQ("709a50c4", QuicVersionLabelToString(CreateQuicVersionLabel( + ParsedQuicVersion::V2Draft01()))); + QuicVersionLabelVector version_labels = { MakeVersionLabel('Q', '0', '3', '5'), - MakeVersionLabel('Q', '0', '3', '7'), MakeVersionLabel('T', '0', '3', '8'), + MakeVersionLabel(0xff, 0, 0, 7), }; EXPECT_EQ("Q035", QuicVersionLabelToString(version_labels[0])); - EXPECT_EQ("T038", QuicVersionLabelToString(version_labels[2])); + EXPECT_EQ("T038", QuicVersionLabelToString(version_labels[1])); + EXPECT_EQ("ff000007", QuicVersionLabelToString(version_labels[2])); - EXPECT_EQ("Q035,Q037,T038", QuicVersionLabelVectorToString(version_labels)); - EXPECT_EQ("Q035:Q037:T038", + EXPECT_EQ("Q035,T038,ff000007", + QuicVersionLabelVectorToString(version_labels)); + EXPECT_EQ("Q035:T038:ff000007", QuicVersionLabelVectorToString(version_labels, ":", 2)); - EXPECT_EQ("Q035|Q037|...", + EXPECT_EQ("Q035|T038|...", QuicVersionLabelVectorToString(version_labels, "|", 1)); std::ostringstream os; os << version_labels; - EXPECT_EQ("Q035,Q037,T038", os.str()); + EXPECT_EQ("Q035,T038,ff000007", os.str()); } -TEST_F(QuicVersionsTest, QuicVersionToString) { +TEST(QuicVersionsTest, ParseQuicVersionLabelString) { + static_assert(SupportedVersions().size() == 6u, + "Supported versions out of sync"); + // Explicitly test known QUIC version label strings. + EXPECT_EQ(ParsedQuicVersion::Q043(), ParseQuicVersionLabelString("Q043")); + EXPECT_EQ(ParsedQuicVersion::Q046(), ParseQuicVersionLabelString("Q046")); + EXPECT_EQ(ParsedQuicVersion::Q050(), ParseQuicVersionLabelString("Q050")); + EXPECT_EQ(ParsedQuicVersion::Draft29(), + ParseQuicVersionLabelString("ff00001d")); + EXPECT_EQ(ParsedQuicVersion::RFCv1(), + ParseQuicVersionLabelString("00000001")); + EXPECT_EQ(ParsedQuicVersion::V2Draft01(), + ParseQuicVersionLabelString("709a50c4")); + + // Sanity check that a variety of other serialization formats are ignored. + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabelString("1")); + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabelString("46")); + EXPECT_EQ(UnsupportedQuicVersion(), + ParseQuicVersionLabelString("QUIC_VERSION_46")); + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabelString("h3")); + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabelString("h3-29")); + + // Test round-trips between QuicVersionLabelToString and + // ParseQuicVersionLabelString. + for (const ParsedQuicVersion& version : AllSupportedVersions()) { + EXPECT_EQ(version, ParseQuicVersionLabelString(QuicVersionLabelToString( + CreateQuicVersionLabel(version)))); + } +} + +TEST(QuicVersionsTest, QuicVersionToString) { EXPECT_EQ("QUIC_VERSION_UNSUPPORTED", QuicVersionToString(QUIC_VERSION_UNSUPPORTED)); @@ -285,13 +347,15 @@ TEST_F(QuicVersionsTest, QuicVersionToString) { EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_43", os.str()); } -TEST_F(QuicVersionsTest, ParsedQuicVersionToString) { +TEST(QuicVersionsTest, ParsedQuicVersionToString) { EXPECT_EQ("0", ParsedQuicVersionToString(ParsedQuicVersion::Unsupported())); EXPECT_EQ("Q043", ParsedQuicVersionToString(ParsedQuicVersion::Q043())); EXPECT_EQ("Q046", ParsedQuicVersionToString(ParsedQuicVersion::Q046())); EXPECT_EQ("Q050", ParsedQuicVersionToString(ParsedQuicVersion::Q050())); EXPECT_EQ("draft29", ParsedQuicVersionToString(ParsedQuicVersion::Draft29())); EXPECT_EQ("RFCv1", ParsedQuicVersionToString(ParsedQuicVersion::RFCv1())); + EXPECT_EQ("v2draft01", + ParsedQuicVersionToString(ParsedQuicVersion::V2Draft01())); ParsedQuicVersionVector versions_vector = {ParsedQuicVersion::Q043()}; EXPECT_EQ("Q043", ParsedQuicVersionVectorToString(versions_vector)); @@ -314,7 +378,7 @@ TEST_F(QuicVersionsTest, ParsedQuicVersionToString) { EXPECT_EQ("0,Q043", os.str()); } -TEST_F(QuicVersionsTest, FilterSupportedVersionsAllVersions) { +TEST(QuicVersionsTest, FilterSupportedVersionsAllVersions) { for (const ParsedQuicVersion& version : AllSupportedVersions()) { QuicEnableVersion(version); } @@ -327,7 +391,7 @@ TEST_F(QuicVersionsTest, FilterSupportedVersionsAllVersions) { EXPECT_EQ(expected_parsed_versions, AllSupportedVersions()); } -TEST_F(QuicVersionsTest, FilterSupportedVersionsWithoutFirstVersion) { +TEST(QuicVersionsTest, FilterSupportedVersionsWithoutFirstVersion) { for (const ParsedQuicVersion& version : AllSupportedVersions()) { QuicEnableVersion(version); } @@ -341,7 +405,7 @@ TEST_F(QuicVersionsTest, FilterSupportedVersionsWithoutFirstVersion) { FilterSupportedVersions(AllSupportedVersions())); } -TEST_F(QuicVersionsTest, LookUpParsedVersionByIndex) { +TEST(QuicVersionsTest, LookUpParsedVersionByIndex) { ParsedQuicVersionVector all_versions = AllSupportedVersions(); int version_count = all_versions.size(); for (int i = -5; i <= version_count + 1; ++i) { @@ -357,27 +421,29 @@ TEST_F(QuicVersionsTest, LookUpParsedVersionByIndex) { // This test may appear to be so simplistic as to be unnecessary, // yet a typo was made in doing the #defines and it was caught // only in some test far removed from here... Better safe than sorry. -TEST_F(QuicVersionsTest, CheckTransportVersionNumbersForTypos) { - static_assert(SupportedVersions().size() == 5u, +TEST(QuicVersionsTest, CheckTransportVersionNumbersForTypos) { + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); EXPECT_EQ(QUIC_VERSION_43, 43); EXPECT_EQ(QUIC_VERSION_46, 46); EXPECT_EQ(QUIC_VERSION_50, 50); EXPECT_EQ(QUIC_VERSION_IETF_DRAFT_29, 73); EXPECT_EQ(QUIC_VERSION_IETF_RFC_V1, 80); + EXPECT_EQ(QUIC_VERSION_IETF_2_DRAFT_01, 81); } -TEST_F(QuicVersionsTest, AlpnForVersion) { - static_assert(SupportedVersions().size() == 5u, +TEST(QuicVersionsTest, AlpnForVersion) { + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); EXPECT_EQ("h3-Q043", AlpnForVersion(ParsedQuicVersion::Q043())); EXPECT_EQ("h3-Q046", AlpnForVersion(ParsedQuicVersion::Q046())); EXPECT_EQ("h3-Q050", AlpnForVersion(ParsedQuicVersion::Q050())); EXPECT_EQ("h3-29", AlpnForVersion(ParsedQuicVersion::Draft29())); EXPECT_EQ("h3", AlpnForVersion(ParsedQuicVersion::RFCv1())); + EXPECT_EQ("h3", AlpnForVersion(ParsedQuicVersion::V2Draft01())); } -TEST_F(QuicVersionsTest, QuicVersionEnabling) { +TEST(QuicVersionsTest, QuicVersionEnabling) { for (const ParsedQuicVersion& version : AllSupportedVersions()) { QuicFlagSaver flag_saver; QuicDisableVersion(version); @@ -387,7 +453,7 @@ TEST_F(QuicVersionsTest, QuicVersionEnabling) { } } -TEST_F(QuicVersionsTest, ReservedForNegotiation) { +TEST(QuicVersionsTest, ReservedForNegotiation) { EXPECT_EQ(QUIC_VERSION_RESERVED_FOR_NEGOTIATION, QuicVersionReservedForNegotiation().transport_version); // QUIC_VERSION_RESERVED_FOR_NEGOTIATION MUST NOT be supported. @@ -396,7 +462,7 @@ TEST_F(QuicVersionsTest, ReservedForNegotiation) { } } -TEST_F(QuicVersionsTest, SupportedVersionsHasCorrectList) { +TEST(QuicVersionsTest, SupportedVersionsHasCorrectList) { size_t index = 0; for (HandshakeProtocol handshake_protocol : SupportedHandshakeProtocols()) { for (int trans_vers = 255; trans_vers > 0; trans_vers--) { @@ -414,7 +480,7 @@ TEST_F(QuicVersionsTest, SupportedVersionsHasCorrectList) { EXPECT_EQ(SupportedVersions().size(), index); } -TEST_F(QuicVersionsTest, SupportedVersionsAllDistinct) { +TEST(QuicVersionsTest, SupportedVersionsAllDistinct) { for (size_t index1 = 0; index1 < SupportedVersions().size(); ++index1) { ParsedQuicVersion version1 = SupportedVersions()[index1]; for (size_t index2 = index1 + 1; index2 < SupportedVersions().size(); @@ -424,13 +490,17 @@ TEST_F(QuicVersionsTest, SupportedVersionsAllDistinct) { EXPECT_NE(CreateQuicVersionLabel(version1), CreateQuicVersionLabel(version2)) << version1 << " " << version2; - EXPECT_NE(AlpnForVersion(version1), AlpnForVersion(version2)) - << version1 << " " << version2; + // The one pair where ALPNs are the same. + if ((version1 != ParsedQuicVersion::V2Draft01()) && + (version2 != ParsedQuicVersion::RFCv1())) { + EXPECT_NE(AlpnForVersion(version1), AlpnForVersion(version2)) + << version1 << " " << version2; + } } } } -TEST_F(QuicVersionsTest, CurrentSupportedHttp3Versions) { +TEST(QuicVersionsTest, CurrentSupportedHttp3Versions) { ParsedQuicVersionVector h3_versions = CurrentSupportedHttp3Versions(); ParsedQuicVersionVector all_current_supported_versions = CurrentSupportedVersions(); diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc index c8306a83590..3cd47ad04c4 100644 --- a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc +++ b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc @@ -209,15 +209,17 @@ bool TlsClientHandshaker::SetAlpn() { // Enable ALPS only for versions that use HTTP/3 frames. for (const std::string& alpn_string : alpns) { - ParsedQuicVersion version = ParseQuicVersionString(alpn_string); - if (!version.IsKnown() || !version.UsesHttp3()) { - continue; - } - if (SSL_add_application_settings( - ssl(), reinterpret_cast<const uint8_t*>(alpn_string.data()), - alpn_string.size(), nullptr, /* settings_len = */ 0) != 1) { - QUIC_BUG(quic_bug_10576_7) << "Failed to enable ALPS."; - return false; + for (const ParsedQuicVersion& version : session()->supported_versions()) { + if (!version.UsesHttp3() || AlpnForVersion(version) != alpn_string) { + continue; + } + if (SSL_add_application_settings( + ssl(), reinterpret_cast<const uint8_t*>(alpn_string.data()), + alpn_string.size(), nullptr, /* settings_len = */ 0) != 1) { + QUIC_BUG(quic_bug_10576_7) << "Failed to enable ALPS."; + return false; + } + break; } } @@ -240,9 +242,6 @@ bool TlsClientHandshaker::SetTransportParameters() { if (!handshaker_delegate()->FillTransportParameters(¶ms)) { return false; } - if (!user_agent_id_.empty()) { - params.user_agent_id = user_agent_id_; - } // Notify QuicConnectionDebugVisitor. session()->connection()->OnTransportParametersSent(params); @@ -395,10 +394,6 @@ size_t TlsClientHandshaker::BufferSizeLimitForLevel( return TlsHandshaker::BufferSizeLimitForLevel(level); } -bool TlsClientHandshaker::KeyUpdateSupportedLocally() const { - return true; -} - std::unique_ptr<QuicDecrypter> TlsClientHandshaker::AdvanceKeysAndCreateCurrentOneRttDecrypter() { return TlsHandshaker::AdvanceKeysAndCreateCurrentOneRttDecrypter(); diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h index 4543f9b2007..c7db0edd36d 100644 --- a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h +++ b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h @@ -61,7 +61,6 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker CryptoMessageParser* crypto_message_parser() override; HandshakeState GetHandshakeState() const override; size_t BufferSizeLimitForLevel(EncryptionLevel level) const override; - bool KeyUpdateSupportedLocally() const override; std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() override; std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override; diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc index ac959f251d4..2eee1cc7559 100644 --- a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc +++ b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc @@ -25,8 +25,7 @@ TlsHandshaker::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl( TlsHandshaker::ProofVerifierCallbackImpl::~ProofVerifierCallbackImpl() {} void TlsHandshaker::ProofVerifierCallbackImpl::Run( - bool ok, - const std::string& /*error_details*/, + bool ok, const std::string& /*error_details*/, std::unique_ptr<ProofVerifyDetails>* details) { if (parent_ == nullptr) { return; @@ -42,9 +41,7 @@ void TlsHandshaker::ProofVerifierCallbackImpl::Run( parent_->AdvanceHandshake(); } -void TlsHandshaker::ProofVerifierCallbackImpl::Cancel() { - parent_ = nullptr; -} +void TlsHandshaker::ProofVerifierCallbackImpl::Cancel() { parent_ = nullptr; } TlsHandshaker::TlsHandshaker(QuicCryptoStream* stream, QuicSession* session) : stream_(stream), handshaker_delegate_(session) {} @@ -243,10 +240,13 @@ void TlsHandshaker::SetWriteSecret(EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter = QuicEncrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); const EVP_MD* prf = Prf(cipher); - CryptoUtils::SetKeyAndIV(prf, write_secret, encrypter.get()); + CryptoUtils::SetKeyAndIV(prf, write_secret, + handshaker_delegate_->parsed_version(), + encrypter.get()); std::vector<uint8_t> header_protection_key = - CryptoUtils::GenerateHeaderProtectionKey(prf, write_secret, - encrypter->GetKeySize()); + CryptoUtils::GenerateHeaderProtectionKey( + prf, write_secret, handshaker_delegate_->parsed_version(), + encrypter->GetKeySize()); encrypter->SetHeaderProtectionKey( absl::string_view(reinterpret_cast<char*>(header_protection_key.data()), header_protection_key.size())); @@ -266,10 +266,13 @@ bool TlsHandshaker::SetReadSecret(EncryptionLevel level, std::unique_ptr<QuicDecrypter> decrypter = QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); const EVP_MD* prf = Prf(cipher); - CryptoUtils::SetKeyAndIV(prf, read_secret, decrypter.get()); + CryptoUtils::SetKeyAndIV(prf, read_secret, + handshaker_delegate_->parsed_version(), + decrypter.get()); std::vector<uint8_t> header_protection_key = - CryptoUtils::GenerateHeaderProtectionKey(prf, read_secret, - decrypter->GetKeySize()); + CryptoUtils::GenerateHeaderProtectionKey( + prf, read_secret, handshaker_delegate_->parsed_version(), + decrypter->GetKeySize()); decrypter->SetHeaderProtectionKey( absl::string_view(reinterpret_cast<char*>(header_protection_key.data()), header_protection_key.size())); @@ -296,14 +299,16 @@ TlsHandshaker::AdvanceKeysAndCreateCurrentOneRttDecrypter() { } const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl()); const EVP_MD* prf = Prf(cipher); - latest_read_secret_ = - CryptoUtils::GenerateNextKeyPhaseSecret(prf, latest_read_secret_); - latest_write_secret_ = - CryptoUtils::GenerateNextKeyPhaseSecret(prf, latest_write_secret_); + latest_read_secret_ = CryptoUtils::GenerateNextKeyPhaseSecret( + prf, handshaker_delegate_->parsed_version(), latest_read_secret_); + latest_write_secret_ = CryptoUtils::GenerateNextKeyPhaseSecret( + prf, handshaker_delegate_->parsed_version(), latest_write_secret_); std::unique_ptr<QuicDecrypter> decrypter = QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); - CryptoUtils::SetKeyAndIV(prf, latest_read_secret_, decrypter.get()); + CryptoUtils::SetKeyAndIV(prf, latest_read_secret_, + handshaker_delegate_->parsed_version(), + decrypter.get()); decrypter->SetHeaderProtectionKey(absl::string_view( reinterpret_cast<char*>(one_rtt_read_header_protection_key_.data()), one_rtt_read_header_protection_key_.size())); @@ -322,7 +327,9 @@ std::unique_ptr<QuicEncrypter> TlsHandshaker::CreateCurrentOneRttEncrypter() { const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl()); std::unique_ptr<QuicEncrypter> encrypter = QuicEncrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); - CryptoUtils::SetKeyAndIV(Prf(cipher), latest_write_secret_, encrypter.get()); + CryptoUtils::SetKeyAndIV(Prf(cipher), latest_write_secret_, + handshaker_delegate_->parsed_version(), + encrypter.get()); encrypter->SetHeaderProtectionKey(absl::string_view( reinterpret_cast<char*>(one_rtt_write_header_protection_key_.data()), one_rtt_write_header_protection_key_.size())); @@ -333,9 +340,7 @@ bool TlsHandshaker::ExportKeyingMaterialForLabel(absl::string_view label, absl::string_view context, size_t result_len, std::string* result) { - // TODO(haoyuewang) Adding support of keying material export when 0-RTT is - // accepted. - if (SSL_in_init(ssl())) { + if (result == nullptr) { return false; } result->resize(result_len); diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc index 15eed38605e..a16e72956b1 100644 --- a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc +++ b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc @@ -419,10 +419,6 @@ size_t TlsServerHandshaker::BufferSizeLimitForLevel( return TlsHandshaker::BufferSizeLimitForLevel(level); } -bool TlsServerHandshaker::KeyUpdateSupportedLocally() const { - return true; -} - std::unique_ptr<QuicDecrypter> TlsServerHandshaker::AdvanceKeysAndCreateCurrentOneRttDecrypter() { return TlsHandshaker::AdvanceKeysAndCreateCurrentOneRttDecrypter(); @@ -483,24 +479,6 @@ bool TlsServerHandshaker::ProcessTransportParameters( // Notify QuicConnectionDebugVisitor. session()->connection()->OnTransportParametersReceived(client_params); - if (GetQuicReloadableFlag(quic_ignore_key_update_not_yet_supported)) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_ignore_key_update_not_yet_supported, 2, - 2); - } else { - // Chrome clients before 86.0.4233.0 did not send the - // key_update_not_yet_supported transport parameter, but they did send a - // Google-internal transport parameter with identifier 0x4751. We treat - // reception of 0x4751 as having received key_update_not_yet_supported to - // ensure we do not use key updates with those older clients. - // TODO(dschinazi) remove this workaround once all of our QUIC+TLS Finch - // experiments have a min_version greater than 86.0.4233.0. - if (client_params.custom_parameters.find( - static_cast<TransportParameters::TransportParameterId>(0x4751)) != - client_params.custom_parameters.end()) { - client_params.key_update_not_yet_supported = true; - } - } - if (client_params.legacy_version_information.has_value() && CryptoUtils::ValidateClientHelloVersion( client_params.legacy_version_information.value().version, @@ -524,10 +502,6 @@ bool TlsServerHandshaker::ProcessTransportParameters( } ProcessAdditionalTransportParameters(client_params); - if (!session()->user_agent_id().has_value() && - client_params.user_agent_id.has_value()) { - session()->SetUserAgentId(client_params.user_agent_id.value()); - } return true; } diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h index 01cf19b1107..d2f37b0eb26 100644 --- a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h +++ b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h @@ -80,7 +80,6 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker void SetServerApplicationStateForResumption( std::unique_ptr<ApplicationState> state) override; size_t BufferSizeLimitForLevel(EncryptionLevel level) const override; - bool KeyUpdateSupportedLocally() const override; std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() override; std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override; diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc index 214866c5fab..01fb7ab2ee4 100644 --- a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc @@ -10,6 +10,7 @@ #include "absl/base/macros.h" #include "absl/strings/string_view.h" +#include "quic/core/crypto/certificate_util.h" #include "quic/core/crypto/client_proof_source.h" #include "quic/core/crypto/proof_source.h" #include "quic/core/crypto/quic_random.h" @@ -49,21 +50,6 @@ namespace { const char kServerHostname[] = "test.example.com"; const uint16_t kServerPort = 443; -QuicReferenceCountedPointer<ClientProofSource::Chain> TestClientCertChain() { - return QuicReferenceCountedPointer<ClientProofSource::Chain>( - new ClientProofSource::Chain({std::string(kTestCertificate)})); -} - -CertificatePrivateKey TestClientCertPrivateKey() { - CBS private_key_cbs; - CBS_init(&private_key_cbs, - reinterpret_cast<const uint8_t*>(kTestCertificatePrivateKey.data()), - kTestCertificatePrivateKey.size()); - - return CertificatePrivateKey( - bssl::UniquePtr<EVP_PKEY>(EVP_parse_private_key(&private_key_cbs))); -} - struct TestParams { ParsedQuicVersion version; bool disable_resumption; @@ -400,6 +386,34 @@ class TlsServerHandshakerTest : public QuicTestWithParam<TestParams> { } protected: + // Setup the client to send a (self-signed) client cert to the server, if + // requested. InitializeFakeClient() must be called after this to take effect. + bool SetupClientCert() { + auto client_proof_source = std::make_unique<DefaultClientProofSource>(); + + CertificatePrivateKey client_cert_key( + MakeKeyPairForSelfSignedCertificate()); + + CertificateOptions options; + options.subject = "CN=subject"; + options.serial_number = 0x12345678; + options.validity_start = {2020, 1, 1, 0, 0, 0}; + options.validity_end = {2049, 12, 31, 0, 0, 0}; + std::string der_cert = + CreateSelfSignedCertificate(*client_cert_key.private_key(), options); + + QuicReferenceCountedPointer<ClientProofSource::Chain> client_cert_chain( + new ClientProofSource::Chain({der_cert})); + + if (!client_proof_source->AddCertAndKey({"*"}, client_cert_chain, + std::move(client_cert_key))) { + return false; + } + + client_crypto_config_->set_proof_source(std::move(client_proof_source)); + return true; + } + // Every connection gets its own MockQuicConnectionHelper and // MockAlarmFactory, tracked separately from the server and client state so // their lifetimes persist through the whole test. @@ -901,10 +915,7 @@ TEST_P(TlsServerHandshakerTest, ZeroRttRejectOnApplicationStateChange) { } TEST_P(TlsServerHandshakerTest, RequestClientCert) { - auto client_proof_source = std::make_unique<DefaultClientProofSource>(); - ASSERT_TRUE(client_proof_source->AddCertAndKey({"*"}, TestClientCertChain(), - TestClientCertPrivateKey())); - client_crypto_config_->set_proof_source(std::move(client_proof_source)); + ASSERT_TRUE(SetupClientCert()); InitializeFakeClient(); initial_client_cert_mode_ = ClientCertMode::kRequest; @@ -924,10 +935,7 @@ TEST_P(TlsServerHandshakerTest, RequestClientCert) { } TEST_P(TlsServerHandshakerTest, RequestClientCertByDelayedSslConfig) { - auto client_proof_source = std::make_unique<DefaultClientProofSource>(); - ASSERT_TRUE(client_proof_source->AddCertAndKey({"*"}, TestClientCertChain(), - TestClientCertPrivateKey())); - client_crypto_config_->set_proof_source(std::move(client_proof_source)); + ASSERT_TRUE(SetupClientCert()); InitializeFakeClient(); QuicDelayedSSLConfig delayed_ssl_config; @@ -966,10 +974,7 @@ TEST_P(TlsServerHandshakerTest, RequestClientCert_NoCert) { } TEST_P(TlsServerHandshakerTest, RequestAndRequireClientCert) { - auto client_proof_source = std::make_unique<DefaultClientProofSource>(); - ASSERT_TRUE(client_proof_source->AddCertAndKey({"*"}, TestClientCertChain(), - TestClientCertPrivateKey())); - client_crypto_config_->set_proof_source(std::move(client_proof_source)); + ASSERT_TRUE(SetupClientCert()); InitializeFakeClient(); initial_client_cert_mode_ = ClientCertMode::kRequire; @@ -990,10 +995,7 @@ TEST_P(TlsServerHandshakerTest, RequestAndRequireClientCert) { } TEST_P(TlsServerHandshakerTest, RequestAndRequireClientCertByDelayedSslConfig) { - auto client_proof_source = std::make_unique<DefaultClientProofSource>(); - ASSERT_TRUE(client_proof_source->AddCertAndKey({"*"}, TestClientCertChain(), - TestClientCertPrivateKey())); - client_crypto_config_->set_proof_source(std::move(client_proof_source)); + ASSERT_TRUE(SetupClientCert()); InitializeFakeClient(); QuicDelayedSSLConfig delayed_ssl_config; diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc index 8f20b33c183..c25329c5fc8 100644 --- a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc +++ b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc @@ -228,7 +228,8 @@ void UberReceivedPacketManager::set_max_ack_ranges(size_t max_ack_ranges) { void UberReceivedPacketManager::set_save_timestamps(bool save_timestamps) { for (auto& received_packet_manager : received_packet_managers_) { - received_packet_manager.set_save_timestamps(save_timestamps); + received_packet_manager.set_save_timestamps( + save_timestamps, supports_multiple_packet_number_spaces_); } } diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc index 8af288fd37a..fb6a61d5b5a 100644 --- a/chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc +++ b/chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc @@ -23,17 +23,15 @@ #include "quic/platform/api/quic_socket_address.h" #include "quic/platform/api/quic_system_event_loop.h" #include "quic/tools/fake_proof_verifier.h" +#include "common/platform/api/quiche_command_line_flags.h" -DEFINE_QUIC_COMMAND_LINE_FLAG(bool, - disable_certificate_verification, - false, - "If true, don't verify the server certificate."); +DEFINE_QUICHE_COMMAND_LINE_FLAG( + bool, disable_certificate_verification, false, + "If true, don't verify the server certificate."); -DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, - masque_mode, - "", - "Allows setting MASQUE mode, valid values are " - "open and legacy. Defaults to open."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, masque_mode, "", + "Allows setting MASQUE mode, valid values are " + "open and legacy. Defaults to open."); namespace quic { @@ -48,9 +46,10 @@ int RunMasqueClient(int argc, char* argv[]) { // Note that the URI template expansion currently only supports string // replacement of {target_host} and {target_port}, not // {?target_host,target_port}. - std::vector<std::string> urls = QuicParseCommandLineFlags(usage, argc, argv); + std::vector<std::string> urls = + quiche::QuicheParseCommandLineFlags(usage, argc, argv); if (urls.empty()) { - QuicPrintCommandLineFlagHelp(usage); + quiche::QuichePrintCommandLineFlagHelp(usage); return 1; } diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc index aaccda3722e..666f67f5bf0 100644 --- a/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc +++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc @@ -15,40 +15,33 @@ #include "quic/platform/api/quic_logging.h" #include "quic/platform/api/quic_socket_address.h" #include "quic/platform/api/quic_system_event_loop.h" +#include "common/platform/api/quiche_command_line_flags.h" -DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, - port, - 9661, - "The port the MASQUE server will listen on."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, port, 9661, + "The port the MASQUE server will listen on."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - cache_dir, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, cache_dir, "", "Specifies the directory used during QuicHttpResponseCache " "construction to seed the cache. Cache directory can be " "generated using `wget -p --save-headers <url>`"); -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - server_authority, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, server_authority, "", "Specifies the authority over which the server will accept MASQUE " "requests. Defaults to empty which allows all authorities."); -DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, - masque_mode, - "", - "Allows setting MASQUE mode, valid values are " - "open and legacy. Defaults to open."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, masque_mode, "", + "Allows setting MASQUE mode, valid values are " + "open and legacy. Defaults to open."); int main(int argc, char* argv[]) { QuicSystemEventLoop event_loop("masque_server"); const char* usage = "Usage: masque_server [options]"; std::vector<std::string> non_option_args = - quic::QuicParseCommandLineFlags(usage, argc, argv); + quiche::QuicheParseCommandLineFlags(usage, argc, argv); if (!non_option_args.empty()) { - quic::QuicPrintCommandLineFlagHelp(usage); + quiche::QuichePrintCommandLineFlagHelp(usage); return 0; } diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_flags.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_flags.h index 1a9f2d99fa2..762e5907645 100644 --- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_flags.h +++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_flags.h @@ -8,8 +8,7 @@ #include <string> #include <vector> -#include "net/quic/platform/impl/quic_flags_impl.h" - +#include "quiche_platform_impl/quic_flags_impl.h" #include "common/platform/api/quiche_flags.h" #define GetQuicReloadableFlag(flag) GetQuicheReloadableFlag(quic, flag) @@ -20,31 +19,4 @@ #define GetQuicFlag(flag) GetQuicheFlag(flag) #define SetQuicFlag(flag, value) SetQuicheFlag(flag, value) -// Define a command-line flag that can be automatically set via -// QuicParseCommandLineFlags(). -#define DEFINE_QUIC_COMMAND_LINE_FLAG(type, name, default_value, help) \ - DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL(type, name, default_value, help) - -namespace quic { - -// Parses command-line flags, setting flag variables defined using -// DEFINE_QUIC_COMMAND_LINE_FLAG if they appear in the command line, and -// returning a list of any non-flag arguments specified in the command line. If -// the command line specifies '-h' or '--help', prints a usage message with flag -// descriptions to stdout and exits with status 0. If a flag has an unparsable -// value, writes an error message to stderr and exits with status 1. -inline std::vector<std::string> QuicParseCommandLineFlags( - const char* usage, - int argc, - const char* const* argv) { - return QuicParseCommandLineFlagsImpl(usage, argc, argv); -} - -// Prints a usage message with flag descriptions to stdout. -inline void QuicPrintCommandLineFlagHelp(const char* usage) { - QuicPrintCommandLineFlagHelpImpl(usage); -} - -} // namespace quic - #endif // QUICHE_QUIC_PLATFORM_API_QUIC_FLAGS_H_ diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc index fce08d290ea..87cfb2d5266 100644 --- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc +++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc @@ -9,8 +9,9 @@ #include "absl/strings/string_view.h" #include "quic/core/quic_types.h" #include "quic/qbone/qbone_constants.h" +#include "common/platform/api/quiche_command_line_flags.h" -DEFINE_QUIC_COMMAND_LINE_FLAG( +DEFINE_QUICHE_COMMAND_LINE_FLAG( bool, qbone_client_defer_control_stream_creation, true, "If true, control stream in QBONE client session is created after " "encryption established."); diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc index 7303b06091a..61a9afe4de9 100644 --- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc +++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc @@ -6,6 +6,7 @@ #include <cstdint> #include <limits> + #include "absl/strings/string_view.h" #include "quic/core/quic_session.h" #include "quic/platform/api/quic_bug_tracker.h" @@ -25,6 +26,14 @@ QboneControlStreamBase::QboneControlStreamBase(QuicSession* session) BIDIRECTIONAL), pending_message_size_(0) {} +QboneControlStreamBase::QboneControlStreamBase(quic::PendingStream* pending, + QuicSession* session) + : QuicStream(pending, session, /*is_static=*/true), + pending_message_size_(0) { + QUICHE_DCHECK_EQ(pending->id(), QboneConstants::GetControlStreamId( + session->transport_version())); +} + void QboneControlStreamBase::OnDataAvailable() { sequencer()->Read(&buffer_); while (true) { diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.h index d0c2b1a1ed4..c38697dd2c6 100644 --- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.h +++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.h @@ -16,6 +16,7 @@ class QboneSessionBase; class QUIC_EXPORT_PRIVATE QboneControlStreamBase : public QuicStream { public: explicit QboneControlStreamBase(QuicSession* session); + QboneControlStreamBase(quic::PendingStream* pending, QuicSession* session); void OnDataAvailable() override; @@ -46,6 +47,9 @@ class QUIC_EXPORT_PRIVATE QboneControlStream : public QboneControlStreamBase { QboneControlStream(QuicSession* session, Handler* handler) : QboneControlStreamBase(session), handler_(handler) {} + QboneControlStream(quic::PendingStream* pending, QuicSession* session, + Handler* handler) + : QboneControlStreamBase(pending, session), handler_(handler) {} bool SendRequest(const Outgoing& request) { return SendMessage(request); } diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc index 2ddb8e4454b..bc2d8e53a3c 100644 --- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc +++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc @@ -12,8 +12,9 @@ #include "quic/core/quic_types.h" #include "quic/core/quic_utils.h" #include "quic/qbone/qbone_constants.h" +#include "common/platform/api/quiche_command_line_flags.h" -DEFINE_QUIC_COMMAND_LINE_FLAG( +DEFINE_QUICHE_COMMAND_LINE_FLAG( bool, qbone_server_defer_control_stream_creation, true, "If true, control stream in QBONE server session is created after " "encryption established."); @@ -72,6 +73,17 @@ void QboneServerSession::CreateControlStream() { ActivateStream(std::move(control_stream)); } +QuicStream* QboneServerSession::CreateControlStreamFromPendingStream( + PendingStream* pending) { + QUICHE_DCHECK(control_stream_ == nullptr); + // Register the reserved control stream. + auto control_stream = + std::make_unique<QboneServerControlStream>(pending, this, handler_); + control_stream_ = control_stream.get(); + ActivateStream(std::move(control_stream)); + return control_stream_; +} + void QboneServerSession::Initialize() { QboneSessionBase::Initialize(); if (!GetQuicFlag(FLAGS_qbone_server_defer_control_stream_creation)) { diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.h index f5af8b43d33..d206e4d7012 100644 --- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.h +++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.h @@ -76,15 +76,20 @@ class QUIC_EXPORT_PRIVATE QboneServerSession // QboneSessionBase interface implementation. std::unique_ptr<QuicCryptoStream> CreateCryptoStream() override; - // Instantiate QboneServerControlStream. + // Instantiates QboneServerControlStream. void CreateControlStream(); + // Instantiates QboneServerControlStream from the pending stream and returns a + // pointer to it. + QuicStream* CreateControlStreamFromPendingStream(PendingStream* pending); + // The packet processor. QbonePacketProcessor processor_; - private: // Config for QUIC crypto server stream, used by the server. const QuicCryptoServerConfig* quic_crypto_server_config_; + + private: // Used by QUIC crypto server stream to track most recently compressed certs. QuicCompressedCertsCache* compressed_certs_cache_; // This helper is needed when create QuicCryptoServerStream. diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc index 2f2f31e3239..702f185e2e2 100644 --- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc +++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc @@ -18,11 +18,10 @@ #include "quic/platform/api/quic_testvalue.h" #include "quic/qbone/platform/icmp_packet.h" #include "quic/qbone/qbone_constants.h" +#include "common/platform/api/quiche_command_line_flags.h" -DEFINE_QUIC_COMMAND_LINE_FLAG( - bool, - qbone_close_ephemeral_frames, - true, +DEFINE_QUICHE_COMMAND_LINE_FLAG( + bool, qbone_close_ephemeral_frames, true, "If true, we'll call CloseStream even when we receive ephemeral frames."); namespace quic { @@ -108,7 +107,7 @@ bool QboneSessionBase::ShouldKeepConnectionAlive() const { std::unique_ptr<QuicStream> QboneSessionBase::CreateDataStream( QuicStreamId id) { - if (crypto_stream_ == nullptr || !crypto_stream_->encryption_established()) { + if (!IsEncryptionEstablished()) { // Encryption not active so no stream created return nullptr; } diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc index 5aac3e73ada..39012336662 100644 --- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc +++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc @@ -10,11 +10,10 @@ #include "quic/core/quic_types.h" #include "quic/qbone/qbone_constants.h" #include "quic/qbone/qbone_session_base.h" +#include "common/platform/api/quiche_command_line_flags.h" -DEFINE_QUIC_COMMAND_LINE_FLAG(int, - qbone_stream_ttl_secs, - 3, - "The QBONE Stream TTL in seconds."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(int, qbone_stream_ttl_secs, 3, + "The QBONE Stream TTL in seconds."); namespace quic { diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc index ec58386cfba..649406a914d 100644 --- a/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc +++ b/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc @@ -158,6 +158,14 @@ QuicAsyncStatus WebTransportFingerprintProofVerifier::VerifyCertChain( return QUIC_FAILURE; } + if (!IsKeyTypeAllowedByPolicy(*view)) { + *details = std::make_unique<Details>(Status::kDisallowedKeyAlgorithm); + *error_details = + absl::StrCat("Certificate uses a disallowed public key type (", + PublicKeyTypeToString(view->public_key_type()), ")"); + return QUIC_FAILURE; + } + *details = std::make_unique<Details>(Status::kValidCertificate); return QUIC_SUCCESS; } @@ -201,4 +209,21 @@ bool WebTransportFingerprintProofVerifier::IsWithinValidityPeriod( now.IsBefore(certificate.validity_end()); } +bool WebTransportFingerprintProofVerifier::IsKeyTypeAllowedByPolicy( + const CertificateView& certificate) { + switch (certificate.public_key_type()) { + // https://github.com/w3c/webtransport/pull/375 defines P-256 as an MTI + // algorithm, and prohibits RSA. We also allow P-384 and Ed25519. + case PublicKeyType::kP256: + case PublicKeyType::kP384: + case PublicKeyType::kEd25519: + return true; + case PublicKeyType::kRsa: + // TODO(b/213614428): this should be false by default. + return true; + default: + return false; + } +} + } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.h b/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.h index 76323d50428..9a03c665818 100644 --- a/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.h +++ b/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.h @@ -61,8 +61,9 @@ class QUIC_EXPORT_PRIVATE WebTransportFingerprintProofVerifier kExpiryTooLong = 3, kExpired = 4, kInternalError = 5, + kDisallowedKeyAlgorithm = 6, - kMaxValue = kInternalError, + kMaxValue = kDisallowedKeyAlgorithm, }; class QUIC_EXPORT_PRIVATE Details : public ProofVerifyDetails { @@ -115,6 +116,9 @@ class QUIC_EXPORT_PRIVATE WebTransportFingerprintProofVerifier std::unique_ptr<ProofVerifierCallback> callback) override; std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override; + protected: + virtual bool IsKeyTypeAllowedByPolicy(const CertificateView& certificate); + private: bool HasKnownFingerprint(absl::string_view der_certificate); bool HasValidExpiry(const CertificateView& certificate); diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc index 634c16ff009..cbf4fe2aa7e 100644 --- a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc +++ b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc @@ -393,6 +393,53 @@ void CommunicateHandshakeMessages(PacketSavingConnection* client_conn, } } +bool CommunicateHandshakeMessagesUntil(PacketSavingConnection* client_conn, + QuicCryptoStream* client, + std::function<bool()> client_condition, + PacketSavingConnection* server_conn, + QuicCryptoStream* server, + std::function<bool()> server_condition) { + size_t client_next_packet_to_deliver = + client_conn->number_of_packets_delivered_; + size_t server_next_packet_to_deliver = + server_conn->number_of_packets_delivered_; + while ( + client_conn->connected() && server_conn->connected() && + (!client_condition() || !server_condition()) && + (client_conn->encrypted_packets_.size() > client_next_packet_to_deliver || + server_conn->encrypted_packets_.size() > + server_next_packet_to_deliver)) { + if (!server_condition()) { + QUIC_LOG(INFO) << "Processing " + << client_conn->encrypted_packets_.size() - + client_next_packet_to_deliver + << " packets client->server"; + MovePackets(client_conn, &client_next_packet_to_deliver, server, + server_conn, Perspective::IS_SERVER); + } + if (!client_condition()) { + QUIC_LOG(INFO) << "Processing " + << server_conn->encrypted_packets_.size() - + server_next_packet_to_deliver + << " packets server->client"; + MovePackets(server_conn, &server_next_packet_to_deliver, client, + client_conn, Perspective::IS_CLIENT); + } + } + client_conn->number_of_packets_delivered_ = client_next_packet_to_deliver; + server_conn->number_of_packets_delivered_ = server_next_packet_to_deliver; + bool result = client_condition() && server_condition(); + if (!result) { + QUIC_LOG(INFO) << "CommunicateHandshakeMessagesUnti failed with state: " + "client connected? " + << client_conn->connected() << " server connected? " + << server_conn->connected() << " client condition met? " + << client_condition() << " server condition met? " + << server_condition(); + } + return result; +} + std::pair<size_t, size_t> AdvanceHandshake(PacketSavingConnection* client_conn, QuicCryptoStream* client, size_t client_i, diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h index 87e354a9f79..b4d772adb68 100644 --- a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h +++ b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h @@ -109,6 +109,19 @@ void CommunicateHandshakeMessages(PacketSavingConnection* client_conn, PacketSavingConnection* server_conn, QuicCryptoStream* server); +// CommunicateHandshakeMessagesUntil: +// 1) Moves messages from |client| to |server| until |server_condition| is met. +// 2) Moves messages from |server| to |client| until |client_condition| is met. +// 3) Returns true if both conditions are met. +// 4) Returns false if either connection is closed or there is no more packet to +// deliver before both conditions are met. +bool CommunicateHandshakeMessagesUntil(PacketSavingConnection* client_conn, + QuicCryptoStream* client, + std::function<bool()> client_condition, + PacketSavingConnection* server_conn, + QuicCryptoStream* server, + std::function<bool()> server_condition); + // AdvanceHandshake attempts to moves messages from |client| to |server| and // |server| to |client|. Returns the number of messages moved. std::pair<size_t, size_t> AdvanceHandshake(PacketSavingConnection* client_conn, diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h index 23d54aab638..2230fbec940 100644 --- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h +++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h @@ -33,6 +33,7 @@ class MockQpackStreamSenderDelegate : public QpackStreamSenderDelegate { ~MockQpackStreamSenderDelegate() override = default; MOCK_METHOD(void, WriteStreamData, (absl::string_view data), (override)); + MOCK_METHOD(uint64_t, NumBytesBuffered, (), (const, override)); }; class NoopQpackStreamSenderDelegate : public QpackStreamSenderDelegate { @@ -40,6 +41,8 @@ class NoopQpackStreamSenderDelegate : public QpackStreamSenderDelegate { ~NoopQpackStreamSenderDelegate() override = default; void WriteStreamData(absl::string_view /*data*/) override {} + + uint64_t NumBytesBuffered() const override { return 0; } }; } // namespace test diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_client_session_cache_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_client_session_cache_peer.h index 6f0c667eb59..227a48de075 100644 --- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_client_session_cache_peer.h +++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_client_session_cache_peer.h @@ -20,6 +20,11 @@ class QuicClientSessionCachePeer { } return iter->second->token; } + + static bool HasEntry(QuicClientSessionCache* cache, + const QuicServerId& server_id) { + return cache->cache_.Lookup(server_id) != cache->cache_.end(); + } }; } // namespace test diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc index b5119498c74..207582f738a 100644 --- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc +++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc @@ -57,6 +57,12 @@ QuicTime::Delta QuicConnectionPeer::GetNetworkTimeout( } // static +QuicTime::Delta QuicConnectionPeer::GetHandshakeTimeout( + QuicConnection* connection) { + return connection->idle_network_detector_.handshake_timeout_; +} + +// static void QuicConnectionPeer::SetPerspective(QuicConnection* connection, Perspective perspective) { connection->perspective_ = perspective; @@ -407,12 +413,6 @@ size_t QuicConnectionPeer::NumUndecryptablePackets(QuicConnection* connection) { return connection->undecryptable_packets_.size(); } -// static -size_t QuicConnectionPeer::NumPendingPathChallengesToResponse( - QuicConnection* connection) { - return connection->pending_path_challenge_payloads_.size(); -} - void QuicConnectionPeer::SetConnectionClose(QuicConnection* connection) { connection->connected_ = false; } diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h index aa30c2417ee..62ed60e2bef 100644 --- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h +++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h @@ -50,6 +50,8 @@ class QuicConnectionPeer { static QuicTime::Delta GetNetworkTimeout(QuicConnection* connection); + static QuicTime::Delta GetHandshakeTimeout(QuicConnection* connection); + static void SetPerspective(QuicConnection* connection, Perspective perspective); @@ -166,8 +168,6 @@ class QuicConnectionPeer { static size_t NumUndecryptablePackets(QuicConnection* connection); - static size_t NumPendingPathChallengesToResponse(QuicConnection* connection); - static void SetConnectionClose(QuicConnection* connection); static void SendPing(QuicConnection* connection); diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc index 7d1ba86c666..8689535ecff 100644 --- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc +++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc @@ -27,12 +27,6 @@ void QuicSentPacketManagerPeer::SetMaxTailLossProbes( } // static -bool QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe( - QuicSentPacketManager* sent_packet_manager) { - return sent_packet_manager->enable_half_rtt_tail_loss_probe_; -} - -// static bool QuicSentPacketManagerPeer::GetUseNewRto( QuicSentPacketManager* sent_packet_manager) { return sent_packet_manager->use_new_rto_; @@ -180,6 +174,12 @@ void QuicSentPacketManagerPeer::DisablePacerBursts( } // static +int QuicSentPacketManagerPeer::GetPacerInitialBurstSize( + QuicSentPacketManager* sent_packet_manager) { + return sent_packet_manager->pacing_sender_.initial_burst_size_; +} + +// static void QuicSentPacketManagerPeer::SetNextPacedPacketTime( QuicSentPacketManager* sent_packet_manager, QuicTime time) { diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h index a39915f15be..ef0af1e4654 100644 --- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h +++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h @@ -24,9 +24,6 @@ class QuicSentPacketManagerPeer { static void SetMaxTailLossProbes(QuicSentPacketManager* sent_packet_manager, size_t max_tail_loss_probes); - static bool GetEnableHalfRttTailLossProbe( - QuicSentPacketManager* sent_packet_manager); - static bool GetUseNewRto(QuicSentPacketManager* sent_packet_manager); static void SetPerspective(QuicSentPacketManager* sent_packet_manager, @@ -85,6 +82,9 @@ class QuicSentPacketManagerPeer { static void DisablePacerBursts(QuicSentPacketManager* sent_packet_manager); + static int GetPacerInitialBurstSize( + QuicSentPacketManager* sent_packet_manager); + static void SetNextPacedPacketTime(QuicSentPacketManager* sent_packet_manager, QuicTime time); diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.cc index 6db9a4a96c1..ea21081d36c 100644 --- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.cc +++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.cc @@ -28,5 +28,10 @@ bool QuicSpdyStreamPeer::use_datagram_contexts(QuicSpdyStream* stream) { return stream->use_datagram_contexts_; } +// static +bool QuicSpdyStreamPeer::OnHeadersFrameEnd(QuicSpdyStream* stream) { + return stream->OnHeadersFrameEnd(); +} + } // namespace test } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h index 8a5042689a0..692cbc38c20 100644 --- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h +++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h @@ -24,6 +24,7 @@ class QuicSpdyStreamPeer { static const QuicIntervalSet<QuicStreamOffset>& unacked_frame_headers_offsets( QuicSpdyStream* stream); static bool use_datagram_contexts(QuicSpdyStream* stream); + static bool OnHeadersFrameEnd(QuicSpdyStream* stream); }; } // namespace test diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h index b064a4abd9c..d8d09796162 100644 --- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h +++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h @@ -745,6 +745,9 @@ class PacketSavingConnection : public MockQuicConnection { MOCK_METHOD(void, OnPacketSent, (EncryptionLevel, TransmissionType)); std::vector<std::unique_ptr<QuicEncryptedPacket>> encrypted_packets_; + // Number of packets in encrypted_packets that has been delivered to the peer + // connection. + size_t number_of_packets_delivered_ = 0; MockClock clock_; }; @@ -845,7 +848,6 @@ class MockQuicCryptoStream : public QuicCryptoStream { HandshakeState GetHandshakeState() const override { return HANDSHAKE_START; } void SetServerApplicationStateForResumption( std::unique_ptr<ApplicationState> /*application_state*/) override {} - bool KeyUpdateSupportedLocally() const override { return false; } std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() override { return nullptr; @@ -1464,7 +1466,7 @@ void CreateClientSessionForTest( // start time, otherwise nonce verification will fail. // supported_versions: Set of QUIC versions this server supports. // helper: Pointer to the MockQuicConnectionHelper to use for the session. -// crypto_server_config: Pointer to the crypto server config. +// server_crypto_config: Pointer to the crypto server config. // server_connection: Pointer reference for newly created // connection. This object will be owned by the // server_session. @@ -1474,7 +1476,7 @@ void CreateServerSessionForTest( QuicServerId server_id, QuicTime::Delta connection_start_time, ParsedQuicVersionVector supported_versions, MockQuicConnectionHelper* helper, MockAlarmFactory* alarm_factory, - QuicCryptoServerConfig* crypto_server_config, + QuicCryptoServerConfig* server_crypto_config, QuicCompressedCertsCache* compressed_certs_cache, PacketSavingConnection** server_connection, TestQuicSpdyServerSession** server_session); diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client_bin.cc index 0b981255200..deeddddbd9d 100644 --- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_bin.cc +++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_bin.cc @@ -47,6 +47,7 @@ #include "quic/platform/api/quic_system_event_loop.h" #include "quic/tools/quic_epoll_client_factory.h" #include "quic/tools/quic_toy_client.h" +#include "common/platform/api/quiche_command_line_flags.h" int main(int argc, char* argv[]) { QuicSystemEventLoop event_loop("quic_client"); @@ -54,9 +55,9 @@ int main(int argc, char* argv[]) { // All non-flag arguments should be interpreted as URLs to fetch. std::vector<std::string> urls = - quic::QuicParseCommandLineFlags(usage, argc, argv); + quiche::QuicheParseCommandLineFlags(usage, argc, argv); if (urls.size() != 1) { - quic::QuicPrintCommandLineFlagHelp(usage); + quiche::QuichePrintCommandLineFlagHelp(usage); exit(0); } diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc index c90c8dd4c26..6c14cc3e308 100644 --- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc +++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc @@ -19,19 +19,16 @@ #include "quic/tools/fake_proof_verifier.h" #include "quic/tools/quic_client.h" #include "quic/tools/quic_url.h" +#include "common/platform/api/quiche_command_line_flags.h" -DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, - host, - "", - "The IP or hostname to connect to."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, host, "", + "The IP or hostname to connect to."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - quic_version, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, quic_version, "", "The QUIC version to use. Defaults to most recent IETF QUIC version."); -DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, port, 0, "The port to connect to."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, port, 0, "The port to connect to."); namespace quic { @@ -403,9 +400,9 @@ int main(int argc, char* argv[]) { const char* usage = "Usage: quic_client_interop_test [options] [url]"; std::vector<std::string> args = - quic::QuicParseCommandLineFlags(usage, argc, argv); + quiche::QuicheParseCommandLineFlags(usage, argc, argv); if (args.size() > 1) { - quic::QuicPrintCommandLineFlagHelp(usage); + quiche::QuichePrintCommandLineFlagHelp(usage); exit(1); } std::string dns_host = GetQuicFlag(FLAGS_host); @@ -426,7 +423,7 @@ int main(int argc, char* argv[]) { port = 443; } if (dns_host.empty()) { - quic::QuicPrintCommandLineFlagHelp(usage); + quiche::QuichePrintCommandLineFlagHelp(usage); exit(1); } if (url_host.empty()) { diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h index b8d28103ced..72c57843d60 100644 --- a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h +++ b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h @@ -154,9 +154,9 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend { void FetchResponseFromBackend( const spdy::Http2HeaderBlock& request_headers, const std::string& request_body, - QuicSimpleServerBackend::RequestHandler* quic_server_stream) override; + QuicSimpleServerBackend::RequestHandler* quic_stream) override; void CloseBackendResponseStream( - QuicSimpleServerBackend::RequestHandler* quic_server_stream) override; + QuicSimpleServerBackend::RequestHandler* quic_stream) override; WebTransportResponse ProcessWebTransportRequest( const spdy::Http2HeaderBlock& request_headers, WebTransportSession* session) override; diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc index ad357e9b43c..8ffae272ffe 100644 --- a/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc +++ b/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc @@ -34,12 +34,11 @@ #include "quic/core/quic_types.h" #include "quic/core/quic_utils.h" #include "quic/platform/api/quic_flags.h" +#include "common/platform/api/quiche_command_line_flags.h" #include "common/quiche_text_utils.h" -DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, - quic_version, - "", - "If set, specify the QUIC version to use."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, quic_version, "", + "If set, specify the QUIC version to use."); namespace quic { @@ -248,10 +247,10 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface { int main(int argc, char* argv[]) { const char* usage = "Usage: quic_packet_printer client|server <hex>"; std::vector<std::string> args = - quic::QuicParseCommandLineFlags(usage, argc, argv); + quiche::QuicheParseCommandLineFlags(usage, argc, argv); if (args.size() < 2) { - quic::QuicPrintCommandLineFlagHelp(usage); + quiche::QuichePrintCommandLineFlagHelp(usage); return 1; } @@ -263,7 +262,7 @@ int main(int argc, char* argv[]) { perspective = quic::Perspective::IS_SERVER; } else { std::cerr << "Invalid perspective" << std::endl; - quic::QuicPrintCommandLineFlagHelp(usage); + quiche::QuichePrintCommandLineFlagHelp(usage); return 1; } std::string hex = absl::HexStringToBytes(args[1]); diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_reject_reason_decoder_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_reject_reason_decoder_bin.cc index 68443f37d1a..ed83d278b7d 100644 --- a/chromium/net/third_party/quiche/src/quic/tools/quic_reject_reason_decoder_bin.cc +++ b/chromium/net/third_party/quiche/src/quic/tools/quic_reject_reason_decoder_bin.cc @@ -11,6 +11,7 @@ #include "quic/core/crypto/crypto_handshake.h" #include "quic/core/crypto/crypto_utils.h" #include "quic/platform/api/quic_flags.h" +#include "common/platform/api/quiche_command_line_flags.h" #include "common/quiche_text_utils.h" using quic::CryptoUtils; @@ -20,7 +21,7 @@ using quic::MAX_FAILURE_REASON; int main(int argc, char* argv[]) { const char* usage = "Usage: quic_reject_reason_decoder <packed_reason>"; std::vector<std::string> args = - quic::QuicParseCommandLineFlags(usage, argc, argv); + quiche::QuicheParseCommandLineFlags(usage, argc, argv); if (args.size() != 1) { std::cerr << usage << std::endl; diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc index c9713670a9c..5d3ed7202f4 100644 --- a/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc +++ b/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc @@ -12,14 +12,15 @@ #include "quic/platform/api/quic_system_event_loop.h" #include "quic/tools/quic_epoll_server_factory.h" #include "quic/tools/quic_toy_server.h" +#include "common/platform/api/quiche_command_line_flags.h" int main(int argc, char* argv[]) { QuicSystemEventLoop event_loop("quic_server"); const char* usage = "Usage: quic_server [options]"; std::vector<std::string> non_option_args = - quic::QuicParseCommandLineFlags(usage, argc, argv); + quiche::QuicheParseCommandLineFlags(usage, argc, argv); if (!non_option_args.empty()) { - quic::QuicPrintCommandLineFlagHelp(usage); + quiche::QuichePrintCommandLineFlagHelp(usage); exit(0); } diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc index d23ba5d53c4..9cc7bfda17c 100644 --- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc +++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc @@ -39,7 +39,6 @@ #include "quic/tools/quic_simple_server_stream.h" using testing::_; -using testing::AnyNumber; using testing::AtLeast; using testing::InSequence; using testing::Invoke; diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc index 59fe4ec229b..7b6b760a6bb 100644 --- a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc +++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc @@ -63,171 +63,129 @@ #include "quic/platform/api/quic_system_event_loop.h" #include "quic/tools/fake_proof_verifier.h" #include "quic/tools/quic_url.h" +#include "common/platform/api/quiche_command_line_flags.h" #include "common/quiche_text_utils.h" namespace { -using quic::QuicUrl; using quiche::QuicheTextUtils; } // namespace -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - host, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, host, "", "The IP or hostname to connect to. If not provided, the host " "will be derived from the provided URL."); -DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, port, 0, "The port to connect to."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, port, 0, "The port to connect to."); -DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, - ip_version_for_host_lookup, - "", - "Only used if host address lookup is needed. " - "4=ipv4; 6=ipv6; otherwise=don't care."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, ip_version_for_host_lookup, "", + "Only used if host address lookup is needed. " + "4=ipv4; 6=ipv6; otherwise=don't care."); -DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, - body, - "", - "If set, send a POST with this body."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, body, "", + "If set, send a POST with this body."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - body_hex, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, body_hex, "", "If set, contents are converted from hex to ascii, before " "sending as body of a POST. e.g. --body_hex=\"68656c6c6f\""); -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - headers, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, headers, "", "A semicolon separated list of key:value pairs to " "add to request headers."); -DEFINE_QUIC_COMMAND_LINE_FLAG(bool, - quiet, - false, - "Set to true for a quieter output experience."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, quiet, false, + "Set to true for a quieter output experience."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - quic_version, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, quic_version, "", "QUIC version to speak, e.g. 21. If not set, then all available " "versions are offered in the handshake. Also supports wire versions " "such as Q043 or T099."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - connection_options, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, connection_options, "", "Connection options as ASCII tags separated by commas, " "e.g. \"ABCD,EFGH\""); -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - client_connection_options, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, client_connection_options, "", "Client connection options as ASCII tags separated by commas, " "e.g. \"ABCD,EFGH\""); -DEFINE_QUIC_COMMAND_LINE_FLAG(bool, - quic_ietf_draft, - false, - "Use the IETF draft version. This also enables " - "required internal QUIC flags."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, quic_ietf_draft, false, + "Use the IETF draft version. This also enables " + "required internal QUIC flags."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - bool, - version_mismatch_ok, - false, +DEFINE_QUICHE_COMMAND_LINE_FLAG( + bool, version_mismatch_ok, false, "If true, a version mismatch in the handshake is not considered a " "failure. Useful for probing a server to determine if it speaks " "any version of QUIC."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - bool, - force_version_negotiation, - false, +DEFINE_QUICHE_COMMAND_LINE_FLAG( + bool, force_version_negotiation, false, "If true, start by proposing a version that is reserved for version " "negotiation."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - bool, - multi_packet_chlo, - false, +DEFINE_QUICHE_COMMAND_LINE_FLAG( + bool, multi_packet_chlo, false, "If true, add a transport parameter to make the ClientHello span two " "packets. Only works with QUIC+TLS."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - bool, - redirect_is_success, - true, +DEFINE_QUICHE_COMMAND_LINE_FLAG( + bool, redirect_is_success, true, "If true, an HTTP response code of 3xx is considered to be a " "successful response, otherwise a failure."); -DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, - initial_mtu, - 0, - "Initial MTU of the connection."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, initial_mtu, 0, + "Initial MTU of the connection."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - int32_t, - num_requests, - 1, +DEFINE_QUICHE_COMMAND_LINE_FLAG( + int32_t, num_requests, 1, "How many sequential requests to make on a single connection."); -DEFINE_QUIC_COMMAND_LINE_FLAG(bool, - disable_certificate_verification, - false, - "If true, don't verify the server certificate."); +DEFINE_QUICHE_COMMAND_LINE_FLAG( + bool, disable_certificate_verification, false, + "If true, don't verify the server certificate."); -DEFINE_QUIC_COMMAND_LINE_FLAG( +DEFINE_QUICHE_COMMAND_LINE_FLAG( std::string, default_client_cert, "", "The path to the file containing PEM-encoded client default certificate to " "be sent to the server, if server requested client certs."); -DEFINE_QUIC_COMMAND_LINE_FLAG( +DEFINE_QUICHE_COMMAND_LINE_FLAG( std::string, default_client_cert_key, "", "The path to the file containing PEM-encoded private key of the client's " "default certificate for signing, if server requested client certs."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - bool, - drop_response_body, - false, +DEFINE_QUICHE_COMMAND_LINE_FLAG( + bool, drop_response_body, false, "If true, drop response body immediately after it is received."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - bool, - disable_port_changes, - false, +DEFINE_QUICHE_COMMAND_LINE_FLAG( + bool, disable_port_changes, false, "If true, do not change local port after each request."); -DEFINE_QUIC_COMMAND_LINE_FLAG(bool, - one_connection_per_request, - false, - "If true, close the connection after each " - "request. This allows testing 0-RTT."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, one_connection_per_request, false, + "If true, close the connection after each " + "request. This allows testing 0-RTT."); -DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, - server_connection_id_length, - -1, - "Length of the server connection ID used."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, server_connection_id_length, -1, + "Length of the server connection ID used."); -DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, - client_connection_id_length, - -1, - "Length of the client connection ID used."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, client_connection_id_length, -1, + "Length of the client connection ID used."); -DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, max_time_before_crypto_handshake_ms, - 10000, - "Max time to wait before handshake completes."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, max_time_before_crypto_handshake_ms, + 10000, + "Max time to wait before handshake completes."); -DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, max_inbound_header_list_size, 128 * 1024, - "Max inbound header list size. 0 means default."); +DEFINE_QUICHE_COMMAND_LINE_FLAG( + int32_t, max_inbound_header_list_size, 128 * 1024, + "Max inbound header list size. 0 means default."); namespace quic { namespace { diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc index e7b4e1ecd7a..cdbe9b3bce9 100644 --- a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc +++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc @@ -12,44 +12,33 @@ #include "quic/platform/api/quic_flags.h" #include "quic/platform/api/quic_socket_address.h" #include "quic/tools/quic_memory_cache_backend.h" +#include "common/platform/api/quiche_command_line_flags.h" -DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, - port, - 6121, - "The port the quic server will listen on."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, port, 6121, + "The port the quic server will listen on."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - quic_response_cache_dir, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, quic_response_cache_dir, "", "Specifies the directory used during QuicHttpResponseCache " "construction to seed the cache. Cache directory can be " "generated using `wget -p --save-headers <url>`"); -DEFINE_QUIC_COMMAND_LINE_FLAG( - bool, - generate_dynamic_responses, - false, +DEFINE_QUICHE_COMMAND_LINE_FLAG( + bool, generate_dynamic_responses, false, "If true, then URLs which have a numeric path will send a dynamically " "generated response of that many bytes."); -DEFINE_QUIC_COMMAND_LINE_FLAG(bool, - quic_ietf_draft, - false, - "Only enable IETF draft versions. This also " - "enables required internal QUIC flags."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, quic_ietf_draft, false, + "Only enable IETF draft versions. This also " + "enables required internal QUIC flags."); -DEFINE_QUIC_COMMAND_LINE_FLAG( - std::string, - quic_versions, - "", +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, quic_versions, "", "QUIC versions to enable, e.g. \"h3-25,h3-27\". If not set, then all " "available versions are enabled."); -DEFINE_QUIC_COMMAND_LINE_FLAG(bool, - enable_webtransport, - false, - "If true, WebTransport support is enabled."); +DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, enable_webtransport, false, + "If true, WebTransport support is enabled."); namespace quic { |