diff options
Diffstat (limited to 'chromium/net/third_party/quiche/src/quiche/quic')
257 files changed, 5015 insertions, 9002 deletions
diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.cc index 71b8f128421..617890762f4 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.cc @@ -16,6 +16,7 @@ #include "quiche/quic/platform/api/quic_flag_utils.h" #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_logging.h" +#include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/print_elements.h" namespace quic { @@ -221,7 +222,7 @@ Limits<QuicByteCount> Bbr2Sender::GetCwndLimitsByMode() const { case Bbr2Mode::PROBE_RTT: return probe_rtt_.GetCwndLimits(); default: - QUIC_NOTREACHED(); + QUICHE_NOTREACHED(); return Unlimited<QuicByteCount>(); } } @@ -504,11 +505,6 @@ void Bbr2Sender::OnExitQuiescence(QuicTime now) { } } -bool Bbr2Sender::ShouldSendProbingPacket() const { - // TODO(wub): Implement ShouldSendProbingPacket properly. - return BBR2_MODE_DISPATCH(IsProbingForBandwidth()); -} - std::string Bbr2Sender::GetDebugState() const { std::ostringstream stream; stream << ExportDebugState(); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.h b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.h index b9c0a410a76..7f47a4ed3c9 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.h @@ -42,8 +42,6 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface { return false; } - bool ShouldSendProbingPacket() const override; - void SetFromConfig(const QuicConfig& config, Perspective perspective) override; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_simulator_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_simulator_test.cc index 6a0e5815838..fdf036b981c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_simulator_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_simulator_test.cc @@ -127,7 +127,8 @@ class Bbr2SimulatorTest : public QuicTest { } void SetUp() override { - if (GetQuicFlag(FLAGS_quic_bbr2_test_regression_mode) == "regress") { + if (quiche::GetQuicheCommandLineFlag( + FLAGS_quic_bbr2_test_regression_mode) == "regress") { SendAlgorithmTestResult expected; ASSERT_TRUE(LoadSendAlgorithmTestResult(&expected)); random_seed_ = expected.random_seed(); @@ -140,7 +141,7 @@ class Bbr2SimulatorTest : public QuicTest { ~Bbr2SimulatorTest() override { const std::string regression_mode = - GetQuicFlag(FLAGS_quic_bbr2_test_regression_mode); + quiche::GetQuicheCommandLineFlag(FLAGS_quic_bbr2_test_regression_mode); const QuicTime::Delta simulated_duration = SimulatedNow() - QuicTime::Zero(); if (regression_mode == "record") { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender.cc index aa121d4d626..878b5985804 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender.cc @@ -204,16 +204,6 @@ bool BbrSender::InRecovery() const { return recovery_state_ != NOT_IN_RECOVERY; } -bool BbrSender::ShouldSendProbingPacket() const { - if (pacing_gain_ <= 1) { - return false; - } - - // TODO(b/77975811): If the pipe is highly under-utilized, consider not - // sending a probing transmission, because the extra bandwidth is not needed. - return true; -} - void BbrSender::SetFromConfig(const QuicConfig& config, Perspective perspective) { if (config.HasClientRequestedIndependentOption(k1RTT, perspective)) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender.h b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender.h index 9fe11999595..5f711fd493c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender.h @@ -100,7 +100,6 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface { // Start implementation of SendAlgorithmInterface. bool InSlowStart() const override; bool InRecovery() const override; - bool ShouldSendProbingPacket() const override; void SetFromConfig(const QuicConfig& config, Perspective perspective) override; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender_test.cc index 199d322d30c..bbdbee6fc6f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender_test.cc @@ -108,7 +108,8 @@ class BbrSenderTest : public QuicTest { } void SetUp() override { - if (GetQuicFlag(FLAGS_quic_bbr_test_regression_mode) == "regress") { + if (quiche::GetQuicheCommandLineFlag(FLAGS_quic_bbr_test_regression_mode) == + "regress") { SendAlgorithmTestResult expected; ASSERT_TRUE(LoadSendAlgorithmTestResult(&expected)); random_seed_ = expected.random_seed(); @@ -121,7 +122,7 @@ class BbrSenderTest : public QuicTest { ~BbrSenderTest() { const std::string regression_mode = - GetQuicFlag(FLAGS_quic_bbr_test_regression_mode); + quiche::GetQuicheCommandLineFlag(FLAGS_quic_bbr_test_regression_mode); const QuicTime::Delta simulated_duration = clock_->Now() - QuicTime::Zero(); if (regression_mode == "record") { RecordSendAlgorithmTestResult(random_seed_, diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats.cc index 74b5c851426..d679cd63631 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats.cc @@ -39,14 +39,14 @@ void RttStats::ExpireSmoothedMetrics() { } // Updates the RTT based on a new sample. -void RttStats::UpdateRtt(QuicTime::Delta send_delta, QuicTime::Delta ack_delay, +bool RttStats::UpdateRtt(QuicTime::Delta send_delta, QuicTime::Delta ack_delay, QuicTime now) { if (send_delta.IsInfinite() || send_delta <= QuicTime::Delta::Zero()) { QUIC_LOG_FIRST_N(WARNING, 3) << "Ignoring measured send_delta, because it's is " << "either infinite, zero, or negative. send_delta = " << send_delta.ToMicroseconds(); - return; + return false; } last_update_time_ = now; @@ -92,6 +92,7 @@ void RttStats::UpdateRtt(QuicTime::Delta send_delta, QuicTime::Delta ack_delay, QUIC_DVLOG(1) << " smoothed_rtt(us):" << smoothed_rtt_.ToMicroseconds() << " mean_deviation(us):" << mean_deviation_.ToMicroseconds(); } + return true; } void RttStats::OnConnectionMigration() { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats.h b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats.h index c9dcab05c72..04a0148433a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats.h @@ -47,7 +47,8 @@ class QUIC_EXPORT_PRIVATE RttStats { // Updates the RTT from an incoming ack which is received |send_delta| after // the packet is sent and the peer reports the ack being delayed |ack_delay|. - void UpdateRtt(QuicTime::Delta send_delta, QuicTime::Delta ack_delay, + // Returns true if RTT was updated, and false if the sample was ignored. + bool UpdateRtt(QuicTime::Delta send_delta, QuicTime::Delta ack_delay, QuicTime now); // Causes the smoothed_rtt to be increased to the latest_rtt if the latest_rtt diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats_test.cc index d1a70808afe..11bf11a3cf8 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats_test.cc @@ -6,13 +6,9 @@ #include <cmath> -#include "quiche/quic/platform/api/quic_logging.h" -#include "quiche/quic/platform/api/quic_mock_log.h" #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/test_tools/quic_test_utils.h" -#include "quiche/quic/test_tools/rtt_stats_peer.h" -using testing::_; using testing::Message; namespace quic { @@ -141,9 +137,6 @@ TEST_F(RttStatsTest, ExpireSmoothedMetrics) { } TEST_F(RttStatsTest, UpdateRttWithBadSendDeltas) { - // Make sure we ignore bad RTTs. - CREATE_QUIC_MOCK_LOG(log); - QuicTime::Delta initial_rtt = QuicTime::Delta::FromMilliseconds(10); rtt_stats_.UpdateRtt(initial_rtt, QuicTime::Delta::Zero(), QuicTime::Zero()); EXPECT_EQ(initial_rtt, rtt_stats_.min_rtt()); @@ -153,16 +146,12 @@ TEST_F(RttStatsTest, UpdateRttWithBadSendDeltas) { bad_send_deltas.push_back(QuicTime::Delta::Zero()); bad_send_deltas.push_back(QuicTime::Delta::Infinite()); bad_send_deltas.push_back(QuicTime::Delta::FromMicroseconds(-1000)); - log.StartCapturingLogs(); for (QuicTime::Delta bad_send_delta : bad_send_deltas) { SCOPED_TRACE(Message() << "bad_send_delta = " << bad_send_delta.ToMicroseconds()); - if (QUIC_LOG_WARNING_IS_ON()) { - EXPECT_QUIC_LOG_CALL_CONTAINS(log, WARNING, "Ignoring"); - } - rtt_stats_.UpdateRtt(bad_send_delta, QuicTime::Delta::Zero(), - QuicTime::Zero()); + EXPECT_FALSE(rtt_stats_.UpdateRtt(bad_send_delta, QuicTime::Delta::Zero(), + QuicTime::Zero())); EXPECT_EQ(initial_rtt, rtt_stats_.min_rtt()); EXPECT_EQ(initial_rtt, rtt_stats_.smoothed_rtt()); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/send_algorithm_interface.h b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/send_algorithm_interface.h index 75c69a29ee3..db14a1e3637 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/send_algorithm_interface.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/send_algorithm_interface.h @@ -39,13 +39,11 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface { : 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 && is_rtt_trusted == other.is_rtt_trusted; } @@ -53,7 +51,6 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface { QuicBandwidth bandwidth = QuicBandwidth::Zero(); QuicTime::Delta rtt = QuicTime::Delta::Zero(); int max_initial_congestion_window = 0; - int burst_token = 0; bool allow_cwnd_to_decrease = false; bool is_rtt_trusted = false; }; @@ -132,12 +129,6 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface { // Whether the send algorithm is currently in recovery. virtual bool InRecovery() const = 0; - // True when the congestion control is probing for more bandwidth and needs - // enough data to not be app-limited to do so. - // TODO(ianswett): In the future, this API may want to indicate the size of - // the probing packet. - virtual bool ShouldSendProbingPacket() const = 0; - // Returns the size of the slow start congestion window in bytes, // aka ssthresh. Only defined for Cubic and Reno, other algorithms return 0. virtual QuicByteCount GetSlowStartThreshold() const = 0; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.cc index 966a000b97c..af0a5a9ffc2 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.cc @@ -233,8 +233,6 @@ bool TcpCubicSenderBytes::InRecovery() const { largest_acked_packet_number_ <= largest_sent_at_last_cutback_; } -bool TcpCubicSenderBytes::ShouldSendProbingPacket() const { return false; } - void TcpCubicSenderBytes::OnRetransmissionTimeout(bool packets_retransmitted) { largest_sent_at_last_cutback_.Clear(); if (!packets_retransmitted) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h index a30f78dc78e..2531e5a3f6f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h @@ -69,7 +69,6 @@ class QUIC_EXPORT_PRIVATE TcpCubicSenderBytes : public SendAlgorithmInterface { CongestionControlType GetCongestionControlType() const override; bool InSlowStart() const override; bool InRecovery() const override; - bool ShouldSendProbingPacket() const override; std::string GetDebugState() const override; void OnApplicationLimited(QuicByteCount bytes_in_flight) override; void PopulateConnectionStats(QuicConnectionStats* /*stats*/) const override {} diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.cc index 1c4d3a2ca37..c3b187ce766 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.cc @@ -79,8 +79,12 @@ PublicKeyType PublicKeyTypeFromKey(EVP_PKEY* public_key) { } } +} // namespace + PublicKeyType PublicKeyTypeFromSignatureAlgorithm( uint16_t signature_algorithm) { + // This should be kept in sync with the list in + // SupportedSignatureAlgorithmsForQuic(). switch (signature_algorithm) { case SSL_SIGN_RSA_PSS_RSAE_SHA256: return PublicKeyType::kRsa; @@ -95,6 +99,17 @@ PublicKeyType PublicKeyTypeFromSignatureAlgorithm( } } +QUIC_EXPORT_PRIVATE QuicSignatureAlgorithmVector +SupportedSignatureAlgorithmsForQuic() { + // This should be kept in sync with the list in + // PublicKeyTypeFromSignatureAlgorithm(). + return QuicSignatureAlgorithmVector{ + SSL_SIGN_ED25519, SSL_SIGN_ECDSA_SECP256R1_SHA256, + SSL_SIGN_ECDSA_SECP384R1_SHA384, SSL_SIGN_RSA_PSS_RSAE_SHA256}; +} + +namespace { + std::string AttributeNameToString(const CBS& oid_cbs) { absl::string_view oid = CbsToStringPiece(oid_cbs); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.h b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.h index a0ca3c33ecf..5c2aafc1af3 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.h @@ -43,6 +43,13 @@ enum class PublicKeyType { kUnknown, }; QUIC_EXPORT_PRIVATE std::string PublicKeyTypeToString(PublicKeyType type); +QUIC_EXPORT_PRIVATE PublicKeyType +PublicKeyTypeFromSignatureAlgorithm(uint16_t signature_algorithm); + +// Returns the list of the signature algorithms that can be processed by +// CertificateView::VerifySignature() and CertificatePrivateKey::Sign(). +QUIC_EXPORT_PRIVATE QuicSignatureAlgorithmVector +SupportedSignatureAlgorithmsForQuic(); // 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 diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view_test.cc index b9ca08abc09..d142ae45215 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view_test.cc @@ -4,9 +4,11 @@ #include "quiche/quic/core/crypto/certificate_view.h" +#include <limits> #include <memory> #include <sstream> +#include "absl/algorithm/container.h" #include "absl/strings/escaping.h" #include "absl/strings/string_view.h" #include "openssl/base.h" @@ -209,6 +211,20 @@ TEST(CertificateViewTest, NameAttribute) { X509NameAttributeToString(StringPieceToCbs(invalid_oid))); } +TEST(CertificateViewTest, SupportedSignatureAlgorithmsForQuicIsUpToDate) { + QuicSignatureAlgorithmVector supported = + SupportedSignatureAlgorithmsForQuic(); + for (int i = 0; i < std::numeric_limits<uint16_t>::max(); i++) { + uint16_t sigalg = static_cast<uint16_t>(i); + PublicKeyType key_type = PublicKeyTypeFromSignatureAlgorithm(sigalg); + if (absl::c_find(supported, sigalg) == supported.end()) { + EXPECT_EQ(key_type, PublicKeyType::kUnknown); + } else { + EXPECT_NE(key_type, PublicKeyType::kUnknown); + } + } +} + } // namespace } // namespace test } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h index 7dbbb6d36b0..352242f3381 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h @@ -300,6 +300,8 @@ const QuicTag kNPCO = TAG('N', 'P', 'C', 'O'); // No pacing offload. // Enable bandwidth resumption experiment. const QuicTag kBWRE = TAG('B', 'W', 'R', 'E'); // Bandwidth resumption. const QuicTag kBWMX = TAG('B', 'W', 'M', 'X'); // Max bandwidth resumption. +const QuicTag kBWID = TAG('B', 'W', 'I', 'D'); // Send bandwidth when idle. +const QuicTag kBWR1 = TAG('B', 'W', 'I', '1'); // Resume bandwidth experiment 1 const QuicTag kBWRS = TAG('B', 'W', 'R', 'S'); // Server bandwidth resumption. const QuicTag kBWS2 = TAG('B', 'W', 'S', '2'); // Server bw resumption v2. const QuicTag kBWS3 = TAG('B', 'W', 'S', '3'); // QUIC Initial CWND - Control. @@ -425,7 +427,17 @@ const QuicTag kIGNP = TAG('I', 'G', 'N', 'P'); // Do not use PING only packet const QuicTag kSRWP = TAG('S', 'R', 'W', 'P'); // Enable retransmittable on // wire PING (ROWP) on the // server side. -const QuicTag kGSR0 = TAG('G', 'S', 'R', '0'); // Selective Resumption +const QuicTag kROWF = TAG('R', 'O', 'W', 'F'); // Send first 1-RTT packet on + // ROWP timeout. +const QuicTag kROWR = TAG('R', 'O', 'W', 'R'); // Send random bytes on ROWP + // timeout. +// Selective Resumption variants. +const QuicTag kGSR0 = TAG('G', 'S', 'R', '0'); +const QuicTag kGSR1 = TAG('G', 'S', 'R', '1'); +const QuicTag kGSR2 = TAG('G', 'S', 'R', '2'); +const QuicTag kGSR3 = TAG('G', 'S', 'R', '3'); + +const QuicTag kNRES = TAG('N', 'R', 'E', 'S'); // No resumption const QuicTag kINVC = TAG('I', 'N', 'V', 'C'); // Send connection close for // INVALID_VERSION diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.cc index 334c4d8d054..9b33b0b1098 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.cc @@ -55,7 +55,7 @@ namespace { // Secret, Label, and Length are passed in as |secret|, |label|, and // |out_len|, respectively. The resulting expanded secret is returned. std::vector<uint8_t> HkdfExpandLabel(const EVP_MD* prf, - const std::vector<uint8_t>& secret, + absl::Span<const uint8_t> secret, const std::string& label, size_t out_len) { bssl::ScopedCBB quic_hkdf_label; CBB inner_label; @@ -115,7 +115,7 @@ void CryptoUtils::InitializeCrypterSecrets( } void CryptoUtils::SetKeyAndIV(const EVP_MD* prf, - const std::vector<uint8_t>& pp_secret, + absl::Span<const uint8_t> pp_secret, const ParsedQuicVersion& version, QuicCrypter* crypter) { std::vector<uint8_t> key = @@ -130,7 +130,7 @@ void CryptoUtils::SetKeyAndIV(const EVP_MD* prf, } std::vector<uint8_t> CryptoUtils::GenerateHeaderProtectionKey( - const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const EVP_MD* prf, absl::Span<const uint8_t> pp_secret, const ParsedQuicVersion& version, size_t out_len) { return HkdfExpandLabel(prf, pp_secret, getLabelForVersion(version, "hp"), out_len); @@ -787,4 +787,24 @@ bool CryptoUtils::GetSSLCapabilities(const SSL* ssl, return true; } +// static +absl::optional<std::string> CryptoUtils::GenerateProofPayloadToBeSigned( + absl::string_view chlo_hash, absl::string_view server_config) { + size_t payload_size = sizeof(kProofSignatureLabel) + sizeof(uint32_t) + + chlo_hash.size() + server_config.size(); + std::string payload; + payload.resize(payload_size); + QuicDataWriter payload_writer(payload_size, payload.data(), + quiche::Endianness::HOST_BYTE_ORDER); + bool success = payload_writer.WriteBytes(kProofSignatureLabel, + sizeof(kProofSignatureLabel)) && + payload_writer.WriteUInt32(chlo_hash.size()) && + payload_writer.WriteStringPiece(chlo_hash) && + payload_writer.WriteStringPiece(server_config); + if (!success) { + return absl::nullopt; + } + return payload; +} + } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.h b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.h index 4b803f8ece9..87bf30915b8 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.h @@ -91,13 +91,13 @@ class QUIC_EXPORT_PRIVATE CryptoUtils { // protection key. GenerateHeaderProtectionKey/SetHeaderProtectionKey must be // called before using |crypter|. static void SetKeyAndIV(const EVP_MD* prf, - const std::vector<uint8_t>& pp_secret, + absl::Span<const 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, + const EVP_MD* prf, absl::Span<const 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. @@ -248,6 +248,11 @@ class QUIC_EXPORT_PRIVATE CryptoUtils { static bool GetSSLCapabilities(const SSL* ssl, bssl::UniquePtr<uint8_t>* capabilities, size_t* capabilities_len); + + // Computes the contents of a binary message that is signed inside QUIC Crypto + // protocol using the certificate key. + static absl::optional<std::string> GenerateProofPayloadToBeSigned( + absl::string_view chlo_hash, absl::string_view server_config); }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.h b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.h index ffa5fec21bf..ab2a4872525 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.h @@ -173,7 +173,7 @@ class QUIC_EXPORT_PRIVATE ProofSource { // // If returns a non-empty list, ComputeTlsSignature will only be called with a // algorithm in the list. - virtual absl::InlinedVector<uint16_t, 8> SupportedTlsSignatureAlgorithms() + virtual QuicSignatureAlgorithmVector SupportedTlsSignatureAlgorithms() const = 0; class QUIC_EXPORT_PRIVATE DecryptCallback { @@ -219,7 +219,7 @@ class QUIC_EXPORT_PRIVATE ProofSource { // |in|. If decryption fails, the callback is invoked with an empty // vector. virtual void Decrypt(absl::string_view in, - std::unique_ptr<DecryptCallback> callback) = 0; + std::shared_ptr<DecryptCallback> callback) = 0; }; // Returns the TicketCrypter used for encrypting and decrypting TLS diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source_x509.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source_x509.cc index 5f26855d7c4..a86c78bf81f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source_x509.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source_x509.cc @@ -8,23 +8,34 @@ #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" +#include "absl/types/optional.h" #include "openssl/ssl.h" #include "quiche/quic/core/crypto/certificate_view.h" #include "quiche/quic/core/crypto/crypto_protocol.h" +#include "quiche/quic/core/crypto/crypto_utils.h" #include "quiche/quic/core/quic_data_writer.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/common/quiche_endian.h" namespace quic { +ProofSourceX509::ProofSourceX509( + quiche::QuicheReferenceCountedPointer<Chain> default_chain, + CertificatePrivateKey default_key) { + if (!AddCertificateChain(default_chain, std::move(default_key))) { + return; + } + default_certificate_ = &certificates_.front(); +} + std::unique_ptr<ProofSourceX509> ProofSourceX509::Create( quiche::QuicheReferenceCountedPointer<Chain> default_chain, CertificatePrivateKey default_key) { - std::unique_ptr<ProofSourceX509> result(new ProofSourceX509()); - if (!result->AddCertificateChain(default_chain, std::move(default_key))) { + std::unique_ptr<ProofSourceX509> result( + new ProofSourceX509(default_chain, std::move(default_key))); + if (!result->valid()) { return nullptr; } - result->default_certificate_ = &result->certificates_.front(); return result; } @@ -36,25 +47,24 @@ void ProofSourceX509::GetProof( std::unique_ptr<ProofSource::Callback> callback) { QuicCryptoProof proof; - size_t payload_size = sizeof(kProofSignatureLabel) + sizeof(uint32_t) + - chlo_hash.size() + server_config.size(); - auto payload = std::make_unique<char[]>(payload_size); - QuicDataWriter payload_writer(payload_size, payload.get(), - quiche::Endianness::HOST_BYTE_ORDER); - bool success = payload_writer.WriteBytes(kProofSignatureLabel, - sizeof(kProofSignatureLabel)) && - payload_writer.WriteUInt32(chlo_hash.size()) && - payload_writer.WriteStringPiece(chlo_hash) && - payload_writer.WriteStringPiece(server_config); - if (!success) { + if (!valid()) { + QUIC_BUG(ProofSourceX509::GetProof called in invalid state) + << "ProofSourceX509::GetProof called while the object is not valid"; + callback->Run(/*ok=*/false, nullptr, proof, nullptr); + return; + } + + absl::optional<std::string> payload = + CryptoUtils::GenerateProofPayloadToBeSigned(chlo_hash, server_config); + if (!payload.has_value()) { callback->Run(/*ok=*/false, nullptr, proof, nullptr); return; } Certificate* certificate = GetCertificate(hostname, &proof.cert_matched_sni); proof.signature = - certificate->key.Sign(absl::string_view(payload.get(), payload_size), - SSL_SIGN_RSA_PSS_RSAE_SHA256); + certificate->key.Sign(*payload, SSL_SIGN_RSA_PSS_RSAE_SHA256); + MaybeAddSctsForHostname(hostname, proof.leaf_cert_scts); callback->Run(/*ok=*/!proof.signature.empty(), certificate->chain, proof, nullptr); } @@ -64,6 +74,13 @@ ProofSourceX509::GetCertChain(const QuicSocketAddress& /*server_address*/, const QuicSocketAddress& /*client_address*/, const std::string& hostname, bool* cert_matched_sni) { + if (!valid()) { + QUIC_BUG(ProofSourceX509::GetCertChain called in invalid state) + << "ProofSourceX509::GetCertChain called while the object is not " + "valid"; + return nullptr; + } + return GetCertificate(hostname, cert_matched_sni)->chain; } @@ -72,17 +89,23 @@ void ProofSourceX509::ComputeTlsSignature( const QuicSocketAddress& /*client_address*/, const std::string& hostname, uint16_t signature_algorithm, absl::string_view in, std::unique_ptr<ProofSource::SignatureCallback> callback) { + if (!valid()) { + QUIC_BUG(ProofSourceX509::ComputeTlsSignature called in invalid state) + << "ProofSourceX509::ComputeTlsSignature called while the object is " + "not valid"; + callback->Run(/*ok=*/false, "", nullptr); + return; + } + bool cert_matched_sni; std::string signature = GetCertificate(hostname, &cert_matched_sni) ->key.Sign(in, signature_algorithm); callback->Run(/*ok=*/!signature.empty(), signature, nullptr); } -absl::InlinedVector<uint16_t, 8> -ProofSourceX509::SupportedTlsSignatureAlgorithms() const { - // Let ComputeTlsSignature() report an error if a bad signature algorithm is - // requested. - return {}; +QuicSignatureAlgorithmVector ProofSourceX509::SupportedTlsSignatureAlgorithms() + const { + return SupportedSignatureAlgorithmsForQuic(); } ProofSource::TicketCrypter* ProofSourceX509::GetTicketCrypter() { @@ -124,6 +147,7 @@ bool ProofSourceX509::AddCertificateChain( ProofSourceX509::Certificate* ProofSourceX509::GetCertificate( const std::string& hostname, bool* cert_matched_sni) const { + QUICHE_DCHECK(valid()); auto it = certificate_map_.find(hostname); if (it != certificate_map_.end()) { *cert_matched_sni = true; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source_x509.h b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source_x509.h index d5a3c6f1e4c..fa62bbf90d3 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source_x509.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source_x509.h @@ -13,7 +13,7 @@ #include "absl/strings/string_view.h" #include "quiche/quic/core/crypto/certificate_view.h" #include "quiche/quic/core/crypto/proof_source.h" -#include "quiche/quic/platform/api/quic_containers.h" +#include "quiche/quic/core/crypto/quic_crypto_proof.h" namespace quic { @@ -43,8 +43,7 @@ class QUIC_EXPORT_PRIVATE ProofSourceX509 : public ProofSource { const QuicSocketAddress& client_address, const std::string& hostname, uint16_t signature_algorithm, absl::string_view in, std::unique_ptr<SignatureCallback> callback) override; - absl::InlinedVector<uint16_t, 8> SupportedTlsSignatureAlgorithms() - const override; + QuicSignatureAlgorithmVector SupportedTlsSignatureAlgorithms() const override; TicketCrypter* GetTicketCrypter() override; // Adds a certificate chain to the verifier. Returns false if the chain is @@ -54,9 +53,17 @@ class QUIC_EXPORT_PRIVATE ProofSourceX509 : public ProofSource { quiche::QuicheReferenceCountedPointer<Chain> chain, CertificatePrivateKey key); - private: - ProofSourceX509() = default; + protected: + ProofSourceX509(quiche::QuicheReferenceCountedPointer<Chain> default_chain, + CertificatePrivateKey default_key); + bool valid() const { return default_certificate_ != nullptr; } + + // Gives an opportunity for the subclass proof source to provide SCTs for a + // given hostname. + virtual void MaybeAddSctsForHostname(absl::string_view /*hostname*/, + std::string& /*leaf_cert_scts*/) {} + private: struct QUIC_EXPORT_PRIVATE Certificate { quiche::QuicheReferenceCountedPointer<Chain> chain; CertificatePrivateKey key; @@ -68,7 +75,7 @@ class QUIC_EXPORT_PRIVATE ProofSourceX509 : public ProofSource { bool* cert_matched_sni) const; std::forward_list<Certificate> certificates_; - Certificate* default_certificate_; + Certificate* default_certificate_ = nullptr; absl::node_hash_map<std::string, Certificate*> certificate_map_; }; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.cc index 11ccc2f23bf..7a651bf81f9 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.cc @@ -706,7 +706,7 @@ void QuicCryptoServerConfig::ProcessClientHello( params, quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config, QuicByteCount total_framing_overhead, QuicByteCount chlo_packet_size, - std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const { + std::shared_ptr<ProcessClientHelloResultCallback> done_cb) const { QUICHE_DCHECK(done_cb); auto context = std::make_unique<ProcessClientHelloContext>( validate_chlo_result, reject_only, connection_id, server_address, diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.h b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.h index c3febdc63b8..f114546fe68 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.h @@ -335,7 +335,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config, QuicByteCount total_framing_overhead, QuicByteCount chlo_packet_size, - std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const; + std::shared_ptr<ProcessClientHelloResultCallback> done_cb) const; // BuildServerConfigUpdateMessage invokes |cb| with a SCUP message containing // the current primary config, an up to date source-address token, and cert @@ -587,7 +587,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config, QuicByteCount total_framing_overhead, QuicByteCount chlo_packet_size, - std::unique_ptr<ProcessClientHelloResultCallback> done_cb) + std::shared_ptr<ProcessClientHelloResultCallback> done_cb) : validate_chlo_result_(validate_chlo_result), reject_only_(reject_only), connection_id_(connection_id), @@ -674,7 +674,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { signed_config_; const QuicByteCount total_framing_overhead_; const QuicByteCount chlo_packet_size_; - std::unique_ptr<ProcessClientHelloResultCallback> done_cb_; + std::shared_ptr<ProcessClientHelloResultCallback> done_cb_; }; // Callback class for bridging between ProcessClientHello and diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/tls_connection.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/tls_connection.cc index 61e4c23b03d..1b54b14645f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/tls_connection.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/tls_connection.cc @@ -158,12 +158,9 @@ int TlsConnection::SetReadSecretCallback(SSL* ssl, const SSL_CIPHER* cipher, const uint8_t* secret, size_t secret_length) { - // TODO(nharper): replace this vector with a span (which unfortunately doesn't - // yet exist in quic/platform/api). - std::vector<uint8_t> secret_vec(secret, secret + secret_length); TlsConnection::Delegate* delegate = ConnectionFromSsl(ssl)->delegate_; if (!delegate->SetReadSecret(QuicEncryptionLevel(level), cipher, - secret_vec)) { + absl::MakeSpan(secret, secret_length))) { return 0; } return 1; @@ -175,11 +172,9 @@ int TlsConnection::SetWriteSecretCallback(SSL* ssl, const SSL_CIPHER* cipher, const uint8_t* secret, size_t secret_length) { - // TODO(nharper): replace this vector with a span (which unfortunately doesn't - // yet exist in quic/platform/api). - std::vector<uint8_t> secret_vec(secret, secret + secret_length); TlsConnection::Delegate* delegate = ConnectionFromSsl(ssl)->delegate_; - delegate->SetWriteSecret(QuicEncryptionLevel(level), cipher, secret_vec); + delegate->SetWriteSecret(QuicEncryptionLevel(level), cipher, + absl::MakeSpan(secret, secret_length)); return 1; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/tls_connection.h b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/tls_connection.h index a4887e8c32b..5c4e8b8884a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/tls_connection.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/tls_connection.h @@ -47,7 +47,7 @@ class QUIC_EXPORT_PRIVATE TlsConnection { // traffic secrets and application traffic secrets. The provided write // secret must be used with the provided cipher suite |cipher|. virtual void SetWriteSecret(EncryptionLevel level, const SSL_CIPHER* cipher, - const std::vector<uint8_t>& write_secret) = 0; + absl::Span<const uint8_t> write_secret) = 0; // SetReadSecret is similar to SetWriteSecret, except that it is used for // decrypting messages. SetReadSecret at a particular level is always called @@ -55,7 +55,7 @@ class QUIC_EXPORT_PRIVATE TlsConnection { // where the EncryptionLevel for SetWriteSecret is // ENCRYPTION_FORWARD_SECURE. virtual bool SetReadSecret(EncryptionLevel level, const SSL_CIPHER* cipher, - const std::vector<uint8_t>& read_secret) = 0; + absl::Span<const uint8_t> read_secret) = 0; // WriteMessage is called when there is |data| from the TLS stack ready for // the QUIC stack to write in a crypto frame. The data must be transmitted diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters.cc index ca2adc8509f..635d159a653 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters.cc @@ -660,8 +660,7 @@ bool TransportParameters::AreValid(std::string* error_details) const { TransportParameters::~TransportParameters() = default; -bool SerializeTransportParameters(ParsedQuicVersion /*version*/, - const TransportParameters& in, +bool SerializeTransportParameters(const TransportParameters& in, std::vector<uint8_t>* out) { std::string error_details; if (!in.AreValid(&error_details)) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters.h b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters.h index 5be5ab4f89d..e1f349b6da9 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters.h @@ -17,7 +17,6 @@ #include "quiche/quic/core/quic_tag.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_socket_address.h" namespace quic { @@ -274,8 +273,7 @@ struct QUIC_EXPORT_PRIVATE TransportParameters { // TLS extension. The serialized bytes are written to |*out|. Returns if the // parameters are valid and serialization succeeded. QUIC_EXPORT_PRIVATE bool SerializeTransportParameters( - ParsedQuicVersion version, const TransportParameters& in, - std::vector<uint8_t>* out); + const TransportParameters& in, std::vector<uint8_t>* out); // Parses bytes from the quic_transport_parameters TLS extension and writes the // parsed parameters into |*out|. Input is read from |in| for |in_len| bytes. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters_test.cc index fe9a2ceae9a..76613f0e1f8 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters_test.cc @@ -323,7 +323,7 @@ TEST_P(TransportParametersTest, RoundTripClient) { orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value; std::vector<uint8_t> serialized; - ASSERT_TRUE(SerializeTransportParameters(version_, orig_params, &serialized)); + ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized)); TransportParameters new_params; std::string error_details; @@ -369,7 +369,7 @@ TEST_P(TransportParametersTest, RoundTripServer) { orig_params.google_connection_options = CreateFakeGoogleConnectionOptions(); std::vector<uint8_t> serialized; - ASSERT_TRUE(SerializeTransportParameters(version_, orig_params, &serialized)); + ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized)); TransportParameters new_params; std::string error_details; @@ -484,12 +484,10 @@ TEST_P(TransportParametersTest, NoClientParamsWithStatelessResetToken) { orig_params.max_udp_payload_size.set_value(kMaxPacketSizeForTest); std::vector<uint8_t> out; - bool ok = true; EXPECT_QUIC_BUG( - ok = SerializeTransportParameters(version_, orig_params, &out), + EXPECT_FALSE(SerializeTransportParameters(orig_params, &out)), "Not serializing invalid transport parameters: Client cannot send " "stateless reset token"); - EXPECT_FALSE(ok); } TEST_P(TransportParametersTest, ParseClientParams) { @@ -970,7 +968,7 @@ TEST_P(TransportParametersTest, VeryLongCustomParameter) { orig_params.custom_parameters[kCustomParameter1] = custom_value; std::vector<uint8_t> serialized; - ASSERT_TRUE(SerializeTransportParameters(version_, orig_params, &serialized)); + ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized)); TransportParameters new_params; std::string error_details; @@ -1013,15 +1011,13 @@ TEST_P(TransportParametersTest, SerializationOrderIsRandom) { orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value; std::vector<uint8_t> first_serialized; - ASSERT_TRUE( - SerializeTransportParameters(version_, orig_params, &first_serialized)); + ASSERT_TRUE(SerializeTransportParameters(orig_params, &first_serialized)); // Test that a subsequent serialization is different from the first. // Run in a loop to avoid a failure in the unlikely event that randomization // produces the same result multiple times. for (int i = 0; i < 1000; i++) { std::vector<uint8_t> serialized; - ASSERT_TRUE( - SerializeTransportParameters(version_, orig_params, &serialized)); + ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized)); if (serialized != first_serialized) { return; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.h b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.h index 7142a823165..4a20e665a54 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.h @@ -10,7 +10,6 @@ #include "quiche/quic/core/quic_interval.h" #include "quiche/quic/core/quic_interval_set.h" #include "quiche/quic/core/quic_types.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_flags.h" diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_blocked_frame.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_blocked_frame.cc index a3e8ebe3c4d..594de278e0c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_blocked_frame.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_blocked_frame.cc @@ -11,13 +11,6 @@ namespace quic { QuicBlockedFrame::QuicBlockedFrame() : QuicInlinedFrame(BLOCKED_FRAME) {} QuicBlockedFrame::QuicBlockedFrame(QuicControlFrameId control_frame_id, - QuicStreamId stream_id) - : QuicInlinedFrame(BLOCKED_FRAME), - control_frame_id(control_frame_id), - stream_id(stream_id), - offset(0) {} - -QuicBlockedFrame::QuicBlockedFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id, QuicStreamOffset offset) : QuicInlinedFrame(BLOCKED_FRAME), @@ -28,7 +21,8 @@ QuicBlockedFrame::QuicBlockedFrame(QuicControlFrameId control_frame_id, std::ostream& operator<<(std::ostream& os, const QuicBlockedFrame& blocked_frame) { os << "{ control_frame_id: " << blocked_frame.control_frame_id - << ", stream_id: " << blocked_frame.stream_id << " }\n"; + << ", stream_id: " << blocked_frame.stream_id + << ", offset: " << blocked_frame.offset << " }\n"; return os; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_blocked_frame.h b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_blocked_frame.h index c3f45f36d21..982e1e8ca8c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_blocked_frame.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_blocked_frame.h @@ -20,7 +20,6 @@ namespace quic { struct QUIC_EXPORT_PRIVATE QuicBlockedFrame : public QuicInlinedFrame<QuicBlockedFrame> { QuicBlockedFrame(); - QuicBlockedFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id); QuicBlockedFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id, QuicStreamOffset offset); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_crypto_frame.h b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_crypto_frame.h index bc76da14670..19fb5793610 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_crypto_frame.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_crypto_frame.h @@ -25,6 +25,8 @@ struct QUIC_EXPORT_PRIVATE QuicCryptoFrame { friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const QuicCryptoFrame& s); + // TODO(haoyuewang) Consider replace the EncryptionLevel here with + // PacketNumberSpace. // When writing a crypto frame to a packet, the packet must be encrypted at // |level|. When a crypto frame is read, the encryption level of the packet it // was received in is put in |level|. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.h b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.h index 8b0fbfcec88..358b20e1265 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.h @@ -34,7 +34,6 @@ #include "quiche/quic/core/frames/quic_streams_blocked_frame.h" #include "quiche/quic/core/frames/quic_window_update_frame.h" #include "quiche/quic/core/quic_types.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_export.h" #ifndef QUIC_FRAME_DEBUG diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_frames_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_frames_test.cc index 56269142368..671e7724014 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_frames_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_frames_test.cc @@ -252,9 +252,10 @@ TEST_F(QuicFramesTest, BlockedFrameToString) { SetControlFrameId(4, &frame); EXPECT_EQ(4u, GetControlFrameId(frame)); frame.blocked_frame.stream_id = 1; + frame.blocked_frame.offset = 2; std::ostringstream stream; stream << frame.blocked_frame; - EXPECT_EQ("{ control_frame_id: 4, stream_id: 1 }\n", stream.str()); + EXPECT_EQ("{ control_frame_id: 4, stream_id: 1, offset: 2 }\n", stream.str()); EXPECT_TRUE(IsControlFrame(frame.type)); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_message_frame.h b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_message_frame.h index e376ef6826d..91f73646f63 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_message_frame.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/frames/quic_message_frame.h @@ -8,7 +8,6 @@ #include "absl/container/inlined_vector.h" #include "absl/types/span.h" #include "quiche/quic/core/quic_types.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/common/platform/api/quiche_mem_slice.h" diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule.cc index f17c76914b8..3fba85e05af 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule.cc @@ -20,18 +20,10 @@ namespace quic { std::string CapsuleTypeToString(CapsuleType capsule_type) { switch (capsule_type) { - case CapsuleType::REGISTER_DATAGRAM_CONTEXT: - return "REGISTER_DATAGRAM_CONTEXT"; - case CapsuleType::CLOSE_DATAGRAM_CONTEXT: - return "CLOSE_DATAGRAM_CONTEXT"; case CapsuleType::LEGACY_DATAGRAM: return "LEGACY_DATAGRAM"; - case CapsuleType::DATAGRAM_WITH_CONTEXT: - return "DATAGRAM_WITH_CONTEXT"; case CapsuleType::DATAGRAM_WITHOUT_CONTEXT: return "DATAGRAM_WITHOUT_CONTEXT"; - case CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT: - return "REGISTER_DATAGRAM_NO_CONTEXT"; case CapsuleType::CLOSE_WEBTRANSPORT_SESSION: return "CLOSE_WEBTRANSPORT_SESSION"; } @@ -43,45 +35,6 @@ std::ostream& operator<<(std::ostream& os, const CapsuleType& capsule_type) { return os; } -std::string DatagramFormatTypeToString( - DatagramFormatType datagram_format_type) { - switch (datagram_format_type) { - case DatagramFormatType::UDP_PAYLOAD: - return "UDP_PAYLOAD"; - case DatagramFormatType::WEBTRANSPORT: - return "WEBTRANSPORT"; - } - return absl::StrCat("Unknown(", static_cast<uint64_t>(datagram_format_type), - ")"); -} - -std::ostream& operator<<(std::ostream& os, - const DatagramFormatType& datagram_format_type) { - os << DatagramFormatTypeToString(datagram_format_type); - return os; -} - -std::string ContextCloseCodeToString(ContextCloseCode context_close_code) { - switch (context_close_code) { - case ContextCloseCode::CLOSE_NO_ERROR: - return "NO_ERROR"; - case ContextCloseCode::UNKNOWN_FORMAT: - return "UNKNOWN_FORMAT"; - case ContextCloseCode::DENIED: - return "DENIED"; - case ContextCloseCode::RESOURCE_LIMIT: - return "RESOURCE_LIMIT"; - } - return absl::StrCat("Unknown(", static_cast<uint64_t>(context_close_code), - ")"); -} - -std::ostream& operator<<(std::ostream& os, - const ContextCloseCode& context_close_code) { - os << ContextCloseCodeToString(context_close_code); - return os; -} - Capsule::Capsule(CapsuleType capsule_type) : capsule_type_(capsule_type) { switch (capsule_type) { case CapsuleType::LEGACY_DATAGRAM: @@ -91,13 +44,6 @@ Capsule::Capsule(CapsuleType capsule_type) : capsule_type_(capsule_type) { "All capsule structs must have these properties"); legacy_datagram_capsule_ = LegacyDatagramCapsule(); break; - case CapsuleType::DATAGRAM_WITH_CONTEXT: - static_assert( - std::is_standard_layout<DatagramWithContextCapsule>::value && - std::is_trivially_destructible<DatagramWithContextCapsule>::value, - "All capsule structs must have these properties"); - datagram_with_context_capsule_ = DatagramWithContextCapsule(); - break; case CapsuleType::DATAGRAM_WITHOUT_CONTEXT: static_assert( std::is_standard_layout<DatagramWithoutContextCapsule>::value && @@ -106,31 +52,6 @@ Capsule::Capsule(CapsuleType capsule_type) : capsule_type_(capsule_type) { "All capsule structs must have these properties"); datagram_without_context_capsule_ = DatagramWithoutContextCapsule(); break; - case CapsuleType::REGISTER_DATAGRAM_CONTEXT: - static_assert( - std::is_standard_layout<RegisterDatagramContextCapsule>::value && - std::is_trivially_destructible< - RegisterDatagramContextCapsule>::value, - "All capsule structs must have these properties"); - register_datagram_context_capsule_ = RegisterDatagramContextCapsule(); - break; - case CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT: - static_assert( - std::is_standard_layout<RegisterDatagramNoContextCapsule>::value && - std::is_trivially_destructible< - RegisterDatagramNoContextCapsule>::value, - "All capsule structs must have these properties"); - register_datagram_no_context_capsule_ = - RegisterDatagramNoContextCapsule(); - break; - case CapsuleType::CLOSE_DATAGRAM_CONTEXT: - static_assert( - std::is_standard_layout<CloseDatagramContextCapsule>::value && - std::is_trivially_destructible< - CloseDatagramContextCapsule>::value, - "All capsule structs must have these properties"); - close_datagram_context_capsule_ = CloseDatagramContextCapsule(); - break; case CapsuleType::CLOSE_WEBTRANSPORT_SESSION: static_assert( std::is_standard_layout<CloseWebTransportSessionCapsule>::value && @@ -147,26 +68,14 @@ Capsule::Capsule(CapsuleType capsule_type) : capsule_type_(capsule_type) { // static Capsule Capsule::LegacyDatagram( - absl::optional<QuicDatagramContextId> context_id, absl::string_view http_datagram_payload) { Capsule capsule(CapsuleType::LEGACY_DATAGRAM); - capsule.legacy_datagram_capsule().context_id = context_id; capsule.legacy_datagram_capsule().http_datagram_payload = http_datagram_payload; return capsule; } // static -Capsule Capsule::DatagramWithContext(QuicDatagramContextId context_id, - absl::string_view http_datagram_payload) { - Capsule capsule(CapsuleType::DATAGRAM_WITH_CONTEXT); - capsule.datagram_with_context_capsule().context_id = context_id; - capsule.datagram_with_context_capsule().http_datagram_payload = - http_datagram_payload; - return capsule; -} - -// static Capsule Capsule::DatagramWithoutContext( absl::string_view http_datagram_payload) { Capsule capsule(CapsuleType::DATAGRAM_WITHOUT_CONTEXT); @@ -176,39 +85,6 @@ Capsule Capsule::DatagramWithoutContext( } // static -Capsule Capsule::RegisterDatagramContext( - QuicDatagramContextId context_id, DatagramFormatType format_type, - absl::string_view format_additional_data) { - Capsule capsule(CapsuleType::REGISTER_DATAGRAM_CONTEXT); - capsule.register_datagram_context_capsule().context_id = context_id; - capsule.register_datagram_context_capsule().format_type = format_type; - capsule.register_datagram_context_capsule().format_additional_data = - format_additional_data; - return capsule; -} - -// static -Capsule Capsule::RegisterDatagramNoContext( - DatagramFormatType format_type, absl::string_view format_additional_data) { - Capsule capsule(CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT); - capsule.register_datagram_no_context_capsule().format_type = format_type; - capsule.register_datagram_no_context_capsule().format_additional_data = - format_additional_data; - return capsule; -} - -// static -Capsule Capsule::CloseDatagramContext(QuicDatagramContextId context_id, - ContextCloseCode close_code, - absl::string_view close_details) { - Capsule capsule(CapsuleType::CLOSE_DATAGRAM_CONTEXT); - capsule.close_datagram_context_capsule().context_id = context_id; - capsule.close_datagram_context_capsule().close_code = close_code; - capsule.close_datagram_context_capsule().close_details = close_details; - return capsule; -} - -// static Capsule Capsule::CloseWebTransportSession(WebTransportSessionError error_code, absl::string_view error_message) { Capsule capsule(CapsuleType::CLOSE_WEBTRANSPORT_SESSION); @@ -231,24 +107,10 @@ Capsule& Capsule::operator=(const Capsule& other) { case CapsuleType::LEGACY_DATAGRAM: legacy_datagram_capsule_ = other.legacy_datagram_capsule_; break; - case CapsuleType::DATAGRAM_WITH_CONTEXT: - datagram_with_context_capsule_ = other.datagram_with_context_capsule_; - break; case CapsuleType::DATAGRAM_WITHOUT_CONTEXT: datagram_without_context_capsule_ = other.datagram_without_context_capsule_; break; - case CapsuleType::REGISTER_DATAGRAM_CONTEXT: - register_datagram_context_capsule_ = - other.register_datagram_context_capsule_; - break; - case CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT: - register_datagram_no_context_capsule_ = - other.register_datagram_no_context_capsule_; - break; - case CapsuleType::CLOSE_DATAGRAM_CONTEXT: - close_datagram_context_capsule_ = other.close_datagram_context_capsule_; - break; case CapsuleType::CLOSE_WEBTRANSPORT_SESSION: close_web_transport_session_capsule_ = other.close_web_transport_session_capsule_; @@ -270,39 +132,11 @@ bool Capsule::operator==(const Capsule& other) const { } switch (capsule_type_) { case CapsuleType::LEGACY_DATAGRAM: - return legacy_datagram_capsule_.context_id == - other.legacy_datagram_capsule_.context_id && - legacy_datagram_capsule_.http_datagram_payload == - other.legacy_datagram_capsule_.http_datagram_payload; - case CapsuleType::DATAGRAM_WITH_CONTEXT: - return datagram_with_context_capsule_.context_id == - other.datagram_with_context_capsule_.context_id && - datagram_with_context_capsule_.http_datagram_payload == - other.datagram_with_context_capsule_.http_datagram_payload; + return legacy_datagram_capsule_.http_datagram_payload == + other.legacy_datagram_capsule_.http_datagram_payload; case CapsuleType::DATAGRAM_WITHOUT_CONTEXT: return datagram_without_context_capsule_.http_datagram_payload == other.datagram_without_context_capsule_.http_datagram_payload; - case CapsuleType::REGISTER_DATAGRAM_CONTEXT: - return register_datagram_context_capsule_.context_id == - other.register_datagram_context_capsule_.context_id && - register_datagram_context_capsule_.format_type == - other.register_datagram_context_capsule_.format_type && - register_datagram_context_capsule_.format_additional_data == - other.register_datagram_context_capsule_ - .format_additional_data; - case CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT: - return register_datagram_no_context_capsule_.format_type == - other.register_datagram_no_context_capsule_.format_type && - register_datagram_no_context_capsule_.format_additional_data == - other.register_datagram_no_context_capsule_ - .format_additional_data; - case CapsuleType::CLOSE_DATAGRAM_CONTEXT: - return close_datagram_context_capsule_.context_id == - other.close_datagram_context_capsule_.context_id && - close_datagram_context_capsule_.close_code == - other.close_datagram_context_capsule_.close_code && - close_datagram_context_capsule_.close_details == - other.close_datagram_context_capsule_.close_details; case CapsuleType::CLOSE_WEBTRANSPORT_SESSION: return close_web_transport_session_capsule_.error_code == other.close_web_transport_session_capsule_.error_code && @@ -317,21 +151,11 @@ std::string Capsule::ToString() const { std::string rv = CapsuleTypeToString(capsule_type_); switch (capsule_type_) { case CapsuleType::LEGACY_DATAGRAM: - if (legacy_datagram_capsule_.context_id.has_value()) { - absl::StrAppend(&rv, "(", legacy_datagram_capsule_.context_id.value(), - ")"); - } absl::StrAppend(&rv, "[", absl::BytesToHexString( legacy_datagram_capsule_.http_datagram_payload), "]"); break; - case CapsuleType::DATAGRAM_WITH_CONTEXT: - absl::StrAppend(&rv, "(", datagram_with_context_capsule_.context_id, ")[", - absl::BytesToHexString( - datagram_with_context_capsule_.http_datagram_payload), - "]"); - break; case CapsuleType::DATAGRAM_WITHOUT_CONTEXT: absl::StrAppend( &rv, "[", @@ -339,36 +163,6 @@ std::string Capsule::ToString() const { datagram_without_context_capsule_.http_datagram_payload), "]"); break; - case CapsuleType::REGISTER_DATAGRAM_CONTEXT: - absl::StrAppend( - &rv, "(context_id=", register_datagram_context_capsule_.context_id, - ",format_type=", - DatagramFormatTypeToString( - register_datagram_context_capsule_.format_type), - "){", - absl::BytesToHexString( - register_datagram_context_capsule_.format_additional_data), - "}"); - break; - case CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT: - absl::StrAppend( - &rv, "(format_type=", - DatagramFormatTypeToString( - register_datagram_no_context_capsule_.format_type), - "){", - absl::BytesToHexString( - register_datagram_no_context_capsule_.format_additional_data), - "}"); - break; - case CapsuleType::CLOSE_DATAGRAM_CONTEXT: - absl::StrAppend( - &rv, "(context_id=", close_datagram_context_capsule_.context_id, - ",close_code=", - ContextCloseCodeToString(close_datagram_context_capsule_.close_code), - ",close_details=\"", - absl::BytesToHexString(close_datagram_context_capsule_.close_details), - "\")"); - break; case CapsuleType::CLOSE_WEBTRANSPORT_SESSION: absl::StrAppend( &rv, "(error_code=", close_web_transport_session_capsule_.error_code, @@ -401,46 +195,11 @@ quiche::QuicheBuffer SerializeCapsule( case CapsuleType::LEGACY_DATAGRAM: capsule_data_length = capsule.legacy_datagram_capsule().http_datagram_payload.length(); - if (capsule.legacy_datagram_capsule().context_id.has_value()) { - capsule_data_length += QuicDataWriter::GetVarInt62Len( - capsule.legacy_datagram_capsule().context_id.value()); - } - break; - case CapsuleType::DATAGRAM_WITH_CONTEXT: - capsule_data_length = - QuicDataWriter::GetVarInt62Len( - capsule.datagram_with_context_capsule().context_id) + - capsule.datagram_with_context_capsule() - .http_datagram_payload.length(); break; case CapsuleType::DATAGRAM_WITHOUT_CONTEXT: capsule_data_length = capsule.datagram_without_context_capsule() .http_datagram_payload.length(); break; - case CapsuleType::REGISTER_DATAGRAM_CONTEXT: - capsule_data_length = - QuicDataWriter::GetVarInt62Len( - capsule.register_datagram_context_capsule().context_id) + - QuicDataWriter::GetVarInt62Len(static_cast<uint64_t>( - capsule.register_datagram_context_capsule().format_type)) + - capsule.register_datagram_context_capsule() - .format_additional_data.length(); - break; - case CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT: - capsule_data_length = - QuicDataWriter::GetVarInt62Len(static_cast<uint64_t>( - capsule.register_datagram_no_context_capsule().format_type)) + - capsule.register_datagram_no_context_capsule() - .format_additional_data.length(); - break; - case CapsuleType::CLOSE_DATAGRAM_CONTEXT: - capsule_data_length = - QuicDataWriter::GetVarInt62Len( - capsule.close_datagram_context_capsule().context_id) + - QuicDataWriter::GetVarInt62Len(static_cast<uint64_t>( - capsule.close_datagram_context_capsule().close_code)) + - capsule.close_datagram_context_capsule().close_details.length(); - break; case CapsuleType::CLOSE_WEBTRANSPORT_SESSION: capsule_data_length = sizeof(WebTransportSessionError) + @@ -466,14 +225,6 @@ quiche::QuicheBuffer SerializeCapsule( } switch (capsule.capsule_type()) { case CapsuleType::LEGACY_DATAGRAM: - if (capsule.legacy_datagram_capsule().context_id.has_value()) { - if (!writer.WriteVarInt62( - capsule.legacy_datagram_capsule().context_id.value())) { - QUIC_BUG(datagram capsule context ID write fail) - << "Failed to write LEGACY_DATAGRAM CAPSULE context ID"; - return {}; - } - } if (!writer.WriteStringPiece( capsule.legacy_datagram_capsule().http_datagram_payload)) { QUIC_BUG(datagram capsule payload write fail) @@ -481,20 +232,6 @@ quiche::QuicheBuffer SerializeCapsule( return {}; } break; - case CapsuleType::DATAGRAM_WITH_CONTEXT: - if (!writer.WriteVarInt62( - capsule.datagram_with_context_capsule().context_id)) { - QUIC_BUG(datagram capsule context ID write fail) - << "Failed to write DATAGRAM_WITH_CONTEXT CAPSULE context ID"; - return {}; - } - if (!writer.WriteStringPiece( - capsule.datagram_with_context_capsule().http_datagram_payload)) { - QUIC_BUG(datagram capsule payload write fail) - << "Failed to write DATAGRAM_WITH_CONTEXT CAPSULE payload"; - return {}; - } - break; case CapsuleType::DATAGRAM_WITHOUT_CONTEXT: if (!writer.WriteStringPiece(capsule.datagram_without_context_capsule() .http_datagram_payload)) { @@ -503,64 +240,6 @@ quiche::QuicheBuffer SerializeCapsule( return {}; } break; - case CapsuleType::REGISTER_DATAGRAM_CONTEXT: - if (!writer.WriteVarInt62( - capsule.register_datagram_context_capsule().context_id)) { - QUIC_BUG(register context capsule context ID write fail) - << "Failed to write REGISTER_DATAGRAM_CONTEXT CAPSULE context ID"; - return {}; - } - if (!writer.WriteVarInt62(static_cast<uint64_t>( - capsule.register_datagram_context_capsule().format_type))) { - QUIC_BUG(register context capsule format type write fail) - << "Failed to write REGISTER_DATAGRAM_CONTEXT CAPSULE format type"; - return {}; - } - if (!writer.WriteStringPiece(capsule.register_datagram_context_capsule() - .format_additional_data)) { - QUIC_BUG(register context capsule additional data write fail) - << "Failed to write REGISTER_DATAGRAM_CONTEXT CAPSULE additional " - "data"; - return {}; - } - break; - case CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT: - if (!writer.WriteVarInt62(static_cast<uint64_t>( - capsule.register_datagram_no_context_capsule().format_type))) { - QUIC_BUG(register no context capsule format type write fail) - << "Failed to write REGISTER_DATAGRAM_NO_CONTEXT CAPSULE format " - "type"; - return {}; - } - if (!writer.WriteStringPiece( - capsule.register_datagram_no_context_capsule() - .format_additional_data)) { - QUIC_BUG(register no context capsule additional data write fail) - << "Failed to write REGISTER_DATAGRAM_NO_CONTEXT CAPSULE " - "additional data"; - return {}; - } - break; - case CapsuleType::CLOSE_DATAGRAM_CONTEXT: - if (!writer.WriteVarInt62( - capsule.close_datagram_context_capsule().context_id)) { - QUIC_BUG(close context capsule context ID write fail) - << "Failed to write CLOSE_DATAGRAM_CONTEXT CAPSULE context ID"; - return {}; - } - if (!writer.WriteVarInt62(static_cast<uint64_t>( - capsule.close_datagram_context_capsule().close_code))) { - QUIC_BUG(close context capsule close code write fail) - << "Failed to write CLOSE_DATAGRAM_CONTEXT CAPSULE close code"; - return {}; - } - if (!writer.WriteStringPiece( - capsule.close_datagram_context_capsule().close_details)) { - QUIC_BUG(close context capsule close details write fail) - << "Failed to write CLOSE_DATAGRAM_CONTEXT CAPSULE close details"; - return {}; - } - break; case CapsuleType::CLOSE_WEBTRANSPORT_SESSION: if (!writer.WriteUInt32( capsule.close_web_transport_session_capsule().error_code)) { @@ -638,75 +317,13 @@ size_t CapsuleParser::AttemptParseCapsule() { Capsule capsule(static_cast<CapsuleType>(capsule_type64)); switch (capsule.capsule_type()) { case CapsuleType::LEGACY_DATAGRAM: - if (datagram_context_id_present_) { - uint64_t context_id; - if (!capsule_data_reader.ReadVarInt62(&context_id)) { - ReportParseFailure( - "Unable to parse capsule LEGACY_DATAGRAM context ID"); - return 0; - } - capsule.legacy_datagram_capsule().context_id = context_id; - } capsule.legacy_datagram_capsule().http_datagram_payload = capsule_data_reader.ReadRemainingPayload(); break; - case CapsuleType::DATAGRAM_WITH_CONTEXT: - uint64_t context_id; - if (!capsule_data_reader.ReadVarInt62(&context_id)) { - ReportParseFailure( - "Unable to parse capsule DATAGRAM_WITH_CONTEXT context ID"); - return 0; - } - capsule.datagram_with_context_capsule().context_id = context_id; - capsule.datagram_with_context_capsule().http_datagram_payload = - capsule_data_reader.ReadRemainingPayload(); - break; case CapsuleType::DATAGRAM_WITHOUT_CONTEXT: capsule.datagram_without_context_capsule().http_datagram_payload = capsule_data_reader.ReadRemainingPayload(); break; - case CapsuleType::REGISTER_DATAGRAM_CONTEXT: - if (!capsule_data_reader.ReadVarInt62( - &capsule.register_datagram_context_capsule().context_id)) { - ReportParseFailure( - "Unable to parse capsule REGISTER_DATAGRAM_CONTEXT context ID"); - return 0; - } - if (!capsule_data_reader.ReadVarInt62(reinterpret_cast<uint64_t*>( - &capsule.register_datagram_context_capsule().format_type))) { - ReportParseFailure( - "Unable to parse capsule REGISTER_DATAGRAM_CONTEXT format type"); - return 0; - } - capsule.register_datagram_context_capsule().format_additional_data = - capsule_data_reader.ReadRemainingPayload(); - break; - case CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT: - if (!capsule_data_reader.ReadVarInt62(reinterpret_cast<uint64_t*>( - &capsule.register_datagram_no_context_capsule().format_type))) { - ReportParseFailure( - "Unable to parse capsule REGISTER_DATAGRAM_NO_CONTEXT format type"); - return 0; - } - capsule.register_datagram_no_context_capsule().format_additional_data = - capsule_data_reader.ReadRemainingPayload(); - break; - case CapsuleType::CLOSE_DATAGRAM_CONTEXT: - if (!capsule_data_reader.ReadVarInt62( - &capsule.close_datagram_context_capsule().context_id)) { - ReportParseFailure( - "Unable to parse capsule CLOSE_DATAGRAM_CONTEXT context ID"); - return 0; - } - if (!capsule_data_reader.ReadVarInt62(reinterpret_cast<uint64_t*>( - &capsule.close_datagram_context_capsule().close_code))) { - ReportParseFailure( - "Unable to parse capsule CLOSE_DATAGRAM_CONTEXT close code"); - return 0; - } - capsule.close_datagram_context_capsule().close_details = - capsule_data_reader.ReadRemainingPayload(); - break; case CapsuleType::CLOSE_WEBTRANSPORT_SESSION: if (!capsule_data_reader.ReadUInt32( &capsule.close_web_transport_session_capsule().error_code)) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule.h index 5a93bd38304..7b4cc46d16b 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule.h @@ -20,12 +20,9 @@ namespace quic { enum class CapsuleType : uint64_t { // Casing in this enum matches the IETF specification. - LEGACY_DATAGRAM = 0xff37a0, // draft-ietf-masque-h3-datagram-04 - REGISTER_DATAGRAM_CONTEXT = 0xff37a1, - REGISTER_DATAGRAM_NO_CONTEXT = 0xff37a2, - CLOSE_DATAGRAM_CONTEXT = 0xff37a3, - DATAGRAM_WITH_CONTEXT = 0xff37a4, - DATAGRAM_WITHOUT_CONTEXT = 0xff37a5, + LEGACY_DATAGRAM = 0xff37a0, // draft-ietf-masque-h3-datagram-04. + DATAGRAM_WITHOUT_CONTEXT = + 0xff37a5, // draft-ietf-masque-h3-datagram-05 to -08. CLOSE_WEBTRANSPORT_SESSION = 0x2843, }; @@ -33,55 +30,12 @@ QUIC_EXPORT_PRIVATE std::string CapsuleTypeToString(CapsuleType capsule_type); QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const CapsuleType& capsule_type); -enum class DatagramFormatType : uint64_t { - // Casing in this enum matches the IETF specification. - UDP_PAYLOAD = 0xff6f00, - WEBTRANSPORT = 0xff7c00, -}; - -QUIC_EXPORT_PRIVATE std::string DatagramFormatTypeToString( - DatagramFormatType datagram_format_type); -QUIC_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& os, const DatagramFormatType& datagram_format_type); - -enum class ContextCloseCode : uint64_t { - // Casing in this enum matches the IETF specification. - CLOSE_NO_ERROR = 0xff78a0, // NO_ERROR already exists in winerror.h. - UNKNOWN_FORMAT = 0xff78a1, - DENIED = 0xff78a2, - RESOURCE_LIMIT = 0xff78a3, -}; - -QUIC_EXPORT_PRIVATE std::string ContextCloseCodeToString( - ContextCloseCode context_close_code); -QUIC_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& os, const ContextCloseCode& context_close_code); - struct QUIC_EXPORT_PRIVATE LegacyDatagramCapsule { - absl::optional<QuicDatagramContextId> context_id; - absl::string_view http_datagram_payload; -}; -struct QUIC_EXPORT_PRIVATE DatagramWithContextCapsule { - QuicDatagramContextId context_id; absl::string_view http_datagram_payload; }; struct QUIC_EXPORT_PRIVATE DatagramWithoutContextCapsule { absl::string_view http_datagram_payload; }; -struct QUIC_EXPORT_PRIVATE RegisterDatagramContextCapsule { - QuicDatagramContextId context_id; - DatagramFormatType format_type; - absl::string_view format_additional_data; -}; -struct QUIC_EXPORT_PRIVATE RegisterDatagramNoContextCapsule { - DatagramFormatType format_type; - absl::string_view format_additional_data; -}; -struct QUIC_EXPORT_PRIVATE CloseDatagramContextCapsule { - QuicDatagramContextId context_id; - ContextCloseCode close_code; - absl::string_view close_details; -}; struct QUIC_EXPORT_PRIVATE CloseWebTransportSessionCapsule { WebTransportSessionError error_code; absl::string_view error_message; @@ -95,23 +49,9 @@ struct QUIC_EXPORT_PRIVATE CloseWebTransportSessionCapsule { class QUIC_EXPORT_PRIVATE Capsule { public: static Capsule LegacyDatagram( - absl::optional<QuicDatagramContextId> context_id = absl::nullopt, - absl::string_view http_datagram_payload = absl::string_view()); - static Capsule DatagramWithContext( - QuicDatagramContextId context_id, absl::string_view http_datagram_payload = absl::string_view()); static Capsule DatagramWithoutContext( absl::string_view http_datagram_payload = absl::string_view()); - static Capsule RegisterDatagramContext( - QuicDatagramContextId context_id, DatagramFormatType format_type, - absl::string_view format_additional_data = absl::string_view()); - static Capsule RegisterDatagramNoContext( - DatagramFormatType format_type, - absl::string_view format_additional_data = absl::string_view()); - static Capsule CloseDatagramContext( - QuicDatagramContextId context_id, - ContextCloseCode close_code = ContextCloseCode::CLOSE_NO_ERROR, - absl::string_view close_details = absl::string_view()); static Capsule CloseWebTransportSession( WebTransportSessionError error_code = 0, absl::string_view error_message = ""); @@ -138,14 +78,6 @@ class QUIC_EXPORT_PRIVATE Capsule { QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::LEGACY_DATAGRAM); return legacy_datagram_capsule_; } - DatagramWithContextCapsule& datagram_with_context_capsule() { - QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::DATAGRAM_WITH_CONTEXT); - return datagram_with_context_capsule_; - } - const DatagramWithContextCapsule& datagram_with_context_capsule() const { - QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::DATAGRAM_WITH_CONTEXT); - return datagram_with_context_capsule_; - } DatagramWithoutContextCapsule& datagram_without_context_capsule() { QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::DATAGRAM_WITHOUT_CONTEXT); return datagram_without_context_capsule_; @@ -155,32 +87,6 @@ class QUIC_EXPORT_PRIVATE Capsule { QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::DATAGRAM_WITHOUT_CONTEXT); return datagram_without_context_capsule_; } - RegisterDatagramContextCapsule& register_datagram_context_capsule() { - QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::REGISTER_DATAGRAM_CONTEXT); - return register_datagram_context_capsule_; - } - const RegisterDatagramContextCapsule& register_datagram_context_capsule() - const { - QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::REGISTER_DATAGRAM_CONTEXT); - return register_datagram_context_capsule_; - } - RegisterDatagramNoContextCapsule& register_datagram_no_context_capsule() { - QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT); - return register_datagram_no_context_capsule_; - } - const RegisterDatagramNoContextCapsule& register_datagram_no_context_capsule() - const { - QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT); - return register_datagram_no_context_capsule_; - } - CloseDatagramContextCapsule& close_datagram_context_capsule() { - QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::CLOSE_DATAGRAM_CONTEXT); - return close_datagram_context_capsule_; - } - const CloseDatagramContextCapsule& close_datagram_context_capsule() const { - QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::CLOSE_DATAGRAM_CONTEXT); - return close_datagram_context_capsule_; - } CloseWebTransportSessionCapsule& close_web_transport_session_capsule() { QUICHE_DCHECK_EQ(capsule_type_, CapsuleType::CLOSE_WEBTRANSPORT_SESSION); return close_web_transport_session_capsule_; @@ -192,22 +98,14 @@ class QUIC_EXPORT_PRIVATE Capsule { } absl::string_view& unknown_capsule_data() { QUICHE_DCHECK(capsule_type_ != CapsuleType::LEGACY_DATAGRAM && - capsule_type_ != CapsuleType::DATAGRAM_WITH_CONTEXT && capsule_type_ != CapsuleType::DATAGRAM_WITHOUT_CONTEXT && - capsule_type_ != CapsuleType::REGISTER_DATAGRAM_CONTEXT && - capsule_type_ != CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT && - capsule_type_ != CapsuleType::CLOSE_DATAGRAM_CONTEXT && capsule_type_ != CapsuleType::CLOSE_WEBTRANSPORT_SESSION) << capsule_type_; return unknown_capsule_data_; } const absl::string_view& unknown_capsule_data() const { QUICHE_DCHECK(capsule_type_ != CapsuleType::LEGACY_DATAGRAM && - capsule_type_ != CapsuleType::DATAGRAM_WITH_CONTEXT && capsule_type_ != CapsuleType::DATAGRAM_WITHOUT_CONTEXT && - capsule_type_ != CapsuleType::REGISTER_DATAGRAM_CONTEXT && - capsule_type_ != CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT && - capsule_type_ != CapsuleType::CLOSE_DATAGRAM_CONTEXT && capsule_type_ != CapsuleType::CLOSE_WEBTRANSPORT_SESSION) << capsule_type_; return unknown_capsule_data_; @@ -217,11 +115,7 @@ class QUIC_EXPORT_PRIVATE Capsule { CapsuleType capsule_type_; union { LegacyDatagramCapsule legacy_datagram_capsule_; - DatagramWithContextCapsule datagram_with_context_capsule_; DatagramWithoutContextCapsule datagram_without_context_capsule_; - RegisterDatagramContextCapsule register_datagram_context_capsule_; - RegisterDatagramNoContextCapsule register_datagram_no_context_capsule_; - CloseDatagramContextCapsule close_datagram_context_capsule_; CloseWebTransportSessionCapsule close_web_transport_session_capsule_; absl::string_view unknown_capsule_data_; }; @@ -252,10 +146,6 @@ class QUIC_EXPORT_PRIVATE CapsuleParser { // |visitor| must be non-null, and must outlive CapsuleParser. explicit CapsuleParser(Visitor* visitor); - void set_datagram_context_id_present(bool datagram_context_id_present) { - datagram_context_id_present_ = datagram_context_id_present; - } - // Ingests a capsule fragment (any fragment of bytes from the capsule data // stream) and parses and complete capsules it encounters. Returns false if a // parsing error occurred. @@ -272,8 +162,6 @@ class QUIC_EXPORT_PRIVATE CapsuleParser { size_t AttemptParseCapsule(); void ReportParseFailure(const std::string& error_message); - // Whether HTTP Datagram Context IDs are present. - bool datagram_context_id_present_ = false; // Whether a parsing error has occurred. bool parsing_error_occurred_ = false; // Visitor which will receive callbacks, unowned. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule_test.cc index 895f275ad6f..1791bb6a504 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/capsule_test.cc @@ -31,11 +31,6 @@ class CapsuleParserPeer { namespace { -constexpr DatagramFormatType kFakeFormatType = - static_cast<DatagramFormatType>(0x123456); -constexpr ContextCloseCode kFakeCloseCode = - static_cast<ContextCloseCode>(0x654321); - class MockCapsuleParserVisitor : public CapsuleParser::Visitor { public: MockCapsuleParserVisitor() { @@ -79,27 +74,7 @@ TEST_F(CapsuleTest, LegacyDatagramCapsule) { "a1a2a3a4a5a6a7a8" // HTTP Datagram payload ); std::string datagram_payload = absl::HexStringToBytes("a1a2a3a4a5a6a7a8"); - Capsule expected_capsule = - Capsule::LegacyDatagram(/*context_id=*/absl::nullopt, datagram_payload); - { - EXPECT_CALL(visitor_, OnCapsule(expected_capsule)); - ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment)); - } - ValidateParserIsEmpty(); - TestSerialization(expected_capsule, capsule_fragment); -} - -TEST_F(CapsuleTest, LegacyDatagramCapsuleWithContext) { - std::string capsule_fragment = absl::HexStringToBytes( - "80ff37a0" // LEGACY_DATAGRAM capsule type - "09" // capsule length - "04" // context ID - "a1a2a3a4a5a6a7a8" // HTTP Datagram payload - ); - capsule_parser_.set_datagram_context_id_present(true); - std::string datagram_payload = absl::HexStringToBytes("a1a2a3a4a5a6a7a8"); - Capsule expected_capsule = - Capsule::LegacyDatagram(/*context_id=*/4, datagram_payload); + Capsule expected_capsule = Capsule::LegacyDatagram(datagram_payload); { EXPECT_CALL(visitor_, OnCapsule(expected_capsule)); ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment)); @@ -124,82 +99,6 @@ TEST_F(CapsuleTest, DatagramWithoutContextCapsule) { TestSerialization(expected_capsule, capsule_fragment); } -TEST_F(CapsuleTest, DatagramWithContextCapsule) { - std::string capsule_fragment = absl::HexStringToBytes( - "80ff37a4" // DATAGRAM_WITH_CONTEXT capsule type - "09" // capsule length - "04" // context ID - "a1a2a3a4a5a6a7a8" // HTTP Datagram payload - ); - std::string datagram_payload = absl::HexStringToBytes("a1a2a3a4a5a6a7a8"); - Capsule expected_capsule = - Capsule::DatagramWithContext(/*context_id=*/4, datagram_payload); - { - EXPECT_CALL(visitor_, OnCapsule(expected_capsule)); - ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment)); - } - ValidateParserIsEmpty(); - TestSerialization(expected_capsule, capsule_fragment); -} - -TEST_F(CapsuleTest, RegisterContextCapsule) { - std::string capsule_fragment = absl::HexStringToBytes( - "80ff37a1" // REGISTER_DATAGRAM_CONTEXT capsule type - "0d" // capsule length - "04" // context ID - "80123456" // 0x123456 datagram format type - "f1f2f3f4f5f6f7f8" // format additional data - ); - std::string format_additional_data = - absl::HexStringToBytes("f1f2f3f4f5f6f7f8"); - Capsule expected_capsule = Capsule::RegisterDatagramContext( - /*context_id=*/4, kFakeFormatType, format_additional_data); - { - EXPECT_CALL(visitor_, OnCapsule(expected_capsule)); - ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment)); - } - ValidateParserIsEmpty(); - TestSerialization(expected_capsule, capsule_fragment); -} - -TEST_F(CapsuleTest, RegisterNoContextCapsule) { - std::string capsule_fragment = absl::HexStringToBytes( - "80ff37a2" // REGISTER_DATAGRAM_NO_CONTEXT capsule type - "0c" // capsule length - "80123456" // 0x123456 datagram format type - "f1f2f3f4f5f6f7f8" // format additional data - ); - std::string format_additional_data = - absl::HexStringToBytes("f1f2f3f4f5f6f7f8"); - Capsule expected_capsule = Capsule::RegisterDatagramNoContext( - kFakeFormatType, format_additional_data); - { - EXPECT_CALL(visitor_, OnCapsule(expected_capsule)); - ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment)); - } - ValidateParserIsEmpty(); - TestSerialization(expected_capsule, capsule_fragment); -} - -TEST_F(CapsuleTest, CloseContextCapsule) { - std::string capsule_fragment = absl::HexStringToBytes( - "80ff37a3" // CLOSE_DATAGRAM_CONTEXT capsule type - "27" // capsule length - "04" // context ID - "80654321" // 0x654321 close code - ); - std::string close_details = "All your contexts are belong to us"; - capsule_fragment += close_details; - Capsule expected_capsule = Capsule::CloseDatagramContext( - /*context_id=*/4, kFakeCloseCode, close_details); - { - EXPECT_CALL(visitor_, OnCapsule(expected_capsule)); - ASSERT_TRUE(capsule_parser_.IngestCapsuleFragment(capsule_fragment)); - } - ValidateParserIsEmpty(); - TestSerialization(expected_capsule, capsule_fragment); -} - TEST_F(CapsuleTest, CloseWebTransportStreamCapsule) { std::string capsule_fragment = absl::HexStringToBytes( "6843" // CLOSE_WEBTRANSPORT_STREAM capsule type diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/end_to_end_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/end_to_end_test.cc index e2891a9c1ee..d602f388392 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/end_to_end_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/end_to_end_test.cc @@ -17,10 +17,12 @@ #include "absl/time/time.h" #include "quiche/quic/core/crypto/null_encrypter.h" #include "quiche/quic/core/crypto/quic_client_session_cache.h" +#include "quiche/quic/core/frames/quic_blocked_frame.h" #include "quiche/quic/core/http/http_constants.h" #include "quiche/quic/core/http/quic_spdy_client_stream.h" #include "quiche/quic/core/http/web_transport_http3.h" #include "quiche/quic/core/quic_connection.h" +#include "quiche/quic/core/quic_constants.h" #include "quiche/quic/core/quic_data_writer.h" #include "quiche/quic/core/quic_epoll_connection_helper.h" #include "quiche/quic/core/quic_error_codes.h" @@ -91,27 +93,39 @@ const char kFooResponseBody[] = "Artichoke hearts make me happy."; const char kBarResponseBody[] = "Palm hearts are pretty delicious, also."; const char kTestUserAgentId[] = "quic/core/http/end_to_end_test.cc"; const float kSessionToStreamRatio = 1.5; +const int kLongConnectionIdLength = 16; // Run all tests with the cross products of all versions. struct TestParams { - TestParams(const ParsedQuicVersion& version, QuicTag congestion_control_tag) - : version(version), congestion_control_tag(congestion_control_tag) {} + TestParams(const ParsedQuicVersion& version, QuicTag congestion_control_tag, + int override_server_connection_id_length) + : version(version), + congestion_control_tag(congestion_control_tag), + override_server_connection_id_length( + override_server_connection_id_length) {} friend std::ostream& operator<<(std::ostream& os, const TestParams& p) { os << "{ version: " << ParsedQuicVersionToString(p.version); os << " congestion_control_tag: " - << QuicTagToString(p.congestion_control_tag) << " }"; + << QuicTagToString(p.congestion_control_tag) + << " connection ID length: " << p.override_server_connection_id_length + << " }"; return os; } ParsedQuicVersion version; QuicTag congestion_control_tag; + int override_server_connection_id_length; }; // Used by ::testing::PrintToStringParamName(). std::string PrintToString(const TestParams& p) { - std::string rv = absl::StrCat(ParsedQuicVersionToString(p.version), "_", - QuicTagToString(p.congestion_control_tag)); + std::string rv = absl::StrCat( + ParsedQuicVersionToString(p.version), "_", + QuicTagToString(p.congestion_control_tag), "_", + std::to_string((p.override_server_connection_id_length == -1) + ? static_cast<int>(kQuicDefaultConnectionIdLength) + : p.override_server_connection_id_length)); std::replace(rv.begin(), rv.end(), ',', '_'); std::replace(rv.begin(), rv.end(), ' ', '_'); return rv; @@ -120,15 +134,27 @@ std::string PrintToString(const TestParams& p) { // Constructs various test permutations. std::vector<TestParams> GetTestParams() { std::vector<TestParams> params; - for (const QuicTag congestion_control_tag : {kRENO, kTBBR, kQBIC, kB2ON}) { - if (!GetQuicReloadableFlag(quic_allow_client_enabled_bbr_v2) && - congestion_control_tag == kB2ON) { - continue; - } - for (const ParsedQuicVersion& version : CurrentSupportedVersions()) { - params.push_back(TestParams(version, congestion_control_tag)); - } // End of outer version loop. - } // End of congestion_control_tag loop. + std::vector<int> connection_id_lengths{-1, kLongConnectionIdLength}; + for (auto connection_id_length : connection_id_lengths) { + for (const QuicTag congestion_control_tag : {kTBBR, kQBIC, kB2ON}) { + if (!GetQuicReloadableFlag(quic_allow_client_enabled_bbr_v2) && + congestion_control_tag == kB2ON) { + continue; + } + for (const ParsedQuicVersion& version : CurrentSupportedVersions()) { + // TODO(b/232269029): Q050 should be able to handle 0-RTT when the + // initial connection ID is > 8 bytes, but it cannot. This is an + // invasive fix that has no impact as long as gQUIC clients always use + // 8B server connection IDs. If this bug is fixed, we can change + // 'UsesTls' to 'AllowsVariableLengthConnectionIds()' below to test + // qQUIC as well. + if (connection_id_length == -1 || version.UsesTls()) { + params.push_back(TestParams(version, congestion_control_tag, + connection_id_length)); + } + } // End of outer version loop. + } // End of congestion_control_tag loop. + } // End of connection_id_length loop. return params; } @@ -182,6 +208,8 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { server_supported_versions_(CurrentSupportedVersions()), chlo_multiplier_(0), stream_factory_(nullptr), + override_server_connection_id_length_( + GetParam().override_server_connection_id_length), expected_server_connection_id_length_(kQuicDefaultConnectionIdLength) { QUIC_LOG(INFO) << "Using Configuration: " << GetParam(); @@ -227,7 +255,6 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { client->UseClientConnectionIdLength(override_client_connection_id_length_); client->client()->set_connection_debug_visitor(connection_debug_visitor_); client->client()->set_enable_web_transport(enable_web_transport_); - client->client()->set_use_datagram_contexts(use_datagram_contexts_); client->Connect(); return client; } @@ -367,9 +394,6 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { if (enable_web_transport_) { memory_cache_backend_.set_enable_webtransport(true); } - if (use_datagram_contexts_) { - memory_cache_backend_.set_use_datagram_contexts(true); - } QuicTagVector copt; server_config_.SetConnectionOptionsToSend(copt); @@ -444,12 +468,12 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { } void StartServer() { - auto* test_server = new QuicTestServer( + auto test_server = std::make_unique<QuicTestServer>( crypto_test_utils::ProofSourceForTesting(), server_config_, server_supported_versions_, &memory_cache_backend_, expected_server_connection_id_length_); server_thread_ = - std::make_unique<ServerThread>(test_server, server_address_); + std::make_unique<ServerThread>(std::move(test_server), server_address_); if (chlo_multiplier_ != 0) { server_thread_->server()->SetChloMultiplier(chlo_multiplier_); } @@ -800,7 +824,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { } } - ScopedEnvironmentForThreads environment_; + quiche::test::ScopedEnvironmentForThreads environment_; bool initialized_; // If true, the Initialize() function will create |client_| and starts to // connect to the server. @@ -824,11 +848,10 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { QuicTestServer::StreamFactory* stream_factory_; std::string pre_shared_key_client_; std::string pre_shared_key_server_; - int override_server_connection_id_length_ = -1; + int override_server_connection_id_length_; int override_client_connection_id_length_ = -1; uint8_t expected_server_connection_id_length_; bool enable_web_transport_ = false; - bool use_datagram_contexts_ = false; std::vector<std::string> received_webtransport_unidirectional_streams_; }; @@ -1085,7 +1108,8 @@ TEST_P(EndToEndTest, ForcedVersionNegotiation) { } TEST_P(EndToEndTest, SimpleRequestResponseZeroConnectionID) { - if (!version_.AllowsVariableLengthConnectionIds()) { + if (!version_.AllowsVariableLengthConnectionIds() || + override_server_connection_id_length_ > -1) { ASSERT_TRUE(Initialize()); return; } @@ -1103,7 +1127,8 @@ TEST_P(EndToEndTest, SimpleRequestResponseZeroConnectionID) { } TEST_P(EndToEndTest, ZeroConnectionID) { - if (!version_.AllowsVariableLengthConnectionIds()) { + if (!version_.AllowsVariableLengthConnectionIds() || + override_server_connection_id_length_ > -1) { ASSERT_TRUE(Initialize()); return; } @@ -1119,7 +1144,8 @@ TEST_P(EndToEndTest, ZeroConnectionID) { } TEST_P(EndToEndTest, BadConnectionIdLength) { - if (!version_.AllowsVariableLengthConnectionIds()) { + if (!version_.AllowsVariableLengthConnectionIds() || + override_server_connection_id_length_ > -1) { ASSERT_TRUE(Initialize()); return; } @@ -1133,23 +1159,6 @@ TEST_P(EndToEndTest, BadConnectionIdLength) { .length()); } -// Tests a very long (16-byte) initial destination connection ID to make -// sure the dispatcher properly replaces it with an 8-byte one. -TEST_P(EndToEndTest, LongBadConnectionIdLength) { - if (!version_.AllowsVariableLengthConnectionIds()) { - ASSERT_TRUE(Initialize()); - return; - } - override_server_connection_id_length_ = 16; - ASSERT_TRUE(Initialize()); - SendSynchronousFooRequestAndCheckResponse(); - EXPECT_EQ(kQuicDefaultConnectionIdLength, client_->client() - ->client_session() - ->connection() - ->connection_id() - .length()); -} - TEST_P(EndToEndTest, ClientConnectionId) { if (!version_.SupportsClientConnectionIds()) { ASSERT_TRUE(Initialize()); @@ -1184,7 +1193,8 @@ TEST_P(EndToEndTest, ForcedVersionNegotiationAndClientConnectionId) { } TEST_P(EndToEndTest, ForcedVersionNegotiationAndBadConnectionIdLength) { - if (!version_.AllowsVariableLengthConnectionIds()) { + if (!version_.AllowsVariableLengthConnectionIds() || + override_server_connection_id_length_ > -1) { ASSERT_TRUE(Initialize()); return; } @@ -1205,13 +1215,13 @@ TEST_P(EndToEndTest, ForcedVersionNegotiationAndBadConnectionIdLength) { // connection ID. TEST_P(EndToEndTest, ForcedVersNegoAndClientCIDAndLongCID) { if (!version_.SupportsClientConnectionIds() || - !version_.AllowsVariableLengthConnectionIds()) { + !version_.AllowsVariableLengthConnectionIds() || + override_server_connection_id_length_ != kLongConnectionIdLength) { ASSERT_TRUE(Initialize()); return; } client_supported_versions_.insert(client_supported_versions_.begin(), QuicVersionReservedForNegotiation()); - override_server_connection_id_length_ = 16; override_client_connection_id_length_ = 18; ASSERT_TRUE(Initialize()); ASSERT_TRUE(ServerSendsVersionNegotiation()); @@ -1229,7 +1239,8 @@ TEST_P(EndToEndTest, ForcedVersNegoAndClientCIDAndLongCID) { } TEST_P(EndToEndTest, MixGoodAndBadConnectionIdLengths) { - if (!version_.AllowsVariableLengthConnectionIds()) { + if (!version_.AllowsVariableLengthConnectionIds() || + override_server_connection_id_length_ > -1) { ASSERT_TRUE(Initialize()); return; } @@ -1377,7 +1388,8 @@ TEST_P(EndToEndTest, MultipleRequestResponse) { } TEST_P(EndToEndTest, MultipleRequestResponseZeroConnectionID) { - if (!version_.AllowsVariableLengthConnectionIds()) { + if (!version_.AllowsVariableLengthConnectionIds() || + override_server_connection_id_length_ > -1) { ASSERT_TRUE(Initialize()); return; } @@ -1496,7 +1508,8 @@ TEST_P(EndToEndTest, LargePostNoPacketLoss) { VerifyCleanConnection(true); } -TEST_P(EndToEndTest, LargePostNoPacketLoss1sRTT) { +// Marked as slow since this adds a real-clock one second of delay. +TEST_P(EndToEndTest, QUICHE_SLOW_TEST(LargePostNoPacketLoss1sRTT)) { ASSERT_TRUE(Initialize()); SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(1000)); @@ -1536,7 +1549,14 @@ TEST_P(EndToEndTest, LargePostWithPacketLoss) { EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(headers, body)); - VerifyCleanConnection(true); + if (override_server_connection_id_length_ == -1) { + // If the client sends a longer connection ID, we can end up with dropped + // packets. The packets_dropped counter increments whenever a packet arrives + // with a new server connection ID that is not INITIAL, RETRY, or 1-RTT. + // With packet losses, we could easily lose a server INITIAL and have the + // first observed server packet be HANDSHAKE. + VerifyCleanConnection(true); + } } // Regression test for b/80090281. @@ -1618,7 +1638,13 @@ TEST_P(EndToEndTest, LargePostNoPacketLossWithDelayAndReordering) { client_->SendCustomSynchronousRequest(headers, body)); } -TEST_P(EndToEndTest, AddressToken) { +// TODO(b/214587920): make this test not rely on timeouts. +TEST_P(EndToEndTest, QUICHE_SLOW_TEST(AddressToken)) { + client_config_.set_max_time_before_crypto_handshake( + QuicTime::Delta::FromSeconds(3)); + client_config_.set_max_idle_time_before_crypto_handshake( + QuicTime::Delta::FromSeconds(1)); + client_extra_copts_.push_back(kTRTT); ASSERT_TRUE(Initialize()); if (!version_.HasIetfQuicFrames()) { @@ -1667,11 +1693,7 @@ TEST_P(EndToEndTest, AddressToken) { // QuicSentPacketManager::SetInitialRtt clamps the initial_rtt to between // [min_initial_rtt, max_initial_rtt]. const QuicTime::Delta min_initial_rtt = - server_connection->sent_packet_manager().use_lower_min_irtt() - ? QuicTime::Delta::FromMicroseconds( - kMinTrustedInitialRoundTripTimeUs) - : QuicTime::Delta::FromMicroseconds( - kMinUntrustedInitialRoundTripTimeUs); + QuicTime::Delta::FromMicroseconds(kMinTrustedInitialRoundTripTimeUs); const QuicTime::Delta max_initial_rtt = QuicTime::Delta::FromMicroseconds(kMaxInitialRoundTripTimeUs); const QuicTime::Delta expected_initial_rtt = @@ -1734,7 +1756,13 @@ TEST_P(EndToEndTest, AddressToken) { } // Verify that client does not reuse a source address token. -TEST_P(EndToEndTest, AddressTokenNotReusedByClient) { +// TODO(b/214587920): make this test not rely on timeouts. +TEST_P(EndToEndTest, QUICHE_SLOW_TEST(AddressTokenNotReusedByClient)) { + client_config_.set_max_time_before_crypto_handshake( + QuicTime::Delta::FromSeconds(3)); + client_config_.set_max_idle_time_before_crypto_handshake( + QuicTime::Delta::FromSeconds(1)); + ASSERT_TRUE(Initialize()); if (!version_.HasIetfQuicFrames()) { return; @@ -1968,6 +1996,31 @@ TEST_P(EndToEndTest, LargePostSynchronousRequest) { VerifyCleanConnection(false); } +TEST_P(EndToEndTest, DisableResumption) { + client_extra_copts_.push_back(kNRES); + ASSERT_TRUE(Initialize()); + if (!version_.UsesTls()) { + return; + } + SendSynchronousFooRequestAndCheckResponse(); + QuicSpdyClientSession* client_session = GetClientSession(); + ASSERT_TRUE(client_session); + EXPECT_EQ(client_session->GetCryptoStream()->EarlyDataReason(), + ssl_early_data_no_session_offered); + client_->Disconnect(); + + SendSynchronousFooRequestAndCheckResponse(); + client_session = GetClientSession(); + ASSERT_TRUE(client_session); + if (GetQuicReloadableFlag(quic_enable_disable_resumption)) { + EXPECT_EQ(client_session->GetCryptoStream()->EarlyDataReason(), + ssl_early_data_session_not_resumed); + } else { + EXPECT_EQ(client_session->GetCryptoStream()->EarlyDataReason(), + ssl_early_data_accepted); + } +} + // This is a regression test for b/162595387 TEST_P(EndToEndTest, PostZeroRTTRequestDuringHandshake) { if (!version_.UsesTls()) { @@ -4210,7 +4263,8 @@ TEST_P(EndToEndTest, BadPacketHeaderFlags) { // Send a packet from the client with bad encrypted data. The server should not // tear down the connection. -TEST_P(EndToEndTest, BadEncryptedData) { +// Marked as slow since it calls absl::SleepFor(). +TEST_P(EndToEndTest, QUICHE_SLOW_TEST(BadEncryptedData)) { ASSERT_TRUE(Initialize()); // Start the connection. @@ -4434,6 +4488,72 @@ class ServerStreamThatSendsHugeResponseFactory int64_t body_bytes_; }; +class BlockedFrameObserver : public QuicConnectionDebugVisitor { + public: + std::vector<QuicBlockedFrame> blocked_frames() const { + return blocked_frames_; + } + + void OnBlockedFrame(const QuicBlockedFrame& frame) override { + blocked_frames_.push_back(frame); + } + + private: + std::vector<QuicBlockedFrame> blocked_frames_; +}; + +TEST_P(EndToEndTest, BlockedFrameIncludesOffset) { + if (!version_.HasIetfQuicFrames()) { + // For Google QUIC, the BLOCKED frame offset is ignored. + Initialize(); + return; + } + + set_smaller_flow_control_receive_window(); + ASSERT_TRUE(Initialize()); + + // Observe the connection for BLOCKED frames. + BlockedFrameObserver observer; + QuicConnection* client_connection = GetClientConnection(); + ASSERT_TRUE(client_connection); + client_connection->set_debug_visitor(&observer); + + // Set the response body larger than the flow control window so the server + // must receive a window update from the client before it can finish sending + // it (hence, causing the server to send a BLOCKED frame) + uint32_t response_body_size = + client_config_.GetInitialSessionFlowControlWindowToSend() + 10; + std::string response_body(response_body_size, 'a'); + AddToCache("/blocked", 200, response_body); + SendSynchronousRequestAndCheckResponse("/blocked", response_body); + client_->Disconnect(); + + bool include_offset_flag = + GetQuicReloadableFlag(quic_include_offset_in_blocked_frames); + QuicStreamOffset expected_connection_offset = + include_offset_flag + ? client_config_.GetInitialSessionFlowControlWindowToSend() + : 0; + QuicStreamOffset expected_stream_offset = + include_offset_flag + ? client_config_.GetInitialStreamFlowControlWindowToSend() + : 0; + + ASSERT_GE(observer.blocked_frames().size(), static_cast<uint64_t>(0)); + for (const QuicBlockedFrame& frame : observer.blocked_frames()) { + if (frame.stream_id == + QuicUtils::GetInvalidStreamId(version_.transport_version)) { + // connection-level BLOCKED frame + ASSERT_EQ(frame.offset, expected_connection_offset); + } else { + // stream-level BLOCKED frame + ASSERT_EQ(frame.offset, expected_stream_offset); + } + } + + client_connection->set_debug_visitor(nullptr); +} + TEST_P(EndToEndTest, EarlyResponseFinRecording) { set_smaller_flow_control_receive_window(); @@ -4754,6 +4874,8 @@ TEST_P(EndToEndTest, SendStatelessResetTokenInShlo) { // Regression test for b/116200989. TEST_P(EndToEndTest, SendStatelessResetIfServerConnectionClosedLocallyDuringHandshake) { + SetQuicReloadableFlag( + quic_consider_original_connection_id_as_active_pre_handshake, true); connect_to_server_on_initialize_ = false; ASSERT_TRUE(Initialize()); @@ -5542,14 +5664,12 @@ TEST_P(EndToEndPacketReorderingTest, Buffer0RttRequest) { // Disconnect for next 0-rtt request. client_->Disconnect(); - // Client get valid STK now. Do a 0-rtt request. - // Buffer a CHLO till another packets sent out. - reorder_writer_->SetDelay(1); + // Client has valid Session Ticket now. Do a 0-RTT request. + // Buffer a CHLO till the request is sent out. HTTP/3 sends two packets: a + // SETTINGS frame and a request. + reorder_writer_->SetDelay(version_.UsesHttp3() ? 2 : 1); // Only send out a CHLO. client_->client()->Initialize(); - client_->client()->StartConnect(); - EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable()); - ASSERT_TRUE(client_->client()->connected()); // Send a request before handshake finishes. SpdyHeaderBlock headers; @@ -5564,10 +5684,7 @@ TEST_P(EndToEndPacketReorderingTest, Buffer0RttRequest) { QuicConnection* client_connection = GetClientConnection(); ASSERT_TRUE(client_connection); QuicConnectionStats client_stats = client_connection->GetStats(); - // Client sends CHLO in packet 1 and retransmitted in packet 2. Because of - // the delay, server processes packet 2 and later drops packet 1. ACK is - // bundled with SHLO, such that 1 can be detected loss by time threshold. - EXPECT_LE(0u, client_stats.packets_lost); + EXPECT_EQ(0u, client_stats.packets_lost); EXPECT_TRUE(client_->client()->EarlyDataAccepted()); } @@ -5833,7 +5950,8 @@ TEST_P(EndToEndTest, CustomTransportParameters) { } TEST_P(EndToEndTest, LegacyVersionEncapsulation) { - if (!version_.HasLongHeaderLengths()) { + if (!version_.HasLongHeaderLengths() || + override_server_connection_id_length_ > -1) { // Decapsulating Legacy Version Encapsulation packets from these versions // is not currently supported in QuicDispatcher. ASSERT_TRUE(Initialize()); @@ -5850,7 +5968,8 @@ TEST_P(EndToEndTest, LegacyVersionEncapsulation) { } TEST_P(EndToEndTest, LegacyVersionEncapsulationWithMultiPacketChlo) { - if (!version_.HasLongHeaderLengths()) { + if (!version_.HasLongHeaderLengths() || + override_server_connection_id_length_ > -1) { // Decapsulating Legacy Version Encapsulation packets from these versions // is not currently supported in QuicDispatcher. ASSERT_TRUE(Initialize()); @@ -5877,7 +5996,8 @@ TEST_P(EndToEndTest, LegacyVersionEncapsulationWithMultiPacketChlo) { } TEST_P(EndToEndTest, LegacyVersionEncapsulationWithVersionNegotiation) { - if (!version_.HasLongHeaderLengths()) { + if (!version_.HasLongHeaderLengths() || + override_server_connection_id_length_ > -1) { // Decapsulating Legacy Version Encapsulation packets from these versions // is not currently supported in QuicDispatcher. ASSERT_TRUE(Initialize()); @@ -5896,7 +6016,8 @@ TEST_P(EndToEndTest, LegacyVersionEncapsulationWithVersionNegotiation) { } TEST_P(EndToEndTest, LegacyVersionEncapsulationWithLoss) { - if (!version_.HasLongHeaderLengths()) { + if (!version_.HasLongHeaderLengths() || + override_server_connection_id_length_ > -1) { // Decapsulating Legacy Version Encapsulation packets from these versions // is not currently supported in QuicDispatcher. ASSERT_TRUE(Initialize()); @@ -5959,7 +6080,7 @@ TEST_P(EndToEndTest, ChaosProtectionDisabled) { // Parse the saved packet to make sure it's valid. SimpleQuicFramer validation_framer({version_}); validation_framer.framer()->SetInitialObfuscators( - GetClientConnection()->connection_id()); + GetClientConnection()->GetOriginalDestinationConnectionId()); ASSERT_GT(copying_writer->packets().size(), 0u); EXPECT_TRUE(validation_framer.ProcessPacket(*copying_writer->packets()[0])); // TODO(dschinazi) figure out a way to use a MockRandom in this test so we @@ -6574,38 +6695,6 @@ TEST_P(EndToEndTest, WebTransportDatagrams) { EXPECT_GT(received, 0); } -TEST_P(EndToEndTest, WebTransportDatagramsWithContexts) { - enable_web_transport_ = true; - use_datagram_contexts_ = true; - SetPacketLossPercentage(30); - ASSERT_TRUE(Initialize()); - - if (!version_.UsesHttp3()) { - return; - } - - QuicSpdyStream* connect_stream = nullptr; - WebTransportHttp3* session = CreateWebTransportSession( - "/echo", /*wait_for_server_response=*/true, &connect_stream); - ASSERT_TRUE(session != nullptr); - ASSERT_TRUE(connect_stream != nullptr); - NiceMock<MockWebTransportSessionVisitor>& visitor = - SetupWebTransportVisitor(session); - - quiche::SimpleBufferAllocator allocator; - for (int i = 0; i < 10; i++) { - session->SendOrQueueDatagram(MemSliceFromString("test")); - } - - int received = 0; - EXPECT_CALL(visitor, OnDatagramReceived(_)).WillRepeatedly([&received]() { - received++; - }); - client_->WaitUntil(5000, [&received]() { return received > 0; }); - EXPECT_GT(received, 0); - EXPECT_TRUE(QuicSpdyStreamPeer::use_datagram_contexts(connect_stream)); -} - TEST_P(EndToEndTest, WebTransportSessionClose) { enable_web_transport_ = true; ASSERT_TRUE(Initialize()); @@ -6830,15 +6919,16 @@ TEST_P(EndToEndTest, RejectExtendedConnect) { client_->WaitForResponse(); CheckResponseHeaders("400"); - // Vanilla CONNECT should be accepted. + // Vanilla CONNECT should be sent to backend. spdy::SpdyHeaderBlock headers2; headers2[":authority"] = "localhost"; headers2[":method"] = "CONNECT"; + // Backend not configured/implemented to fully handle CONNECT requests, so + // expect it to send a 405. client_->SendMessage(headers2, "body", /*fin=*/true); client_->WaitForResponse(); - // No :path header, so 404. - CheckResponseHeaders("404"); + CheckResponseHeaders("405"); } TEST_P(EndToEndTest, RejectInvalidRequestHeader) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_constants.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_constants.cc index ea372cd393c..a22620d9f94 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_constants.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_constants.cc @@ -17,15 +17,15 @@ std::string H3SettingsToString(Http3AndQpackSettingsIdentifiers identifier) { RETURN_STRING_LITERAL(SETTINGS_QPACK_MAX_TABLE_CAPACITY); RETURN_STRING_LITERAL(SETTINGS_MAX_FIELD_SECTION_SIZE); RETURN_STRING_LITERAL(SETTINGS_QPACK_BLOCKED_STREAMS); - RETURN_STRING_LITERAL(SETTINGS_H3_DATAGRAM_DRAFT00); RETURN_STRING_LITERAL(SETTINGS_H3_DATAGRAM_DRAFT04); + RETURN_STRING_LITERAL(SETTINGS_H3_DATAGRAM_DRAFT09); RETURN_STRING_LITERAL(SETTINGS_WEBTRANS_DRAFT00); RETURN_STRING_LITERAL(SETTINGS_ENABLE_CONNECT_PROTOCOL); } return absl::StrCat("UNSUPPORTED_SETTINGS_TYPE(", identifier, ")"); } -const absl::string_view kUserAgentHeaderName = "user-agent"; +ABSL_CONST_INIT const absl::string_view kUserAgentHeaderName = "user-agent"; #undef RETURN_STRING_LITERAL // undef for jumbo builds diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_constants.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_constants.h index 097b2a38379..9e1a696dbbb 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_constants.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_constants.h @@ -38,10 +38,10 @@ enum Http3AndQpackSettingsIdentifiers : uint64_t { // Same value as spdy::SETTINGS_MAX_HEADER_LIST_SIZE. SETTINGS_MAX_FIELD_SECTION_SIZE = 0x06, SETTINGS_QPACK_BLOCKED_STREAMS = 0x07, - // draft-ietf-masque-h3-datagram-00. - SETTINGS_H3_DATAGRAM_DRAFT00 = 0x276, // draft-ietf-masque-h3-datagram-04. SETTINGS_H3_DATAGRAM_DRAFT04 = 0xffd277, + // draft-ietf-masque-h3-datagram-09. + SETTINGS_H3_DATAGRAM_DRAFT09 = 0x33, // draft-ietf-webtrans-http3-00 SETTINGS_WEBTRANS_DRAFT00 = 0x2b603742, // draft-ietf-httpbis-h3-websockets diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder.cc index 0008d14fa03..5845a37b264 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder.cc @@ -528,8 +528,8 @@ bool HttpDecoder::ParseEntirePayload(QuicDataReader* reader) { return visitor_->OnGoAwayFrame(frame); } case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): { - MaxPushIdFrame frame; - if (!reader->ReadVarInt62(&frame.push_id)) { + uint64_t unused; + if (!reader->ReadVarInt62(&unused)) { RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read MAX_PUSH_ID push_id."); return false; @@ -539,7 +539,7 @@ bool HttpDecoder::ParseEntirePayload(QuicDataReader* reader) { "Superfluous data in MAX_PUSH_ID frame."); return false; } - return visitor_->OnMaxPushIdFrame(frame); + return visitor_->OnMaxPushIdFrame(); } case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM): { PriorityUpdateFrame frame; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder.h index 137755e04a7..ac6827663ad 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder.h @@ -45,7 +45,7 @@ class QUIC_EXPORT_PRIVATE HttpDecoder { // processed. At that point it is safe to consume |header_length| bytes. // Called when a MAX_PUSH_ID frame has been successfully parsed. - virtual bool OnMaxPushIdFrame(const MaxPushIdFrame& frame) = 0; + virtual bool OnMaxPushIdFrame() = 0; // Called when a GOAWAY frame has been successfully parsed. virtual bool OnGoAwayFrame(const GoAwayFrame& frame) = 0; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder_test.cc index f3854102b26..7f80d175b10 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_decoder_test.cc @@ -45,8 +45,7 @@ class MockHttpDecoderVisitor : public HttpDecoder::Visitor { // Called if an error is detected. MOCK_METHOD(void, OnError, (HttpDecoder*), (override)); - MOCK_METHOD(bool, OnMaxPushIdFrame, (const MaxPushIdFrame& frame), - (override)); + MOCK_METHOD(bool, OnMaxPushIdFrame, (), (override)); MOCK_METHOD(bool, OnGoAwayFrame, (const GoAwayFrame& frame), (override)); MOCK_METHOD(bool, OnSettingsFrameStart, (QuicByteCount header_length), (override)); @@ -90,7 +89,7 @@ class MockHttpDecoderVisitor : public HttpDecoder::Visitor { class HttpDecoderTest : public QuicTest { public: HttpDecoderTest() : decoder_(&visitor_) { - ON_CALL(visitor_, OnMaxPushIdFrame(_)).WillByDefault(Return(true)); + ON_CALL(visitor_, OnMaxPushIdFrame()).WillByDefault(Return(true)); ON_CALL(visitor_, OnGoAwayFrame(_)).WillByDefault(Return(true)); ON_CALL(visitor_, OnSettingsFrameStart(_)).WillByDefault(Return(true)); ON_CALL(visitor_, OnSettingsFrame(_)).WillByDefault(Return(true)); @@ -230,20 +229,19 @@ TEST_F(HttpDecoderTest, MaxPushId) { "01"); // Push Id // Visitor pauses processing. - EXPECT_CALL(visitor_, OnMaxPushIdFrame(MaxPushIdFrame({1}))) - .WillOnce(Return(false)); + EXPECT_CALL(visitor_, OnMaxPushIdFrame()).WillOnce(Return(false)); EXPECT_EQ(input.size(), ProcessInputWithGarbageAppended(input)); EXPECT_THAT(decoder_.error(), IsQuicNoError()); EXPECT_EQ("", decoder_.error_detail()); // Process the full frame. - EXPECT_CALL(visitor_, OnMaxPushIdFrame(MaxPushIdFrame({1}))); + EXPECT_CALL(visitor_, OnMaxPushIdFrame()); EXPECT_EQ(input.size(), ProcessInput(input)); EXPECT_THAT(decoder_.error(), IsQuicNoError()); EXPECT_EQ("", decoder_.error_detail()); // Process the frame incrementally. - EXPECT_CALL(visitor_, OnMaxPushIdFrame(MaxPushIdFrame({1}))); + EXPECT_CALL(visitor_, OnMaxPushIdFrame()); ProcessInputCharByChar(input); EXPECT_THAT(decoder_.error(), IsQuicNoError()); EXPECT_EQ("", decoder_.error_detail()); @@ -1068,9 +1066,12 @@ TEST(HttpDecoderTestNoFixture, WebTransportStreamError) { EXPECT_CALL(visitor, OnWebTransportStreamFrameType(_, _)); decoder.ProcessInput(input.data(), input.size()); - EXPECT_CALL(visitor, OnError(_)); - EXPECT_QUIC_BUG(decoder.ProcessInput(input.data(), input.size()), - "HttpDecoder called after an indefinite-length frame"); + EXPECT_QUIC_BUG( + { + EXPECT_CALL(visitor, OnError(_)); + decoder.ProcessInput(input.data(), input.size()); + }, + "HttpDecoder called after an indefinite-length frame"); } TEST_F(HttpDecoderTest, DecodeSettings) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_frames.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_frames.h index eae52ee649f..b96c5fbec8a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_frames.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_frames.h @@ -20,9 +20,6 @@ namespace quic { -// TODO(b/171463363): Remove. -using PushId = uint64_t; - enum class HttpFrameType { DATA = 0x0, HEADERS = 0x1, @@ -101,18 +98,6 @@ struct QUIC_EXPORT_PRIVATE GoAwayFrame { bool operator==(const GoAwayFrame& rhs) const { return id == rhs.id; } }; -// 7.2.7. MAX_PUSH_ID -// -// The MAX_PUSH_ID frame (type=0xD) is used by clients to control the -// number of server pushes that the server can initiate. -struct QUIC_EXPORT_PRIVATE MaxPushIdFrame { - PushId push_id; - - bool operator==(const MaxPushIdFrame& rhs) const { - return push_id == rhs.push_id; - } -}; - // https://httpwg.org/http-extensions/draft-ietf-httpbis-priority.html // // The PRIORITY_UPDATE frame specifies the sender-advised priority of a stream. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_frames_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_frames_test.cc index 1eefd7e6a55..446a6b92ca7 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_frames_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/http_frames_test.cc @@ -44,17 +44,6 @@ TEST(HttpFramesTest, GoAwayFrame) { EXPECT_TRUE(a == b); } -TEST(HttpFramesTest, MaxPushIdFrame) { - MaxPushIdFrame a{1}; - EXPECT_TRUE(a == a); - - MaxPushIdFrame b{2}; - EXPECT_FALSE(a == b); - - b.push_id = 1; - EXPECT_TRUE(a == b); -} - TEST(HttpFramesTest, PriorityUpdateFrame) { PriorityUpdateFrame a{REQUEST_STREAM, 0, ""}; EXPECT_TRUE(a == a); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_header_list_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_header_list_test.cc index 6007bccdfc6..573aae5ee66 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_header_list_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_header_list_test.cc @@ -12,7 +12,7 @@ using ::testing::ElementsAre; using ::testing::Pair; -namespace quic { +namespace quic::test { class QuicHeaderListTest : public QuicTest {}; @@ -83,4 +83,4 @@ TEST_F(QuicHeaderListTest, IsCopyableAndAssignable) { Pair("beep", ""))); } -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_headers_stream.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_headers_stream.h index 1fae938bff6..ba3a27b3850 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_headers_stream.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_headers_stream.h @@ -11,7 +11,6 @@ #include "quiche/quic/core/http/quic_header_list.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_stream.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/spdy/core/spdy_framer.h" diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_headers_stream_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_headers_stream_test.cc index d72eded7235..76083f33330 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_headers_stream_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_headers_stream_test.cc @@ -31,7 +31,7 @@ #include "quiche/spdy/core/recording_headers_handler.h" #include "quiche/spdy/core/spdy_alt_svc_wire_format.h" #include "quiche/spdy/core/spdy_protocol.h" -#include "quiche/spdy/core/spdy_test_utils.h" +#include "quiche/spdy/test_tools/spdy_test_utils.h" using spdy::ERROR_CODE_PROTOCOL_ERROR; using spdy::RecordingHeadersHandler; @@ -101,9 +101,9 @@ class MockVisitor : public SpdyFramerVisitorInterface { (SpdyStreamId last_accepted_stream_id, SpdyErrorCode error_code), (override)); MOCK_METHOD(void, OnHeaders, - (SpdyStreamId stream_id, bool has_priority, int weight, - SpdyStreamId parent_stream_id, bool exclusive, bool fin, - bool end), + (SpdyStreamId stream_id, size_t payload_length, bool has_priority, + int weight, SpdyStreamId parent_stream_id, bool exclusive, + bool fin, bool end), (override)); MOCK_METHOD(void, OnWindowUpdate, (SpdyStreamId stream_id, int delta_window_size), (override)); @@ -111,7 +111,8 @@ class MockVisitor : public SpdyFramerVisitorInterface { (SpdyStreamId stream_id, SpdyStreamId promised_stream_id, bool end), (override)); - MOCK_METHOD(void, OnContinuation, (SpdyStreamId stream_id, bool end), + MOCK_METHOD(void, OnContinuation, + (SpdyStreamId stream_id, size_t payload_size, bool end), (override)); MOCK_METHOD( void, OnAltSvc, @@ -281,17 +282,20 @@ class QuicHeadersStreamTest : public QuicTestWithParam<TestParams> { // Parse the outgoing data and check that it matches was was written. if (is_request) { - EXPECT_CALL(visitor_, - OnHeaders(stream_id, kHasPriority, - Spdy3PriorityToHttp2Weight(priority), - /*parent_stream_id=*/0, - /*exclusive=*/false, fin, kFrameComplete)); + EXPECT_CALL( + visitor_, + OnHeaders(stream_id, saved_data_.length() - spdy::kFrameHeaderSize, + kHasPriority, Spdy3PriorityToHttp2Weight(priority), + /*parent_stream_id=*/0, + /*exclusive=*/false, fin, kFrameComplete)); } else { - EXPECT_CALL(visitor_, - OnHeaders(stream_id, !kHasPriority, - /*weight=*/0, - /*parent_stream_id=*/0, - /*exclusive=*/false, fin, kFrameComplete)); + EXPECT_CALL( + visitor_, + OnHeaders(stream_id, saved_data_.length() - spdy::kFrameHeaderSize, + !kHasPriority, + /*weight=*/0, + /*parent_stream_id=*/0, + /*exclusive=*/false, fin, kFrameComplete)); } headers_handler_ = std::make_unique<RecordingHeadersHandler>(); EXPECT_CALL(visitor_, OnHeaderFrameStart(stream_id)) @@ -629,7 +633,7 @@ TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameSupportedFields) { ->header_encoder_table_size()); } -// Regression bug for b/208997000. +// Regression test for b/208997000. TEST_P(QuicHeadersStreamTest, LimitEncoderDynamicTableSize) { const uint32_t kVeryLargeTableSizeLimit = 1024 * 1024 * 1024; SpdySettingsIR data; @@ -638,14 +642,8 @@ TEST_P(QuicHeadersStreamTest, LimitEncoderDynamicTableSize) { stream_frame_.data_buffer = frame.data(); stream_frame_.data_length = frame.size(); headers_stream_->OnStreamFrame(stream_frame_); - if (GetQuicReloadableFlag(quic_limit_encoder_dynamic_table_size)) { - EXPECT_EQ(16384u, QuicSpdySessionPeer::GetSpdyFramer(&session_) - ->header_encoder_table_size()); - } else { - EXPECT_EQ(kVeryLargeTableSizeLimit, - QuicSpdySessionPeer::GetSpdyFramer(&session_) - ->header_encoder_table_size()); - } + EXPECT_EQ(16384u, QuicSpdySessionPeer::GetSpdyFramer(&session_) + ->header_encoder_table_size()); } TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_receive_control_stream.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_receive_control_stream.cc index 853909aa03c..c0a76af879a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_receive_control_stream.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_receive_control_stream.cc @@ -62,21 +62,8 @@ void QuicReceiveControlStream::OnError(HttpDecoder* decoder) { stream_delegate()->OnStreamError(decoder->error(), decoder->error_detail()); } -bool QuicReceiveControlStream::OnMaxPushIdFrame(const MaxPushIdFrame& frame) { - if (GetQuicReloadableFlag(quic_ignore_max_push_id)) { - QUIC_RELOADABLE_FLAG_COUNT(quic_ignore_max_push_id); - return ValidateFrameType(HttpFrameType::MAX_PUSH_ID); - } - - if (spdy_session()->debug_visitor()) { - spdy_session()->debug_visitor()->OnMaxPushIdFrameReceived(frame); - } - - if (!ValidateFrameType(HttpFrameType::MAX_PUSH_ID)) { - return false; - } - - return spdy_session()->OnMaxPushIdFrame(frame.push_id); +bool QuicReceiveControlStream::OnMaxPushIdFrame() { + return ValidateFrameType(HttpFrameType::MAX_PUSH_ID); } bool QuicReceiveControlStream::OnGoAwayFrame(const GoAwayFrame& frame) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_receive_control_stream.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_receive_control_stream.h index 0cf34fad6fe..71d0bf2fa62 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_receive_control_stream.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_receive_control_stream.h @@ -35,7 +35,7 @@ class QUIC_EXPORT_PRIVATE QuicReceiveControlStream // HttpDecoder::Visitor implementation. void OnError(HttpDecoder* decoder) override; - bool OnMaxPushIdFrame(const MaxPushIdFrame& frame) override; + bool OnMaxPushIdFrame() override; bool OnGoAwayFrame(const GoAwayFrame& frame) override; bool OnSettingsFrameStart(QuicByteCount header_length) override; bool OnSettingsFrame(const SettingsFrame& frame) override; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_send_control_stream.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_send_control_stream.h index c606ff50244..18ee01fb938 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_send_control_stream.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_send_control_stream.h @@ -10,6 +10,7 @@ #include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_logging.h" +#include "quiche/common/platform/api/quiche_logging.h" namespace quic { @@ -46,7 +47,7 @@ class QUIC_EXPORT_PRIVATE QuicSendControlStream : public QuicStream { // The send control stream is write unidirectional, so this method should // never be called. - void OnDataAvailable() override { QUIC_NOTREACHED(); } + void OnDataAvailable() override { QUICHE_NOTREACHED(); } private: // Track if a settings frame is already sent. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_send_control_stream_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_send_control_stream_test.cc index aa7606fe8cc..f146cee9baf 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_send_control_stream_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_send_control_stream_test.cc @@ -133,11 +133,11 @@ TEST_P(QuicSendControlStreamTest, WriteSettings) { if ((!GetQuicReloadableFlag(quic_verify_request_headers_2) || perspective() == Perspective::IS_CLIENT) && QuicSpdySessionPeer::LocalHttpDatagramSupport(&session_) == - HttpDatagramSupport::kDraft00And04) { + HttpDatagramSupport::kDraft04) { expected_write_data = absl::HexStringToBytes( "00" // stream type: control stream "04" // frame type: SETTINGS frame - "0e" // frame length + "0b" // frame length "01" // SETTINGS_QPACK_MAX_TABLE_CAPACITY "40ff" // 255 "06" // SETTINGS_MAX_HEADER_LIST_SIZE @@ -146,8 +146,6 @@ TEST_P(QuicSendControlStreamTest, WriteSettings) { "10" // 16 "4040" // 0x40 as the reserved settings id "14" // 20 - "4276" // SETTINGS_H3_DATAGRAM_DRAFT00 - "01" // 1 "800ffd277" // SETTINGS_H3_DATAGRAM_DRAFT04 "01" // 1 "4040" // 0x40 as the reserved frame type @@ -183,7 +181,7 @@ TEST_P(QuicSendControlStreamTest, WriteSettings) { expected_write_data = absl::HexStringToBytes( "00" // stream type: control stream "04" // frame type: SETTINGS frame - "11" // frame length + "0e" // frame length "01" // SETTINGS_QPACK_MAX_TABLE_CAPACITY "40ff" // 255 "06" // SETTINGS_MAX_HEADER_LIST_SIZE @@ -194,8 +192,6 @@ TEST_P(QuicSendControlStreamTest, WriteSettings) { "01" // 1 "4040" // 0x40 as the reserved settings id "14" // 20 - "4276" // SETTINGS_H3_DATAGRAM_DRAFT00 - "01" // 1 "800ffd277" // SETTINGS_H3_DATAGRAM_DRAFT04 "01" // 1 "4040" // 0x40 as the reserved frame type diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.cc index 7ad1e3acb5e..d59602e103c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.cc @@ -10,12 +10,14 @@ #include "quiche/quic/core/quic_connection.h" #include "quiche/quic/core/quic_stream.h" #include "quiche/quic/core/quic_tag.h" +#include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_utils.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/quic/platform/api/quic_flag_utils.h" #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_logging.h" +#include "quiche/common/platform/api/quiche_logging.h" namespace quic { @@ -45,15 +47,6 @@ void QuicServerSessionBase::Initialize() { void QuicServerSessionBase::OnConfigNegotiated() { QuicSpdySession::OnConfigNegotiated(); - const bool use_lower_min_irtt = - connection()->sent_packet_manager().use_lower_min_irtt(); - - if (!use_lower_min_irtt) { - if (!config()->HasReceivedConnectionOptions()) { - return; - } - } - const CachedNetworkParameters* cached_network_params = crypto_stream_->PreviousCachedNetworkParams(); @@ -63,7 +56,7 @@ void QuicServerSessionBase::OnConfigNegotiated() { if (version().UsesTls() && cached_network_params != nullptr) { if (cached_network_params->serving_region() == serving_region_) { QUIC_CODE_COUNT(quic_server_received_network_params_at_same_region); - if ((!use_lower_min_irtt || config()->HasReceivedConnectionOptions()) && + if (config()->HasReceivedConnectionOptions() && ContainsQuicTag(config()->ReceivedConnectionOptions(), kTRTT)) { QUIC_DLOG(INFO) << "Server: Setting initial rtt to " @@ -72,20 +65,33 @@ void QuicServerSessionBase::OnConfigNegotiated() { connection()->sent_packet_manager().SetInitialRtt( QuicTime::Delta::FromMilliseconds( cached_network_params->min_rtt_ms()), - /*trusted=*/use_lower_min_irtt); + /*trusted=*/true); } } else { QUIC_CODE_COUNT(quic_server_received_network_params_at_different_region); } } - if (use_lower_min_irtt) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_lower_min_for_trusted_irtt, 1, 2); - if (!config()->HasReceivedConnectionOptions()) { - return; - } + if (!config()->HasReceivedConnectionOptions()) { + return; } + if (GetQuicReloadableFlag(quic_enable_disable_resumption) && + version().UsesTls() && + ContainsQuicTag(config()->ReceivedConnectionOptions(), kNRES) && + crypto_stream_->ResumptionAttempted()) { + QUIC_RELOADABLE_FLAG_COUNT(quic_enable_disable_resumption); + const bool disabled = crypto_stream_->DisableResumption(); + QUIC_BUG_IF(quic_failed_to_disable_resumption, !disabled) + << "Failed to disable resumption"; + } + + enable_sending_bandwidth_estimate_when_network_idle_ = + GetQuicRestartFlag( + quic_enable_sending_bandwidth_estimate_when_network_idle) && + version().HasIetfQuicFrames() && + ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWID); + // Enable bandwidth resumption if peer sent correct connection options. const bool last_bandwidth_resumption = ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWRE); @@ -128,7 +134,31 @@ void QuicServerSessionBase::OnConnectionClosed( } } +void QuicServerSessionBase::OnBandwidthUpdateTimeout() { + if (!enable_sending_bandwidth_estimate_when_network_idle_) { + return; + } + QUIC_DVLOG(1) << "Bandwidth update timed out."; + const SendAlgorithmInterface* send_algorithm = + connection()->sent_packet_manager().GetSendAlgorithm(); + if (send_algorithm != nullptr && + send_algorithm->HasGoodBandwidthEstimateForResumption()) { + const bool success = MaybeSendAddressToken(); + QUIC_BUG_IF(QUIC_BUG_25522, !success) << "Failed to send address token."; + QUIC_RESTART_FLAG_COUNT_N( + quic_enable_sending_bandwidth_estimate_when_network_idle, 2, 3); + } +} + void QuicServerSessionBase::OnCongestionWindowChange(QuicTime now) { + // Sending bandwidth is no longer conditioned on if session does bandwidth + // resumption. + if (GetQuicRestartFlag( + quic_enable_sending_bandwidth_estimate_when_network_idle)) { + QUIC_RESTART_FLAG_COUNT_N( + quic_enable_sending_bandwidth_estimate_when_network_idle, 3, 3); + return; + } if (!bandwidth_resumption_enabled_) { return; } @@ -280,7 +310,7 @@ const QuicCryptoServerStreamBase* QuicServerSessionBase::GetCryptoStream() int32_t QuicServerSessionBase::BandwidthToCachedParameterBytesPerSecond( const QuicBandwidth& bandwidth) const { return static_cast<int32_t>(std::min<int64_t>( - bandwidth.ToBytesPerSecond(), std::numeric_limits<uint32_t>::max())); + bandwidth.ToBytesPerSecond(), std::numeric_limits<int32_t>::max())); } void QuicServerSessionBase::SendSettingsToCryptoStream() { @@ -335,30 +365,55 @@ QuicServerSessionBase::GenerateCachedNetworkParameters() const { sent_packet_manager.GetRttStats()->min_rtt().ToMilliseconds()); } - // Populate bandwidth estimates if any. - if (bandwidth_recorder != nullptr && bandwidth_recorder->HasEstimate()) { - const int32_t bw_estimate_bytes_per_second = - BandwidthToCachedParameterBytesPerSecond( - bandwidth_recorder->BandwidthEstimate()); - const int32_t max_bw_estimate_bytes_per_second = - BandwidthToCachedParameterBytesPerSecond( - bandwidth_recorder->MaxBandwidthEstimate()); - QUIC_BUG_IF(quic_bug_12513_1, max_bw_estimate_bytes_per_second < 0) - << max_bw_estimate_bytes_per_second; - QUIC_BUG_IF(quic_bug_10393_1, bw_estimate_bytes_per_second < 0) - << bw_estimate_bytes_per_second; - - cached_network_params.set_bandwidth_estimate_bytes_per_second( - bw_estimate_bytes_per_second); - cached_network_params.set_max_bandwidth_estimate_bytes_per_second( - max_bw_estimate_bytes_per_second); - cached_network_params.set_max_bandwidth_timestamp_seconds( - bandwidth_recorder->MaxBandwidthTimestamp()); - - cached_network_params.set_previous_connection_state( - bandwidth_recorder->EstimateRecordedDuringSlowStart() - ? CachedNetworkParameters::SLOW_START - : CachedNetworkParameters::CONGESTION_AVOIDANCE); + if (enable_sending_bandwidth_estimate_when_network_idle_) { + const SendAlgorithmInterface* send_algorithm = + sent_packet_manager.GetSendAlgorithm(); + if (send_algorithm != nullptr && + send_algorithm->HasGoodBandwidthEstimateForResumption()) { + cached_network_params.set_bandwidth_estimate_bytes_per_second( + BandwidthToCachedParameterBytesPerSecond( + send_algorithm->BandwidthEstimate())); + QUIC_CODE_COUNT(quic_send_measured_bandwidth_in_token); + } else { + const quic::CachedNetworkParameters* previous_cached_network_params = + crypto_stream()->PreviousCachedNetworkParams(); + if (previous_cached_network_params != nullptr && + previous_cached_network_params + ->bandwidth_estimate_bytes_per_second() > 0) { + cached_network_params.set_bandwidth_estimate_bytes_per_second( + previous_cached_network_params + ->bandwidth_estimate_bytes_per_second()); + QUIC_CODE_COUNT(quic_send_previous_bandwidth_in_token); + } else { + QUIC_CODE_COUNT(quic_not_send_bandwidth_in_token); + } + } + } else { + // Populate bandwidth estimates if any. + if (bandwidth_recorder != nullptr && bandwidth_recorder->HasEstimate()) { + const int32_t bw_estimate_bytes_per_second = + BandwidthToCachedParameterBytesPerSecond( + bandwidth_recorder->BandwidthEstimate()); + const int32_t max_bw_estimate_bytes_per_second = + BandwidthToCachedParameterBytesPerSecond( + bandwidth_recorder->MaxBandwidthEstimate()); + QUIC_BUG_IF(quic_bug_12513_1, max_bw_estimate_bytes_per_second < 0) + << max_bw_estimate_bytes_per_second; + QUIC_BUG_IF(quic_bug_10393_1, bw_estimate_bytes_per_second < 0) + << bw_estimate_bytes_per_second; + + cached_network_params.set_bandwidth_estimate_bytes_per_second( + bw_estimate_bytes_per_second); + cached_network_params.set_max_bandwidth_estimate_bytes_per_second( + max_bw_estimate_bytes_per_second); + cached_network_params.set_max_bandwidth_timestamp_seconds( + bandwidth_recorder->MaxBandwidthTimestamp()); + + cached_network_params.set_previous_connection_state( + bandwidth_recorder->EstimateRecordedDuringSlowStart() + ? CachedNetworkParameters::SLOW_START + : CachedNetworkParameters::CONGESTION_AVOIDANCE); + } } if (!serving_region_.empty()) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.h index d30b9dd359f..fcfda0e89f5 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.h @@ -48,6 +48,9 @@ class QUIC_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession { void OnConnectionClosed(const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) override; + // Override to send bandwidth estimate. + void OnBandwidthUpdateTimeout() override; + // Sends a server config update to the client, containing new bandwidth // estimate. void OnCongestionWindowChange(QuicTime now) override; @@ -72,6 +75,10 @@ class QUIC_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession { QuicSSLConfig GetSSLConfig() const override; + bool enable_sending_bandwidth_estimate_when_network_idle() const { + return enable_sending_bandwidth_estimate_when_network_idle_; + } + protected: // QuicSession methods(override them with return type of QuicSpdyStream*): QuicCryptoServerStreamBase* GetMutableCryptoStream() override; @@ -129,8 +136,9 @@ class QUIC_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession { // The most recent bandwidth estimate sent to the client. QuicBandwidth bandwidth_estimate_sent_to_client_; - // Text describing server location. Sent to the client as part of the bandwith - // estimate in the source-address token. Optional, can be left empty. + // Text describing server location. Sent to the client as part of the + // bandwidth estimate in the source-address token. Optional, can be left + // empty. std::string serving_region_; // Time at which we send the last SCUP to the client. @@ -144,6 +152,8 @@ class QUIC_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession { // should go away once we fix http://b//27897982 int32_t BandwidthToCachedParameterBytesPerSecond( const QuicBandwidth& bandwidth) const; + + bool enable_sending_bandwidth_estimate_when_network_idle_ = false; }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base_test.cc index 56aa06a59b6..df099a66f3d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base_test.cc @@ -510,6 +510,7 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) { // Client has sent kBWRE connection option to trigger bandwidth resumption. QuicTagVector copt; copt.push_back(kBWRE); + copt.push_back(kBWID); QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt); connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); session_->OnConfigNegotiated(); @@ -606,35 +607,40 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) { sent_packet_manager->OnPacketSent(&packet, now, NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, true); - // Verify that the proto has exactly the values we expect. - CachedNetworkParameters expected_network_params; - expected_network_params.set_bandwidth_estimate_bytes_per_second( - bandwidth_recorder.BandwidthEstimate().ToBytesPerSecond()); - expected_network_params.set_max_bandwidth_estimate_bytes_per_second( - bandwidth_recorder.MaxBandwidthEstimate().ToBytesPerSecond()); - expected_network_params.set_max_bandwidth_timestamp_seconds( - bandwidth_recorder.MaxBandwidthTimestamp()); - expected_network_params.set_min_rtt_ms(session_->connection() - ->sent_packet_manager() - .GetRttStats() - ->min_rtt() - .ToMilliseconds()); - expected_network_params.set_previous_connection_state( - CachedNetworkParameters::CONGESTION_AVOIDANCE); - expected_network_params.set_timestamp( - session_->connection()->clock()->WallNow().ToUNIXSeconds()); - expected_network_params.set_serving_region(serving_region); - - if (quic_crypto_stream) { - EXPECT_CALL(*quic_crypto_stream, - SendServerConfigUpdate(EqualsProto(expected_network_params))) - .Times(1); + if (GetQuicRestartFlag( + quic_enable_sending_bandwidth_estimate_when_network_idle)) { + EXPECT_CALL(*connection_, OnSendConnectionState(_)).Times(0); } else { - EXPECT_CALL(*tls_server_stream, - GetAddressToken(EqualsProto(expected_network_params))) - .WillOnce(testing::Return("Test address token")); + // Verify that the proto has exactly the values we expect. + CachedNetworkParameters expected_network_params; + expected_network_params.set_bandwidth_estimate_bytes_per_second( + bandwidth_recorder.BandwidthEstimate().ToBytesPerSecond()); + expected_network_params.set_max_bandwidth_estimate_bytes_per_second( + bandwidth_recorder.MaxBandwidthEstimate().ToBytesPerSecond()); + expected_network_params.set_max_bandwidth_timestamp_seconds( + bandwidth_recorder.MaxBandwidthTimestamp()); + expected_network_params.set_min_rtt_ms(session_->connection() + ->sent_packet_manager() + .GetRttStats() + ->min_rtt() + .ToMilliseconds()); + expected_network_params.set_previous_connection_state( + CachedNetworkParameters::CONGESTION_AVOIDANCE); + expected_network_params.set_timestamp( + session_->connection()->clock()->WallNow().ToUNIXSeconds()); + expected_network_params.set_serving_region(serving_region); + + if (quic_crypto_stream) { + EXPECT_CALL(*quic_crypto_stream, + SendServerConfigUpdate(EqualsProto(expected_network_params))) + .Times(1); + } else { + EXPECT_CALL(*tls_server_stream, + GetAddressToken(EqualsProto(expected_network_params))) + .WillOnce(testing::Return("Test address token")); + } + EXPECT_CALL(*connection_, OnSendConnectionState(_)).Times(1); } - EXPECT_CALL(*connection_, OnSendConnectionState(_)).Times(1); session_->OnCongestionWindowChange(now); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.h index f75874e28e5..79e49abd4be 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.h @@ -10,7 +10,6 @@ #include "absl/container/flat_hash_map.h" #include "quiche/quic/core/http/quic_spdy_session.h" #include "quiche/quic/core/quic_crypto_client_stream.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_export.h" namespace quic { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc index 14550db5393..e54c84616b4 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc @@ -74,7 +74,7 @@ class AlpsFrameDecoder : public HttpDecoder::Visitor { // HttpDecoder::Visitor implementation. void OnError(HttpDecoder* /*decoder*/) override {} - bool OnMaxPushIdFrame(const MaxPushIdFrame& /*frame*/) override { + bool OnMaxPushIdFrame() override { error_detail_ = "MAX_PUSH_ID frame forbidden"; return false; } @@ -318,8 +318,9 @@ class QuicSpdySession::SpdyFramerVisitor QUIC_INVALID_HEADERS_STREAM_DATA); } - void OnHeaders(SpdyStreamId stream_id, bool has_priority, int weight, - SpdyStreamId /* parent_stream_id */, bool /* exclusive */, + void OnHeaders(SpdyStreamId stream_id, size_t /*payload_length*/, + bool has_priority, int weight, + SpdyStreamId /*parent_stream_id*/, bool /*exclusive*/, bool fin, bool /*end*/) override { if (!session_->IsConnected()) { return; @@ -362,7 +363,8 @@ class QuicSpdySession::SpdyFramerVisitor session_->OnPushPromise(stream_id, promised_stream_id); } - void OnContinuation(SpdyStreamId /*stream_id*/, bool /*end*/) override {} + void OnContinuation(SpdyStreamId /*stream_id*/, size_t /*payload_size*/, + bool /*end*/) override {} void OnPriority(SpdyStreamId stream_id, SpdyStreamId /* parent_id */, int weight, bool /* exclusive */) override { @@ -516,15 +518,19 @@ void QuicSpdySession::FillSettingsFrame() { settings_.values[SETTINGS_MAX_FIELD_SECTION_SIZE] = max_inbound_header_list_size_; if (version().UsesHttp3()) { - HttpDatagramSupport local_http_datagram_support = - LocalHttpDatagramSupport(); - if (local_http_datagram_support == HttpDatagramSupport::kDraft00 || - local_http_datagram_support == HttpDatagramSupport::kDraft00And04) { - settings_.values[SETTINGS_H3_DATAGRAM_DRAFT00] = 1; - } - if (local_http_datagram_support == HttpDatagramSupport::kDraft04 || - local_http_datagram_support == HttpDatagramSupport::kDraft00And04) { - settings_.values[SETTINGS_H3_DATAGRAM_DRAFT04] = 1; + switch (LocalHttpDatagramSupport()) { + case HttpDatagramSupport::kNone: + break; + case HttpDatagramSupport::kDraft04: + settings_.values[SETTINGS_H3_DATAGRAM_DRAFT04] = 1; + break; + case HttpDatagramSupport::kDraft09: + settings_.values[SETTINGS_H3_DATAGRAM_DRAFT09] = 1; + break; + case HttpDatagramSupport::kDraft04And09: + settings_.values[SETTINGS_H3_DATAGRAM_DRAFT04] = 1; + settings_.values[SETTINGS_H3_DATAGRAM_DRAFT09] = 1; + break; } } if (WillNegotiateWebTransport()) { @@ -776,21 +782,12 @@ void QuicSpdySession::SendHttp3GoAway(QuicErrorCode error_code, stream_id = QuicUtils::GetMaxClientInitiatedBidirectionalStreamId( transport_version()); - if (last_sent_http3_goaway_id_.has_value()) { - if (last_sent_http3_goaway_id_.value() == stream_id) { - // Do not send GOAWAY twice. - return; - } - if (last_sent_http3_goaway_id_.value() < stream_id) { - // A previous GOAWAY frame was sent with smaller stream ID. This is not - // possible, because the only time a GOAWAY frame with non-maximal - // stream ID is sent is right before closing connection. - QUIC_BUG(quic_bug_10360_3) - << "Not sending GOAWAY frame with " << stream_id - << " because one with " << last_sent_http3_goaway_id_.value() - << " already sent on connection " << connection()->connection_id(); - return; - } + if (last_sent_http3_goaway_id_.has_value() && + last_sent_http3_goaway_id_.value() <= stream_id) { + // Do not send GOAWAY frame with a higher id, because it is forbidden. + // Do not send one with same stream id as before, since frames on the + // control stream are guaranteed to be processed in order. + return; } send_control_stream_->SendGoAway(stream_id); @@ -880,8 +877,6 @@ void QuicSpdySession::OnNewEncryptionKeyAvailable( bool QuicSpdySession::ShouldNegotiateWebTransport() { return false; } -bool QuicSpdySession::ShouldNegotiateDatagramContexts() { return false; } - bool QuicSpdySession::ShouldValidateWebTransportVersion() const { return true; } bool QuicSpdySession::WillNegotiateWebTransport() { @@ -1152,15 +1147,15 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) { absl::StrCat("received HTTP/2 specific setting in HTTP/3 session: ", id)); return false; - case SETTINGS_H3_DATAGRAM_DRAFT00: { + case SETTINGS_H3_DATAGRAM_DRAFT04: { HttpDatagramSupport local_http_datagram_support = LocalHttpDatagramSupport(); - if (local_http_datagram_support != HttpDatagramSupport::kDraft00 && - local_http_datagram_support != HttpDatagramSupport::kDraft00And04) { + if (local_http_datagram_support != HttpDatagramSupport::kDraft04 && + local_http_datagram_support != HttpDatagramSupport::kDraft04And09) { break; } QUIC_DVLOG(1) << ENDPOINT - << "SETTINGS_H3_DATAGRAM_DRAFT00 received with value " + << "SETTINGS_H3_DATAGRAM_DRAFT04 received with value " << value; if (!version().UsesHttp3()) { break; @@ -1168,21 +1163,21 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) { if (!VerifySettingIsZeroOrOne(id, value)) { return false; } - if (value && http_datagram_support_ != HttpDatagramSupport::kDraft04) { - // If both draft-00 and draft-04 are supported, use draft-04. - http_datagram_support_ = HttpDatagramSupport::kDraft00; + if (value && http_datagram_support_ != HttpDatagramSupport::kDraft09) { + // If both draft-04 and draft-09 are supported, use draft-09. + http_datagram_support_ = HttpDatagramSupport::kDraft04; } break; } - case SETTINGS_H3_DATAGRAM_DRAFT04: { + case SETTINGS_H3_DATAGRAM_DRAFT09: { HttpDatagramSupport local_http_datagram_support = LocalHttpDatagramSupport(); - if (local_http_datagram_support != HttpDatagramSupport::kDraft04 && - local_http_datagram_support != HttpDatagramSupport::kDraft00And04) { + if (local_http_datagram_support != HttpDatagramSupport::kDraft09 && + local_http_datagram_support != HttpDatagramSupport::kDraft04And09) { break; } QUIC_DVLOG(1) << ENDPOINT - << "SETTINGS_H3_DATAGRAM_DRAFT04 received with value " + << "SETTINGS_H3_DATAGRAM_DRAFT09 received with value " << value; if (!version().UsesHttp3()) { break; @@ -1191,7 +1186,7 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) { return false; } if (value) { - http_datagram_support_ = HttpDatagramSupport::kDraft04; + http_datagram_support_ = HttpDatagramSupport::kDraft09; } break; } @@ -1225,13 +1220,8 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) { QUIC_DVLOG(1) << ENDPOINT << "SETTINGS_HEADER_TABLE_SIZE received with value " << value; - if (GetQuicReloadableFlag(quic_limit_encoder_dynamic_table_size)) { - QUIC_RELOADABLE_FLAG_COUNT(quic_limit_encoder_dynamic_table_size); - spdy_framer_.UpdateHeaderEncoderTableSize( - std::min<uint64_t>(value, kHpackEncoderDynamicTableSizeLimit)); - break; - } - spdy_framer_.UpdateHeaderEncoderTableSize(value); + spdy_framer_.UpdateHeaderEncoderTableSize( + std::min<uint64_t>(value, kHpackEncoderDynamicTableSizeLimit)); break; case spdy::SETTINGS_ENABLE_PUSH: if (perspective() == Perspective::IS_SERVER) { @@ -1535,18 +1525,9 @@ void QuicSpdySession::BeforeConnectionCloseSent() { } if (last_sent_http3_goaway_id_.has_value() && last_sent_http3_goaway_id_.value() <= stream_id) { - // A previous GOAWAY frame was sent with smaller stream ID. This is not - // possible, because this is the only method sending a GOAWAY frame with - // non-maximal stream ID, and this must only be called once, right - // before closing connection. - QUIC_BUG(QuicGoawayFrameAlreadySent) - << "Not sending GOAWAY frame with " << stream_id << " because one with " - << last_sent_http3_goaway_id_.value() << " already sent on connection " - << connection()->connection_id(); - - // MUST not send GOAWAY with identifier larger than previously sent. - // Do not bother sending one with same identifier as before, since GOAWAY - // frames on the control stream are guaranteed to be processed in order. + // Do not send GOAWAY frame with a higher id, because it is forbidden. + // Do not send one with same stream id as before, since frames on the + // control stream are guaranteed to be processed in order. return; } @@ -1560,38 +1541,6 @@ void QuicSpdySession::OnCanCreateNewOutgoingStream(bool unidirectional) { } } -bool QuicSpdySession::OnMaxPushIdFrame(PushId max_push_id) { - QUICHE_DCHECK(VersionUsesHttp3(transport_version())); - QUICHE_DCHECK_EQ(Perspective::IS_SERVER, perspective()); - - if (max_push_id_.has_value()) { - QUIC_DVLOG(1) << "Setting max_push_id to: " << max_push_id - << " from: " << max_push_id_.value(); - } else { - QUIC_DVLOG(1) << "Setting max_push_id to: " << max_push_id - << " from unset"; - } - absl::optional<PushId> old_max_push_id = max_push_id_; - max_push_id_ = max_push_id; - - if (!old_max_push_id.has_value() || max_push_id > old_max_push_id.value()) { - OnCanCreateNewOutgoingStream(true); - return true; - } - - // Equal value is not considered an error. - if (max_push_id < old_max_push_id.value()) { - CloseConnectionWithDetails( - QUIC_HTTP_INVALID_MAX_PUSH_ID, - absl::StrCat("MAX_PUSH_ID received with value ", max_push_id, - " which is smaller that previously received value ", - old_max_push_id.value())); - return false; - } - - return true; -} - bool QuicSpdySession::goaway_received() const { return VersionUsesHttp3(transport_version()) ? last_received_http3_goaway_id_.has_value() @@ -1656,25 +1605,17 @@ void QuicSpdySession::LogHeaderCompressionRatioHistogram( } } -MessageStatus QuicSpdySession::SendHttp3Datagram( - QuicDatagramStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - absl::string_view payload) { +MessageStatus QuicSpdySession::SendHttp3Datagram(QuicStreamId stream_id, + absl::string_view payload) { if (!SupportsH3Datagram()) { QUIC_BUG(send http datagram too early) << "Refusing to send HTTP Datagram before SETTINGS received"; return MESSAGE_STATUS_INTERNAL_ERROR; } - uint64_t stream_id_to_write = stream_id; - if (http_datagram_support_ != HttpDatagramSupport::kDraft00) { - // Stream ID is sent divided by four as per the specification. - stream_id_to_write /= kHttpDatagramStreamIdDivisor; - } + // Stream ID is sent divided by four as per the specification. + uint64_t stream_id_to_write = stream_id / kHttpDatagramStreamIdDivisor; size_t slice_length = QuicDataWriter::GetVarInt62Len(stream_id_to_write) + payload.length(); - if (context_id.has_value()) { - slice_length += QuicDataWriter::GetVarInt62Len(context_id.value()); - } quiche::QuicheBuffer buffer( connection()->helper()->GetStreamSendBufferAllocator(), slice_length); QuicDataWriter writer(slice_length, buffer.data()); @@ -1683,13 +1624,6 @@ MessageStatus QuicSpdySession::SendHttp3Datagram( << "Failed to write HTTP/3 datagram stream ID"; return MESSAGE_STATUS_INTERNAL_ERROR; } - if (context_id.has_value()) { - if (!writer.WriteVarInt62(context_id.value())) { - QUIC_BUG(h3 datagram context ID write fail) - << "Failed to write HTTP/3 datagram context ID"; - return MESSAGE_STATUS_INTERNAL_ERROR; - } - } if (!writer.WriteBytes(payload.data(), payload.length())) { QUIC_BUG(h3 datagram payload write fail) << "Failed to write HTTP/3 datagram payload"; @@ -1707,16 +1641,6 @@ void QuicSpdySession::SetMaxDatagramTimeInQueueForStreamId( datagram_queue()->SetMaxTimeInQueue(max_time_in_queue); } -void QuicSpdySession::RegisterHttp3DatagramFlowId(QuicDatagramStreamId flow_id, - QuicStreamId stream_id) { - h3_datagram_flow_id_to_stream_id_map_[flow_id] = stream_id; -} - -void QuicSpdySession::UnregisterHttp3DatagramFlowId( - QuicDatagramStreamId flow_id) { - h3_datagram_flow_id_to_stream_id_map_.erase(flow_id); -} - void QuicSpdySession::OnMessageReceived(absl::string_view message) { QuicSession::OnMessageReceived(message); if (!SupportsH3Datagram()) { @@ -1729,35 +1653,24 @@ void QuicSpdySession::OnMessageReceived(absl::string_view message) { QUIC_DLOG(ERROR) << "Failed to parse stream ID in received HTTP/3 datagram"; return; } - if (http_datagram_support_ != HttpDatagramSupport::kDraft00) { - // Stream ID is sent divided by four as per the specification. - stream_id64 *= kHttpDatagramStreamIdDivisor; - } - if (perspective() == Perspective::IS_SERVER && - http_datagram_support_ == HttpDatagramSupport::kDraft00) { - auto it = h3_datagram_flow_id_to_stream_id_map_.find(stream_id64); - if (it == h3_datagram_flow_id_to_stream_id_map_.end()) { - QUIC_DLOG(INFO) << "Received unknown HTTP/3 datagram flow ID " - << stream_id64; - return; - } - stream_id64 = it->second; - } - if (stream_id64 > std::numeric_limits<QuicStreamId>::max()) { - // TODO(b/181256914) make this a connection close once we deprecate - // draft-ietf-masque-h3-datagram-00 in favor of later drafts. - QUIC_DLOG(ERROR) << "Received unexpectedly high HTTP/3 datagram stream ID " - << stream_id64; + // Stream ID is sent divided by four as per the specification. + if (stream_id64 > + std::numeric_limits<QuicStreamId>::max() / kHttpDatagramStreamIdDivisor) { + CloseConnectionWithDetails( + QUIC_HTTP_FRAME_ERROR, + absl::StrCat("Received HTTP Datagram with invalid quarter stream ID ", + stream_id64)); return; } + stream_id64 *= kHttpDatagramStreamIdDivisor; QuicStreamId stream_id = static_cast<QuicStreamId>(stream_id64); QuicSpdyStream* stream = static_cast<QuicSpdyStream*>(GetActiveStream(stream_id)); if (stream == nullptr) { QUIC_DLOG(INFO) << "Received HTTP/3 datagram for unknown stream ID " << stream_id; - // TODO(b/181256914) buffer unknown HTTP/3 datagram flow IDs for a short - // period of time in case they were reordered. + // TODO(b/181256914) buffer HTTP/3 datagrams with unknown stream IDs for a + // short period of time in case they were reordered. return; } stream->OnDatagramReceived(&reader); @@ -1909,12 +1822,12 @@ std::string HttpDatagramSupportToString( switch (http_datagram_support) { case HttpDatagramSupport::kNone: return "None"; - case HttpDatagramSupport::kDraft00: - return "Draft00"; case HttpDatagramSupport::kDraft04: return "Draft04"; - case HttpDatagramSupport::kDraft00And04: - return "Draft00And04"; + case HttpDatagramSupport::kDraft09: + return "Draft09"; + case HttpDatagramSupport::kDraft04And09: + return "Draft04And09"; } return absl::StrCat("Unknown(", static_cast<int>(http_datagram_support), ")"); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h index b6038030930..f1173280d9c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h @@ -31,7 +31,6 @@ #include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/common/quiche_circular_deque.h" #include "quiche/spdy/core/http2_frame_decoder_adapter.h" @@ -81,8 +80,6 @@ class QUIC_EXPORT_PRIVATE Http3DebugVisitor { // Incoming HTTP/3 frames on the control stream. virtual void OnSettingsFrameReceived(const SettingsFrame& /*frame*/) = 0; virtual void OnGoAwayFrameReceived(const GoAwayFrame& /*frame*/) {} - // TODO(b/171463363): Remove. - virtual void OnMaxPushIdFrameReceived(const MaxPushIdFrame& /*frame*/) {} virtual void OnPriorityUpdateFrameReceived( const PriorityUpdateFrame& /*frame*/) {} virtual void OnAcceptChFrameReceived(const AcceptChFrame& /*frame*/) {} @@ -121,10 +118,10 @@ class QUIC_EXPORT_PRIVATE Http3DebugVisitor { // Whether draft-ietf-masque-h3-datagram is supported on this session and if so // which draft is currently in use. enum class HttpDatagramSupport : uint8_t { - kNone = 0, // HTTP Datagrams are not supported for this session. - kDraft00 = 1, - kDraft04 = 2, - kDraft00And04 = 3, // only used locally, we only negotiate one draft. + kNone, // HTTP Datagrams are not supported for this session. + kDraft04, + kDraft09, + kDraft04And09, // Only used locally for sending, we only negotiate one draft. }; QUIC_EXPORT_PRIVATE std::string HttpDatagramSupportToString( @@ -322,14 +319,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession // those streams are not initialized yet. void OnCanCreateNewOutgoingStream(bool unidirectional) override; - // Sets |max_push_id_|. - // This method must only be called if protocol is IETF QUIC and perspective is - // server. It must only be called if a MAX_PUSH_ID frame is received. - // Returns whether |max_push_id| is greater than or equal to current - // |max_push_id_|. - // TODO(b/171463363): Remove. - bool OnMaxPushIdFrame(PushId max_push_id); - int32_t destruction_indicator() const { return destruction_indicator_; } void set_debug_visitor(Http3DebugVisitor* debug_visitor) { @@ -389,19 +378,11 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession } // This must not be used except by QuicSpdyStream::SendHttp3Datagram. - MessageStatus SendHttp3Datagram( - QuicDatagramStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - absl::string_view payload); + MessageStatus SendHttp3Datagram(QuicStreamId stream_id, + absl::string_view payload); // This must not be used except by QuicSpdyStream::SetMaxDatagramTimeInQueue. void SetMaxDatagramTimeInQueueForStreamId(QuicStreamId stream_id, QuicTime::Delta max_time_in_queue); - // This must not be used except by - // QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders. - void RegisterHttp3DatagramFlowId(QuicDatagramStreamId flow_id, - QuicStreamId stream_id); - // This must not be used except by QuicSpdyStream::OnClose. - void UnregisterHttp3DatagramFlowId(QuicDatagramStreamId flow_id); // Override from QuicSession to support HTTP/3 datagrams. void OnMessageReceived(absl::string_view message) override; @@ -462,10 +443,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession QuicSpdyStream* GetOrCreateSpdyDataStream(const QuicStreamId stream_id); - // Indicates whether we will try to negotiate datagram contexts on newly - // created WebTransport sessions over HTTP/3. - virtual bool ShouldNegotiateDatagramContexts(); - // Indicates whether the client should check that the // `Sec-Webtransport-Http3-Draft` header is valid. // TODO(vasilvv): remove this once this is enabled in Chromium. @@ -538,6 +515,12 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession // in settings and accept remote settings for. virtual HttpDatagramSupport LocalHttpDatagramSupport(); + // Sends any data which should be sent at the start of a connection, including + // the initial SETTINGS frame. When using 0-RTT, this method is called twice: + // once when encryption is established, and again when 1-RTT keys are + // available. + void SendInitialData(); + private: friend class test::QuicSpdySessionPeer; @@ -572,13 +555,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession void CloseConnectionOnDuplicateHttp3UnidirectionalStreams( absl::string_view type); - // Sends any data which should be sent at the start of a connection, including - // the initial SETTINGS frame, and (when IETF QUIC is used) also a MAX_PUSH_ID - // frame if SetMaxPushId() had been called before encryption was established. - // When using 0-RTT, this method is called twice: once when encryption is - // established, and again when 1-RTT keys are available. - void SendInitialData(); - void FillSettingsFrame(); bool VerifySettingIsZeroOrOne(uint64_t id, uint64_t value); @@ -637,20 +613,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession http2::Http2DecoderAdapter h2_deframer_; std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_; - // Used in IETF QUIC only. - // For a server: - // the push ID in the most recently received MAX_PUSH_ID frame, - // or unset if no MAX_PUSH_ID frame has been received. - // For a client: - // unset until SetMaxPushId() is called; - // before encryption is established, the push ID to be sent in the initial - // MAX_PUSH_ID frame; - // after encryption is established, the push ID in the most recently sent - // MAX_PUSH_ID frame. - // Once set, never goes back to unset. - // TODO(b/171463363): Remove. - absl::optional<PushId> max_push_id_; - // Not owned by the session. Http3DebugVisitor* debug_visitor_; @@ -677,12 +639,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession // Whether the peer has indicated WebTransport support. bool peer_supports_webtransport_ = false; - // This maps from draft-ietf-masque-h3-datagram-00 flow IDs to stream IDs. - // TODO(b/181256914) remove this when we deprecate support for that draft in - // favor of more recent ones. - absl::flat_hash_map<uint64_t, QuicStreamId> - h3_datagram_flow_id_to_stream_id_map_; - // Whether any settings have been received, either from the peer or from a // session ticket. bool any_settings_received_ = false; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session_test.cc index b5e895abc6a..4cfb5b72fa5 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session_test.cc @@ -195,11 +195,29 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker { void OnConnectionClosed(QuicErrorCode /*error*/, ConnectionCloseSource /*source*/) override {} SSL* GetSsl() const override { return nullptr; } + bool IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const override { + return level != ENCRYPTION_ZERO_RTT; + } + EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const override { + switch (space) { + case INITIAL_DATA: + return ENCRYPTION_INITIAL; + case HANDSHAKE_DATA: + return ENCRYPTION_HANDSHAKE; + case APPLICATION_DATA: + return ENCRYPTION_FORWARD_SECURE; + default: + QUICHE_DCHECK(false); + return NUM_ENCRYPTION_LEVELS; + } + } bool ExportKeyingMaterial(absl::string_view /*label*/, absl::string_view /*context*/, - size_t /*result_len*/, - std::string* /*result*/) override { + size_t /*result_len*/, std::string* + /*result*/) override { return false; } @@ -502,29 +520,6 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> { return std::string(priority_buffer.get(), priority_frame_length); } - // TODO(b/171463363): Remove. - std::string SerializeMaxPushIdFrame(PushId push_id) { - const QuicByteCount payload_length = - QuicDataWriter::GetVarInt62Len(push_id); - - const QuicByteCount total_length = - QuicDataWriter::GetVarInt62Len( - static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID)) + - QuicDataWriter::GetVarInt62Len(payload_length) + - QuicDataWriter::GetVarInt62Len(push_id); - - std::string max_push_id_frame(total_length, '\0'); - QuicDataWriter writer(total_length, &*max_push_id_frame.begin()); - - QUICHE_CHECK(writer.WriteVarInt62( - static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID))); - QUICHE_CHECK(writer.WriteVarInt62(payload_length)); - QUICHE_CHECK(writer.WriteVarInt62(push_id)); - QUICHE_CHECK_EQ(0u, writer.remaining()); - - return max_push_id_frame; - } - QuicStreamId StreamCountToId(QuicStreamCount stream_count, Perspective perspective, bool bidirectional) { // Calculate and build up stream ID rather than use @@ -587,16 +582,8 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> { headers.OnHeaderBlockStart(); headers.OnHeader(":method", "CONNECT"); headers.OnHeader(":protocol", "webtransport"); - if (session_.http_datagram_support() == HttpDatagramSupport::kDraft00) { - headers.OnHeader("datagram-flow-id", absl::StrCat(session_id)); - } else { - headers.OnHeader("sec-webtransport-http3-draft02", "1"); - } + headers.OnHeader("sec-webtransport-http3-draft02", "1"); stream->OnStreamHeaderList(/*fin=*/true, 0, headers); - if (session_.http_datagram_support() != HttpDatagramSupport::kDraft00) { - stream->OnCapsule( - Capsule::RegisterDatagramNoContext(DatagramFormatType::WEBTRANSPORT)); - } WebTransportHttp3* web_transport = session_.GetWebTransportSession(session_id); ASSERT_TRUE(web_transport != nullptr); @@ -1327,8 +1314,7 @@ TEST_P(QuicSpdySessionTestServer, Http3GoAwayLargerIdThanBefore) { } EXPECT_FALSE(session_.goaway_received()); - PushId push_id1 = 0; - session_.OnHttp3GoAway(push_id1); + session_.OnHttp3GoAway(/* id = */ 0); EXPECT_TRUE(session_.goaway_received()); EXPECT_CALL( @@ -1337,8 +1323,7 @@ TEST_P(QuicSpdySessionTestServer, Http3GoAwayLargerIdThanBefore) { QUIC_HTTP_GOAWAY_ID_LARGER_THAN_PREVIOUS, "GOAWAY received with ID 1 greater than previously received ID 0", _)); - PushId push_id2 = 1; - session_.OnHttp3GoAway(push_id2); + session_.OnHttp3GoAway(/* id = */ 1); } // Test that server session will send a connectivity probe in response to a @@ -1819,60 +1804,6 @@ TEST_P(QuicSpdySessionTestServer, DrainingStreamsDoNotCountAsOpened) { } } -// TODO(b/171463363): Remove. -TEST_P(QuicSpdySessionTestServer, ReduceMaxPushId) { - if (GetQuicReloadableFlag(quic_ignore_max_push_id)) { - return; - } - - if (!VersionUsesHttp3(transport_version())) { - return; - } - - StrictMock<MockHttp3DebugVisitor> debug_visitor; - session_.set_debug_visitor(&debug_visitor); - - // Use an arbitrary stream id for incoming control stream. - QuicStreamId stream_id = - GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3); - char type[] = {kControlStream}; - absl::string_view stream_type(type, 1); - - QuicStreamOffset offset = 0; - QuicStreamFrame data1(stream_id, false, offset, stream_type); - offset += stream_type.length(); - EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(stream_id)); - session_.OnStreamFrame(data1); - EXPECT_EQ(stream_id, - QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id()); - - SettingsFrame settings; - std::string settings_frame = EncodeSettings(settings); - QuicStreamFrame data2(stream_id, false, offset, settings_frame); - offset += settings_frame.length(); - - EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(settings)); - session_.OnStreamFrame(data2); - - std::string max_push_id_frame1 = SerializeMaxPushIdFrame(/* push_id = */ 3); - QuicStreamFrame data3(stream_id, false, offset, max_push_id_frame1); - offset += max_push_id_frame1.length(); - - EXPECT_CALL(debug_visitor, OnMaxPushIdFrameReceived(_)); - session_.OnStreamFrame(data3); - - std::string max_push_id_frame2 = SerializeMaxPushIdFrame(/* push_id = */ 1); - QuicStreamFrame data4(stream_id, false, offset, max_push_id_frame2); - - EXPECT_CALL(debug_visitor, OnMaxPushIdFrameReceived(_)); - EXPECT_CALL(*connection_, - CloseConnection(QUIC_HTTP_INVALID_MAX_PUSH_ID, - "MAX_PUSH_ID received with value 1 which is " - "smaller that previously received value 3", - _)); - session_.OnStreamFrame(data4); -} - class QuicSpdySessionTestClient : public QuicSpdySessionTestBase { protected: QuicSpdySessionTestClient() @@ -2251,7 +2182,7 @@ TEST_P(QuicSpdySessionTestServer, RetransmitFrames) { EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _, _)) .WillOnce(Return(true)); EXPECT_CALL(*send_algorithm, OnApplicationLimited(_)); - session_.RetransmitFrames(frames, TLP_RETRANSMISSION); + session_.RetransmitFrames(frames, PTO_RETRANSMISSION); } TEST_P(QuicSpdySessionTestServer, OnPriorityFrame) { @@ -2748,11 +2679,13 @@ TEST_P(QuicSpdySessionTestClient, DuplicateHttp3UnidirectionalStreams) { GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 1); QuicStreamFrame data2(id2, false, 0, absl::string_view(type1, 1)); EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(id2)).Times(0); - EXPECT_CALL(*connection_, - CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM, - "Control stream is received twice.", _)); EXPECT_QUIC_PEER_BUG( - session_.OnStreamFrame(data2), + { + EXPECT_CALL(*connection_, + CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM, + "Control stream is received twice.", _)); + session_.OnStreamFrame(data2); + }, "Received a duplicate Control stream: Closing connection."); QuicStreamId id3 = @@ -2767,11 +2700,14 @@ TEST_P(QuicSpdySessionTestClient, DuplicateHttp3UnidirectionalStreams) { GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 3); QuicStreamFrame data4(id4, false, 0, absl::string_view(type2, 1)); EXPECT_CALL(debug_visitor, OnPeerQpackEncoderStreamCreated(id4)).Times(0); - EXPECT_CALL(*connection_, - CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM, - "QPACK encoder stream is received twice.", _)); EXPECT_QUIC_PEER_BUG( - session_.OnStreamFrame(data4), + { + EXPECT_CALL( + *connection_, + CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM, + "QPACK encoder stream is received twice.", _)); + session_.OnStreamFrame(data4); + }, "Received a duplicate QPACK encoder stream: Closing connection."); QuicStreamId id5 = @@ -2786,11 +2722,14 @@ TEST_P(QuicSpdySessionTestClient, DuplicateHttp3UnidirectionalStreams) { GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 5); QuicStreamFrame data6(id6, false, 0, absl::string_view(type3, 1)); EXPECT_CALL(debug_visitor, OnPeerQpackDecoderStreamCreated(id6)).Times(0); - EXPECT_CALL(*connection_, - CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM, - "QPACK decoder stream is received twice.", _)); EXPECT_QUIC_PEER_BUG( - session_.OnStreamFrame(data6), + { + EXPECT_CALL( + *connection_, + CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM, + "QPACK decoder stream is received twice.", _)); + session_.OnStreamFrame(data6); + }, "Received a duplicate QPACK decoder stream: Closing connection."); } @@ -3454,15 +3393,15 @@ void QuicSpdySessionTestBase::TestHttpDatagramSetting( switch (remote_support) { case HttpDatagramSupport::kNone: break; - case HttpDatagramSupport::kDraft00: - settings.values[SETTINGS_H3_DATAGRAM_DRAFT00] = 1; - break; case HttpDatagramSupport::kDraft04: settings.values[SETTINGS_H3_DATAGRAM_DRAFT04] = 1; break; - case HttpDatagramSupport::kDraft00And04: - settings.values[SETTINGS_H3_DATAGRAM_DRAFT00] = 1; + case HttpDatagramSupport::kDraft09: + settings.values[SETTINGS_H3_DATAGRAM_DRAFT09] = 1; + break; + case HttpDatagramSupport::kDraft04And09: settings.values[SETTINGS_H3_DATAGRAM_DRAFT04] = 1; + settings.values[SETTINGS_H3_DATAGRAM_DRAFT09] = 1; break; } std::string data = std::string(1, kControlStream) + EncodeSettings(settings); @@ -3478,84 +3417,83 @@ void QuicSpdySessionTestBase::TestHttpDatagramSetting( EXPECT_EQ(session_.SupportsH3Datagram(), expected_datagram_supported); } -TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal00Remote00) { +TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal04Remote04) { TestHttpDatagramSetting( - /*local_support=*/HttpDatagramSupport::kDraft00, - /*remote_support=*/HttpDatagramSupport::kDraft00, - /*expected_support=*/HttpDatagramSupport::kDraft00, + /*local_support=*/HttpDatagramSupport::kDraft04, + /*remote_support=*/HttpDatagramSupport::kDraft04, + /*expected_support=*/HttpDatagramSupport::kDraft04, /*expected_datagram_supported=*/true); } -TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal00Remote04) { +TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal04Remote09) { TestHttpDatagramSetting( - /*local_support=*/HttpDatagramSupport::kDraft00, - /*remote_support=*/HttpDatagramSupport::kDraft04, + /*local_support=*/HttpDatagramSupport::kDraft04, + /*remote_support=*/HttpDatagramSupport::kDraft09, /*expected_support=*/HttpDatagramSupport::kNone, /*expected_datagram_supported=*/false); } -TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal00Remote00And04) { +TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal04Remote04And09) { TestHttpDatagramSetting( - /*local_support=*/HttpDatagramSupport::kDraft00, - /*remote_support=*/HttpDatagramSupport::kDraft00And04, - /*expected_support=*/HttpDatagramSupport::kDraft00, + /*local_support=*/HttpDatagramSupport::kDraft04, + /*remote_support=*/HttpDatagramSupport::kDraft04And09, + /*expected_support=*/HttpDatagramSupport::kDraft04, /*expected_datagram_supported=*/true); } -TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal04Remote00) { +TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal09Remote04) { TestHttpDatagramSetting( - /*local_support=*/HttpDatagramSupport::kDraft04, - /*remote_support=*/HttpDatagramSupport::kDraft00, + /*local_support=*/HttpDatagramSupport::kDraft09, + /*remote_support=*/HttpDatagramSupport::kDraft04, /*expected_support=*/HttpDatagramSupport::kNone, /*expected_datagram_supported=*/false); } -TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal04Remote04) { +TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal09Remote09) { TestHttpDatagramSetting( - /*local_support=*/HttpDatagramSupport::kDraft04, - /*remote_support=*/HttpDatagramSupport::kDraft04, - /*expected_support=*/HttpDatagramSupport::kDraft04, + /*local_support=*/HttpDatagramSupport::kDraft09, + /*remote_support=*/HttpDatagramSupport::kDraft09, + /*expected_support=*/HttpDatagramSupport::kDraft09, /*expected_datagram_supported=*/true); } -TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal04Remote00And04) { +TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal09Remote04And09) { TestHttpDatagramSetting( - /*local_support=*/HttpDatagramSupport::kDraft04, - /*remote_support=*/HttpDatagramSupport::kDraft00And04, - /*expected_support=*/HttpDatagramSupport::kDraft04, + /*local_support=*/HttpDatagramSupport::kDraft09, + /*remote_support=*/HttpDatagramSupport::kDraft04And09, + /*expected_support=*/HttpDatagramSupport::kDraft09, /*expected_datagram_supported=*/true); } -TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal00And04Remote00) { +TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal04And09Remote04) { TestHttpDatagramSetting( - /*local_support=*/HttpDatagramSupport::kDraft00And04, - /*remote_support=*/HttpDatagramSupport::kDraft00, - /*expected_support=*/HttpDatagramSupport::kDraft00, + /*local_support=*/HttpDatagramSupport::kDraft04And09, + /*remote_support=*/HttpDatagramSupport::kDraft04, + /*expected_support=*/HttpDatagramSupport::kDraft04, /*expected_datagram_supported=*/true); } -TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal00And04Remote04) { +TEST_P(QuicSpdySessionTestClient, HttpDatagramSettingLocal04And09Remote09) { TestHttpDatagramSetting( - /*local_support=*/HttpDatagramSupport::kDraft00And04, - /*remote_support=*/HttpDatagramSupport::kDraft04, - /*expected_support=*/HttpDatagramSupport::kDraft04, + /*local_support=*/HttpDatagramSupport::kDraft04And09, + /*remote_support=*/HttpDatagramSupport::kDraft09, + /*expected_support=*/HttpDatagramSupport::kDraft09, /*expected_datagram_supported=*/true); } TEST_P(QuicSpdySessionTestClient, - HttpDatagramSettingLocal00And04Remote00And04) { + HttpDatagramSettingLocal04And09Remote04And09) { TestHttpDatagramSetting( - /*local_support=*/HttpDatagramSupport::kDraft00And04, - /*remote_support=*/HttpDatagramSupport::kDraft00And04, - /*expected_support=*/HttpDatagramSupport::kDraft04, + /*local_support=*/HttpDatagramSupport::kDraft04And09, + /*remote_support=*/HttpDatagramSupport::kDraft04And09, + /*expected_support=*/HttpDatagramSupport::kDraft09, /*expected_datagram_supported=*/true); } - TEST_P(QuicSpdySessionTestClient, WebTransportSetting) { if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); session_.set_supports_webtransport(true); EXPECT_FALSE(session_.SupportsWebTransport()); @@ -3578,7 +3516,7 @@ TEST_P(QuicSpdySessionTestClient, WebTransportSettingSetToZero) { if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); session_.set_supports_webtransport(true); EXPECT_FALSE(session_.SupportsWebTransport()); @@ -3608,7 +3546,7 @@ TEST_P(QuicSpdySessionTestServer, WebTransportSetting) { if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); session_.set_supports_webtransport(true); EXPECT_FALSE(session_.SupportsWebTransport()); @@ -3625,7 +3563,7 @@ TEST_P(QuicSpdySessionTestServer, BufferingIncomingStreams) { if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); session_.set_supports_webtransport(true); CompleteHandshake(); @@ -3658,7 +3596,7 @@ TEST_P(QuicSpdySessionTestServer, BufferingIncomingStreamsLimit) { if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); session_.set_supports_webtransport(true); CompleteHandshake(); @@ -3699,7 +3637,7 @@ TEST_P(QuicSpdySessionTestServer, ResetOutgoingWebTransportStreams) { if (!version().UsesHttp3()) { return; } - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); session_.set_supports_webtransport(true); CompleteHandshake(); @@ -3736,7 +3674,7 @@ TEST_P(QuicSpdySessionTestClient, WebTransportWithoutExtendedConnect) { } SetQuicReloadableFlag(quic_verify_request_headers_2, true); SetQuicReloadableFlag(quic_act_upon_invalid_header, true); - session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_.set_local_http_datagram_support(HttpDatagramSupport::kDraft04); session_.set_supports_webtransport(true); EXPECT_FALSE(session_.SupportsWebTransport()); @@ -3757,7 +3695,7 @@ TEST_P(QuicSpdySessionTestClient, WebTransportWithoutExtendedConnect) { EXPECT_TRUE(session_.SupportsWebTransport()); } -// Regression bug for b/208997000. +// Regression test for b/208997000. TEST_P(QuicSpdySessionTestClient, LimitEncoderDynamicTableSize) { if (version().UsesHttp3()) { return; @@ -3788,43 +3726,25 @@ TEST_P(QuicSpdySessionTestClient, LimitEncoderDynamicTableSize) { QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer)->slice; absl::string_view stream_data(slice.data(), slice.length()); - if (GetQuicReloadableFlag(quic_limit_encoder_dynamic_table_size)) { - EXPECT_EQ(absl::HexStringToBytes( - "000009" // frame length - "01" // frame type HEADERS - "25"), // flags END_STREAM | END_HEADERS | PRIORITY - stream_data.substr(0, 5)); - stream_data.remove_prefix(5); - } else { - EXPECT_EQ(absl::HexStringToBytes( - "00000c" // frame length - "01" // frame type HEADERS - "25"), // flags END_STREAM | END_HEADERS | PRIORITY - stream_data.substr(0, 5)); - stream_data.remove_prefix(5); - } + EXPECT_EQ(absl::HexStringToBytes( + "000009" // frame length + "01" // frame type HEADERS + "25"), // flags END_STREAM | END_HEADERS | PRIORITY + stream_data.substr(0, 5)); + stream_data.remove_prefix(5); // Ignore stream ID as it might differ between QUIC versions. stream_data.remove_prefix(4); - // Ignore stream dependency and weight. EXPECT_EQ(absl::HexStringToBytes("00000000" // stream dependency "92"), // stream weight stream_data.substr(0, 5)); stream_data.remove_prefix(5); - if (GetQuicReloadableFlag(quic_limit_encoder_dynamic_table_size)) { - EXPECT_EQ(absl::HexStringToBytes( - "3fe17f" // Dynamic Table Size Update to 16384 - "82"), // Indexed Header Field Representation with index 2 - stream_data); - } else { - EXPECT_EQ( - absl::HexStringToBytes( - "3fe1ffffff03" // Dynamic Table Size Update to 1024 * 1024 * 1024 - "82"), // Indexed Header Field Representation with index 2 - stream_data); - } + EXPECT_EQ(absl::HexStringToBytes( + "3fe17f" // Dynamic Table Size Update to 16384 + "82"), // Indexed Header Field Representation with index 2 + stream_data); } class QuicSpdySessionTestServerNoExtendedConnect @@ -3878,10 +3798,12 @@ TEST_P(QuicSpdySessionTestServerNoExtendedConnect, BadExtendedConnectSetting) { ? GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3) : GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 3); QuicStreamFrame frame(control_stream_id, /*fin=*/false, /*offset=*/0, data); - EXPECT_CALL(*connection_, - CloseConnection(QUIC_HTTP_INVALID_SETTING_VALUE, _, _)); EXPECT_QUIC_PEER_BUG( - session_.OnStreamFrame(frame), + { + EXPECT_CALL(*connection_, + CloseConnection(QUIC_HTTP_INVALID_SETTING_VALUE, _, _)); + session_.OnStreamFrame(frame); + }, "Received SETTINGS_ENABLE_CONNECT_PROTOCOL with invalid value"); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc index 82077cd9869..10d76afb171 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc @@ -53,7 +53,7 @@ class QuicSpdyStream::HttpDecoderVisitor : public HttpDecoder::Visitor { stream_->OnUnrecoverableError(decoder->error(), decoder->error_detail()); } - bool OnMaxPushIdFrame(const MaxPushIdFrame& /*frame*/) override { + bool OnMaxPushIdFrame() override { CloseConnectionOnWrongFrame("Max Push Id"); return false; } @@ -193,11 +193,7 @@ QuicSpdyStream::QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session, sequencer_offset_(0), is_decoder_processing_input_(false), ack_listener_(nullptr), - last_sent_urgency_(kDefaultUrgency), - datagram_next_available_context_id_(spdy_session->perspective() == - Perspective::IS_SERVER - ? kFirstDatagramContextIdServer - : kFirstDatagramContextIdClient) { + last_sent_urgency_(kDefaultUrgency) { QUICHE_DCHECK_EQ(session()->connection(), spdy_session->connection()); QUICHE_DCHECK_EQ(transport_version(), spdy_session->transport_version()); QUICHE_DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id)); @@ -253,13 +249,6 @@ QuicSpdyStream::QuicSpdyStream(PendingStream* pending, QuicSpdyStream::~QuicSpdyStream() {} -bool QuicSpdyStream::ShouldUseDatagramContexts() const { - return spdy_session_->SupportsH3Datagram() && - spdy_session_->http_datagram_support() != - HttpDatagramSupport::kDraft00 && - use_datagram_contexts_; -} - size_t QuicSpdyStream::WriteHeaders( SpdyHeaderBlock header_block, bool fin, quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> @@ -288,14 +277,7 @@ size_t QuicSpdyStream::WriteHeaders( MaybeProcessSentWebTransportHeaders(header_block); - if (ShouldUseDatagramContexts()) { - // RegisterHttp3DatagramRegistrationVisitor caller wishes to use contexts, - // inform the peer. - header_block["sec-use-datagram-contexts"] = "?1"; - } - if (web_transport_ != nullptr && - spdy_session_->http_datagram_support() != HttpDatagramSupport::kDraft00 && spdy_session_->perspective() == Perspective::IS_SERVER) { header_block["sec-webtransport-http3-draft"] = "draft02"; } @@ -313,11 +295,21 @@ size_t QuicSpdyStream::WriteHeaders( if (web_transport_ != nullptr && session()->perspective() == Perspective::IS_CLIENT) { - // This will send a capsule and therefore needs to happen after headers have - // been sent. - RegisterHttp3DatagramContextId( - web_transport_->context_id(), DatagramFormatType::WEBTRANSPORT, - /*format_additional_data=*/absl::string_view(), web_transport_.get()); + WriteGreaseCapsule(); + if (spdy_session_->http_datagram_support() == + HttpDatagramSupport::kDraft04) { + // Send a REGISTER_DATAGRAM_NO_CONTEXT capsule to support servers that + // are running draft-ietf-masque-h3-datagram-04 or -05. + uint64_t capsule_type = 0xff37a2; // REGISTER_DATAGRAM_NO_CONTEXT + constexpr unsigned char capsule_data[4] = { + 0x80, 0xff, 0x7c, 0x00, // WEBTRANSPORT datagram format type + }; + WriteCapsule(Capsule::Unknown( + capsule_type, + absl::string_view(reinterpret_cast<const char*>(capsule_data), + sizeof(capsule_data)))); + WriteGreaseCapsule(); + } } return bytes_written; @@ -654,19 +646,6 @@ void QuicSpdyStream::OnInitialHeadersComplete( if (!GetQuicReloadableFlag(quic_verify_request_headers_2) || !header_too_large) { MaybeProcessReceivedWebTransportHeaders(); - if (ShouldUseDatagramContexts()) { - bool peer_wishes_to_use_datagram_contexts = false; - for (const auto& header : header_list_) { - if (header.first == "sec-use-datagram-contexts" && - header.second == "?1") { - peer_wishes_to_use_datagram_contexts = true; - break; - } - } - if (!peer_wishes_to_use_datagram_contexts) { - use_datagram_contexts_ = false; - } - } } if (VersionUsesHttp3(transport_version())) { @@ -775,18 +754,20 @@ void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) { return; } - if (GetQuicReloadableFlag(quic_fix_on_stream_reset) && - VersionUsesHttp3(transport_version())) { - QUIC_RELOADABLE_FLAG_COUNT(quic_fix_on_stream_reset); - 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; - } + if (VersionUsesHttp3(transport_version())) { + QUIC_CODE_COUNT(quic_fix_on_stream_reset); + if (GetQuicReloadableFlag(quic_fix_on_stream_reset)) { + QUIC_RELOADABLE_FLAG_COUNT(quic_fix_on_stream_reset); + 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); - return; + QuicStream::OnStreamReset(frame); + return; + } } QUIC_DVLOG(1) << ENDPOINT @@ -920,10 +901,6 @@ void QuicSpdyStream::OnClose() { visitor->OnClose(this); } - if (datagram_flow_id_.has_value()) { - spdy_session_->UnregisterHttp3DatagramFlowId(datagram_flow_id_.value()); - } - if (web_transport_ != nullptr) { web_transport_->OnConnectStreamClosing(); } @@ -1275,8 +1252,6 @@ void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() { std::string method; std::string protocol; - absl::optional<QuicDatagramStreamId> flow_id; - bool version_indicated = false; for (const auto& [header_name, header_value] : header_list_) { if (header_name == ":method") { if (!method.empty() || header_value.empty()) { @@ -1291,21 +1266,10 @@ void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() { protocol = header_value; } if (header_name == "datagram-flow-id") { - if (spdy_session_->http_datagram_support() != - HttpDatagramSupport::kDraft00) { - QUIC_DLOG(ERROR) << ENDPOINT - << "Rejecting WebTransport due to unexpected " - "Datagram-Flow-Id header"; - return; - } - if (flow_id.has_value() || header_value.empty()) { - return; - } - QuicDatagramStreamId flow_id_out; - if (!absl::SimpleAtoi(header_value, &flow_id_out)) { - return; - } - flow_id = flow_id_out; + QUIC_DLOG(ERROR) << ENDPOINT + << "Rejecting WebTransport due to unexpected " + "Datagram-Flow-Id header"; + return; } if (header_name == "sec-webtransport-http3-draft02") { if (header_value != "1") { @@ -1314,7 +1278,6 @@ void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() { "Sec-Webtransport-Http3-Draft02 header"; return; } - version_indicated = true; } } @@ -1322,38 +1285,8 @@ void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() { return; } - if (!version_indicated && - spdy_session_->http_datagram_support() != HttpDatagramSupport::kDraft00) { - QUIC_DLOG(ERROR) - << ENDPOINT - << "WebTransport request rejected due to missing version header."; - return; - } - - if (spdy_session_->http_datagram_support() == HttpDatagramSupport::kDraft00) { - if (!flow_id.has_value()) { - QUIC_DLOG(ERROR) - << ENDPOINT - << "Rejecting WebTransport due to missing Datagram-Flow-Id header"; - return; - } - RegisterHttp3DatagramFlowId(*flow_id); - } - - web_transport_ = std::make_unique<WebTransportHttp3>( - spdy_session_, this, id(), - spdy_session_->ShouldNegotiateDatagramContexts()); - - if (spdy_session_->http_datagram_support() != HttpDatagramSupport::kDraft00) { - return; - } - // If we're in draft-ietf-masque-h3-datagram-00 mode, pretend we also received - // a REGISTER_DATAGRAM_NO_CONTEXT capsule. - // TODO(b/181256914) remove this when we remove support for - // draft-ietf-masque-h3-datagram-00 in favor of later drafts. - RegisterHttp3DatagramContextId( - /*context_id=*/absl::nullopt, DatagramFormatType::WEBTRANSPORT, - /*format_additional_data=*/absl::string_view(), web_transport_.get()); + web_transport_ = + std::make_unique<WebTransportHttp3>(spdy_session_, this, id()); } void QuicSpdyStream::MaybeProcessSentWebTransportHeaders( @@ -1375,15 +1308,10 @@ void QuicSpdyStream::MaybeProcessSentWebTransportHeaders( return; } - if (spdy_session_->http_datagram_support() == HttpDatagramSupport::kDraft00) { - headers["datagram-flow-id"] = absl::StrCat(id()); - } else { - headers["sec-webtransport-http3-draft02"] = "1"; - } + headers["sec-webtransport-http3-draft02"] = "1"; - web_transport_ = std::make_unique<WebTransportHttp3>( - spdy_session_, this, id(), - spdy_session_->ShouldNegotiateDatagramContexts()); + web_transport_ = + std::make_unique<WebTransportHttp3>(spdy_session_, this, id()); } void QuicSpdyStream::OnCanWriteNewData() { @@ -1443,28 +1371,12 @@ QuicSpdyStream::WebTransportDataStream::WebTransportDataStream( : session_id(session_id), adapter(stream->spdy_session_, stream, stream->sequencer()) {} -void QuicSpdyStream::HandleReceivedDatagram( - absl::optional<QuicDatagramContextId> context_id, - absl::string_view payload) { - Http3DatagramVisitor* visitor; - if (context_id.has_value()) { - auto it = datagram_context_visitors_.find(context_id.value()); - if (it == datagram_context_visitors_.end()) { - QUIC_DLOG(ERROR) << ENDPOINT - << "Received datagram without any visitor for context " - << context_id.value(); - return; - } - visitor = it->second; - } else { - if (datagram_no_context_visitor_ == nullptr) { - QUIC_DLOG(ERROR) - << ENDPOINT << "Received datagram without any visitor for no context"; - return; - } - visitor = datagram_no_context_visitor_; +void QuicSpdyStream::HandleReceivedDatagram(absl::string_view payload) { + if (datagram_visitor_ == nullptr) { + QUIC_DLOG(ERROR) << ENDPOINT << "Received datagram without any visitor"; + return; } - visitor->OnHttp3Datagram(id(), context_id, payload); + datagram_visitor_->OnHttp3Datagram(id(), payload); } bool QuicSpdyStream::OnCapsule(const Capsule& capsule) { @@ -1485,65 +1397,12 @@ bool QuicSpdyStream::OnCapsule(const Capsule& capsule) { switch (capsule.capsule_type()) { case CapsuleType::LEGACY_DATAGRAM: { HandleReceivedDatagram( - capsule.legacy_datagram_capsule().context_id, capsule.legacy_datagram_capsule().http_datagram_payload); } break; - case CapsuleType::DATAGRAM_WITH_CONTEXT: { - HandleReceivedDatagram( - capsule.datagram_with_context_capsule().context_id, - capsule.datagram_with_context_capsule().http_datagram_payload); - } break; case CapsuleType::DATAGRAM_WITHOUT_CONTEXT: { - absl::optional<QuicDatagramContextId> context_id; - if (use_datagram_contexts_) { - // draft-ietf-masque-h3-datagram-05 encodes context ID 0 using - // DATAGRAM_WITHOUT_CONTEXT. - context_id = 0; - } HandleReceivedDatagram( - context_id, capsule.datagram_without_context_capsule().http_datagram_payload); } break; - case CapsuleType::REGISTER_DATAGRAM_CONTEXT: { - if (datagram_registration_visitor_ == nullptr) { - QUIC_DLOG(ERROR) << ENDPOINT << "Received capsule " << capsule - << " without any registration visitor"; - return false; - } - datagram_registration_visitor_->OnContextReceived( - id(), capsule.register_datagram_context_capsule().context_id, - capsule.register_datagram_context_capsule().format_type, - capsule.register_datagram_context_capsule().format_additional_data); - } break; - case CapsuleType::REGISTER_DATAGRAM_NO_CONTEXT: { - if (datagram_registration_visitor_ == nullptr) { - QUIC_DLOG(ERROR) << ENDPOINT << "Received capsule " << capsule - << " without any registration visitor"; - return false; - } - absl::optional<QuicDatagramContextId> context_id; - if (use_datagram_contexts_) { - // draft-ietf-masque-h3-datagram-05 encodes context ID 0 using - // REGISTER_DATAGRAM_NO_CONTEXT. - context_id = 0; - } - datagram_registration_visitor_->OnContextReceived( - id(), context_id, - capsule.register_datagram_no_context_capsule().format_type, - capsule.register_datagram_no_context_capsule() - .format_additional_data); - } break; - case CapsuleType::CLOSE_DATAGRAM_CONTEXT: { - if (datagram_registration_visitor_ == nullptr) { - QUIC_DLOG(ERROR) << ENDPOINT << "Received capsule " << capsule - << " without any registration visitor"; - return false; - } - datagram_registration_visitor_->OnContextClosed( - id(), capsule.close_datagram_context_capsule().context_id, - capsule.close_datagram_context_capsule().close_code, - capsule.close_datagram_context_capsule().close_details); - } break; case CapsuleType::CLOSE_WEBTRANSPORT_SESSION: { if (web_transport_ == nullptr) { QUIC_DLOG(ERROR) << ENDPOINT << "Received capsule " << capsule @@ -1588,202 +1447,50 @@ void QuicSpdyStream::WriteGreaseCapsule() { WriteCapsule(capsule, /*fin=*/false); } -MessageStatus QuicSpdyStream::SendHttp3Datagram( - absl::optional<QuicDatagramContextId> context_id, - absl::string_view payload) { - QuicDatagramStreamId stream_id = - datagram_flow_id_.has_value() ? datagram_flow_id_.value() : id(); - return spdy_session_->SendHttp3Datagram(stream_id, context_id, payload); -} - -void QuicSpdyStream::RegisterHttp3DatagramRegistrationVisitor( - Http3DatagramRegistrationVisitor* visitor, bool use_datagram_contexts) { - if (visitor == nullptr) { - QUIC_BUG(null datagram registration visitor) - << ENDPOINT << "Null datagram registration visitor for" << id(); - return; - } - if (datagram_registration_visitor_ != nullptr) { - QUIC_BUG(double datagram registration visitor) - << ENDPOINT << "Double datagram registration visitor for" << id(); - return; - } - use_datagram_contexts_ = use_datagram_contexts; - QUIC_DLOG(INFO) << ENDPOINT << "Registering datagram stream ID " << id() - << " with" << (use_datagram_contexts_ ? "" : "out") - << " contexts"; - datagram_registration_visitor_ = visitor; - QUICHE_DCHECK(!capsule_parser_); - capsule_parser_.reset(new CapsuleParser(this)); +MessageStatus QuicSpdyStream::SendHttp3Datagram(absl::string_view payload) { + return spdy_session_->SendHttp3Datagram(id(), payload); } -void QuicSpdyStream::UnregisterHttp3DatagramRegistrationVisitor() { - QUIC_BUG_IF(h3 datagram unregister unknown stream ID, - datagram_registration_visitor_ == nullptr) - << ENDPOINT - << "Attempted to unregister unknown HTTP/3 datagram stream ID " << id(); - QUIC_DLOG(INFO) << ENDPOINT << "Unregistering datagram stream ID " << id(); - datagram_registration_visitor_ = nullptr; -} - -void QuicSpdyStream::MoveHttp3DatagramRegistration( - Http3DatagramRegistrationVisitor* visitor) { - QUIC_BUG_IF(h3 datagram move unknown stream ID, - datagram_registration_visitor_ == nullptr) - << ENDPOINT << "Attempted to move unknown HTTP/3 datagram stream ID " - << id(); - QUIC_DLOG(INFO) << ENDPOINT << "Moving datagram stream ID " << id(); - datagram_registration_visitor_ = visitor; -} - -void QuicSpdyStream::RegisterHttp3DatagramContextId( - absl::optional<QuicDatagramContextId> context_id, - DatagramFormatType format_type, absl::string_view format_additional_data, +void QuicSpdyStream::RegisterHttp3DatagramVisitor( Http3DatagramVisitor* visitor) { if (visitor == nullptr) { QUIC_BUG(null datagram visitor) - << ENDPOINT << "Null datagram visitor for stream ID " << id() - << " context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) : "none"); + << ENDPOINT << "Null datagram visitor for stream ID " << id(); return; } - if (datagram_registration_visitor_ == nullptr) { - QUIC_BUG(context registration without registration visitor) - << ENDPOINT << "Cannot register context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) : "none") - << " without registration visitor for stream ID " << id(); + QUIC_DLOG(INFO) << ENDPOINT << "Registering datagram visitor with stream ID " + << id(); + + if (datagram_visitor_ != nullptr) { + QUIC_BUG(h3 datagram double registration) + << ENDPOINT + << "Attempted to doubly register HTTP/3 datagram with stream ID " + << id(); return; } - QUIC_DLOG(INFO) << ENDPOINT << "Registering datagram context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) - : "none") - << " with stream ID " << id(); - - if (context_id.has_value()) { - if (datagram_no_context_visitor_ != nullptr) { - QUIC_BUG(h3 datagram context ID mix1) - << ENDPOINT - << "Attempted to mix registrations without and with context IDs " - "for stream ID " - << id(); - return; - } - auto insertion_result = - datagram_context_visitors_.insert({context_id.value(), visitor}); - if (!insertion_result.second) { - QUIC_BUG(h3 datagram double context registration) - << ENDPOINT << "Attempted to doubly register HTTP/3 stream ID " - << id() << " context ID " << context_id.value(); - return; - } - capsule_parser_->set_datagram_context_id_present(true); - } else { - // Registration without a context ID. - if (!datagram_context_visitors_.empty()) { - QUIC_BUG(h3 datagram context ID mix2) - << ENDPOINT - << "Attempted to mix registrations with and without context IDs " - "for stream ID " - << id(); - return; - } - if (datagram_no_context_visitor_ != nullptr) { - QUIC_BUG(h3 datagram double no context registration) - << ENDPOINT << "Attempted to doubly register HTTP/3 stream ID " - << id() << " with no context ID"; - return; - } - datagram_no_context_visitor_ = visitor; - capsule_parser_->set_datagram_context_id_present(false); - } - if (spdy_session_->http_datagram_support() == HttpDatagramSupport::kDraft04) { - const bool is_client = session()->perspective() == Perspective::IS_CLIENT; - if (context_id.has_value()) { - const bool is_client_context = context_id.value() % 2 == 0; - if (is_client == is_client_context) { - QuicConnection::ScopedPacketFlusher flusher( - spdy_session_->connection()); - WriteGreaseCapsule(); - if (context_id.value() != 0) { - WriteCapsule(Capsule::RegisterDatagramContext( - context_id.value(), format_type, format_additional_data)); - } else { - // draft-ietf-masque-h3-datagram-05 encodes context ID 0 using - // REGISTER_DATAGRAM_NO_CONTEXT. - WriteCapsule(Capsule::RegisterDatagramNoContext( - format_type, format_additional_data)); - } - WriteGreaseCapsule(); - } - } else if (is_client) { - QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection()); - WriteGreaseCapsule(); - WriteCapsule(Capsule::RegisterDatagramNoContext(format_type, - format_additional_data)); - WriteGreaseCapsule(); - } - } + datagram_visitor_ = visitor; + QUICHE_DCHECK(!capsule_parser_); + capsule_parser_ = std::make_unique<CapsuleParser>(this); } -void QuicSpdyStream::UnregisterHttp3DatagramContextId( - absl::optional<QuicDatagramContextId> context_id) { - if (datagram_registration_visitor_ == nullptr) { - QUIC_BUG(context unregistration without registration visitor) - << ENDPOINT << "Cannot unregister context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) : "none") - << " without registration visitor for stream ID " << id(); - return; - } - QUIC_DLOG(INFO) << ENDPOINT << "Unregistering datagram context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) - : "none") - << " with stream ID " << id(); - if (context_id.has_value()) { - size_t num_erased = datagram_context_visitors_.erase(context_id.value()); - QUIC_BUG_IF(h3 datagram unregister unknown context, num_erased != 1) - << "Attempted to unregister unknown HTTP/3 context ID " - << context_id.value() << " on stream ID " << id(); - } else { - // Unregistration without a context ID. - QUIC_BUG_IF(h3 datagram unknown context unregistration, - datagram_no_context_visitor_ == nullptr) - << "Attempted to unregister unknown no context on HTTP/3 stream ID " +void QuicSpdyStream::UnregisterHttp3DatagramVisitor() { + if (datagram_visitor_ == nullptr) { + QUIC_BUG(datagram visitor empty during unregistration) + << ENDPOINT << "Cannot unregister datagram visitor for stream ID " << id(); - datagram_no_context_visitor_ = nullptr; - } - if (spdy_session_->http_datagram_support() == HttpDatagramSupport::kDraft04 && - context_id.has_value()) { - WriteCapsule(Capsule::CloseDatagramContext(context_id.value())); + return; } + QUIC_DLOG(INFO) << ENDPOINT << "Unregistering datagram visitor for stream ID " + << id(); + datagram_visitor_ = nullptr; } -void QuicSpdyStream::MoveHttp3DatagramContextIdRegistration( - absl::optional<QuicDatagramContextId> context_id, +void QuicSpdyStream::ReplaceHttp3DatagramVisitor( Http3DatagramVisitor* visitor) { - if (datagram_registration_visitor_ == nullptr) { - QUIC_BUG(context move without registration visitor) - << ENDPOINT << "Cannot move context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) : "none") - << " without registration visitor for stream ID " << id(); - return; - } - QUIC_DLOG(INFO) << ENDPOINT << "Moving datagram context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) - : "none") - << " with stream ID " << id(); - if (context_id.has_value()) { - QUIC_BUG_IF(h3 datagram move unknown context, - !datagram_context_visitors_.contains(context_id.value())) - << ENDPOINT << "Attempted to move unknown context ID " - << context_id.value() << " on stream ID " << id(); - datagram_context_visitors_[context_id.value()] = visitor; - return; - } - // Move without a context ID. - QUIC_BUG_IF(h3 datagram unknown context move, - datagram_no_context_visitor_ == nullptr) - << "Attempted to move unknown no context on HTTP/3 stream ID " << id(); - datagram_no_context_visitor_ = visitor; + QUIC_BUG_IF(h3 datagram unknown move, datagram_visitor_ == nullptr) + << "Attempted to move missing datagram visitor on HTTP/3 stream ID " + << id(); + datagram_visitor_ = visitor; } void QuicSpdyStream::SetMaxDatagramTimeInQueue( @@ -1791,51 +1498,25 @@ void QuicSpdyStream::SetMaxDatagramTimeInQueue( spdy_session_->SetMaxDatagramTimeInQueueForStreamId(id(), max_time_in_queue); } -QuicDatagramContextId QuicSpdyStream::GetNextDatagramContextId() { - QuicDatagramContextId result = datagram_next_available_context_id_; - datagram_next_available_context_id_ += kDatagramContextIdIncrement; - return result; -} - void QuicSpdyStream::OnDatagramReceived(QuicDataReader* reader) { if (!headers_decompressed_) { QUIC_DLOG(INFO) << "Dropping datagram received before headers on stream ID " << id(); return; } - absl::optional<QuicDatagramContextId> context_id; - if (use_datagram_contexts_) { - QuicDatagramContextId parsed_context_id; - if (!reader->ReadVarInt62(&parsed_context_id)) { - QUIC_DLOG(ERROR) << "Failed to parse context ID in received HTTP/3 " - "datagram on stream ID " - << id(); - return; - } - context_id = parsed_context_id; - } - absl::string_view payload = reader->ReadRemainingPayload(); - HandleReceivedDatagram(context_id, payload); + HandleReceivedDatagram(reader->ReadRemainingPayload()); } -QuicByteCount QuicSpdyStream::GetMaxDatagramSize( - absl::optional<QuicDatagramContextId> context_id) const { +QuicByteCount QuicSpdyStream::GetMaxDatagramSize() const { QuicByteCount prefix_size = 0; switch (spdy_session_->http_datagram_support()) { - case HttpDatagramSupport::kDraft00: - if (!datagram_flow_id_.has_value()) { - QUIC_BUG(GetMaxDatagramSize with no flow ID) - << "GetMaxDatagramSize() called when no flow ID available"; - break; - } - prefix_size = QuicDataWriter::GetVarInt62Len(*datagram_flow_id_); - break; case HttpDatagramSupport::kDraft04: + case HttpDatagramSupport::kDraft09: prefix_size = QuicDataWriter::GetVarInt62Len(id() / kHttpDatagramStreamIdDivisor); break; case HttpDatagramSupport::kNone: - case HttpDatagramSupport::kDraft00And04: + case HttpDatagramSupport::kDraft04And09: QUIC_BUG(GetMaxDatagramSize called with no datagram support) << "GetMaxDatagramSize() called when no HTTP/3 datagram support has " "been negotiated. Support value: " @@ -1847,31 +1528,17 @@ QuicByteCount QuicSpdyStream::GetMaxDatagramSize( prefix_size = 8; } - if (context_id.has_value()) { - QUIC_BUG_IF( - context_id with draft00 in GetMaxDatagramSize, - spdy_session_->http_datagram_support() == HttpDatagramSupport::kDraft00) - << "GetMaxDatagramSize() called with a context ID specified, but " - "draft00 does not support contexts."; - prefix_size += QuicDataWriter::GetVarInt62Len(*context_id); - } - QuicByteCount max_datagram_size = session()->GetGuaranteedLargestMessagePayload(); if (max_datagram_size < prefix_size) { QUIC_BUG(max_datagram_size smaller than prefix_size) << "GetGuaranteedLargestMessagePayload() returned a datagram size that " - "is not sufficient to fit stream and/or context ID into it."; + "is not sufficient to fit stream ID into it."; return 0; } return max_datagram_size - prefix_size; } -void QuicSpdyStream::RegisterHttp3DatagramFlowId(QuicDatagramStreamId flow_id) { - datagram_flow_id_ = flow_id; - spdy_session_->RegisterHttp3DatagramFlowId(datagram_flow_id_.value(), id()); -} - void QuicSpdyStream::HandleBodyAvailable() { if (!capsule_parser_) { OnBodyAvailable(); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.h index b7fc7141d99..61cd7e36f59 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.h @@ -129,7 +129,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream ack_listener); // Sends |data| to the peer, or buffers if it can't be sent immediately. - void WriteOrBufferBody(absl::string_view data, bool fin); + virtual void WriteOrBufferBody(absl::string_view data, bool fin); // Writes the trailers contained in |trailer_block| on the dedicated headers // stream or on this stream, depending on VersionUsesHttp3(). Trailers will @@ -254,98 +254,37 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream bool OnCapsule(const Capsule& capsule) override; void OnCapsuleParseFailure(const std::string& error_message) override; - // Sends an HTTP/3 datagram. The stream and context IDs are not part of - // |payload|. - MessageStatus SendHttp3Datagram( - absl::optional<QuicDatagramContextId> context_id, - absl::string_view payload); + // Sends an HTTP/3 datagram. The stream ID is not part of |payload|. + MessageStatus SendHttp3Datagram(absl::string_view payload); class QUIC_EXPORT_PRIVATE Http3DatagramVisitor { public: virtual ~Http3DatagramVisitor() {} // Called when an HTTP/3 datagram is received. |payload| does not contain - // the stream or context IDs. Note that this contains the stream ID even if - // flow IDs from draft-ietf-masque-h3-datagram-00 are in use. - virtual void OnHttp3Datagram( - QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - absl::string_view payload) = 0; + // the stream ID. + virtual void OnHttp3Datagram(QuicStreamId stream_id, + absl::string_view payload) = 0; }; - class QUIC_EXPORT_PRIVATE Http3DatagramRegistrationVisitor { - public: - virtual ~Http3DatagramRegistrationVisitor() {} - - // Called when a REGISTER_DATAGRAM_CONTEXT or REGISTER_DATAGRAM_NO_CONTEXT - // capsule is received. Note that this contains the stream ID even if flow - // IDs from draft-ietf-masque-h3-datagram-00 are in use. - virtual void OnContextReceived( - QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - DatagramFormatType format_type, - absl::string_view format_additional_data) = 0; - - // Called when a CLOSE_DATAGRAM_CONTEXT capsule is received. Note that this - // contains the stream ID even if flow IDs from - // draft-ietf-masque-h3-datagram-00 are in use. - virtual void OnContextClosed( - QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - ContextCloseCode close_code, absl::string_view close_details) = 0; - }; + // Registers |visitor| to receive HTTP/3 datagrams. |visitor| must be + // valid until a corresponding call to UnregisterHttp3DatagramVisitor. + void RegisterHttp3DatagramVisitor(Http3DatagramVisitor* visitor); + + // Unregisters an HTTP/3 datagram visitor. Must only be called after a call to + // RegisterHttp3DatagramVisitor. + void UnregisterHttp3DatagramVisitor(); - // Registers |visitor| to receive HTTP/3 datagram context registrations. This - // must not be called without first calling - // UnregisterHttp3DatagramRegistrationVisitor. |visitor| must be valid until a - // corresponding call to UnregisterHttp3DatagramRegistrationVisitor. - void RegisterHttp3DatagramRegistrationVisitor( - Http3DatagramRegistrationVisitor* visitor, - bool use_datagram_contexts = false); - - // Unregisters for HTTP/3 datagram context registrations. Must not be called - // unless previously registered. - void UnregisterHttp3DatagramRegistrationVisitor(); - - // Moves an HTTP/3 datagram registration to a different visitor. Mainly meant - // to be used by the visitors' move operators. - void MoveHttp3DatagramRegistration(Http3DatagramRegistrationVisitor* visitor); - - // Registers |visitor| to receive HTTP/3 datagrams for optional context ID - // |context_id|. This must not be called on a previously registered context ID - // without first calling UnregisterHttp3DatagramContextId. |visitor| must be - // valid until a corresponding call to UnregisterHttp3DatagramContextId. If - // this method is called multiple times, the context ID MUST either be always - // present, or always absent. - void RegisterHttp3DatagramContextId( - absl::optional<QuicDatagramContextId> context_id, - DatagramFormatType format_type, absl::string_view format_additional_data, - Http3DatagramVisitor* visitor); - - // Unregisters an HTTP/3 datagram context ID. Must be called on a previously - // registered context. - void UnregisterHttp3DatagramContextId( - absl::optional<QuicDatagramContextId> context_id); - - // Moves an HTTP/3 datagram context ID to a different visitor. Mainly meant - // to be used by the visitors' move operators. - void MoveHttp3DatagramContextIdRegistration( - absl::optional<QuicDatagramContextId> context_id, - Http3DatagramVisitor* visitor); + // Replaces the current HTTP/3 datagram visitor with a different visitor. + // Mainly meant to be used by the visitors' move operators. + void ReplaceHttp3DatagramVisitor(Http3DatagramVisitor* visitor); // Sets max datagram time in queue. void SetMaxDatagramTimeInQueue(QuicTime::Delta max_time_in_queue); - // Generates a new HTTP/3 datagram context ID for this stream. A datagram - // registration visitor must be currently registered on this stream. - QuicDatagramContextId GetNextDatagramContextId(); - void OnDatagramReceived(QuicDataReader* reader); - void RegisterHttp3DatagramFlowId(QuicDatagramStreamId flow_id); - - QuicByteCount GetMaxDatagramSize( - absl::optional<QuicDatagramContextId> context_id) const; + QuicByteCount GetMaxDatagramSize() const; // Writes |capsule| onto the DATA stream. void WriteCapsule(const Capsule& capsule, bool fin = false); @@ -445,11 +384,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream void HandleBodyAvailable(); // Called when a datagram frame or capsule is received. - void HandleReceivedDatagram(absl::optional<QuicDatagramContextId> context_id, - absl::string_view payload); - - // Whether datagram contexts should be used on this stream. - bool ShouldUseDatagramContexts() const; + void HandleReceivedDatagram(absl::string_view payload); QuicSpdySession* spdy_session_; @@ -526,13 +461,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream std::unique_ptr<WebTransportDataStream> web_transport_data_; // HTTP/3 Datagram support. - Http3DatagramRegistrationVisitor* datagram_registration_visitor_ = nullptr; - Http3DatagramVisitor* datagram_no_context_visitor_ = nullptr; - absl::optional<QuicDatagramStreamId> datagram_flow_id_; - QuicDatagramContextId datagram_next_available_context_id_; - absl::flat_hash_map<QuicDatagramContextId, Http3DatagramVisitor*> - datagram_context_visitors_; - bool use_datagram_contexts_ = false; + Http3DatagramVisitor* datagram_visitor_ = nullptr; }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream_test.cc index b0c972df366..c4526ed99ed 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream_test.cc @@ -187,6 +187,26 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker { SSL* GetSsl() const override { return nullptr; } + bool IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const override { + return level != ENCRYPTION_ZERO_RTT; + } + + EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const override { + switch (space) { + case INITIAL_DATA: + return ENCRYPTION_INITIAL; + case HANDSHAKE_DATA: + return ENCRYPTION_HANDSHAKE; + case APPLICATION_DATA: + return ENCRYPTION_FORWARD_SECURE; + default: + QUICHE_DCHECK(false); + return NUM_ENCRYPTION_LEVELS; + } + } + private: using QuicCryptoStream::session; @@ -979,7 +999,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) { } EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(kWindow - kHeaderLength, true))); - EXPECT_CALL(*session_, SendBlocked(_)); + EXPECT_CALL(*session_, SendBlocked(_, _)); EXPECT_CALL(*connection_, SendControlFrame(_)); stream_->WriteOrBufferBody(body, false); @@ -1234,7 +1254,8 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) { std::string body = ""; bool fin = true; - EXPECT_CALL(*session_, SendBlocked(GetNthClientInitiatedBidirectionalId(0))) + EXPECT_CALL(*session_, + SendBlocked(GetNthClientInitiatedBidirectionalId(0), _)) .Times(0); EXPECT_CALL(*session_, WritevData(_, 0, _, FIN, _, _)); @@ -3055,39 +3076,13 @@ TEST_P(QuicSpdyStreamTest, TwoResetStreamFrames) { } } -TEST_P(QuicSpdyStreamTest, ProcessOutgoingWebTransportHeadersDatagramDraft00) { - if (!UsesHttp3()) { - return; - } - - InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT); - session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); - session_->EnableWebTransport(); - session_->OnSetting(SETTINGS_ENABLE_CONNECT_PROTOCOL, 1); - QuicSpdySessionPeer::EnableWebTransport(session_.get()); - QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(), - HttpDatagramSupport::kDraft00); - - EXPECT_CALL(*stream_, WriteHeadersMock(false)); - EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)) - .Times(AnyNumber()); - - spdy::SpdyHeaderBlock headers; - headers[":method"] = "CONNECT"; - headers[":protocol"] = "webtransport"; - headers["datagram-flow-id"] = absl::StrCat(stream_->id()); - stream_->WriteHeaders(std::move(headers), /*fin=*/false, nullptr); - ASSERT_TRUE(stream_->web_transport() != nullptr); - EXPECT_EQ(stream_->id(), stream_->web_transport()->id()); -} - TEST_P(QuicSpdyStreamTest, ProcessOutgoingWebTransportHeadersDatagramDraft04) { if (!UsesHttp3()) { return; } InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT); - session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft04); session_->EnableWebTransport(); session_->OnSetting(SETTINGS_ENABLE_CONNECT_PROTOCOL, 1); QuicSpdySessionPeer::EnableWebTransport(session_.get()); @@ -3112,7 +3107,7 @@ TEST_P(QuicSpdyStreamTest, ProcessIncomingWebTransportHeadersDatagramDraft04) { } Initialize(kShouldProcessData); - session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft04); session_->EnableWebTransport(); QuicSpdySessionPeer::EnableWebTransport(session_.get()); QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(), @@ -3125,8 +3120,6 @@ TEST_P(QuicSpdyStreamTest, ProcessIncomingWebTransportHeadersDatagramDraft04) { stream_->OnStreamHeadersPriority( spdy::SpdyStreamPrecedence(kV3HighestPriority)); ProcessHeaders(false, headers_); - stream_->OnCapsule( - Capsule::RegisterDatagramNoContext(DatagramFormatType::WEBTRANSPORT)); EXPECT_EQ("", stream_->data()); EXPECT_FALSE(stream_->header_list().empty()); EXPECT_FALSE(stream_->IsDoneReading()); @@ -3134,278 +3127,58 @@ TEST_P(QuicSpdyStreamTest, ProcessIncomingWebTransportHeadersDatagramDraft04) { EXPECT_EQ(stream_->id(), stream_->web_transport()->id()); } -TEST_P(QuicSpdyStreamTest, ProcessIncomingWebTransportHeadersDatagramDraft00) { - if (!UsesHttp3()) { - return; - } - - Initialize(kShouldProcessData); - session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); - session_->EnableWebTransport(); - QuicSpdySessionPeer::EnableWebTransport(session_.get()); - QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(), - HttpDatagramSupport::kDraft00); - - headers_[":method"] = "CONNECT"; - headers_[":protocol"] = "webtransport"; - headers_["datagram-flow-id"] = absl::StrCat(stream_->id()); - - stream_->OnStreamHeadersPriority( - spdy::SpdyStreamPrecedence(kV3HighestPriority)); - ProcessHeaders(false, headers_); - EXPECT_EQ("", stream_->data()); - EXPECT_FALSE(stream_->header_list().empty()); - EXPECT_FALSE(stream_->IsDoneReading()); - ASSERT_TRUE(stream_->web_transport() != nullptr); - EXPECT_EQ(stream_->id(), stream_->web_transport()->id()); -} - -TEST_P(QuicSpdyStreamTest, - ProcessIncomingWebTransportHeadersWithMismatchedFlowId) { - if (!UsesHttp3()) { - return; - } - // TODO(b/181256914) Remove this test when we deprecate - // draft-ietf-masque-h3-datagram-00 in favor of later drafts. - - Initialize(kShouldProcessData); - session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); - session_->EnableWebTransport(); - QuicSpdySessionPeer::EnableWebTransport(session_.get()); - QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(), - HttpDatagramSupport::kDraft00); - - headers_[":method"] = "CONNECT"; - headers_[":protocol"] = "webtransport"; - headers_["datagram-flow-id"] = "2"; - - stream_->OnStreamHeadersPriority( - spdy::SpdyStreamPrecedence(kV3HighestPriority)); - ProcessHeaders(false, headers_); - EXPECT_EQ("", stream_->data()); - EXPECT_FALSE(stream_->header_list().empty()); - EXPECT_FALSE(stream_->IsDoneReading()); - ASSERT_TRUE(stream_->web_transport() != nullptr); - EXPECT_EQ(stream_->id(), stream_->web_transport()->id()); -} - -TEST_P(QuicSpdyStreamTest, GetNextDatagramContextIdClient) { +TEST_P(QuicSpdyStreamTest, ReceiveHttpDatagram) { if (!UsesHttp3()) { return; } InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT); - ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor> visitor; - stream_->RegisterHttp3DatagramRegistrationVisitor(&visitor); - EXPECT_EQ(stream_->GetNextDatagramContextId(), 0u); - EXPECT_EQ(stream_->GetNextDatagramContextId(), 2u); - EXPECT_EQ(stream_->GetNextDatagramContextId(), 4u); - EXPECT_EQ(stream_->GetNextDatagramContextId(), 6u); - stream_->UnregisterHttp3DatagramRegistrationVisitor(); -} - -TEST_P(QuicSpdyStreamTest, GetNextDatagramContextIdServer) { - if (!UsesHttp3()) { - return; - } - InitializeWithPerspective(kShouldProcessData, Perspective::IS_SERVER); - ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor> visitor; - stream_->RegisterHttp3DatagramRegistrationVisitor(&visitor); - EXPECT_EQ(stream_->GetNextDatagramContextId(), 1u); - EXPECT_EQ(stream_->GetNextDatagramContextId(), 3u); - EXPECT_EQ(stream_->GetNextDatagramContextId(), 5u); - EXPECT_EQ(stream_->GetNextDatagramContextId(), 7u); - stream_->UnregisterHttp3DatagramRegistrationVisitor(); -} - -TEST_P(QuicSpdyStreamTest, HttpDatagramRegistrationWithoutContextDraft00) { - if (!UsesHttp3()) { - return; - } - InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT); - session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft09); QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(), - HttpDatagramSupport::kDraft00); + HttpDatagramSupport::kDraft09); headers_[":method"] = "CONNECT"; headers_[":protocol"] = "webtransport"; - headers_["datagram-flow-id"] = absl::StrCat(stream_->id()); ProcessHeaders(false, headers_); - session_->RegisterHttp3DatagramFlowId(stream_->id(), stream_->id()); - ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor> - h3_datagram_registration_visitor; SavingHttp3DatagramVisitor h3_datagram_visitor; - absl::optional<QuicDatagramContextId> context_id; - absl::string_view format_additional_data; ASSERT_EQ(QuicDataWriter::GetVarInt62Len(stream_->id()), 1); std::array<char, 256> datagram; datagram[0] = stream_->id(); for (size_t i = 1; i < datagram.size(); i++) { datagram[i] = i; } - stream_->RegisterHttp3DatagramRegistrationVisitor( - &h3_datagram_registration_visitor); - stream_->RegisterHttp3DatagramContextId( - context_id, DatagramFormatType::UDP_PAYLOAD, format_additional_data, - &h3_datagram_visitor); - session_->OnMessageReceived( - absl::string_view(datagram.data(), datagram.size())); - EXPECT_THAT(h3_datagram_visitor.received_h3_datagrams(), - ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{ - stream_->id(), context_id, - std::string(&datagram[1], datagram.size() - 1)})); - // Test move. - ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor> - h3_datagram_registration_visitor2; - stream_->MoveHttp3DatagramRegistration(&h3_datagram_registration_visitor2); - SavingHttp3DatagramVisitor h3_datagram_visitor2; - stream_->MoveHttp3DatagramContextIdRegistration(context_id, - &h3_datagram_visitor2); - EXPECT_TRUE(h3_datagram_visitor2.received_h3_datagrams().empty()); - session_->OnMessageReceived( - absl::string_view(datagram.data(), datagram.size())); - EXPECT_THAT(h3_datagram_visitor2.received_h3_datagrams(), - ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{ - stream_->id(), context_id, - std::string(&datagram[1], datagram.size() - 1)})); - // Cleanup. - stream_->UnregisterHttp3DatagramContextId(context_id); - stream_->UnregisterHttp3DatagramRegistrationVisitor(); - session_->UnregisterHttp3DatagramFlowId(stream_->id()); -} - -TEST_P(QuicSpdyStreamTest, H3DatagramRegistrationWithoutContextDraft04) { - if (!UsesHttp3()) { - return; - } - InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT); - session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft04); - QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(), - HttpDatagramSupport::kDraft04); - headers_[":method"] = "CONNECT"; - headers_[":protocol"] = "webtransport"; - ProcessHeaders(false, headers_); - ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor> - h3_datagram_registration_visitor; - SavingHttp3DatagramVisitor h3_datagram_visitor; - absl::optional<QuicDatagramContextId> context_id; - absl::string_view format_additional_data; - ASSERT_EQ(QuicDataWriter::GetVarInt62Len(stream_->id()), 1); - std::array<char, 256> datagram; - datagram[0] = stream_->id(); - for (size_t i = 1; i < datagram.size(); i++) { - datagram[i] = i; - } - stream_->RegisterHttp3DatagramRegistrationVisitor( - &h3_datagram_registration_visitor); - - // Expect us to send a REGISTER_DATAGRAM_NO_CONTEXT capsule. - EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)) - .Times(AtLeast(1)); - - stream_->RegisterHttp3DatagramContextId( - context_id, DatagramFormatType::UDP_PAYLOAD, format_additional_data, - &h3_datagram_visitor); - session_->OnMessageReceived( - absl::string_view(datagram.data(), datagram.size())); - EXPECT_THAT(h3_datagram_visitor.received_h3_datagrams(), - ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{ - stream_->id(), context_id, - std::string(&datagram[1], datagram.size() - 1)})); - // Test move. - ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor> - h3_datagram_registration_visitor2; - stream_->MoveHttp3DatagramRegistration(&h3_datagram_registration_visitor2); - SavingHttp3DatagramVisitor h3_datagram_visitor2; - stream_->MoveHttp3DatagramContextIdRegistration(context_id, - &h3_datagram_visitor2); - EXPECT_TRUE(h3_datagram_visitor2.received_h3_datagrams().empty()); - session_->OnMessageReceived( - absl::string_view(datagram.data(), datagram.size())); - EXPECT_THAT(h3_datagram_visitor2.received_h3_datagrams(), - ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{ - stream_->id(), context_id, - std::string(&datagram[1], datagram.size() - 1)})); - // Cleanup. - stream_->UnregisterHttp3DatagramContextId(context_id); - stream_->UnregisterHttp3DatagramRegistrationVisitor(); -} - -TEST_P(QuicSpdyStreamTest, HttpDatagramRegistrationWithContext) { - if (!UsesHttp3()) { - return; - } - InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT); - session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); - QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(), - HttpDatagramSupport::kDraft04); - ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor> - h3_datagram_registration_visitor; - SavingHttp3DatagramVisitor h3_datagram_visitor; - absl::optional<QuicDatagramContextId> context_id = 42; - absl::string_view format_additional_data; - ASSERT_EQ(QuicDataWriter::GetVarInt62Len(stream_->id()), 1); - std::array<char, 256> datagram; - datagram[0] = stream_->id(); - datagram[1] = context_id.value(); - for (size_t i = 2; i < datagram.size(); i++) { - datagram[i] = i; - } - stream_->RegisterHttp3DatagramRegistrationVisitor( - &h3_datagram_registration_visitor, /*use_datagram_contexts=*/true); - headers_[":method"] = "CONNECT"; - headers_[":protocol"] = "webtransport"; - headers_["sec-use-datagram-contexts"] = "?1"; - ProcessHeaders(false, headers_); - // Expect us to send a REGISTER_DATAGRAM_CONTEXT capsule. - EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)) - .Times(AtLeast(1)); - - stream_->RegisterHttp3DatagramContextId( - context_id, DatagramFormatType::UDP_PAYLOAD, format_additional_data, - &h3_datagram_visitor); + stream_->RegisterHttp3DatagramVisitor(&h3_datagram_visitor); session_->OnMessageReceived( absl::string_view(datagram.data(), datagram.size())); - EXPECT_THAT(h3_datagram_visitor.received_h3_datagrams(), - ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{ - stream_->id(), context_id, - std::string(&datagram[2], datagram.size() - 2)})); + EXPECT_THAT( + h3_datagram_visitor.received_h3_datagrams(), + ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{ + stream_->id(), std::string(&datagram[1], datagram.size() - 1)})); // Test move. - ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor> - h3_datagram_registration_visitor2; - stream_->MoveHttp3DatagramRegistration(&h3_datagram_registration_visitor2); SavingHttp3DatagramVisitor h3_datagram_visitor2; - stream_->MoveHttp3DatagramContextIdRegistration(context_id, - &h3_datagram_visitor2); + stream_->ReplaceHttp3DatagramVisitor(&h3_datagram_visitor2); EXPECT_TRUE(h3_datagram_visitor2.received_h3_datagrams().empty()); session_->OnMessageReceived( absl::string_view(datagram.data(), datagram.size())); - EXPECT_THAT(h3_datagram_visitor2.received_h3_datagrams(), - ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{ - stream_->id(), context_id, - std::string(&datagram[2], datagram.size() - 2)})); + EXPECT_THAT( + h3_datagram_visitor2.received_h3_datagrams(), + ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{ + stream_->id(), std::string(&datagram[1], datagram.size() - 1)})); // Cleanup. - - // Expect us to send a CLOSE_DATAGRAM_CONTEXT capsule. - EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)) - .Times(AtLeast(1)); - stream_->UnregisterHttp3DatagramContextId(context_id); - stream_->UnregisterHttp3DatagramRegistrationVisitor(); - session_->UnregisterHttp3DatagramFlowId(stream_->id()); + stream_->UnregisterHttp3DatagramVisitor(); } -TEST_P(QuicSpdyStreamTest, SendHttp3Datagram) { +TEST_P(QuicSpdyStreamTest, SendHttpDatagram) { if (!UsesHttp3()) { return; } Initialize(kShouldProcessData); - session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft09); QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(), - HttpDatagramSupport::kDraft04); - absl::optional<QuicDatagramContextId> context_id; - std::string h3_datagram_payload = {1, 2, 3, 4, 5, 6}; + HttpDatagramSupport::kDraft09); + std::string http_datagram_payload = {1, 2, 3, 4, 5, 6}; EXPECT_CALL(*connection_, SendMessage(1, _, false)) .WillOnce(Return(MESSAGE_STATUS_SUCCESS)); - EXPECT_EQ(stream_->SendHttp3Datagram(context_id, h3_datagram_payload), + EXPECT_EQ(stream_->SendHttp3Datagram(http_datagram_payload), MESSAGE_STATUS_SUCCESS); } @@ -3414,15 +3187,10 @@ TEST_P(QuicSpdyStreamTest, GetMaxDatagramSize) { return; } Initialize(kShouldProcessData); - session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft00And04); + session_->set_local_http_datagram_support(HttpDatagramSupport::kDraft09); QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(), - HttpDatagramSupport::kDraft04); - - QuicByteCount size = stream_->GetMaxDatagramSize(absl::nullopt); - QuicByteCount size_with_context = - stream_->GetMaxDatagramSize(/*context_id=*/1); - EXPECT_GT(size, 512u); - EXPECT_EQ(size - 1, size_with_context); + HttpDatagramSupport::kDraft09); + EXPECT_GT(stream_->GetMaxDatagramSize(), 512u); } TEST_P(QuicSpdyStreamTest, @@ -3444,11 +3212,12 @@ TEST_P(QuicSpdyStreamTest, // 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); + EXPECT_QUIC_BUG( + { + EXPECT_CALL(*connection_, CloseConnection(_, _, _)); + EXPECT_FALSE(QuicSpdyStreamPeer::OnHeadersFrameEnd(stream_)); + }, + "b215142466_OnHeadersFrameEnd.?: 1"); } } // namespace diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.cc index d0eac9fbde1..b8282e43127 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.cc @@ -155,47 +155,6 @@ bool SpdyUtils::PopulateHeaderBlockFromUrl(const std::string url, } // static -absl::optional<QuicDatagramStreamId> SpdyUtils::ParseDatagramFlowIdHeader( - const spdy::SpdyHeaderBlock& headers) { - auto flow_id_pair = headers.find("datagram-flow-id"); - if (flow_id_pair == headers.end()) { - return absl::nullopt; - } - std::vector<absl::string_view> flow_id_strings = - absl::StrSplit(flow_id_pair->second, ','); - absl::optional<QuicDatagramStreamId> first_named_flow_id; - for (absl::string_view flow_id_string : flow_id_strings) { - std::vector<absl::string_view> flow_id_components = - absl::StrSplit(flow_id_string, ';'); - if (flow_id_components.empty()) { - continue; - } - absl::string_view flow_id_value_string = flow_id_components[0]; - quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace( - &flow_id_value_string); - QuicDatagramStreamId flow_id; - if (!absl::SimpleAtoi(flow_id_value_string, &flow_id)) { - continue; - } - if (flow_id_components.size() == 1) { - // This flow ID is unnamed, return this one. - return flow_id; - } - // Otherwise this is a named flow ID. - if (!first_named_flow_id.has_value()) { - first_named_flow_id = flow_id; - } - } - return first_named_flow_id; -} - -// static -void SpdyUtils::AddDatagramFlowIdHeader(spdy::SpdyHeaderBlock* headers, - QuicDatagramStreamId flow_id) { - (*headers)["datagram-flow-id"] = absl::StrCat(flow_id); -} - -// static ParsedQuicVersion SpdyUtils::ExtractQuicVersionFromAltSvcEntry( const spdy::SpdyAltSvcWireFormat::AlternativeService& alternative_service_entry, diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h index 5654b2f1037..d88087c5436 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h @@ -54,15 +54,6 @@ class QUIC_EXPORT_PRIVATE SpdyUtils { static bool PopulateHeaderBlockFromUrl(const std::string url, spdy::SpdyHeaderBlock* headers); - // Parses the "datagram-flow-id" header, returns the flow ID on success, or - // returns absl::nullopt if the header was not present or failed to parse. - static absl::optional<QuicDatagramStreamId> ParseDatagramFlowIdHeader( - const spdy::SpdyHeaderBlock& headers); - - // 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. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils_test.cc index d22a0e8396e..718d54854d9 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils_test.cc @@ -34,14 +34,6 @@ static std::unique_ptr<QuicHeaderList> FromList( return headers; } -static void ValidateDatagramFlowId( - const std::string& header_value, - absl::optional<QuicDatagramStreamId> expected_flow_id) { - SpdyHeaderBlock headers; - headers["datagram-flow-id"] = header_value; - ASSERT_EQ(SpdyUtils::ParseDatagramFlowIdHeader(headers), expected_flow_id); -} - } // anonymous namespace using CopyAndValidateHeaders = QuicTest; @@ -386,30 +378,6 @@ TEST_F(PopulateHeaderBlockFromUrl, Failure) { SpdyUtils::PopulateHeaderBlockFromUrl("www.google.com/", &headers)); } -using DatagramFlowIdTest = QuicTest; - -TEST_F(DatagramFlowIdTest, DatagramFlowId) { - // Test missing header. - SpdyHeaderBlock headers; - EXPECT_EQ(SpdyUtils::ParseDatagramFlowIdHeader(headers), absl::nullopt); - // Add header and verify it parses. - QuicDatagramStreamId flow_id = 123; - SpdyUtils::AddDatagramFlowIdHeader(&headers, flow_id); - EXPECT_EQ(SpdyUtils::ParseDatagramFlowIdHeader(headers), flow_id); - // Test empty header. - ValidateDatagramFlowId("", absl::nullopt); - // Test invalid header. - ValidateDatagramFlowId("M4SQU3", absl::nullopt); - // Test simple header. - ValidateDatagramFlowId("42", 42); - // Test with parameter. - ValidateDatagramFlowId("42; abc=def", 42); - // Test list. - ValidateDatagramFlowId("42, 44; ecn-ect0, 46; ecn-ect1, 48; ecn-ce", 42); - // Test reordered list. - ValidateDatagramFlowId("44; ecn-ect0, 42, 48; ecn-ce, 46; ecn-ect1", 42); -} - using ExtractQuicVersionFromAltSvcEntry = QuicTest; TEST_F(ExtractQuicVersionFromAltSvcEntry, SupportedVersion) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.cc index f0e38495060..a9babe80447 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.cc @@ -42,8 +42,7 @@ class QUIC_NO_EXPORT NoopWebTransportVisitor : public WebTransportVisitor { WebTransportHttp3::WebTransportHttp3(QuicSpdySession* session, QuicSpdyStream* connect_stream, - WebTransportSessionId id, - bool attempt_to_use_datagram_contexts) + WebTransportSessionId id) : session_(session), connect_stream_(connect_stream), id_(id), @@ -51,15 +50,7 @@ WebTransportHttp3::WebTransportHttp3(QuicSpdySession* session, QUICHE_DCHECK(session_->SupportsWebTransport()); QUICHE_DCHECK(IsValidWebTransportSessionId(id, session_->version())); QUICHE_DCHECK_EQ(connect_stream_->id(), id); - connect_stream_->RegisterHttp3DatagramRegistrationVisitor( - this, attempt_to_use_datagram_contexts); - if (session_->perspective() == Perspective::IS_CLIENT) { - context_is_known_ = true; - context_currently_registered_ = true; - if (attempt_to_use_datagram_contexts) { - context_id_ = connect_stream_->GetNextDatagramContextId(); - } - } + connect_stream_->RegisterHttp3DatagramVisitor(this); } void WebTransportHttp3::AssociateStream(QuicStreamId stream_id) { @@ -87,11 +78,7 @@ void WebTransportHttp3::OnConnectStreamClosing() { for (QuicStreamId id : streams) { session_->ResetStream(id, QUIC_STREAM_WEBTRANSPORT_SESSION_GONE); } - if (context_currently_registered_) { - context_currently_registered_ = false; - connect_stream_->UnregisterHttp3DatagramContextId(context_id_); - } - connect_stream_->UnregisterHttp3DatagramRegistrationVisitor(); + connect_stream_->UnregisterHttp3DatagramVisitor(); MaybeNotifyClose(); } @@ -192,7 +179,6 @@ void WebTransportHttp3::HeadersReceived(const spdy::SpdyHeaderBlock& headers) { return; } bool should_validate_version = - session_->http_datagram_support() != HttpDatagramSupport::kDraft00 && session_->ShouldValidateWebTransportVersion(); if (should_validate_version) { auto draft_version_it = headers.find("sec-webtransport-http3-draft"); @@ -283,11 +269,11 @@ WebTransportStream* WebTransportHttp3::OpenOutgoingUnidirectionalStream() { MessageStatus WebTransportHttp3::SendOrQueueDatagram( quiche::QuicheMemSlice datagram) { return connect_stream_->SendHttp3Datagram( - context_id_, absl::string_view(datagram.data(), datagram.length())); + absl::string_view(datagram.data(), datagram.length())); } QuicByteCount WebTransportHttp3::GetMaxDatagramSize() const { - return connect_stream_->GetMaxDatagramSize(context_id_); + return connect_stream_->GetMaxDatagramSize(); } void WebTransportHttp3::SetDatagramMaxTimeInQueue( @@ -295,88 +281,12 @@ void WebTransportHttp3::SetDatagramMaxTimeInQueue( connect_stream_->SetMaxDatagramTimeInQueue(max_time_in_queue); } -void WebTransportHttp3::OnHttp3Datagram( - QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id, - absl::string_view payload) { +void WebTransportHttp3::OnHttp3Datagram(QuicStreamId stream_id, + absl::string_view payload) { QUICHE_DCHECK_EQ(stream_id, connect_stream_->id()); - QUICHE_DCHECK(context_id == context_id_); visitor_->OnDatagramReceived(payload); } -void WebTransportHttp3::OnContextReceived( - QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id, - DatagramFormatType format_type, absl::string_view format_additional_data) { - if (stream_id != connect_stream_->id()) { - QUIC_BUG(WT3 bad datagram context registration) - << ENDPOINT << "Registered stream ID " << stream_id << ", expected " - << connect_stream_->id(); - return; - } - if (format_type != DatagramFormatType::WEBTRANSPORT) { - QUIC_DLOG(INFO) << ENDPOINT << "Ignoring unexpected datagram format type " - << DatagramFormatTypeToString(format_type); - return; - } - if (!format_additional_data.empty()) { - QUIC_DLOG(ERROR) - << ENDPOINT - << "Received non-empty format additional data for context ID " - << (context_id_.has_value() ? context_id_.value() : 0) - << " on stream ID " << connect_stream_->id(); - session_->ResetStream(connect_stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD); - return; - } - if (!context_is_known_) { - context_is_known_ = true; - context_id_ = context_id; - } - if (context_id != context_id_) { - QUIC_DLOG(INFO) << ENDPOINT << "Ignoring unexpected context ID " - << (context_id.has_value() ? context_id.value() : 0) - << " instead of " - << (context_id_.has_value() ? context_id_.value() : 0) - << " on stream ID " << connect_stream_->id(); - return; - } - if (session_->perspective() == Perspective::IS_SERVER) { - if (context_currently_registered_) { - QUIC_DLOG(ERROR) << ENDPOINT << "Received duplicate context ID " - << (context_id_.has_value() ? context_id_.value() : 0) - << " on stream ID " << connect_stream_->id(); - session_->ResetStream(connect_stream_->id(), QUIC_STREAM_CANCELLED); - return; - } - context_currently_registered_ = true; - connect_stream_->RegisterHttp3DatagramContextId( - context_id_, format_type, format_additional_data, this); - } -} - -void WebTransportHttp3::OnContextClosed( - QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id, - ContextCloseCode close_code, absl::string_view close_details) { - if (stream_id != connect_stream_->id()) { - QUIC_BUG(WT3 bad datagram context registration) - << ENDPOINT << "Closed context on stream ID " << stream_id - << ", expected " << connect_stream_->id(); - return; - } - if (context_id != context_id_) { - QUIC_DLOG(INFO) << ENDPOINT << "Ignoring unexpected close of context ID " - << (context_id.has_value() ? context_id.value() : 0) - << " instead of " - << (context_id_.has_value() ? context_id_.value() : 0) - << " on stream ID " << connect_stream_->id(); - return; - } - QUIC_DLOG(INFO) << ENDPOINT - << "Received datagram context close with close code " - << close_code << " close details \"" << close_details - << "\" on stream ID " << connect_stream_->id() - << ", resetting stream"; - session_->ResetStream(connect_stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD); -} - void WebTransportHttp3::MaybeNotifyClose() { if (close_notified_) { return; @@ -437,8 +347,7 @@ bool WebTransportHttp3UnidirectionalStream::ReadSessionId() { // If all of the data has been received, and we still cannot associate the // stream with a session, consume all of the data so that the stream can // be closed. - if (sequencer()->NumBytesConsumed() + sequencer()->NumBytesBuffered() >= - sequencer()->close_offset()) { + if (sequencer()->IsAllDataAvailable()) { QUIC_DLOG(WARNING) << ENDPOINT << "Failed to associate WebTransport stream " << id() << " with a session because the stream ended prematurely."; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.h b/chromium/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.h index 03ed764d6e8..3924a7d41f6 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.h @@ -39,12 +39,10 @@ enum class WebTransportHttp3RejectionReason { // <https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3> class QUIC_EXPORT_PRIVATE WebTransportHttp3 : public WebTransportSession, - public QuicSpdyStream::Http3DatagramRegistrationVisitor, public QuicSpdyStream::Http3DatagramVisitor { public: WebTransportHttp3(QuicSpdySession* session, QuicSpdyStream* connect_stream, - WebTransportSessionId id, - bool attempt_to_use_datagram_contexts); + WebTransportSessionId id); void HeadersReceived(const spdy::SpdyHeaderBlock& headers); void SetVisitor(std::unique_ptr<WebTransportVisitor> visitor) { @@ -53,9 +51,6 @@ class QUIC_EXPORT_PRIVATE WebTransportHttp3 WebTransportSessionId id() { return id_; } bool ready() { return ready_; } - absl::optional<QuicDatagramContextId> context_id() const { - return context_id_; - } void AssociateStream(QuicStreamId stream_id); void OnStreamClosed(QuicStreamId stream_id) { streams_.erase(stream_id); } @@ -91,19 +86,8 @@ class QUIC_EXPORT_PRIVATE WebTransportHttp3 // From QuicSpdyStream::Http3DatagramVisitor. void OnHttp3Datagram(QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, absl::string_view payload) override; - // From QuicSpdyStream::Http3DatagramRegistrationVisitor. - void OnContextReceived(QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - DatagramFormatType format_type, - absl::string_view format_additional_data) override; - void OnContextClosed(QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - ContextCloseCode close_code, - absl::string_view close_details) override; - bool close_received() const { return close_received_; } WebTransportHttp3RejectionReason rejection_reason() const { return rejection_reason_; @@ -117,15 +101,8 @@ class QUIC_EXPORT_PRIVATE WebTransportHttp3 QuicSpdySession* const session_; // Unowned. QuicSpdyStream* const connect_stream_; // Unowned. const WebTransportSessionId id_; - absl::optional<QuicDatagramContextId> context_id_; // |ready_| is set to true when the peer has seen both sets of headers. bool ready_ = false; - // Whether we know which |context_id_| to use. On the client this is always - // true, and on the server it becomes true when we receive a context - // registration capsule. - bool context_is_known_ = false; - // Whether |context_id_| is currently registered with |connect_stream_|. - bool context_currently_registered_ = false; std::unique_ptr<WebTransportVisitor> visitor_; absl::flat_hash_set<QuicStreamId> streams_; quiche::QuicheCircularDeque<QuicStreamId> incoming_bidirectional_streams_; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/packet_number_indexed_queue_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/packet_number_indexed_queue_test.cc index b8a5b2af5c9..f05309beca2 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/packet_number_indexed_queue_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/packet_number_indexed_queue_test.cc @@ -11,7 +11,7 @@ #include "quiche/quic/core/quic_packet_number.h" #include "quiche/quic/platform/api/quic_test.h" -namespace quic { +namespace quic::test { namespace { class PacketNumberIndexedQueueTest : public QuicTest { @@ -202,4 +202,4 @@ TEST_F(PacketNumberIndexedQueueTest, ConstGetter) { } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_blocking_manager.h b/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_blocking_manager.h index 4fc1029ed1f..46e75b803e7 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_blocking_manager.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_blocking_manager.h @@ -11,7 +11,6 @@ #include "absl/container/flat_hash_map.h" #include "quiche/quic/core/quic_types.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_export.h" namespace quic { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_header_table.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_header_table.cc index d0386f2f2bf..d5b834df5f3 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_header_table.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_header_table.cc @@ -7,6 +7,7 @@ #include "absl/strings/string_view.h" #include "quiche/quic/core/qpack/qpack_static_table.h" #include "quiche/quic/platform/api/quic_logging.h" +#include "quiche/common/platform/api/quiche_logging.h" namespace quic { @@ -232,7 +233,7 @@ void QpackDecoderHeaderTable::UnregisterObserver(uint64_t required_insert_count, } // |observer| must have been registered. - QUIC_NOTREACHED(); + QUICHE_NOTREACHED(); } } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instructions.h b/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instructions.h index 212f093e715..a96424278c0 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instructions.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instructions.h @@ -71,6 +71,9 @@ using QpackInstructionFields = std::vector<QpackInstructionField>; // string literal type to guarantee that all bytes of the instruction are // consumed. struct QUIC_EXPORT_PRIVATE QpackInstruction { + QpackInstruction(QpackInstructionOpcode opcode, QpackInstructionFields fields) + : opcode(std::move(opcode)), fields(std::move(fields)) {} + QpackInstruction(const QpackInstruction&) = delete; const QpackInstruction& operator=(const QpackInstruction&) = delete; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_send_stream.h b/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_send_stream.h index 2d8f3f1102f..8c9a764345f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_send_stream.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_send_stream.h @@ -11,6 +11,7 @@ #include "quiche/quic/core/qpack/qpack_stream_sender_delegate.h" #include "quiche/quic/core/quic_stream.h" #include "quiche/quic/platform/api/quic_export.h" +#include "quiche/common/platform/api/quiche_logging.h" namespace quic { @@ -36,7 +37,7 @@ class QUIC_EXPORT_PRIVATE QpackSendStream : public QuicStream, // The send QPACK stream is write unidirectional, so this method // should never be called. - void OnDataAvailable() override { QUIC_NOTREACHED(); } + void OnDataAvailable() override { QUICHE_NOTREACHED(); } // Writes the instructions to peer. The stream type will be sent // before the first instruction so that the peer can open an qpack stream. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_arena_scoped_ptr_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_arena_scoped_ptr_test.cc index 18d4fdff8fc..fd6dd640f7c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_arena_scoped_ptr_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_arena_scoped_ptr_test.cc @@ -7,7 +7,7 @@ #include "quiche/quic/core/quic_one_block_arena.h" #include "quiche/quic/platform/api/quic_test.h" -namespace quic { +namespace quic::test { namespace { enum class TestParam { kFromHeap, kFromArena }; @@ -112,4 +112,4 @@ TEST_P(QuicArenaScopedPtrParamTest, Swap) { } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_bandwidth_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_bandwidth_test.cc index 5f32f11f681..2d2f99471fb 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_bandwidth_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_bandwidth_test.cc @@ -83,21 +83,21 @@ TEST_F(QuicBandwidthTest, Scale) { } TEST_F(QuicBandwidthTest, BytesPerPeriod) { - EXPECT_EQ(2000u, QuicBandwidth::FromKBytesPerSecond(2000).ToBytesPerPeriod( - QuicTime::Delta::FromMilliseconds(1))); - EXPECT_EQ(2u, QuicBandwidth::FromKBytesPerSecond(2000).ToKBytesPerPeriod( - QuicTime::Delta::FromMilliseconds(1))); - EXPECT_EQ(200000u, QuicBandwidth::FromKBytesPerSecond(2000).ToBytesPerPeriod( - QuicTime::Delta::FromMilliseconds(100))); - EXPECT_EQ(200u, QuicBandwidth::FromKBytesPerSecond(2000).ToKBytesPerPeriod( - QuicTime::Delta::FromMilliseconds(100))); + EXPECT_EQ(2000, QuicBandwidth::FromKBytesPerSecond(2000).ToBytesPerPeriod( + QuicTime::Delta::FromMilliseconds(1))); + EXPECT_EQ(2, QuicBandwidth::FromKBytesPerSecond(2000).ToKBytesPerPeriod( + QuicTime::Delta::FromMilliseconds(1))); + EXPECT_EQ(200000, QuicBandwidth::FromKBytesPerSecond(2000).ToBytesPerPeriod( + QuicTime::Delta::FromMilliseconds(100))); + EXPECT_EQ(200, QuicBandwidth::FromKBytesPerSecond(2000).ToKBytesPerPeriod( + QuicTime::Delta::FromMilliseconds(100))); // 1599 * 1001 = 1600599 bits/ms = 200.074875 bytes/s. - EXPECT_EQ(200u, QuicBandwidth::FromBitsPerSecond(1599).ToBytesPerPeriod( - QuicTime::Delta::FromMilliseconds(1001))); + EXPECT_EQ(200, QuicBandwidth::FromBitsPerSecond(1599).ToBytesPerPeriod( + QuicTime::Delta::FromMilliseconds(1001))); - EXPECT_EQ(200u, QuicBandwidth::FromBitsPerSecond(1599).ToKBytesPerPeriod( - QuicTime::Delta::FromSeconds(1001))); + EXPECT_EQ(200, QuicBandwidth::FromBitsPerSecond(1599).ToKBytesPerPeriod( + QuicTime::Delta::FromSeconds(1001))); } TEST_F(QuicBandwidthTest, TransferTime) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.cc index d5aa841d79a..0269cdfddd8 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.cc @@ -6,6 +6,10 @@ #include <string> +#include "absl/strings/string_view.h" +#include "quiche/quic/core/quic_connection_id.h" +#include "quiche/quic/core/quic_types.h" +#include "quiche/quic/core/quic_versions.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/quic/platform/api/quic_flags.h" @@ -176,6 +180,39 @@ BufferedPacketList QuicBufferedPacketStore::DeliverPackets( if (it != undecryptable_packets_.end()) { packets_to_deliver = std::move(it->second); undecryptable_packets_.erase(connection_id); + if (GetQuicReloadableFlag(quic_deliver_initial_packets_first)) { + QUIC_RELOADABLE_FLAG_COUNT(quic_deliver_initial_packets_first); + std::list<BufferedPacket> initial_packets; + std::list<BufferedPacket> other_packets; + for (auto& packet : packets_to_deliver.buffered_packets) { + QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE; + PacketHeaderFormat unused_format; + bool unused_version_flag; + bool unused_use_length_prefix; + QuicVersionLabel unused_version_label; + ParsedQuicVersion unused_parsed_version = UnsupportedQuicVersion(); + QuicConnectionId unused_destination_connection_id; + QuicConnectionId unused_source_connection_id; + absl::optional<absl::string_view> unused_retry_token; + std::string unused_detailed_error; + + QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher( + *packet.packet, kQuicDefaultConnectionIdLength, &unused_format, + &long_packet_type, &unused_version_flag, &unused_use_length_prefix, + &unused_version_label, &unused_parsed_version, + &unused_destination_connection_id, &unused_source_connection_id, + &unused_retry_token, &unused_detailed_error); + + if (error_code == QUIC_NO_ERROR && long_packet_type == INITIAL) { + initial_packets.push_back(std::move(packet)); + } else { + other_packets.push_back(std::move(packet)); + } + } + + initial_packets.splice(initial_packets.end(), other_packets); + packets_to_deliver.buffered_packets = std::move(initial_packets); + } } return packets_to_deliver; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store_test.cc index b6d65e1b1c9..012ae6e4fad 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store_test.cc @@ -5,8 +5,13 @@ #include "quiche/quic/core/quic_buffered_packet_store.h" #include <list> +#include <memory> #include <string> +#include "quiche/quic/core/crypto/transport_parameters.h" +#include "quiche/quic/core/quic_connection_id.h" +#include "quiche/quic/core/quic_error_codes.h" +#include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_versions.h" #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_test.h" @@ -30,7 +35,14 @@ const absl::optional<ParsedClientHello> kDefaultParsedChlo = using BufferedPacket = QuicBufferedPacketStore::BufferedPacket; using BufferedPacketList = QuicBufferedPacketStore::BufferedPacketList; using EnqueuePacketResult = QuicBufferedPacketStore::EnqueuePacketResult; +using ::testing::A; +using ::testing::Conditional; +using ::testing::Each; using ::testing::ElementsAre; +using ::testing::Ne; +using ::testing::SizeIs; +using ::testing::Truly; + class QuicBufferedPacketStoreVisitor : public QuicBufferedPacketStore::VisitorInterface { public: @@ -497,6 +509,94 @@ TEST_F(QuicBufferedPacketStoreTest, IngestPacketForTlsChloExtraction) { EXPECT_FALSE(resumption_attempted); EXPECT_FALSE(early_data_attempted); } + +TEST_F(QuicBufferedPacketStoreTest, DeliverInitialPacketsFirst) { + QuicConfig config; + QuicConnectionId connection_id = TestConnectionId(1); + + // Force the TLS CHLO to span multiple packets. + constexpr auto kCustomParameterId = + static_cast<TransportParameters::TransportParameterId>(0xff33); + std::string custom_parameter_value(2000, '-'); + config.custom_transport_parameters_to_send()[kCustomParameterId] = + custom_parameter_value; + auto initial_packets = GetFirstFlightOfPackets(valid_version_, config); + ASSERT_THAT(initial_packets, SizeIs(2)); + + // Verify that the packets generated are INITIAL packets. + EXPECT_THAT( + initial_packets, + Each(Truly([](const std::unique_ptr<QuicReceivedPacket>& packet) { + QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE; + PacketHeaderFormat unused_format; + bool unused_version_flag; + bool unused_use_length_prefix; + QuicVersionLabel unused_version_label; + ParsedQuicVersion unused_parsed_version = UnsupportedQuicVersion(); + QuicConnectionId unused_destination_connection_id; + QuicConnectionId unused_source_connection_id; + absl::optional<absl::string_view> unused_retry_token; + std::string unused_detailed_error; + QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher( + *packet, kQuicDefaultConnectionIdLength, &unused_format, + &long_packet_type, &unused_version_flag, &unused_use_length_prefix, + &unused_version_label, &unused_parsed_version, + &unused_destination_connection_id, &unused_source_connection_id, + &unused_retry_token, &unused_detailed_error); + return error_code == QUIC_NO_ERROR && long_packet_type == INITIAL; + }))); + + QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE; + PacketHeaderFormat unused_format; + bool unused_version_flag; + bool unused_use_length_prefix; + QuicVersionLabel unused_version_label; + ParsedQuicVersion unused_parsed_version = UnsupportedQuicVersion(); + QuicConnectionId unused_destination_connection_id; + QuicConnectionId unused_source_connection_id; + absl::optional<absl::string_view> unused_retry_token; + std::string unused_detailed_error; + QuicErrorCode error_code = QUIC_NO_ERROR; + + // Verify that packet_ is not an INITIAL packet. + error_code = QuicFramer::ParsePublicHeaderDispatcher( + packet_, kQuicDefaultConnectionIdLength, &unused_format, + &long_packet_type, &unused_version_flag, &unused_use_length_prefix, + &unused_version_label, &unused_parsed_version, + &unused_destination_connection_id, &unused_source_connection_id, + &unused_retry_token, &unused_detailed_error); + EXPECT_THAT(error_code, IsQuicNoError()); + EXPECT_NE(long_packet_type, INITIAL); + + store_.EnqueuePacket(connection_id, false, packet_, self_address_, + peer_address_, valid_version_, kNoParsedChlo); + store_.EnqueuePacket(connection_id, false, *initial_packets[0], self_address_, + peer_address_, valid_version_, kNoParsedChlo); + store_.EnqueuePacket(connection_id, false, *initial_packets[1], self_address_, + peer_address_, valid_version_, kNoParsedChlo); + + BufferedPacketList delivered_packets = store_.DeliverPackets(connection_id); + EXPECT_THAT(delivered_packets.buffered_packets, SizeIs(3)); + + QuicLongHeaderType previous_packet_type = INITIAL; + for (const auto& packet : delivered_packets.buffered_packets) { + error_code = QuicFramer::ParsePublicHeaderDispatcher( + *packet.packet, kQuicDefaultConnectionIdLength, &unused_format, + &long_packet_type, &unused_version_flag, &unused_use_length_prefix, + &unused_version_label, &unused_parsed_version, + &unused_destination_connection_id, &unused_source_connection_id, + &unused_retry_token, &unused_detailed_error); + EXPECT_THAT(error_code, IsQuicNoError()); + + if (GetQuicReloadableFlag(quic_deliver_initial_packets_first)) { + // INITIAL packets should not follow a non-INITIAL packet. + EXPECT_THAT(long_packet_type, + Conditional(previous_packet_type == INITIAL, + A<QuicLongHeaderType>(), Ne(INITIAL))); + previous_packet_type = long_packet_type; + } + } +} } // namespace } // namespace test } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_clock.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_clock.cc index 94ca72f9876..571dc599d5c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_clock.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_clock.cc @@ -10,46 +10,8 @@ namespace quic { -QuicClock::QuicClock() - : is_calibrated_(false), calibration_offset_(QuicTime::Delta::Zero()) {} - -QuicClock::~QuicClock() {} - -QuicTime::Delta QuicClock::ComputeCalibrationOffset() const { - // In the ideal world, all we need to do is to return the difference of - // WallNow() and Now(). In the real world, things like context switch may - // happen between the calls to WallNow() and Now(), causing their difference - // to be arbitrarily large, so we repeat the calculation many times and use - // the one with the minimum difference as the true offset. - int64_t min_offset_us = std::numeric_limits<int64_t>::max(); - - for (int i = 0; i < 128; ++i) { - int64_t now_in_us = (Now() - QuicTime::Zero()).ToMicroseconds(); - int64_t wallnow_in_us = - static_cast<int64_t>(WallNow().ToUNIXMicroseconds()); - - int64_t offset_us = wallnow_in_us - now_in_us; - if (offset_us < min_offset_us) { - min_offset_us = offset_us; - } - } - - return QuicTime::Delta::FromMicroseconds(min_offset_us); -} - -void QuicClock::SetCalibrationOffset(QuicTime::Delta offset) { - QUICHE_DCHECK(!is_calibrated_) << "A clock should only be calibrated once"; - calibration_offset_ = offset; - is_calibrated_ = true; -} - QuicTime QuicClock::ConvertWallTimeToQuicTime( const QuicWallTime& walltime) const { - if (is_calibrated_) { - int64_t time_in_us = static_cast<int64_t>(walltime.ToUNIXMicroseconds()) - - calibration_offset_.ToMicroseconds(); - return QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(time_in_us); - } // .......................... // | | | diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_clock.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_clock.h index f128f9e4eef..69aed4e4d9e 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_clock.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_clock.h @@ -18,25 +18,12 @@ namespace quic { // Interface for retrieving the current time. class QUIC_EXPORT_PRIVATE QuicClock { public: - QuicClock(); - virtual ~QuicClock(); + QuicClock() = default; + virtual ~QuicClock() = default; QuicClock(const QuicClock&) = delete; QuicClock& operator=(const QuicClock&) = delete; - // Compute the offset between this clock with the Unix Epoch clock. - // Return the calibrated offset between WallNow() and Now(), in the form of - // (wallnow_in_us - now_in_us). - // The return value can be used by SetCalibrationOffset() to actually - // calibrate the clock, or all instances of this clock type. - QuicTime::Delta ComputeCalibrationOffset() const; - - // Calibrate this clock. A calibrated clock guarantees that the - // ConvertWallTimeToQuicTime() function always return the same result for the - // same walltime. - // Should not be called more than once for each QuicClock. - void SetCalibrationOffset(QuicTime::Delta offset); - // Returns the approximate current time as a QuicTime object. virtual QuicTime ApproximateNow() const = 0; @@ -57,14 +44,6 @@ class QUIC_EXPORT_PRIVATE QuicClock { QuicTime CreateTimeFromMicroseconds(uint64_t time_us) const { return QuicTime(time_us); } - - private: - // True if |calibration_offset_| is valid. - bool is_calibrated_; - // If |is_calibrated_|, |calibration_offset_| is the (fixed) offset between - // the Unix Epoch clock and this clock. - // In other words, the offset between WallNow() and Now(). - QuicTime::Delta calibration_offset_; }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc index de739d6d639..92db72835af 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc @@ -34,6 +34,7 @@ #include "quiche/quic/core/quic_legacy_version_encapsulator.h" #include "quiche/quic/core/quic_packet_creator.h" #include "quiche/quic/core/quic_packet_writer.h" +#include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_path_validator.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_utils.h" @@ -127,6 +128,7 @@ class PingAlarmDelegate : public QuicConnectionAlarmDelegate { void OnAlarm() override { QUICHE_DCHECK(connection_->connected()); + QUICHE_DCHECK(!GetQuicReloadableFlag(quic_use_ping_manager2)); connection_->OnPingTimeout(); } }; @@ -210,6 +212,20 @@ CongestionControlType GetDefaultCongestionControlType() { return kCubicBytes; } +bool ContainsNonProbingFrame(const SerializedPacket& packet) { + for (const QuicFrame& frame : packet.nonretransmittable_frames) { + if (!QuicUtils::IsProbingFrame(frame.type)) { + return true; + } + } + for (const QuicFrame& frame : packet.retransmittable_frames) { + if (!QuicUtils::IsProbingFrame(frame.type)) { + return true; + } + } + return false; +} + } // namespace #define ENDPOINT \ @@ -244,10 +260,7 @@ QuicConnection::QuicConnection( /*stateless_reset_token=*/absl::nullopt), active_effective_peer_migration_type_(NO_CHANGE), support_key_update_for_connection_(false), - last_packet_decrypted_(false), - last_size_(0), current_packet_data_(nullptr), - last_decrypted_packet_level_(ENCRYPTION_INITIAL), should_last_packet_instigate_acks_(false), max_undecryptable_packets_(0), max_tracked_packets_(GetQuicFlag(FLAGS_quic_max_tracked_packet_count)), @@ -258,7 +271,7 @@ QuicConnection::QuicConnection( stop_waiting_count_(0), pending_retransmission_alarm_(false), defer_send_in_response_to_packets_(false), - ping_timeout_(QuicTime::Delta::FromSeconds(kPingTimeoutSecs)), + keep_alive_ping_timeout_(QuicTime::Delta::FromSeconds(kPingTimeoutSecs)), initial_retransmittable_on_wire_timeout_(QuicTime::Delta::Infinite()), consecutive_retransmittable_on_wire_ping_count_(0), retransmittable_on_wire_ping_count_(0), @@ -300,8 +313,6 @@ QuicConnection::QuicConnection( max_consecutive_num_packets_with_no_retransmittable_frames_( kMaxConsecutiveNonRetransmittablePackets), bundle_retransmittable_with_pto_ack_(false), - fill_up_link_during_probing_(false), - probing_retransmission_pending_(false), last_control_frame_id_(kInvalidControlFrameId), is_path_degrading_(false), processing_ack_frame_(false), @@ -312,7 +323,7 @@ QuicConnection::QuicConnection( alarm_factory_, &context_), path_validator_(alarm_factory_, &arena_, this, random_generator_, &context_), - most_recent_frame_type_(NUM_FRAME_TYPES) { + ping_manager_(perspective, this, &arena_, alarm_factory_, &context_) { QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT || default_path_.self_address.IsInitialized()); @@ -572,6 +583,16 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) { if (config.HasClientRequestedIndependentOption(kFIDT, perspective_)) { idle_network_detector_.enable_shorter_idle_timeout_on_sent_packet(); } + if (perspective_ == Perspective::IS_CLIENT && version().HasIetfQuicFrames()) { + // Only conduct those experiments in IETF QUIC because random packets may + // elicit reset and gQUIC PUBLIC_RESET will cause connection close. + if (config.HasClientRequestedIndependentOption(kROWF, perspective_)) { + retransmittable_on_wire_behavior_ = SEND_FIRST_FORWARD_SECURE_PACKET; + } + if (config.HasClientRequestedIndependentOption(kROWR, perspective_)) { + retransmittable_on_wire_behavior_ = SEND_RANDOM_BYTES; + } + } if (config.HasClientRequestedIndependentOption(k3AFF, perspective_)) { anti_amplification_factor_ = 3; } @@ -594,12 +615,10 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) { if (config.HasClientSentConnectionOption(k5RTO, perspective_)) { num_rtos_for_blackhole_detection_ = 5; } - if (sent_packet_manager_.pto_enabled()) { - if (config.HasClientSentConnectionOption(k6PTO, perspective_) || - config.HasClientSentConnectionOption(k7PTO, perspective_) || - config.HasClientSentConnectionOption(k8PTO, perspective_)) { - num_rtos_for_blackhole_detection_ = 5; - } + if (config.HasClientSentConnectionOption(k6PTO, perspective_) || + config.HasClientSentConnectionOption(k7PTO, perspective_) || + config.HasClientSentConnectionOption(k8PTO, perspective_)) { + num_rtos_for_blackhole_detection_ = 5; } if (config.HasClientSentConnectionOption(kNSTP, perspective_)) { no_stop_waiting_frames_ = true; @@ -628,11 +647,8 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) { quic_remove_connection_migration_connection_option_v2); } if (framer_.version().HasIetfQuicFrames() && - count_bytes_on_alternative_path_separately_ && - GetQuicReloadableFlag(quic_server_reverse_validate_new_path3) && (remove_connection_migration_connection_option || config.HasClientSentConnectionOption(kRVCM, perspective_))) { - QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 6, 6); validate_client_addresses_ = true; } // Having connection_migration_use_new_cid_ depends on the same set of flags @@ -790,14 +806,16 @@ bool QuicConnection::SelectMutualVersion( void QuicConnection::OnError(QuicFramer* framer) { // Packets that we can not or have not decrypted are dropped. // TODO(rch): add stats to measure this. - if (!connected_ || last_packet_decrypted_ == false) { + if (!connected_ || !last_received_packet_info_.decrypted) { return; } CloseConnection(framer->error(), framer->detailed_error(), ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); } -void QuicConnection::OnPacket() { last_packet_decrypted_ = false; } +void QuicConnection::OnPacket() { + last_received_packet_info_.decrypted = false; +} void QuicConnection::OnPublicResetPacket(const QuicPublicResetPacket& packet) { // Check that any public reset packet with a different connection ID that was @@ -988,15 +1006,16 @@ bool QuicConnection::ValidateServerConnectionId( bool QuicConnection::OnUnauthenticatedPublicHeader( const QuicPacketHeader& header) { - last_packet_destination_connection_id_ = header.destination_connection_id; + last_received_packet_info_.destination_connection_id = + header.destination_connection_id; // If last packet destination connection ID is the original server // connection ID chosen by client, replaces it with the connection ID chosen // by server. if (perspective_ == Perspective::IS_SERVER && original_destination_connection_id_.has_value() && - last_packet_destination_connection_id_ == + last_received_packet_info_.destination_connection_id == *original_destination_connection_id_) { - last_packet_destination_connection_id_ = + last_received_packet_info_.destination_connection_id = original_destination_connection_id_replacement_; } @@ -1139,8 +1158,8 @@ void QuicConnection::OnUserAgentIdKnown(const std::string& /*user_agent_id*/) { void QuicConnection::OnDecryptedPacket(size_t /*length*/, EncryptionLevel level) { - last_decrypted_packet_level_ = level; - last_packet_decrypted_ = true; + last_received_packet_info_.decrypted_level = level; + last_received_packet_info_.decrypted = true; if (level == ENCRYPTION_FORWARD_SECURE && !have_decrypted_first_one_rtt_packet_) { have_decrypted_first_one_rtt_packet_ = true; @@ -1156,8 +1175,7 @@ void QuicConnection::OnDecryptedPacket(size_t /*length*/, } } if (EnforceAntiAmplificationLimit() && !IsHandshakeConfirmed() && - (last_decrypted_packet_level_ == ENCRYPTION_HANDSHAKE || - last_decrypted_packet_level_ == ENCRYPTION_FORWARD_SECURE)) { + (level == ENCRYPTION_HANDSHAKE || level == ENCRYPTION_FORWARD_SECURE)) { // Address is validated by successfully processing a HANDSHAKE or 1-RTT // packet. default_path_.validated = true; @@ -1179,7 +1197,7 @@ QuicSocketAddress QuicConnection::GetEffectivePeerAddressFromCurrentPacket() bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) { if (debug_visitor_ != nullptr) { debug_visitor_->OnPacketHeader(header, clock_->ApproximateNow(), - last_decrypted_packet_level_); + last_received_packet_info_.decrypted_level); } // Will be decremented below if we fall through to return true. @@ -1190,7 +1208,6 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) { } // Initialize the current packet content state. - most_recent_frame_type_ = NUM_FRAME_TYPES; current_packet_content_ = NO_FRAMES_RECEIVED; is_current_packet_connectivity_probing_ = false; has_path_challenge_in_current_packet_ = false; @@ -1233,30 +1250,30 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) { // connection ID set on path. // 1) If client uses 1 unique server connection ID per path and the packet // is received from an existing path, then - // last_packet_destination_connection_id_ will always be the same as the - // server connection ID on path. Server side will maintain the 1-to-1 - // mapping from server connection ID to path. - // 2) If client uses multiple server connection IDs on the same path, - // compared to the server_connection_id on path, - // last_packet_destination_connection_id_ has the advantage that it is - // still present in the session map since the packet can be routed here - // regardless of packet reordering. + // last_received_packet_info_.destination_connection_id will always be the + // same as the server connection ID on path. Server side will maintain the + // 1-to-1 mapping from server connection ID to path. 2) If client uses + // multiple server connection IDs on the same path, compared to the + // server_connection_id on path, + // last_received_packet_info_.destination_connection_id has the advantage + // that it is still present in the session map since the packet can be + // routed here regardless of packet reordering. if (IsDefaultPath(last_received_packet_info_.destination_address, effective_peer_address)) { default_path_.server_connection_id = - last_packet_destination_connection_id_; + last_received_packet_info_.destination_connection_id; } else if (IsAlternativePath( last_received_packet_info_.destination_address, effective_peer_address)) { alternative_path_.server_connection_id = - last_packet_destination_connection_id_; + last_received_packet_info_.destination_connection_id; } } - if (last_packet_destination_connection_id_ != + if (last_received_packet_info_.destination_connection_id != default_path_.server_connection_id && (!original_destination_connection_id_.has_value() || - last_packet_destination_connection_id_ != + last_received_packet_info_.destination_connection_id != *original_destination_connection_id_)) { QUIC_CODE_COUNT(quic_connection_id_change); } @@ -1271,9 +1288,10 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) { --stats_.packets_dropped; QUIC_DVLOG(1) << ENDPOINT << "Received packet header: " << header; - last_header_ = header; + last_received_packet_info_.header = header; if (!stats_.first_decrypted_packet.IsInitialized()) { - stats_.first_decrypted_packet = last_header_.packet_number; + stats_.first_decrypted_packet = + last_received_packet_info_.header.packet_number; } // Record packet receipt to populate ack info before processing stream @@ -1283,7 +1301,8 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) { receipt_time = last_received_packet_info_.receipt_time; } uber_received_packet_manager_.RecordPacketReceived( - last_decrypted_packet_level_, last_header_, receipt_time); + last_received_packet_info_.decrypted_level, + last_received_packet_info_.header, receipt_time); if (EnforceAntiAmplificationLimit() && !IsHandshakeConfirmed() && !header.retry_token.empty() && visitor_->ValidateToken(header.retry_token)) { @@ -1298,8 +1317,9 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) { bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) { QUIC_BUG_IF(quic_bug_12714_3, !connected_) - << "Processing STREAM frame when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing STREAM frame when connection is closed. Received packet " + "info: " + << last_received_packet_info_; // Since a stream frame was received, this is not a connectivity probe. // A probe only contains a PING and full padding. @@ -1311,7 +1331,7 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) { debug_visitor_->OnStreamFrame(frame); } if (!QuicUtils::IsCryptoStreamId(transport_version(), frame.stream_id) && - last_decrypted_packet_level_ == ENCRYPTION_INITIAL) { + last_received_packet_info_.decrypted_level == ENCRYPTION_INITIAL) { if (MaybeConsiderAsMemoryCorruption(frame)) { CloseConnection(QUIC_MAYBE_CORRUPTED_MEMORY, "Received crypto frame on non crypto stream.", @@ -1321,7 +1341,7 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) { QUIC_PEER_BUG(quic_peer_bug_10511_6) << ENDPOINT << "Received an unencrypted data frame: closing connection" - << " packet_number:" << last_header_.packet_number + << " packet_number:" << last_received_packet_info_.header.packet_number << " stream_id:" << frame.stream_id << " received_packets:" << ack_frame(); CloseConnection(QUIC_UNENCRYPTED_STREAM_DATA, @@ -1335,14 +1355,19 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) { MaybeUpdateAckTimeout(); visitor_->OnStreamFrame(frame); stats_.stream_bytes_received += frame.data_length; - consecutive_retransmittable_on_wire_ping_count_ = 0; + if (use_ping_manager_) { + ping_manager_.reset_consecutive_retransmittable_on_wire_count(); + } else { + consecutive_retransmittable_on_wire_ping_count_ = 0; + } return connected_; } bool QuicConnection::OnCryptoFrame(const QuicCryptoFrame& frame) { QUIC_BUG_IF(quic_bug_12714_4, !connected_) - << "Processing CRYPTO frame when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing CRYPTO frame when connection is closed. Received packet " + "info: " + << last_received_packet_info_; // Since a CRYPTO frame was received, this is not a connectivity probe. // A probe only contains a PING and full padding. @@ -1361,8 +1386,9 @@ bool QuicConnection::OnCryptoFrame(const QuicCryptoFrame& frame) { bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked, QuicTime::Delta ack_delay_time) { QUIC_BUG_IF(quic_bug_12714_5, !connected_) - << "Processing ACK frame start when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing ACK frame start when connection is closed. Received " + "packet info: " + << last_received_packet_info_; if (processing_ack_frame_) { CloseConnection(QUIC_INVALID_ACK_DATA, @@ -1381,7 +1407,8 @@ bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked, << "OnAckFrameStart, largest_acked: " << largest_acked; if (GetLargestReceivedPacketWithAck().IsInitialized() && - last_header_.packet_number <= GetLargestReceivedPacketWithAck()) { + last_received_packet_info_.header.packet_number <= + GetLargestReceivedPacketWithAck()) { QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring"; return true; } @@ -1393,8 +1420,8 @@ bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked, << " vs " << sent_packet_manager_.GetLargestSentPacket() << ". SupportsMultiplePacketNumberSpaces():" << SupportsMultiplePacketNumberSpaces() - << ", last_decrypted_packet_level_:" - << last_decrypted_packet_level_; + << ", last_received_packet_info_.decrypted_level:" + << last_received_packet_info_.decrypted_level; // We got an ack for data we have not sent. CloseConnection(QUIC_INVALID_ACK_DATA, "Largest observed too high.", ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); @@ -1409,12 +1436,14 @@ bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked, bool QuicConnection::OnAckRange(QuicPacketNumber start, QuicPacketNumber end) { QUIC_BUG_IF(quic_bug_12714_6, !connected_) - << "Processing ACK frame range when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing ACK frame range when connection is closed. Received " + "packet info: " + << last_received_packet_info_; QUIC_DVLOG(1) << ENDPOINT << "OnAckRange: [" << start << ", " << end << ")"; if (GetLargestReceivedPacketWithAck().IsInitialized() && - last_header_.packet_number <= GetLargestReceivedPacketWithAck()) { + last_received_packet_info_.header.packet_number <= + GetLargestReceivedPacketWithAck()) { QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring"; return true; } @@ -1426,14 +1455,15 @@ bool QuicConnection::OnAckRange(QuicPacketNumber start, QuicPacketNumber end) { bool QuicConnection::OnAckTimestamp(QuicPacketNumber packet_number, QuicTime timestamp) { QUIC_BUG_IF(quic_bug_10511_7, !connected_) - << "Processing ACK frame time stamp when connection " - "is closed. Last frame: " - << most_recent_frame_type_; + << "Processing ACK frame time stamp when connection is closed. Received " + "packet info: " + << last_received_packet_info_; QUIC_DVLOG(1) << ENDPOINT << "OnAckTimestamp: [" << packet_number << ", " << timestamp.ToDebuggingValue() << ")"; if (GetLargestReceivedPacketWithAck().IsInitialized() && - last_header_.packet_number <= GetLargestReceivedPacketWithAck()) { + last_received_packet_info_.header.packet_number <= + GetLargestReceivedPacketWithAck()) { QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring"; return true; } @@ -1444,12 +1474,14 @@ bool QuicConnection::OnAckTimestamp(QuicPacketNumber packet_number, bool QuicConnection::OnAckFrameEnd(QuicPacketNumber start) { QUIC_BUG_IF(quic_bug_12714_7, !connected_) - << "Processing ACK frame end when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing ACK frame end when connection is closed. Received packet " + "info: " + << last_received_packet_info_; QUIC_DVLOG(1) << ENDPOINT << "OnAckFrameEnd, start: " << start; if (GetLargestReceivedPacketWithAck().IsInitialized() && - last_header_.packet_number <= GetLargestReceivedPacketWithAck()) { + last_received_packet_info_.header.packet_number <= + GetLargestReceivedPacketWithAck()) { QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring"; return true; } @@ -1459,7 +1491,8 @@ bool QuicConnection::OnAckFrameEnd(QuicPacketNumber start) { sent_packet_manager_.zero_rtt_packet_acked(); const AckResult ack_result = sent_packet_manager_.OnAckFrameEnd( idle_network_detector_.time_of_last_received_packet(), - last_header_.packet_number, last_decrypted_packet_level_); + last_received_packet_info_.header.packet_number, + last_received_packet_info_.decrypted_level); if (ack_result != PACKETS_NEWLY_ACKED && ack_result != NO_PACKETS_NEWLY_ACKED) { // Error occurred (e.g., this ACK tries to ack packets in wrong packet @@ -1488,7 +1521,8 @@ bool QuicConnection::OnAckFrameEnd(QuicPacketNumber start) { // Update pace time into future because smoothed RTT is likely updated. UpdateReleaseTimeIntoFuture(); } - SetLargestReceivedPacketWithAck(last_header_.packet_number); + SetLargestReceivedPacketWithAck( + last_received_packet_info_.header.packet_number); // If the incoming ack's packets set expresses missing packets: peer is still // waiting for a packet lower than a packet that we are no longer planning to // send. @@ -1505,8 +1539,9 @@ bool QuicConnection::OnAckFrameEnd(QuicPacketNumber start) { bool QuicConnection::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) { QUIC_BUG_IF(quic_bug_12714_8, !connected_) - << "Processing STOP_WAITING frame when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing STOP_WAITING frame when connection is closed. Received " + "packet info: " + << last_received_packet_info_; // Since a stop waiting frame was received, this is not a connectivity probe. // A probe only contains a PING and full padding. @@ -1518,7 +1553,8 @@ bool QuicConnection::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) { return true; } if (largest_seen_packet_with_stop_waiting_.IsInitialized() && - last_header_.packet_number <= largest_seen_packet_with_stop_waiting_) { + last_received_packet_info_.header.packet_number <= + largest_seen_packet_with_stop_waiting_) { QUIC_DLOG(INFO) << ENDPOINT << "Received an old stop waiting frame: ignoring"; return true; @@ -1535,16 +1571,18 @@ bool QuicConnection::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) { debug_visitor_->OnStopWaitingFrame(frame); } - largest_seen_packet_with_stop_waiting_ = last_header_.packet_number; + largest_seen_packet_with_stop_waiting_ = + last_received_packet_info_.header.packet_number; uber_received_packet_manager_.DontWaitForPacketsBefore( - last_decrypted_packet_level_, frame.least_unacked); + last_received_packet_info_.decrypted_level, frame.least_unacked); return connected_; } bool QuicConnection::OnPaddingFrame(const QuicPaddingFrame& frame) { QUIC_BUG_IF(quic_bug_12714_9, !connected_) - << "Processing PADDING frame when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing PADDING frame when connection is closed. Received packet " + "info: " + << last_received_packet_info_; if (!UpdatePacketContent(PADDING_FRAME)) { return false; } @@ -1557,8 +1595,9 @@ bool QuicConnection::OnPaddingFrame(const QuicPaddingFrame& frame) { bool QuicConnection::OnPingFrame(const QuicPingFrame& frame) { QUIC_BUG_IF(quic_bug_12714_10, !connected_) - << "Processing PING frame when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing PING frame when connection is closed. Received packet " + "info: " + << last_received_packet_info_; if (!UpdatePacketContent(PING_FRAME)) { return false; } @@ -1588,11 +1627,12 @@ const char* QuicConnection::ValidateStopWaitingFrame( return "Least unacked too small."; } - if (stop_waiting.least_unacked > last_header_.packet_number) { + if (stop_waiting.least_unacked > + last_received_packet_info_.header.packet_number) { QUIC_DLOG(ERROR) << ENDPOINT << "Peer sent least_unacked:" << stop_waiting.least_unacked << " greater than the enclosing packet number:" - << last_header_.packet_number; + << last_received_packet_info_.header.packet_number; return "Least unacked too large."; } @@ -1601,8 +1641,9 @@ const char* QuicConnection::ValidateStopWaitingFrame( bool QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) { QUIC_BUG_IF(quic_bug_12714_11, !connected_) - << "Processing RST_STREAM frame when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing RST_STREAM frame when connection is closed. Received " + "packet info: " + << last_received_packet_info_; // Since a reset stream frame was received, this is not a connectivity probe. // A probe only contains a PING and full padding. @@ -1624,8 +1665,9 @@ bool QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) { bool QuicConnection::OnStopSendingFrame(const QuicStopSendingFrame& frame) { QUIC_BUG_IF(quic_bug_12714_12, !connected_) - << "Processing STOP_SENDING frame when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing STOP_SENDING frame when connection is closed. Received " + "packet info: " + << last_received_packet_info_; // Since a reset stream frame was received, this is not a connectivity probe. // A probe only contains a PING and full padding. @@ -1663,9 +1705,9 @@ class ReversePathValidationContext : public QuicPathValidationContext { bool QuicConnection::OnPathChallengeFrame(const QuicPathChallengeFrame& frame) { QUIC_BUG_IF(quic_bug_10511_8, !connected_) - << "Processing PATH_CHALLENGE frame when connection " - "is closed. Last frame: " - << most_recent_frame_type_; + << "Processing PATH_CHALLENGE frame when connection is closed. Received " + "packet info: " + << last_received_packet_info_; if (has_path_challenge_in_current_packet_) { // Only respond to the 1st PATH_CHALLENGE in the packet. return true; @@ -1673,7 +1715,6 @@ bool QuicConnection::OnPathChallengeFrame(const QuicPathChallengeFrame& frame) { if (!validate_client_addresses_) { return OnPathChallengeFrameInternal(frame); } - QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 1, 6); { // TODO(danzh) inline OnPathChallengeFrameInternal() once // validate_client_addresses_ is deprecated. @@ -1740,9 +1781,9 @@ bool QuicConnection::OnPathChallengeFrameInternal( bool QuicConnection::OnPathResponseFrame(const QuicPathResponseFrame& frame) { QUIC_BUG_IF(quic_bug_10511_9, !connected_) - << "Processing PATH_RESPONSE frame when connection " - "is closed. Last frame: " - << most_recent_frame_type_; + << "Processing PATH_RESPONSE frame when connection is closed. Received " + "packet info: " + << last_received_packet_info_; if (!UpdatePacketContent(PATH_RESPONSE_FRAME)) { return false; } @@ -1758,9 +1799,9 @@ bool QuicConnection::OnPathResponseFrame(const QuicPathResponseFrame& frame) { bool QuicConnection::OnConnectionCloseFrame( const QuicConnectionCloseFrame& frame) { QUIC_BUG_IF(quic_bug_10511_10, !connected_) - << "Processing CONNECTION_CLOSE frame when " - "connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing CONNECTION_CLOSE frame when connection is closed. " + "Received packet info: " + << last_received_packet_info_; // Since a connection close frame was received, this is not a connectivity // probe. A probe only contains a PING and full padding. @@ -1802,9 +1843,10 @@ bool QuicConnection::OnConnectionCloseFrame( } if (frame.quic_error_code == QUIC_BAD_MULTIPATH_FLAG) { - QUIC_LOG_FIRST_N(ERROR, 10) << "Unexpected QUIC_BAD_MULTIPATH_FLAG error." - << " last_received_header: " << last_header_ - << " encryption_level: " << encryption_level_; + QUIC_LOG_FIRST_N(ERROR, 10) + << "Unexpected QUIC_BAD_MULTIPATH_FLAG error." + << " last_received_header: " << last_received_packet_info_.header + << " encryption_level: " << encryption_level_; } TearDownLocalConnectionState(frame, ConnectionCloseSource::FROM_PEER); return connected_; @@ -1812,8 +1854,9 @@ bool QuicConnection::OnConnectionCloseFrame( bool QuicConnection::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) { QUIC_BUG_IF(quic_bug_12714_13, !connected_) - << "Processing MAX_STREAMS frame when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing MAX_STREAMS frame when connection is closed. Received " + "packet info: " + << last_received_packet_info_; if (!UpdatePacketContent(MAX_STREAMS_FRAME)) { return false; } @@ -1828,9 +1871,9 @@ bool QuicConnection::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) { bool QuicConnection::OnStreamsBlockedFrame( const QuicStreamsBlockedFrame& frame) { QUIC_BUG_IF(quic_bug_10511_11, !connected_) - << "Processing STREAMS_BLOCKED frame when " - "connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing STREAMS_BLOCKED frame when connection is closed. Received " + "packet info: " + << last_received_packet_info_; if (!UpdatePacketContent(STREAMS_BLOCKED_FRAME)) { return false; } @@ -1844,8 +1887,9 @@ bool QuicConnection::OnStreamsBlockedFrame( bool QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) { QUIC_BUG_IF(quic_bug_12714_14, !connected_) - << "Processing GOAWAY frame when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing GOAWAY frame when connection is closed. Received packet " + "info: " + << last_received_packet_info_; // Since a go away frame was received, this is not a connectivity probe. // A probe only contains a PING and full padding. @@ -1867,9 +1911,9 @@ bool QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) { bool QuicConnection::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) { QUIC_BUG_IF(quic_bug_10511_12, !connected_) - << "Processing WINDOW_UPDATE frame when connection " - "is closed. Last frame: " - << most_recent_frame_type_; + << "Processing WINDOW_UPDATE frame when connection is closed. Received " + "packet info: " + << last_received_packet_info_; // Since a window update frame was received, this is not a connectivity probe. // A probe only contains a PING and full padding. @@ -1923,29 +1967,6 @@ void QuicConnection::OnClientConnectionIdAvailable() { } } -bool QuicConnection::ShouldSetRetransmissionAlarmOnPacketSent( - bool in_flight, EncryptionLevel level) const { - QUICHE_DCHECK(!sent_packet_manager_.simplify_set_retransmission_alarm()); - if (!retransmission_alarm_->IsSet()) { - return true; - } - if (!in_flight) { - return false; - } - - if (!SupportsMultiplePacketNumberSpaces()) { - return true; - } - // Before handshake gets confirmed, do not re-arm PTO timer on application - // data. Think about this scenario: on the client side, the CHLO gets - // acknowledged and the SHLO is not received yet. The PTO alarm is set when - // the CHLO acknowledge is received (and there is no in flight INITIAL - // packet). Re-arming PTO alarm on 0-RTT packet would keep postponing the PTO - // alarm. - return IsHandshakeConfirmed() || level == ENCRYPTION_INITIAL || - level == ENCRYPTION_HANDSHAKE; -} - bool QuicConnection::OnNewConnectionIdFrameInner( const QuicNewConnectionIdFrame& frame) { if (peer_issued_cid_manager_ == nullptr) { @@ -1974,9 +1995,9 @@ bool QuicConnection::OnNewConnectionIdFrame( const QuicNewConnectionIdFrame& frame) { QUICHE_DCHECK(version().HasIetfQuicFrames()); QUIC_BUG_IF(quic_bug_10511_13, !connected_) - << "Processing NEW_CONNECTION_ID frame when " - "connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing NEW_CONNECTION_ID frame when connection is closed. " + "Received packet info: " + << last_received_packet_info_; if (!UpdatePacketContent(NEW_CONNECTION_ID_FRAME)) { return false; } @@ -1991,9 +2012,9 @@ bool QuicConnection::OnRetireConnectionIdFrame( const QuicRetireConnectionIdFrame& frame) { QUICHE_DCHECK(version().HasIetfQuicFrames()); QUIC_BUG_IF(quic_bug_10511_14, !connected_) - << "Processing RETIRE_CONNECTION_ID frame when " - "connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing RETIRE_CONNECTION_ID frame when connection is closed. " + "Received packet info: " + << last_received_packet_info_; if (!UpdatePacketContent(RETIRE_CONNECTION_ID_FRAME)) { return false; } @@ -2028,8 +2049,9 @@ bool QuicConnection::OnRetireConnectionIdFrame( bool QuicConnection::OnNewTokenFrame(const QuicNewTokenFrame& frame) { QUIC_BUG_IF(quic_bug_12714_15, !connected_) - << "Processing NEW_TOKEN frame when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing NEW_TOKEN frame when connection is closed. Received " + "packet info: " + << last_received_packet_info_; if (!UpdatePacketContent(NEW_TOKEN_FRAME)) { return false; } @@ -2050,8 +2072,9 @@ bool QuicConnection::OnNewTokenFrame(const QuicNewTokenFrame& frame) { bool QuicConnection::OnMessageFrame(const QuicMessageFrame& frame) { QUIC_BUG_IF(quic_bug_12714_16, !connected_) - << "Processing MESSAGE frame when connection is closed. Last frame: " - << most_recent_frame_type_; + << "Processing MESSAGE frame when connection is closed. Received packet " + "info: " + << last_received_packet_info_; // Since a message frame was received, this is not a connectivity probe. // A probe only contains a PING and full padding. @@ -2071,8 +2094,9 @@ bool QuicConnection::OnMessageFrame(const QuicMessageFrame& frame) { bool QuicConnection::OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) { QUIC_BUG_IF(quic_bug_10511_15, !connected_) << "Processing HANDSHAKE_DONE frame when connection " - "is closed. Last frame: " - << most_recent_frame_type_; + "is closed. Received packet " + "info: " + << last_received_packet_info_; if (!version().UsesTls()) { CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, "Handshake done frame is unsupported", @@ -2104,8 +2128,9 @@ bool QuicConnection::OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) { bool QuicConnection::OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) { QUIC_BUG_IF(quic_bug_10511_16, !connected_) << "Processing ACK_FREQUENCY frame when connection " - "is closed. Last frame: " - << most_recent_frame_type_; + "is closed. Received packet " + "info: " + << last_received_packet_info_; if (debug_visitor_ != nullptr) { debug_visitor_->OnAckFrequencyFrame(frame); } @@ -2118,8 +2143,8 @@ bool QuicConnection::OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) { return false; } if (auto packet_number_space = - QuicUtils::GetPacketNumberSpace(last_decrypted_packet_level_) == - APPLICATION_DATA) { + QuicUtils::GetPacketNumberSpace( + last_received_packet_info_.decrypted_level) == APPLICATION_DATA) { uber_received_packet_manager_.OnAckFrequencyFrame(frame); } else { QUIC_LOG_EVERY_N_SEC(ERROR, 120) @@ -2132,8 +2157,9 @@ bool QuicConnection::OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) { bool QuicConnection::OnBlockedFrame(const QuicBlockedFrame& frame) { QUIC_BUG_IF(quic_bug_12714_17, !connected_) - << "Processing BLOCKED frame when connection is closed. Last frame was " - << most_recent_frame_type_; + << "Processing BLOCKED frame when connection is closed. Received packet " + "info: " + << last_received_packet_info_; // Since a blocked frame was received, this is not a connectivity probe. // A probe only contains a PING and full padding. @@ -2166,11 +2192,14 @@ void QuicConnection::OnPacketComplete() { QUIC_DVLOG(1) << ENDPOINT << "Got" << (SupportsMultiplePacketNumberSpaces() - ? (" " + EncryptionLevelToString( - last_decrypted_packet_level_)) + ? (" " + + EncryptionLevelToString( + last_received_packet_info_.decrypted_level)) : "") - << " packet " << last_header_.packet_number << " for " - << GetServerConnectionIdAsRecipient(last_header_, perspective_); + << " packet " << last_received_packet_info_.header.packet_number + << " for " + << GetServerConnectionIdAsRecipient( + last_received_packet_info_.header, perspective_); QUIC_DLOG_IF(INFO, current_packet_content_ == SECOND_FRAME_IS_PADDING) << ENDPOINT << "Received a padded PING packet. is_probing: " @@ -2187,9 +2216,11 @@ void QuicConnection::OnPacketComplete() { // never process a packet while an ACK for it cannot be encrypted. if (!should_last_packet_instigate_acks_) { uber_received_packet_manager_.MaybeUpdateAckTimeout( - should_last_packet_instigate_acks_, last_decrypted_packet_level_, - last_header_.packet_number, last_received_packet_info_.receipt_time, - clock_->ApproximateNow(), sent_packet_manager_.GetRttStats()); + should_last_packet_instigate_acks_, + last_received_packet_info_.decrypted_level, + last_received_packet_info_.header.packet_number, + last_received_packet_info_.receipt_time, clock_->ApproximateNow(), + sent_packet_manager_.GetRttStats()); } ClearLastFrames(); @@ -2209,8 +2240,8 @@ void QuicConnection::MaybeRespondToConnectivityProbingOrMigration() { // packet has been received anyway. QUIC_DVLOG(1) << ENDPOINT << "Received a speculative connectivity probing packet for " - << GetServerConnectionIdAsRecipient(last_header_, - perspective_) + << GetServerConnectionIdAsRecipient( + last_received_packet_info_.header, perspective_) << " from ip:port: " << last_received_packet_info_.source_address.ToString() << " to ip:port: " @@ -2318,7 +2349,8 @@ void QuicConnection::CloseIfTooManyOutstandingSentPackets() { sent_packet_manager_.GetLeastUnacked().ToUint64(), ", packets_processed: ", stats_.packets_processed, ", last_decrypted_packet_level: ", - EncryptionLevelToString(last_decrypted_packet_level_)), + EncryptionLevelToString( + last_received_packet_info_.decrypted_level)), ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); } } @@ -2674,9 +2706,8 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address, if (debug_visitor_ != nullptr) { debug_visitor_->OnPacketReceived(self_address, peer_address, packet); } - last_received_packet_info_ = - ReceivedPacketInfo(self_address, peer_address, packet.receipt_time()); - last_size_ = packet.length(); + last_received_packet_info_ = ReceivedPacketInfo( + self_address, peer_address, packet.receipt_time(), packet.length()); current_packet_data_ = packet.data(); if (!default_path_.self_address.IsInitialized()) { @@ -2701,16 +2732,12 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address, stats_.bytes_received += packet.length(); ++stats_.packets_received; - if (!count_bytes_on_alternative_path_separately_) { - if (EnforceAntiAmplificationLimit()) { - default_path_.bytes_received_before_address_validation += last_size_; - } - } else if (IsDefaultPath(last_received_packet_info_.destination_address, - last_received_packet_info_.source_address) && - EnforceAntiAmplificationLimit()) { - QUIC_CODE_COUNT_N(quic_count_bytes_on_alternative_path_seperately, 1, 5); + if (IsDefaultPath(last_received_packet_info_.destination_address, + last_received_packet_info_.source_address) && + EnforceAntiAmplificationLimit()) { last_received_packet_info_.received_bytes_counted = true; - default_path_.bytes_received_before_address_validation += last_size_; + default_path_.bytes_received_before_address_validation += + last_received_packet_info_.length; } // Ensure the time coming from the packet reader is within 2 minutes of now. @@ -2731,7 +2758,7 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address, // because the CHLO or SHLO packet was lost. QUIC_DVLOG(1) << ENDPOINT << "Unable to process packet. Last packet processed: " - << last_header_.packet_number; + << last_received_packet_info_.header.packet_number; current_packet_data_ = nullptr; is_current_packet_connectivity_probing_ = false; @@ -2957,19 +2984,13 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) { default_path_.self_address.ToString(), ", received packet address: ", last_received_packet_info_.destination_address.ToString(), - ", size: ", last_size_, + ", size: ", last_received_packet_info_.length, ", packet number: ", header.packet_number.ToString(), ", encryption level: ", - EncryptionLevelToString(last_decrypted_packet_level_)); - if (GetQuicReloadableFlag( - quic_drop_packets_with_changed_server_address)) { - QUIC_LOG_EVERY_N_SEC(INFO, 100) << error_details; - QUIC_CODE_COUNT(quic_dropped_packets_with_changed_server_address); - return false; - } - QUIC_PEER_BUG(Server self address change) << error_details; - CloseConnection(QUIC_ERROR_MIGRATING_ADDRESS, error_details, - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + EncryptionLevelToString( + last_received_packet_info_.decrypted_level)); + QUIC_LOG_EVERY_N_SEC(INFO, 100) << error_details; + QUIC_CODE_COUNT(quic_dropped_packets_with_changed_server_address); return false; } } @@ -3014,17 +3035,18 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) { } } - if (last_size_ > largest_received_packet_size_) { - largest_received_packet_size_ = last_size_; + if (last_received_packet_info_.length > largest_received_packet_size_) { + largest_received_packet_size_ = last_received_packet_info_.length; } if (perspective_ == Perspective::IS_SERVER && encryption_level_ == ENCRYPTION_INITIAL && - last_size_ > packet_creator_.max_packet_length()) { + last_received_packet_info_.length > packet_creator_.max_packet_length()) { if (GetQuicFlag(FLAGS_quic_use_lower_server_response_mtu_for_test)) { - SetMaxPacketLength(std::min(last_size_, QuicByteCount(1250))); + SetMaxPacketLength( + std::min(last_received_packet_info_.length, QuicByteCount(1250))); } else { - SetMaxPacketLength(last_size_); + SetMaxPacketLength(last_received_packet_info_.length); } } return true; @@ -3035,10 +3057,11 @@ bool QuicConnection::ValidateReceivedPacketNumber( // If this packet has already been seen, or the sender has told us that it // will not be retransmitted, then stop processing the packet. if (!uber_received_packet_manager_.IsAwaitingPacket( - last_decrypted_packet_level_, packet_number)) { + last_received_packet_info_.decrypted_level, packet_number)) { QUIC_DLOG(INFO) << ENDPOINT << "Packet " << packet_number << " no longer being waited for at level " - << static_cast<int>(last_decrypted_packet_level_) + << static_cast<int>( + last_received_packet_info_.decrypted_level) << ". Discarding."; if (debug_visitor_ != nullptr) { debug_visitor_->OnDuplicatePacket(packet_number); @@ -3061,11 +3084,10 @@ void QuicConnection::WriteQueuedPackets() { } const BufferedPacket& packet = buffered_packets_.front(); WriteResult result = writer_->WritePacket( - packet.encrypted_buffer.data(), packet.encrypted_buffer.length(), - packet.self_address.host(), packet.peer_address, per_packet_options_); + packet.data.get(), packet.length, packet.self_address.host(), + packet.peer_address, per_packet_options_); QUIC_DVLOG(1) << ENDPOINT << "Sending buffered packet, result: " << result; - if (IsMsgTooBig(writer_, result) && - packet.encrypted_buffer.length() > long_term_mtu_) { + if (IsMsgTooBig(writer_, result) && packet.length > long_term_mtu_) { // When MSG_TOO_BIG is returned, the system typically knows what the // actual MTU is, so there is no need to probe further. // TODO(wub): Reduce max packet size to a safe default, or the actual MTU. @@ -3089,17 +3111,6 @@ void QuicConnection::WriteQueuedPackets() { } } -void QuicConnection::SendProbingRetransmissions() { - while (sent_packet_manager_.GetSendAlgorithm()->ShouldSendProbingPacket() && - CanWrite(HAS_RETRANSMITTABLE_DATA)) { - if (!visitor_->SendProbingData()) { - QUIC_DVLOG(1) - << "Cannot send probing retransmissions: nothing to retransmit."; - break; - } - } -} - void QuicConnection::MarkZeroRttPacketsForRetransmission(int reject_reason) { sent_packet_manager_.MarkZeroRttPacketsForRetransmission(); if (debug_visitor_ != nullptr && version().UsesTls()) { @@ -3143,10 +3154,6 @@ bool QuicConnection::ShouldGeneratePacket( "generate packet."; return false; } - if (!count_bytes_on_alternative_path_separately_) { - return CanWrite(retransmittable); - } - QUIC_CODE_COUNT_N(quic_count_bytes_on_alternative_path_seperately, 4, 5); if (IsDefaultPath(default_path_.self_address, packet_creator_.peer_address())) { return CanWrite(retransmittable); @@ -3360,7 +3367,18 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) { WriteResult result(WRITE_STATUS_OK, encrypted_length); QuicSocketAddress send_to_address = packet->peer_address; // Self address is always the default self address on this code path. - bool send_on_current_path = send_to_address == peer_address(); + const bool send_on_current_path = send_to_address == peer_address(); + if (!send_on_current_path && only_send_probing_frames_on_alternative_path_) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_not_bundle_ack_on_alternative_path, 2, 2); + QUIC_BUG_IF(quic_send_non_probing_frames_on_alternative_path, + ContainsNonProbingFrame(*packet)) + << "Packet " << packet->packet_number + << " with non-probing frames was sent on alternative path: " + "nonretransmittable_frames: " + << QuicFramesToString(packet->nonretransmittable_frames) + << " retransmittable_frames: " + << QuicFramesToString(packet->retransmittable_frames); + } switch (fate) { case DISCARD: ++stats_.packets_discarded; @@ -3569,22 +3587,13 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) { QUIC_DVLOG(1) << ENDPOINT << "time we began writing last sent packet: " << packet_send_time.ToDebuggingValue(); - if (!count_bytes_on_alternative_path_separately_) { + if (IsDefaultPath(default_path_.self_address, send_to_address)) { if (EnforceAntiAmplificationLimit()) { // Include bytes sent even if they are not in flight. default_path_.bytes_sent_before_address_validation += encrypted_length; } } else { - QUIC_CODE_COUNT_N(quic_count_bytes_on_alternative_path_seperately, 2, 5); - if (IsDefaultPath(default_path_.self_address, send_to_address)) { - if (EnforceAntiAmplificationLimit()) { - // Include bytes sent even if they are not in flight. - default_path_.bytes_sent_before_address_validation += encrypted_length; - } - } else { - MaybeUpdateBytesSentToAlternativeAddress(send_to_address, - encrypted_length); - } + MaybeUpdateBytesSentToAlternativeAddress(send_to_address, encrypted_length); } // Do not measure rtt of this packet if it's not sent on current path. @@ -3634,13 +3643,7 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) { return true; } } - if (sent_packet_manager_.simplify_set_retransmission_alarm()) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_simplify_set_retransmission_alarm, 1, 2); - if (in_flight || !retransmission_alarm_->IsSet()) { - SetRetransmissionAlarm(); - } - } else if (ShouldSetRetransmissionAlarmOnPacketSent( - in_flight, packet->encryption_level)) { + if (in_flight || !retransmission_alarm_->IsSet()) { SetRetransmissionAlarm(); } SetPingAlarm(); @@ -3916,6 +3919,12 @@ void QuicConnection::OnSerializedPacket(SerializedPacket serialized_packet) { } else { consecutive_num_packets_with_no_retransmittable_frames_ = 0; } + if (retransmittable_on_wire_behavior_ == SEND_FIRST_FORWARD_SECURE_PACKET && + first_serialized_one_rtt_packet_ == nullptr && + serialized_packet.encryption_level == ENCRYPTION_FORWARD_SECURE) { + first_serialized_one_rtt_packet_ = std::make_unique<BufferedPacket>( + serialized_packet, self_address(), peer_address()); + } SendOrQueuePacket(std::move(serialized_packet)); } @@ -4027,6 +4036,7 @@ void QuicConnection::SendOrQueuePacket(SerializedPacket packet) { } void QuicConnection::OnPingTimeout() { + QUICHE_DCHECK(!use_ping_manager_); if (retransmission_alarm_->IsSet() || !visitor_->ShouldKeepConnectionAlive()) { return; @@ -4061,6 +4071,21 @@ void QuicConnection::SendAck() { visitor_->OnAckNeedsRetransmittableFrame(); } +EncryptionLevel QuicConnection::GetEncryptionLevelToSendPingForSpace( + PacketNumberSpace space) const { + switch (space) { + case INITIAL_DATA: + return ENCRYPTION_INITIAL; + case HANDSHAKE_DATA: + return ENCRYPTION_HANDSHAKE; + case APPLICATION_DATA: + return framer_.GetEncryptionLevelToSendApplicationData(); + default: + QUICHE_DCHECK(false); + return NUM_ENCRYPTION_LEVELS; + } +} + void QuicConnection::OnRetransmissionTimeout() { ScopedRetransmissionTimeoutIndicator indicator(this); #ifndef NDEBUG @@ -4077,11 +4102,8 @@ void QuicConnection::OnRetransmissionTimeout() { packet_creator_.packet_number(); const auto retransmission_mode = sent_packet_manager_.OnRetransmissionTimeout(); - if (sent_packet_manager_.skip_packet_number_for_pto() && - retransmission_mode == QuicSentPacketManager::PTO_MODE && - sent_packet_manager_.pending_timer_transmission_count() == 1) { - // Skip a packet number when a single PTO packet is sent to elicit an - // immediate ACK. + if (retransmission_mode == QuicSentPacketManager::PTO_MODE) { + // Skip a packet number when PTO fires to elicit an immediate ACK. const QuicPacketCount num_packet_numbers_to_skip = 1; packet_creator_.SkipNPacketNumbers( num_packet_numbers_to_skip, @@ -4107,23 +4129,14 @@ void QuicConnection::OnRetransmissionTimeout() { if (!connected_) { return; } - - // In the PTO and TLP cases, the SentPacketManager gives the connection the - // opportunity to send new data before retransmitting. - if (sent_packet_manager_.pto_enabled()) { - sent_packet_manager_.MaybeSendProbePackets(); - } else if (sent_packet_manager_.MaybeRetransmitTailLossProbe()) { - // Send the pending retransmission now that it's been queued. - WriteIfNotBlocked(); - } + // When PTO fires, the SentPacketManager gives the connection the opportunity + // to send new data before retransmitting. + sent_packet_manager_.MaybeSendProbePacket(); if (packet_creator_.packet_number() == previous_created_packet_number && - (retransmission_mode == QuicSentPacketManager::TLP_MODE || - retransmission_mode == QuicSentPacketManager::RTO_MODE || - retransmission_mode == QuicSentPacketManager::PTO_MODE) && + retransmission_mode == QuicSentPacketManager::PTO_MODE && !visitor_->WillingAndAbleToWrite()) { - // Send PING if timer fires in TLP/RTO/PTO mode but there is no data to - // send. + // Send PING if timer fires in PTO mode but there is no data to send. QUIC_DLOG(INFO) << ENDPOINT << "No packet gets sent when timer fires in mode " << retransmission_mode << ", send PING"; @@ -4135,7 +4148,8 @@ void QuicConnection::OnRetransmissionTimeout() { if (sent_packet_manager_ .GetEarliestPacketSentTimeForPto(&packet_number_space) .IsInitialized()) { - SendPingAtLevel(QuicUtils::GetEncryptionLevel(packet_number_space)); + SendPingAtLevel( + GetEncryptionLevelToSendPingForSpace(packet_number_space)); } else { // The client must PTO when there is nothing in flight if the server // could be blocked from sending by the amplification limit @@ -4153,13 +4167,9 @@ void QuicConnection::OnRetransmissionTimeout() { } } if (retransmission_mode == QuicSentPacketManager::PTO_MODE) { - sent_packet_manager_.AdjustPendingTimerTransmissions(); - } - if (retransmission_mode != QuicSentPacketManager::LOSS_MODE && - retransmission_mode != QuicSentPacketManager::HANDSHAKE_MODE) { - // When timer fires in TLP/RTO/PTO mode, ensure 1) at least one packet is - // created, or there is data to send and available credit (such that - // packets will be sent eventually). + // When timer fires in PTO mode, ensure 1) at least one packet is created, + // or there is data to send and available credit (such that packets will be + // sent eventually). QUIC_BUG_IF( quic_bug_12714_27, packet_creator_.packet_number() == previous_created_packet_number && @@ -4310,14 +4320,7 @@ void QuicConnection::QueueUndecryptablePacket( undecryptable_packets_.emplace_back(packet, decryption_level, last_received_packet_info_); if (perspective_ == Perspective::IS_CLIENT) { - if (sent_packet_manager_.simplify_set_retransmission_alarm()) { - SetRetransmissionAlarm(); - } else if (!retransmission_alarm_->IsSet() || - GetRetransmissionDeadline() < - retransmission_alarm_->deadline()) { - // Re-arm PTO only if we can make it sooner to speed up recovery. - SetRetransmissionAlarm(); - } + SetRetransmissionAlarm(); } } @@ -4344,7 +4347,6 @@ void QuicConnection::MaybeProcessUndecryptablePackets() { undecryptable_packet->encryption_level); } last_received_packet_info_ = undecryptable_packet->packet_info; - last_size_ = undecryptable_packet->packet->length(); current_packet_data_ = undecryptable_packet->packet->data(); const bool processed = framer_.ProcessPacket(*undecryptable_packet->packet); current_packet_data_ = nullptr; @@ -4382,18 +4384,7 @@ void QuicConnection::MaybeProcessUndecryptablePackets() { undecryptable_packets_.clear(); } if (perspective_ == Perspective::IS_CLIENT) { - if (sent_packet_manager_.simplify_set_retransmission_alarm()) { - SetRetransmissionAlarm(); - } else if (!retransmission_alarm_->IsSet() || - undecryptable_packets_.empty() || - GetRetransmissionDeadline() < - retransmission_alarm_->deadline()) { - // 1) If there is still undecryptable packet, only re-arm PTO to make it - // sooner to speed up recovery. - // 2) If all undecryptable packets get processed, re-arm (which may - // postpone) PTO since no immediate recovery is needed. - SetRetransmissionAlarm(); - } + SetRetransmissionAlarm(); } } @@ -4543,16 +4534,6 @@ void QuicConnection::SendConnectionClosePacket( auto* frame = new QuicConnectionCloseFrame( transport_version(), error, ietf_error, details, framer_.current_received_frame_type()); - if (level == ENCRYPTION_FORWARD_SECURE) { - if (connection_close_frame_sent_.has_value()) { - QUIC_BUG(quic_send_multiple_connection_closes) - << ENDPOINT << "Already sent connection close: " - << connection_close_frame_sent_.value() - << ", going to send connection close: " << *frame; - } else { - connection_close_frame_sent_ = *frame; - } - } packet_creator_.ConsumeRetransmittableControlFrame(QuicFrame(frame)); packet_creator_.FlushCurrentPacket(); } @@ -4605,7 +4586,11 @@ void QuicConnection::CancelAllAlarms() { QUIC_DVLOG(1) << "Cancelling all QuicConnection alarms."; ack_alarm_->PermanentCancel(); - ping_alarm_->PermanentCancel(); + if (use_ping_manager_) { + ping_manager_.Stop(); + } else { + ping_alarm_->PermanentCancel(); + } retransmission_alarm_->PermanentCancel(); send_alarm_->PermanentCancel(); mtu_discovery_alarm_->PermanentCancel(); @@ -4649,6 +4634,13 @@ void QuicConnection::SetPingAlarm() { if (!connected_) { return; } + if (use_ping_manager_) { + QUIC_RELOADABLE_FLAG_COUNT(quic_use_ping_manager2); + ping_manager_.SetAlarm(clock_->ApproximateNow(), + visitor_->ShouldKeepConnectionAlive(), + sent_packet_manager_.HasInFlightPackets()); + return; + } if (perspective_ == Perspective::IS_SERVER && initial_retransmittable_on_wire_timeout_.IsInfinite()) { // The PING alarm exists to support two features: @@ -4670,7 +4662,7 @@ void QuicConnection::SetPingAlarm() { GetQuicFlag(FLAGS_quic_max_retransmittable_on_wire_ping_count)) { if (perspective_ == Perspective::IS_CLIENT) { // Clients send 15s PINGs to avoid NATs from timing out. - ping_alarm_->Update(clock_->ApproximateNow() + ping_timeout_, + ping_alarm_->Update(clock_->ApproximateNow() + keep_alive_ping_timeout_, QuicTime::Delta::FromSeconds(1)); } else { // Servers do not send 15s PINGs. @@ -4678,7 +4670,8 @@ void QuicConnection::SetPingAlarm() { } return; } - QUICHE_DCHECK_LT(initial_retransmittable_on_wire_timeout_, ping_timeout_); + QUICHE_DCHECK_LT(initial_retransmittable_on_wire_timeout_, + keep_alive_ping_timeout_); QuicTime::Delta retransmittable_on_wire_timeout = initial_retransmittable_on_wire_timeout_; int max_aggressive_retransmittable_on_wire_ping_count = @@ -4700,7 +4693,7 @@ void QuicConnection::SetPingAlarm() { return; } - if (retransmittable_on_wire_timeout < ping_timeout_) { + if (retransmittable_on_wire_timeout < keep_alive_ping_timeout_) { // Use a shorter timeout if there are open streams, but nothing on the wire. ping_alarm_->Update( clock_->ApproximateNow() + retransmittable_on_wire_timeout, @@ -4712,7 +4705,7 @@ void QuicConnection::SetPingAlarm() { return; } - ping_alarm_->Update(clock_->ApproximateNow() + ping_timeout_, + ping_alarm_->Update(clock_->ApproximateNow() + keep_alive_ping_timeout_, kAlarmGranularity); } @@ -4736,15 +4729,13 @@ void QuicConnection::SetRetransmissionAlarm() { return; } PacketNumberSpace packet_number_space; - if (sent_packet_manager_.simplify_set_retransmission_alarm() && - SupportsMultiplePacketNumberSpaces() && !IsHandshakeConfirmed() && + if (SupportsMultiplePacketNumberSpaces() && !IsHandshakeConfirmed() && !sent_packet_manager_ .GetEarliestPacketSentTimeForPto(&packet_number_space) .IsInitialized()) { // Before handshake gets confirmed, GetEarliestPacketSentTimeForPto // returning 0 indicates no packets are in flight or only application data // is in flight. - QUIC_RELOADABLE_FLAG_COUNT_N(quic_simplify_set_retransmission_alarm, 2, 2); if (perspective_ == Perspective::IS_SERVER) { // No need to arm PTO on server side. retransmission_alarm_->Cancel(); @@ -4821,29 +4812,19 @@ QuicConnection::ScopedPacketFlusher::~ScopedPacketFlusher() { } } - if (connection_->flush_after_coalesce_higher_space_packets_) { - // INITIAL or HANDSHAKE retransmission could cause peer to derive new - // keys, such that the buffered undecryptable packets may be processed. - // This endpoint would derive an inflated RTT sample when receiving ACKs - // of those undecryptable packets. To mitigate this, tries to coalesce as - // many higher space packets as possible (via for loop inside - // MaybeCoalescePacketOfHigherSpace) to fill the remaining space in the - // coalescer. - QUIC_RELOADABLE_FLAG_COUNT( - quic_flush_after_coalesce_higher_space_packets); - if (connection_->version().CanSendCoalescedPackets()) { - connection_->MaybeCoalescePacketOfHigherSpace(); - } - connection_->packet_creator_.Flush(); - if (connection_->version().CanSendCoalescedPackets()) { - connection_->FlushCoalescedPacket(); - } - } else { - connection_->packet_creator_.Flush(); - if (connection_->version().CanSendCoalescedPackets()) { - connection_->MaybeCoalescePacketOfHigherSpace(); - connection_->FlushCoalescedPacket(); - } + // INITIAL or HANDSHAKE retransmission could cause peer to derive new + // keys, such that the buffered undecryptable packets may be processed. + // This endpoint would derive an inflated RTT sample when receiving ACKs + // of those undecryptable packets. To mitigate this, tries to coalesce as + // many higher space packets as possible (via for loop inside + // MaybeCoalescePacketOfHigherSpace) to fill the remaining space in the + // coalescer. + if (connection_->version().CanSendCoalescedPackets()) { + connection_->MaybeCoalescePacketOfHigherSpace(); + } + connection_->packet_creator_.Flush(); + if (connection_->version().CanSendCoalescedPackets()) { + connection_->FlushCoalescedPacket(); } connection_->FlushPackets(); if (!handshake_packet_sent_ && connection_->handshake_packet_sent_) { @@ -4903,21 +4884,61 @@ QuicConnection::ScopedEncryptionLevelContext::~ScopedEncryptionLevelContext() { QuicConnection::BufferedPacket::BufferedPacket( const SerializedPacket& packet, const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address) - : encrypted_buffer(CopyBuffer(packet), packet.encrypted_length), - self_address(self_address), - peer_address(peer_address) {} + : BufferedPacket(packet.encrypted_buffer, packet.encrypted_length, + self_address, peer_address) {} QuicConnection::BufferedPacket::BufferedPacket( - char* encrypted_buffer, QuicPacketLength encrypted_length, + const char* encrypted_buffer, QuicPacketLength encrypted_length, const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address) - : encrypted_buffer(CopyBuffer(encrypted_buffer, encrypted_length), - encrypted_length), + : length(encrypted_length), self_address(self_address), - peer_address(peer_address) {} + peer_address(peer_address) { + data = std::make_unique<char[]>(encrypted_length); + memcpy(data.get(), encrypted_buffer, encrypted_length); +} -QuicConnection::BufferedPacket::~BufferedPacket() { - delete[] encrypted_buffer.data(); +QuicConnection::BufferedPacket::BufferedPacket( + QuicRandom& random, QuicPacketLength encrypted_length, + const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address) + : length(encrypted_length), + self_address(self_address), + peer_address(peer_address) { + data = std::make_unique<char[]>(encrypted_length); + random.RandBytes(data.get(), encrypted_length); +} + +QuicConnection::ReceivedPacketInfo::ReceivedPacketInfo(QuicTime receipt_time) + : receipt_time(receipt_time) {} +QuicConnection::ReceivedPacketInfo::ReceivedPacketInfo( + const QuicSocketAddress& destination_address, + const QuicSocketAddress& source_address, QuicTime receipt_time, + QuicByteCount length) + : destination_address(destination_address), + source_address(source_address), + receipt_time(receipt_time), + length(length) {} + +std::ostream& operator<<(std::ostream& os, + const QuicConnection::ReceivedPacketInfo& info) { + os << " { destination_address: " << info.destination_address.ToString() + << ", source_address: " << info.source_address.ToString() + << ", received_bytes_counted: " << info.received_bytes_counted + << ", length: " << info.length + << ", destination_connection_id: " << info.destination_connection_id; + if (!info.decrypted) { + os << " }\n"; + return os; + } + os << ", decrypted: " << info.decrypted + << ", decrypted_level: " << EncryptionLevelToString(info.decrypted_level) + << ", header: " << info.header << ", frames: "; + for (const auto frame : info.frames) { + os << frame; + } + os << " }\n"; + return os; } HasRetransmittableData QuicConnection::IsRetransmittable( @@ -5132,7 +5153,6 @@ void QuicConnection::OnEffectivePeerMigrationValidated() { if (!validate_client_addresses_) { return; } - QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 2, 6); if (debug_visitor_ != nullptr) { const QuicTime now = clock_->ApproximateNow(); if (now >= stats_.handshake_completion_time) { @@ -5178,7 +5198,6 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) { return; } - QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 3, 6); if (type == NO_CHANGE) { UpdatePeerAddress(last_received_packet_info_.source_address); QUIC_BUG(quic_bug_10511_36) @@ -5271,12 +5290,13 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) { absl::optional<StatelessResetToken> stateless_reset_token; FindMatchingOrNewClientConnectionIdOrToken( previous_default_path, alternative_path_, - last_packet_destination_connection_id_, &client_connection_id, - &stateless_reset_token); - SetDefaultPathState(PathState( - last_received_packet_info_.destination_address, - current_effective_peer_address, client_connection_id, - last_packet_destination_connection_id_, stateless_reset_token)); + last_received_packet_info_.destination_connection_id, + &client_connection_id, &stateless_reset_token); + SetDefaultPathState( + PathState(last_received_packet_info_.destination_address, + current_effective_peer_address, client_connection_id, + last_received_packet_info_.destination_connection_id, + stateless_reset_token)); // The path is considered validated if its peer IP address matches any // validated path's peer IP address. default_path_.validated = @@ -5287,7 +5307,8 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) { } if (!last_received_packet_info_.received_bytes_counted) { // Increment bytes counting on the new default path. - default_path_.bytes_received_before_address_validation += last_size_; + default_path_.bytes_received_before_address_validation += + last_received_packet_info_.length; last_received_packet_info_.received_bytes_counted = true; } @@ -5389,13 +5410,14 @@ absl::string_view QuicConnection::GetCurrentPacket() { if (current_packet_data_ == nullptr) { return absl::string_view(); } - return absl::string_view(current_packet_data_, last_size_); + return absl::string_view(current_packet_data_, + last_received_packet_info_.length); } bool QuicConnection::MaybeConsiderAsMemoryCorruption( const QuicStreamFrame& frame) { if (QuicUtils::IsCryptoStreamId(transport_version(), frame.stream_id) || - last_decrypted_packet_level_ != ENCRYPTION_INITIAL) { + last_received_packet_info_.decrypted_level != ENCRYPTION_INITIAL) { return false; } @@ -5416,29 +5438,8 @@ bool QuicConnection::MaybeConsiderAsMemoryCorruption( return false; } -void QuicConnection::MaybeSendProbingRetransmissions() { - QUICHE_DCHECK(fill_up_link_during_probing_); - - // Don't send probing retransmissions until the handshake has completed. - if (!IsHandshakeComplete() || - sent_packet_manager().HasUnackedCryptoPackets()) { - return; - } - - if (probing_retransmission_pending_) { - QUIC_BUG(quic_bug_10511_37) - << "MaybeSendProbingRetransmissions is called while another call " - "to it is already in progress"; - return; - } - - probing_retransmission_pending_ = true; - SendProbingRetransmissions(); - probing_retransmission_pending_ = false; -} - void QuicConnection::CheckIfApplicationLimited() { - if (!connected_ || probing_retransmission_pending_) { + if (!connected_) { return; } @@ -5449,18 +5450,11 @@ void QuicConnection::CheckIfApplicationLimited() { return; } - if (fill_up_link_during_probing_) { - MaybeSendProbingRetransmissions(); - if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) { - return; - } - } - sent_packet_manager_.OnApplicationLimited(); } bool QuicConnection::UpdatePacketContent(QuicFrameType type) { - most_recent_frame_type_ = type; + last_received_packet_info_.frames.push_back(type); if (version().HasIetfQuicFrames()) { if (!QuicUtils::IsProbingFrame(type)) { MaybeStartIetfPeerMigration(); @@ -5468,12 +5462,10 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) { } QuicSocketAddress current_effective_peer_address = GetEffectivePeerAddressFromCurrentPacket(); - if (!count_bytes_on_alternative_path_separately_ || - IsDefaultPath(last_received_packet_info_.destination_address, + if (IsDefaultPath(last_received_packet_info_.destination_address, last_received_packet_info_.source_address)) { return connected_; } - QUIC_CODE_COUNT_N(quic_count_bytes_on_alternative_path_seperately, 3, 5); if (perspective_ == Perspective::IS_SERVER && type == PATH_CHALLENGE_FRAME && !IsAlternativePath(last_received_packet_info_.destination_address, @@ -5487,14 +5479,14 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) { absl::optional<StatelessResetToken> stateless_reset_token; FindMatchingOrNewClientConnectionIdOrToken( default_path_, alternative_path_, - last_packet_destination_connection_id_, &client_cid, + last_received_packet_info_.destination_connection_id, &client_cid, &stateless_reset_token); - alternative_path_ = PathState( - last_received_packet_info_.destination_address, - current_effective_peer_address, client_cid, - last_packet_destination_connection_id_, stateless_reset_token); + alternative_path_ = + PathState(last_received_packet_info_.destination_address, + current_effective_peer_address, client_cid, + last_received_packet_info_.destination_connection_id, + stateless_reset_token); } else if (!default_path_.validated) { - QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 4, 6); // Skip reverse path validation because either handshake hasn't // completed or the connection is validating the default path. Using // PATH_CHALLENGE to validate alternative client address before @@ -5508,24 +5500,25 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) { IsHandshakeConfirmed() && !alternative_path_.validated) << "No validated peer address to send after handshake comfirmed."; } else if (!IsReceivedPeerAddressValidated()) { - QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 5, 6); QuicConnectionId client_connection_id; absl::optional<StatelessResetToken> stateless_reset_token; FindMatchingOrNewClientConnectionIdOrToken( default_path_, alternative_path_, - last_packet_destination_connection_id_, &client_connection_id, - &stateless_reset_token); + last_received_packet_info_.destination_connection_id, + &client_connection_id, &stateless_reset_token); // Only override alternative path state upon receiving a PATH_CHALLENGE // from an unvalidated peer address, and the connection isn't validating // a recent peer migration. - alternative_path_ = PathState( - last_received_packet_info_.destination_address, - current_effective_peer_address, client_connection_id, - last_packet_destination_connection_id_, stateless_reset_token); + alternative_path_ = + PathState(last_received_packet_info_.destination_address, + current_effective_peer_address, client_connection_id, + last_received_packet_info_.destination_connection_id, + stateless_reset_token); should_proactively_validate_peer_address_on_path_challenge_ = true; } } - MaybeUpdateBytesReceivedFromAlternativeAddress(last_size_); + MaybeUpdateBytesReceivedFromAlternativeAddress( + last_received_packet_info_.length); return connected_; } // Packet content is tracked to identify connectivity probe in non-IETF @@ -5580,7 +5573,8 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) { current_packet_content_ = NOT_PADDED_PING; if (GetLargestReceivedPacket().IsInitialized() && - last_header_.packet_number == GetLargestReceivedPacket()) { + last_received_packet_info_.header.packet_number == + GetLargestReceivedPacket()) { UpdatePeerAddress(last_received_packet_info_.source_address); if (current_effective_peer_migration_type_ != NO_CHANGE) { // Start effective peer migration immediately when the current packet is @@ -5613,7 +5607,8 @@ void QuicConnection::MaybeStartIetfPeerMigration() { } if (GetLargestReceivedPacket().IsInitialized() && - last_header_.packet_number == GetLargestReceivedPacket()) { + last_received_packet_info_.header.packet_number == + GetLargestReceivedPacket()) { if (current_effective_peer_migration_type_ != NO_CHANGE) { // Start effective peer migration when the current packet contains a // non-probing frame. @@ -5634,10 +5629,10 @@ void QuicConnection::PostProcessAfterAckFrame(bool send_stop_waiting, bool acked_new_packet) { if (no_stop_waiting_frames_ && !packet_creator_.has_ack()) { uber_received_packet_manager_.DontWaitForPacketsBefore( - last_decrypted_packet_level_, + last_received_packet_info_.decrypted_level, SupportsMultiplePacketNumberSpaces() ? sent_packet_manager_.GetLargestPacketPeerKnowsIsAcked( - last_decrypted_packet_level_) + last_received_packet_info_.decrypted_level) : sent_packet_manager_.largest_packet_peer_knows_is_acked()); } // Always reset the retransmission alarm when an ack comes in, since we now @@ -5725,7 +5720,8 @@ QuicPacketLength QuicConnection::GetGuaranteedLargestMessagePayload() const { uint32_t QuicConnection::cipher_id() const { if (version().KnowsWhichDecrypterToUse()) { - return framer_.GetDecrypter(last_decrypted_packet_level_)->cipher_id(); + return framer_.GetDecrypter(last_received_packet_info_.decrypted_level) + ->cipher_id(); } return framer_.decrypter()->cipher_id(); } @@ -5824,7 +5820,8 @@ void QuicConnection::SendAllPendingAcks() { << PacketNumberSpaceToString( static_cast<PacketNumberSpace>(i)); ScopedEncryptionLevelContext context( - this, QuicUtils::GetEncryptionLevel(static_cast<PacketNumberSpace>(i))); + this, QuicUtils::GetEncryptionLevelToSendAckofSpace( + static_cast<PacketNumberSpace>(i))); QuicFrames frames; frames.push_back(uber_received_packet_manager_.GetUpdatedAckFrame( static_cast<PacketNumberSpace>(i), clock_->ApproximateNow())); @@ -5869,10 +5866,9 @@ bool QuicConnection::ShouldBundleRetransmittableFrameWithAck() const { return true; } if (bundle_retransmittable_with_pto_ack_ && - (sent_packet_manager_.GetConsecutiveRtoCount() > 0 || - sent_packet_manager_.GetConsecutivePtoCount() > 0)) { - // Bundle a retransmittable frame with an ACK if the PTO or RTO has fired - // in order to recover more quickly in cases of temporary network outage. + sent_packet_manager_.GetConsecutivePtoCount() > 0) { + // Bundle a retransmittable frame with an ACK if PTO has fired in order to + // recover more quickly in cases of temporary network outage. return true; } return false; @@ -5884,8 +5880,7 @@ void QuicConnection::MaybeCoalescePacketOfHigherSpace() { } if (fill_coalesced_packet_) { // Make sure MaybeCoalescePacketOfHigherSpace is not re-entrant. - QUIC_BUG_IF(quic_coalesce_packet_reentrant, - flush_after_coalesce_higher_space_packets_); + QUIC_BUG(quic_coalesce_packet_reentrant); return; } for (EncryptionLevel retransmission_level : @@ -5939,11 +5934,7 @@ bool QuicConnection::FlushCoalescedPacket() { const size_t length = packet_creator_.SerializeCoalescedPacket( coalesced_packet_, buffer, coalesced_packet_.max_packet_length()); if (length == 0) { - if (packet_creator_ - .close_connection_if_fail_to_serialzie_coalesced_packet() && - connected_) { - QUIC_RELOADABLE_FLAG_COUNT_N( - quic_close_connection_if_fail_to_serialzie_coalesced_packet2, 2, 2); + if (connected_) { CloseConnection(QUIC_FAILED_TO_SERIALIZE_PACKET, "Failed to serialize coalesced packet.", ConnectionCloseBehavior::SILENT_CLOSE); @@ -5985,22 +5976,15 @@ bool QuicConnection::FlushCoalescedPacket() { // Account for added padding. if (length > coalesced_packet_.length()) { size_t padding_size = length - coalesced_packet_.length(); - if (!count_bytes_on_alternative_path_separately_) { + if (IsDefaultPath(coalesced_packet_.self_address(), + coalesced_packet_.peer_address())) { if (EnforceAntiAmplificationLimit()) { + // Include bytes sent even if they are not in flight. default_path_.bytes_sent_before_address_validation += padding_size; } } else { - QUIC_CODE_COUNT_N(quic_count_bytes_on_alternative_path_seperately, 5, 5); - if (IsDefaultPath(coalesced_packet_.self_address(), - coalesced_packet_.peer_address())) { - if (EnforceAntiAmplificationLimit()) { - // Include bytes sent even if they are not in flight. - default_path_.bytes_sent_before_address_validation += padding_size; - } - } else { - MaybeUpdateBytesSentToAlternativeAddress( - coalesced_packet_.peer_address(), padding_size); - } + MaybeUpdateBytesSentToAlternativeAddress(coalesced_packet_.peer_address(), + padding_size); } stats_.bytes_sent += padding_size; if (coalesced_packet_.initial_packet() != nullptr && @@ -6032,7 +6016,7 @@ void QuicConnection::SetLargestReceivedPacketWithAck( QuicPacketNumber new_value) { if (SupportsMultiplePacketNumberSpaces()) { largest_seen_packets_with_ack_[QuicUtils::GetPacketNumberSpace( - last_decrypted_packet_level_)] = new_value; + last_received_packet_info_.decrypted_level)] = new_value; } else { largest_seen_packet_with_ack_ = new_value; } @@ -6067,7 +6051,7 @@ void QuicConnection::OnForwardProgressMade() { QuicPacketNumber QuicConnection::GetLargestReceivedPacketWithAck() const { if (SupportsMultiplePacketNumberSpaces()) { return largest_seen_packets_with_ack_[QuicUtils::GetPacketNumberSpace( - last_decrypted_packet_level_)]; + last_received_packet_info_.decrypted_level)]; } return largest_seen_packet_with_ack_; } @@ -6075,14 +6059,14 @@ QuicPacketNumber QuicConnection::GetLargestReceivedPacketWithAck() const { QuicPacketNumber QuicConnection::GetLargestAckedPacket() const { if (SupportsMultiplePacketNumberSpaces()) { return sent_packet_manager_.GetLargestAckedPacket( - last_decrypted_packet_level_); + last_received_packet_info_.decrypted_level); } return sent_packet_manager_.GetLargestObserved(); } QuicPacketNumber QuicConnection::GetLargestReceivedPacket() const { return uber_received_packet_manager_.GetLargestObserved( - last_decrypted_packet_level_); + last_received_packet_info_.decrypted_level); } bool QuicConnection::EnforceAntiAmplificationLimit() const { @@ -6148,7 +6132,8 @@ void QuicConnection::set_min_received_before_ack_decimation(size_t new_value) { const QuicAckFrame& QuicConnection::ack_frame() const { if (SupportsMultiplePacketNumberSpaces()) { return uber_received_packet_manager_.GetAckFrame( - QuicUtils::GetPacketNumberSpace(last_decrypted_packet_level_)); + QuicUtils::GetPacketNumberSpace( + last_received_packet_info_.decrypted_level)); } return uber_received_packet_manager_.ack_frame(); } @@ -6238,8 +6223,6 @@ void QuicConnection::OnIdleNetworkDetected() { } QUIC_DVLOG(1) << ENDPOINT << error_details; const bool has_consecutive_pto = - sent_packet_manager_.GetConsecutiveTlpCount() > 0 || - sent_packet_manager_.GetConsecutiveRtoCount() > 0 || sent_packet_manager_.GetConsecutivePtoCount() > 0; if (has_consecutive_pto || visitor_->ShouldKeepConnectionAlive()) { if (GetQuicReloadableFlag(quic_add_stream_info_to_idle_close_detail) && @@ -6263,6 +6246,64 @@ void QuicConnection::OnIdleNetworkDetected() { idle_timeout_connection_close_behavior_); } +void QuicConnection::OnBandwidthUpdateTimeout() { + visitor_->OnBandwidthUpdateTimeout(); +} + +void QuicConnection::OnKeepAliveTimeout() { + QUICHE_DCHECK(use_ping_manager_); + if (retransmission_alarm_->IsSet() || + !visitor_->ShouldKeepConnectionAlive()) { + return; + } + SendPingAtLevel(framer().GetEncryptionLevelToSendApplicationData()); +} + +void QuicConnection::OnRetransmittableOnWireTimeout() { + QUICHE_DCHECK(use_ping_manager_); + if (retransmission_alarm_->IsSet() || + !visitor_->ShouldKeepConnectionAlive()) { + return; + } + bool packet_buffered = false; + switch (retransmittable_on_wire_behavior_) { + case DEFAULT: + break; + case SEND_FIRST_FORWARD_SECURE_PACKET: + if (first_serialized_one_rtt_packet_ != nullptr) { + buffered_packets_.emplace_back( + first_serialized_one_rtt_packet_->data.get(), + first_serialized_one_rtt_packet_->length, self_address(), + peer_address()); + packet_buffered = true; + } + break; + case SEND_RANDOM_BYTES: + const QuicPacketLength random_bytes_length = std::max<QuicPacketLength>( + QuicFramer::GetMinStatelessResetPacketLength() + 1, + random_generator_->RandUint64() % + packet_creator_.max_packet_length()); + buffered_packets_.emplace_back(*random_generator_, random_bytes_length, + self_address(), peer_address()); + packet_buffered = true; + break; + } + if (packet_buffered) { + if (!writer_->IsWriteBlocked()) { + WriteQueuedPackets(); + } + if (connected_) { + // Always reset PING alarm with has_in_flight_packets=true. This is used + // to avoid re-arming the alarm in retransmittable-on-wire mode. + ping_manager_.SetAlarm(clock_->ApproximateNow(), + visitor_->ShouldKeepConnectionAlive(), + /*has_in_flight_packets=*/true); + } + return; + } + SendPingAtLevel(framer().GetEncryptionLevelToSendApplicationData()); +} + void QuicConnection::OnPeerIssuedConnectionIdRetired() { QUICHE_DCHECK(peer_issued_cid_manager_ != nullptr); QuicConnectionId* default_path_cid = @@ -6352,9 +6393,11 @@ void QuicConnection::MaybeUpdateAckTimeout() { } should_last_packet_instigate_acks_ = true; uber_received_packet_manager_.MaybeUpdateAckTimeout( - /*should_last_packet_instigate_acks=*/true, last_decrypted_packet_level_, - last_header_.packet_number, last_received_packet_info_.receipt_time, - clock_->ApproximateNow(), sent_packet_manager_.GetRttStats()); + /*should_last_packet_instigate_acks=*/true, + last_received_packet_info_.decrypted_level, + last_received_packet_info_.header.packet_number, + last_received_packet_info_.receipt_time, clock_->ApproximateNow(), + sent_packet_manager_.GetRttStats()); } QuicTime QuicConnection::GetPathDegradingDeadline() const { @@ -6426,28 +6469,60 @@ bool QuicConnection::SendPathChallenge( return connected_; } if (connection_migration_use_new_cid_) { - { - QuicConnectionId client_cid, server_cid; - FindOnPathConnectionIds(self_address, effective_peer_address, &client_cid, - &server_cid); + if (!only_send_probing_frames_on_alternative_path_) { + { + QuicConnectionId client_cid, server_cid; + FindOnPathConnectionIds(self_address, effective_peer_address, + &client_cid, &server_cid); + QuicPacketCreator::ScopedPeerAddressContext context( + &packet_creator_, peer_address, client_cid, server_cid, + connection_migration_use_new_cid_); + if (writer == writer_) { + ScopedPacketFlusher flusher(this); + // It's on current path, add the PATH_CHALLENGE the same way as other + // frames. This may cause connection to be closed. + packet_creator_.AddPathChallengeFrame(data_buffer); + } else { + std::unique_ptr<SerializedPacket> probing_packet = + packet_creator_.SerializePathChallengeConnectivityProbingPacket( + data_buffer); + QUICHE_DCHECK_EQ(IsRetransmittable(*probing_packet), + NO_RETRANSMITTABLE_DATA); + QUICHE_DCHECK_EQ(self_address, alternative_path_.self_address); + WritePacketUsingWriter(std::move(probing_packet), writer, + self_address, peer_address, + /*measure_rtt=*/false); + } + } + return connected_; + } + QUIC_RELOADABLE_FLAG_COUNT_N(quic_not_bundle_ack_on_alternative_path, 1, 2); + QuicConnectionId client_cid, server_cid; + FindOnPathConnectionIds(self_address, effective_peer_address, &client_cid, + &server_cid); + if (writer == writer_) { + ScopedPacketFlusher flusher(this); + { + QuicPacketCreator::ScopedPeerAddressContext context( + &packet_creator_, peer_address, client_cid, server_cid, + connection_migration_use_new_cid_); + // It's using the default writer, add the PATH_CHALLENGE the same way as + // other frames. This may cause connection to be closed. + packet_creator_.AddPathChallengeFrame(data_buffer); + } + } else { + // Switch to the right CID and source/peer addresses. QuicPacketCreator::ScopedPeerAddressContext context( &packet_creator_, peer_address, client_cid, server_cid, connection_migration_use_new_cid_); - if (writer == writer_) { - ScopedPacketFlusher flusher(this); - // It's on current path, add the PATH_CHALLENGE the same way as other - // frames. This may cause connection to be closed. - packet_creator_.AddPathChallengeFrame(data_buffer); - } else { - std::unique_ptr<SerializedPacket> probing_packet = - packet_creator_.SerializePathChallengeConnectivityProbingPacket( - data_buffer); - QUICHE_DCHECK_EQ(IsRetransmittable(*probing_packet), - NO_RETRANSMITTABLE_DATA); - QUICHE_DCHECK_EQ(self_address, alternative_path_.self_address); - WritePacketUsingWriter(std::move(probing_packet), writer, self_address, - peer_address, /*measure_rtt=*/false); - } + std::unique_ptr<SerializedPacket> probing_packet = + packet_creator_.SerializePathChallengeConnectivityProbingPacket( + data_buffer); + QUICHE_DCHECK_EQ(IsRetransmittable(*probing_packet), + NO_RETRANSMITTABLE_DATA); + QUICHE_DCHECK_EQ(self_address, alternative_path_.self_address); + WritePacketUsingWriter(std::move(probing_packet), writer, self_address, + peer_address, /*measure_rtt=*/false); } return connected_; } @@ -6757,11 +6832,38 @@ QuicConnectionId QuicConnection::GetOneActiveServerConnectionId() const { std::vector<QuicConnectionId> QuicConnection::GetActiveServerConnectionIds() const { + QUICHE_DCHECK_EQ(Perspective::IS_SERVER, perspective_); + std::vector<QuicConnectionId> result; if (self_issued_cid_manager_ == nullptr) { - return {default_path_.server_connection_id}; + result.push_back(default_path_.server_connection_id); + } else { + QUICHE_DCHECK(version().HasIetfQuicFrames()); + result = self_issued_cid_manager_->GetUnretiredConnectionIds(); } - QUICHE_DCHECK(version().HasIetfQuicFrames()); - return self_issued_cid_manager_->GetUnretiredConnectionIds(); + if (GetQuicReloadableFlag( + quic_consider_original_connection_id_as_active_pre_handshake)) { + QUIC_RELOADABLE_FLAG_COUNT( + quic_consider_original_connection_id_as_active_pre_handshake); + if (!IsHandshakeComplete() && + original_destination_connection_id_.has_value()) { + // Consider original_destination_connection_id_ as active before handshake + // completes. + if (std::find(result.begin(), result.end(), + original_destination_connection_id_.value()) != + result.end()) { + QUIC_BUG(quic_unexpected_original_destination_connection_id) + << "original_destination_connection_id: " + << original_destination_connection_id_.value() + << " is unexpectedly in active " + "list"; + } else { + result.insert(result.end(), + original_destination_connection_id_.value()); + } + QUIC_CODE_COUNT(quic_active_original_connection_id_pre_handshake); + } + } + return result; } void QuicConnection::CreateConnectionIdManager() { @@ -6783,6 +6885,14 @@ void QuicConnection::CreateConnectionIdManager() { } } +void QuicConnection::QuicBugIfHasPendingFrames(QuicStreamId id) const { + QUIC_BUG_IF(quic_has_pending_frames_unexpectedly, + packet_creator_.HasPendingStreamFramesOfStream(id)) + << "Stream " << id + << " has pending frames unexpectedly. Received packet info: " + << last_received_packet_info_; +} + void QuicConnection::SetUnackedMapInitialCapacity() { sent_packet_manager_.ReserveUnackedPacketsInitialCapacity( GetUnackedMapInitialCapacity()); @@ -6954,7 +7064,8 @@ void QuicConnection::ReversePathValidationResultDelegate:: ", with active_effective_peer_migration_type_ = ", AddressChangeTypeToString(active_effective_peer_migration_type_), ". The last received packet number ", - connection_->last_header_.packet_number.ToString(), + connection_->last_received_packet_info_.header.packet_number + .ToString(), " Connection is connected: ", connection_->connected_); QUIC_BUG(quic_bug_10511_43) << connection_->quic_bug_10511_43_error_detail_; @@ -7058,5 +7169,26 @@ QuicConnection::OnPeerIpAddressChanged() { return old_send_algorithm; } +void QuicConnection::set_keep_alive_ping_timeout( + QuicTime::Delta keep_alive_ping_timeout) { + if (use_ping_manager_) { + ping_manager_.set_keep_alive_timeout(keep_alive_ping_timeout); + return; + } + QUICHE_DCHECK(!ping_alarm_->IsSet()); + keep_alive_ping_timeout_ = keep_alive_ping_timeout; +} + +void QuicConnection::set_initial_retransmittable_on_wire_timeout( + QuicTime::Delta retransmittable_on_wire_timeout) { + if (use_ping_manager_) { + ping_manager_.set_initial_retransmittable_on_wire_timeout( + retransmittable_on_wire_timeout); + return; + } + QUICHE_DCHECK(!ping_alarm_->IsSet()); + initial_retransmittable_on_wire_timeout_ = retransmittable_on_wire_timeout; +} + #undef ENDPOINT // undef for jumbo builds } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection.h index 22c2c50bd9a..aab56b75837 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection.h @@ -50,11 +50,11 @@ #include "quiche/quic/core/quic_packet_writer.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_path_validator.h" +#include "quiche/quic/core/quic_ping_manager.h" #include "quiche/quic/core/quic_sent_packet_manager.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/uber_received_packet_manager.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_socket_address.h" @@ -137,10 +137,6 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface { // Called when a blocked socket becomes writable. virtual void OnCanWrite() = 0; - // Called when the connection needs more data to probe for additional - // bandwidth. Returns true if data was sent, false otherwise. - virtual bool SendProbingData() = 0; - // Called when the connection experiences a change in congestion window. virtual void OnCongestionWindowChange(QuicTime now) = 0; @@ -238,6 +234,9 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface { // Whether the server address is known to the connection. virtual bool IsKnownServerAddress(const QuicSocketAddress& address) const = 0; + + // When bandwidth update alarms. + virtual void OnBandwidthUpdateTimeout() = 0; }; // Interface which gets callbacks from the QuicConnection at interesting @@ -458,7 +457,8 @@ class QUIC_EXPORT_PRIVATE QuicConnection public QuicNetworkBlackholeDetector::Delegate, public QuicIdleNetworkDetector::Delegate, public QuicPathValidator::SendDelegate, - public QuicConnectionIdManagerVisitorInterface { + public QuicConnectionIdManagerVisitorInterface, + public QuicPingManager::Delegate { public: // Constructs a new QuicConnection for |connection_id| and // |initial_peer_address| using |writer| to write packets. |owns_writer| @@ -709,6 +709,11 @@ class QUIC_EXPORT_PRIVATE QuicConnection // QuicIdleNetworkDetector::Delegate void OnHandshakeTimeout() override; void OnIdleNetworkDetected() override; + void OnBandwidthUpdateTimeout() override; + + // QuicPingManager::Delegate + void OnKeepAliveTimeout() override; + void OnRetransmittableOnWireTimeout() override; // QuicConnectionIdManagerVisitorInterface void OnPeerIssuedConnectionIdRetired() override; @@ -741,21 +746,11 @@ class QUIC_EXPORT_PRIVATE QuicConnection } // Used in Chromium, but not internally. // Must only be called before ping_alarm_ is set. - void set_ping_timeout(QuicTime::Delta ping_timeout) { - QUICHE_DCHECK(!ping_alarm_->IsSet()); - ping_timeout_ = ping_timeout; - } - const QuicTime::Delta ping_timeout() const { return ping_timeout_; } + void set_keep_alive_ping_timeout(QuicTime::Delta keep_alive_ping_timeout); // Sets an initial timeout for the ping alarm when there is no retransmittable // data in flight, allowing for a more aggressive ping alarm in that case. void set_initial_retransmittable_on_wire_timeout( - QuicTime::Delta retransmittable_on_wire_timeout) { - QUICHE_DCHECK(!ping_alarm_->IsSet()); - initial_retransmittable_on_wire_timeout_ = retransmittable_on_wire_timeout; - } - const QuicTime::Delta initial_retransmittable_on_wire_timeout() const { - return initial_retransmittable_on_wire_timeout_; - } + QuicTime::Delta retransmittable_on_wire_timeout); // Used in Chromium, but not internally. void set_creator_debug_delegate(QuicPacketCreator::DebugDelegate* visitor) { packet_creator_.set_debug_delegate(visitor); @@ -1010,20 +1005,13 @@ class QUIC_EXPORT_PRIVATE QuicConnection EncryptionLevel encryption_level() const { return encryption_level_; } EncryptionLevel last_decrypted_level() const { - return last_decrypted_packet_level_; + return last_received_packet_info_.decrypted_level; } const QuicSocketAddress& last_packet_source_address() const { return last_received_packet_info_.source_address; } - bool fill_up_link_during_probing() const { - return fill_up_link_during_probing_; - } - void set_fill_up_link_during_probing(bool new_value) { - fill_up_link_during_probing_ = new_value; - } - // This setting may be changed during the crypto handshake in order to // enable/disable padding of different packets in the crypto handshake. // @@ -1217,13 +1205,12 @@ class QUIC_EXPORT_PRIVATE QuicConnection return connection_migration_use_new_cid_; } - bool count_bytes_on_alternative_path_separately() const { - return count_bytes_on_alternative_path_separately_; - } - // Instantiates connection ID manager. void CreateConnectionIdManager(); + // Log QUIC_BUG if there is pending frames for the stream with |id|. + void QuicBugIfHasPendingFrames(QuicStreamId id) const; + QuicConnectionContext* context() { return &context_; } const QuicConnectionContext* context() const { return &context_; } @@ -1295,6 +1282,11 @@ class QUIC_EXPORT_PRIVATE QuicConnection // |ietf_error| may optionally be be used to directly specify the wire // error code. Otherwise if |ietf_error| is NO_IETF_QUIC_ERROR, the // QuicErrorCodeToTransportErrorCode mapping of |error| will be used. + // Caller may choose to call SendConnectionClosePacket() directly instead of + // CloseConnection() to notify peer that the connection is going to be closed, + // for example, when the server is tearing down. Given + // SendConnectionClosePacket() does not close connection, multiple connection + // close packets could be sent to the peer. virtual void SendConnectionClosePacket(QuicErrorCode error, QuicIetfTransportErrorCodes ietf_error, const std::string& details); @@ -1302,13 +1294,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection // Returns true if the packet should be discarded and not sent. virtual bool ShouldDiscardPacket(EncryptionLevel encryption_level); - // Retransmits packets continuously until blocked by the congestion control. - // If there are no packets to retransmit, does not do anything. - void SendProbingRetransmissions(); - - // Decides whether to send probing retransmissions, and does so if required. - void MaybeSendProbingRetransmissions(); - // Notify various components(Session etc.) that this connection has been // migrated. virtual void OnConnectionMigration(); @@ -1337,6 +1322,12 @@ class QUIC_EXPORT_PRIVATE QuicConnection private: friend class test::QuicConnectionPeer; + enum RetransmittableOnWireBehavior { + DEFAULT, // Send packet containing a PING frame. + SEND_FIRST_FORWARD_SECURE_PACKET, // Send 1st 1-RTT packet. + SEND_RANDOM_BYTES // Send random bytes which is an unprocessable packet. + }; + struct QUIC_EXPORT_PRIVATE PendingPathChallenge { QuicPathFrameBuffer received_path_challenge; QuicSocketAddress peer_address; @@ -1394,40 +1385,52 @@ class QUIC_EXPORT_PRIVATE QuicConnection BufferedPacket(const SerializedPacket& packet, const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address); - BufferedPacket(char* encrypted_buffer, QuicPacketLength encrypted_length, + BufferedPacket(const char* encrypted_buffer, + QuicPacketLength encrypted_length, + const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address); + // Please note, this buffered packet contains random bytes (and is not + // *actually* a QUIC packet). + BufferedPacket(QuicRandom& random, QuicPacketLength encrypted_length, const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address); BufferedPacket(const BufferedPacket& other) = delete; BufferedPacket(const BufferedPacket&& other) = delete; - ~BufferedPacket(); + ~BufferedPacket() = default; - // encrypted_buffer is owned by buffered packet. - absl::string_view encrypted_buffer; + std::unique_ptr<char[]> data; + const QuicPacketLength length; // Self and peer addresses when the packet is serialized. const QuicSocketAddress self_address; const QuicSocketAddress peer_address; }; - // ReceivedPacketInfo comprises the received packet information, which can be - // retrieved before the packet gets successfully decrypted. + // ReceivedPacketInfo comprises the received packet information. + // TODO(fayang): move more fields to ReceivedPacketInfo. struct QUIC_EXPORT_PRIVATE ReceivedPacketInfo { - explicit ReceivedPacketInfo(QuicTime receipt_time) - : received_bytes_counted(false), receipt_time(receipt_time) {} + explicit ReceivedPacketInfo(QuicTime receipt_time); ReceivedPacketInfo(const QuicSocketAddress& destination_address, const QuicSocketAddress& source_address, - QuicTime receipt_time) - : received_bytes_counted(false), - destination_address(destination_address), - source_address(source_address), - receipt_time(receipt_time) {} + QuicTime receipt_time, QuicByteCount length); - bool received_bytes_counted; QuicSocketAddress destination_address; QuicSocketAddress source_address; - QuicTime receipt_time; + QuicTime receipt_time = QuicTime::Zero(); + bool received_bytes_counted = false; + QuicByteCount length = 0; + QuicConnectionId destination_connection_id; + // Fields below are only populated if packet gets decrypted successfully. + // TODO(fayang): consider using absl::optional for following fields. + bool decrypted = false; + EncryptionLevel decrypted_level = ENCRYPTION_INITIAL; + QuicPacketHeader header; + absl::InlinedVector<QuicFrameType, 1> frames; }; + QUIC_EXPORT_PRIVATE friend std::ostream& operator<<( + std::ostream& os, const QuicConnection::ReceivedPacketInfo& info); + // UndecrytablePacket comprises a undecryptable packet and related // information. struct QUIC_EXPORT_PRIVATE UndecryptablePacket { @@ -1837,10 +1840,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection // when a new client connection ID is received. void OnClientConnectionIdAvailable(); - // Returns true if connection needs to set retransmission alarm after a packet - // gets sent. - bool ShouldSetRetransmissionAlarmOnPacketSent(bool in_flight, - EncryptionLevel level) const; + // Determines encryption level to send ping in `packet_number_space`. + EncryptionLevel GetEncryptionLevelToSendPingForSpace( + PacketNumberSpace space) const; QuicConnectionContext context_; @@ -1905,15 +1907,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection // key update but before the first packet has been sent. QuicPacketNumber lowest_packet_sent_in_current_key_phase_; - // True if the last packet has gotten far enough in the framer to be - // decrypted. - bool last_packet_decrypted_; - QuicByteCount last_size_; // Size of the last received packet. // TODO(rch): remove this when b/27221014 is fixed. const char* current_packet_data_; // UDP payload of packet currently being // parsed or nullptr. - EncryptionLevel last_decrypted_packet_level_; - QuicPacketHeader last_header_; bool should_last_packet_instigate_acks_; // Track some peer state so we can do less bookkeeping @@ -1975,8 +1971,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection // SendAlarm. bool defer_send_in_response_to_packets_; - // The timeout for PING. - QuicTime::Delta ping_timeout_; + // TODO(fayang): remove PING related fields below when deprecating + // quic_use_ping_manager2. + // The timeout for keep-alive PING. + QuicTime::Delta keep_alive_ping_timeout_; // Initial timeout for how long the wire can have no retransmittable packets. QuicTime::Delta initial_retransmittable_on_wire_timeout_; @@ -1998,6 +1996,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection // An alarm that is scheduled when the SentPacketManager requires a delay // before sending packets and fires when the packet may be sent. QuicArenaScopedPtr<QuicAlarm> send_alarm_; + // TODO(fayang): remove ping_alarm_ when deprecating quic_use_ping_manager2. // An alarm that fires when a ping should be sent. QuicArenaScopedPtr<QuicAlarm> ping_alarm_; // An alarm that fires when an MTU probe should be sent. @@ -2038,12 +2037,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection // close. bool connected_; - // Destination connection ID of the last received packet. If this ID is the - // original server connection ID chosen by client and server replaces it with - // a different ID, last_packet_destination_connection_id_ is set to the - // replacement connection ID on the server side. - QuicConnectionId last_packet_destination_connection_id_; - // Set to false if the connection should not send truncated connection IDs to // the peer, even if the peer supports it. bool can_truncate_connection_ids_; @@ -2091,22 +2084,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection // from the peer. Default to kMaxConsecutiveNonRetransmittablePackets. size_t max_consecutive_num_packets_with_no_retransmittable_frames_; - // If true, bundle an ack-eliciting frame with an ACK if the PTO or RTO alarm - // have previously fired. + // If true, bundle an ack-eliciting frame with an ACK if the PTO alarm have + // previously fired. bool bundle_retransmittable_with_pto_ack_; - // If true, the connection will fill up the pipe with extra data whenever the - // congestion controller needs it in order to make a bandwidth estimate. This - // is useful if the application pesistently underutilizes the link, but still - // relies on having a reasonable bandwidth estimate from the connection, e.g. - // for real time applications. - bool fill_up_link_during_probing_; - - // If true, the probing retransmission will not be started again. This is - // used to safeguard against an accidental tail recursion in probing - // retransmission code. - bool probing_retransmission_pending_; - // Id of latest sent control frame. 0 if no control frame has been sent. QuicControlFrameId last_control_frame_id_; @@ -2224,12 +2205,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection // 2), do not override it on receiving PATH_CHALLENGE (case 1). PathState alternative_path_; - // This field is used to debug b/177312785. - QuicFrameType most_recent_frame_type_; - - bool count_bytes_on_alternative_path_separately_ = - GetQuicReloadableFlag(quic_count_bytes_on_alternative_path_seperately); - // If true, upon seeing a new client address, validate the client address. bool validate_client_addresses_ = false; @@ -2240,20 +2215,25 @@ class QUIC_EXPORT_PRIVATE QuicConnection // Enable this via reloadable flag once this feature is complete. bool connection_migration_use_new_cid_ = false; - const bool flush_after_coalesce_higher_space_packets_ = - GetQuicReloadableFlag(quic_flush_after_coalesce_higher_space_packets); - - // Records the 1-RTT connection close frame sent. - // TODO(b/180103273): remove this after the bug gets fixed. - absl::optional<QuicConnectionCloseFrame> connection_close_frame_sent_; - // If true, send connection close packet on INVALID_VERSION. bool send_connection_close_for_invalid_version_ = false; + const bool use_ping_manager_ = GetQuicReloadableFlag(quic_use_ping_manager2); + + QuicPingManager ping_manager_; + + // Records first serialized 1-RTT packet. + std::unique_ptr<BufferedPacket> first_serialized_one_rtt_packet_; + + RetransmittableOnWireBehavior retransmittable_on_wire_behavior_ = DEFAULT; + // TODO(b/205023946) Debug-only fields, to be deprecated after the bug is // fixed. absl::optional<QuicWallTime> quic_bug_10511_43_timestamp_; std::string quic_bug_10511_43_error_detail_; + + bool only_send_probing_frames_on_alternative_path_ = + GetQuicReloadableFlag(quic_not_bundle_ack_on_alternative_path); }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_context_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_context_test.cc index 0b87d012792..1f68ae93172 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_context_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_context_test.cc @@ -9,7 +9,7 @@ using testing::ElementsAre; -namespace quic { +namespace quic::test { namespace { class TraceCollector : public QuicConnectionTracer { @@ -170,4 +170,4 @@ TEST_F(QuicConnectionContextTest, TestAlternatingSwitch) { } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_id_manager_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_id_manager_test.cc index 543f05433de..1c2657dc581 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_id_manager_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_id_manager_test.cc @@ -13,7 +13,7 @@ #include "quiche/quic/test_tools/quic_connection_id_manager_peer.h" #include "quiche/quic/test_tools/quic_test_utils.h" -namespace quic { +namespace quic::test { namespace { using ::quic::test::IsError; @@ -953,4 +953,4 @@ TEST_F(QuicSelfIssuedConnectionIdManagerTest, } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_id_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_id_test.cc index f421e95d34c..fdd4c6f96c2 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_id_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_id_test.cc @@ -13,7 +13,7 @@ #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/test_tools/quic_test_utils.h" -namespace quic { +namespace quic::test { namespace { @@ -178,4 +178,4 @@ TEST_F(QuicConnectionIdTest, ChangeLength) { } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_test.cc index 50ae2f1cd36..ff845387b5e 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_test.cc @@ -478,11 +478,6 @@ class TestConnection : public QuicConnection { .IsInitialized(); } - void SetMaxTailLossProbes(size_t max_tail_loss_probes) { - QuicSentPacketManagerPeer::SetMaxTailLossProbes( - QuicConnectionPeer::GetSentPacketManager(this), max_tail_loss_probes); - } - QuicByteCount GetBytesInFlight() { return QuicConnectionPeer::GetSentPacketManager(this)->GetBytesInFlight(); } @@ -493,16 +488,6 @@ class TestConnection : public QuicConnection { next_effective_peer_addr_ = std::make_unique<QuicSocketAddress>(addr); } - bool PtoEnabled() { - if (QuicConnectionPeer::GetSentPacketManager(this)->pto_enabled()) { - // TLP/RTO related tests are stale when PTO is enabled. - QUICHE_DCHECK(PROTOCOL_TLS1_3 == version().handshake_protocol || - GetQuicRestartFlag(quic_default_on_pto2)); - return true; - } - return false; - } - void SendOrQueuePacket(SerializedPacket packet) override { QuicConnection::SendOrQueuePacket(std::move(packet)); self_address_on_default_path_while_sending_packet_ = self_address(); @@ -517,7 +502,6 @@ class TestConnection : public QuicConnection { using QuicConnection::active_effective_peer_migration_type; using QuicConnection::IsCurrentPacketConnectivityProbing; using QuicConnection::SelectMutualVersion; - using QuicConnection::SendProbingRetransmissions; using QuicConnection::set_defer_send_in_response_to_packets; protected: @@ -1285,6 +1269,10 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> { void SimulateNextPacketTooLarge() { writer_->SimulateNextPacketTooLarge(); } + void ExpectNextPacketUnprocessable() { + writer_->ExpectNextPacketUnprocessable(); + } + void AlwaysGetPacketTooLarge() { writer_->AlwaysGetPacketTooLarge(); } void SetWritePauseTimeDelta(QuicTime::Delta delta) { @@ -1574,23 +1562,9 @@ TEST_P(QuicConnectionTest, SelfAddressChangeAtServer) { QuicSocketAddress self_address(host, 123); EXPECT_EQ(0u, connection_.GetStats().packets_dropped); EXPECT_CALL(visitor_, AllowSelfAddressChange()).WillOnce(Return(false)); - if (GetQuicReloadableFlag(quic_drop_packets_with_changed_server_address)) { - ProcessFramePacketWithAddresses(MakeCryptoFrame(), self_address, - kPeerAddress, ENCRYPTION_INITIAL); - EXPECT_TRUE(connection_.connected()); - EXPECT_EQ(1u, connection_.GetStats().packets_dropped); - return; - } - if (version().handshake_protocol == PROTOCOL_TLS1_3) { - EXPECT_CALL(visitor_, BeforeConnectionCloseSent()); - } - EXPECT_CALL(visitor_, OnConnectionClosed(_, _)); - EXPECT_QUIC_PEER_BUG( - ProcessFramePacketWithAddresses(MakeCryptoFrame(), self_address, - kPeerAddress, ENCRYPTION_INITIAL), - "Self address migration is not supported at the server"); - EXPECT_FALSE(connection_.connected()); - TestConnectionCloseQuicErrorCode(QUIC_ERROR_MIGRATING_ADDRESS); + ProcessFramePacketWithAddresses(MakeCryptoFrame(), self_address, kPeerAddress, + ENCRYPTION_INITIAL); + EXPECT_TRUE(connection_.connected()); EXPECT_EQ(1u, connection_.GetStats().packets_dropped); } @@ -1688,10 +1662,8 @@ TEST_P(QuicConnectionTest, PeerPortChangeAtServer) { rtt_stats->set_initial_rtt(default_init_rtt * 2); EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt()); - QuicSentPacketManagerPeer::SetConsecutiveRtoCount(manager_, 1); - EXPECT_EQ(1u, manager_->GetConsecutiveRtoCount()); - QuicSentPacketManagerPeer::SetConsecutiveTlpCount(manager_, 2); - EXPECT_EQ(2u, manager_->GetConsecutiveTlpCount()); + QuicSentPacketManagerPeer::SetConsecutivePtoCount(manager_, 1); + EXPECT_EQ(1u, manager_->GetConsecutivePtoCount()); const QuicSocketAddress kNewPeerAddress = QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/23456); @@ -1718,8 +1690,7 @@ TEST_P(QuicConnectionTest, PeerPortChangeAtServer) { EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address()); // PORT_CHANGE shouldn't state change in sent packet manager. EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt()); - EXPECT_EQ(1u, manager_->GetConsecutiveRtoCount()); - EXPECT_EQ(2u, manager_->GetConsecutiveTlpCount()); + EXPECT_EQ(1u, manager_->GetConsecutivePtoCount()); EXPECT_EQ(manager_->GetSendAlgorithm(), send_algorithm_); if (connection_.validate_client_address()) { EXPECT_EQ(NO_CHANGE, connection_.active_effective_peer_migration_type()); @@ -2496,8 +2467,7 @@ TEST_P(QuicConnectionTest, ReceivePathProbingAtServer) { connection_.GetStats().num_connectivity_probing_received); EXPECT_EQ(kPeerAddress, connection_.peer_address()); EXPECT_EQ(kPeerAddress, connection_.effective_peer_address()); - if (GetParam().version.HasIetfQuicFrames() && - GetQuicReloadableFlag(quic_count_bytes_on_alternative_path_seperately)) { + if (GetParam().version.HasIetfQuicFrames()) { QuicByteCount bytes_sent = QuicConnectionPeer::BytesSentOnAlternativePath(&connection_); EXPECT_LT(0u, bytes_sent); @@ -3318,8 +3288,6 @@ TEST_P(QuicConnectionTest, AckNeedsRetransmittableFrames) { } TEST_P(QuicConnectionTest, AckNeedsRetransmittableFramesAfterPto) { - // Disable TLP so the RTO fires immediately. - connection_.SetMaxTailLossProbes(0); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; QuicTagVector connection_options; @@ -3346,8 +3314,7 @@ TEST_P(QuicConnectionTest, AckNeedsRetransmittableFramesAfterPto) { connection_.GetRetransmissionAlarm()->deadline(); clock_.AdvanceTime(retransmission_time - clock_.Now()); connection_.GetRetransmissionAlarm()->Fire(); - ASSERT_TRUE(manager_->GetConsecutiveRtoCount() > 0 || - manager_->GetConsecutivePtoCount() > 0); + ASSERT_LT(0u, manager_->GetConsecutivePtoCount()); // Process a packet, which requests a retransmittable frame be bundled // with the ACK. @@ -4004,9 +3971,7 @@ TEST_P(QuicConnectionTest, CancelRetransmissionAlarmAfterResetStream) { EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); } -TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnRTO) { - connection_.SetMaxTailLossProbes(0); - +TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnPTO) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); @@ -4016,17 +3981,11 @@ TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnRTO) { // Fire the RTO and verify that the RST_STREAM is resent, the stream data // is sent. - const size_t num_retransmissions = connection_.PtoEnabled() ? 1 : 2; - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) - .Times(AtLeast(num_retransmissions)); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1)); clock_.AdvanceTime(DefaultRetransmissionTime()); connection_.GetRetransmissionAlarm()->Fire(); size_t padding_frame_count = writer_->padding_frames().size(); EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count()); - if (num_retransmissions == 2) { - ASSERT_EQ(1u, writer_->rst_stream_frames().size()); - EXPECT_EQ(stream_id, writer_->rst_stream_frames().front().stream_id); - } } TEST_P(QuicConnectionTest, DoNotSendPendingRetransmissionForResetStream) { @@ -4164,33 +4123,6 @@ TEST_P(QuicConnectionTest, RetransmitNackedLargestObserved) { ProcessAckPacket(&frame); } -TEST_P(QuicConnectionTest, QueueAfterTwoRTOs) { - if (connection_.PtoEnabled()) { - return; - } - connection_.SetMaxTailLossProbes(0); - - for (int i = 0; i < 10; ++i) { - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - connection_.SendStreamDataWithString(3, "foo", i * 3, NO_FIN); - } - - // Block the writer and ensure they're queued. - BlockOnNextWrite(); - clock_.AdvanceTime(DefaultRetransmissionTime()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); - connection_.GetRetransmissionAlarm()->Fire(); - EXPECT_TRUE(connection_.HasQueuedData()); - - // Unblock the writer. - writer_->SetWritable(); - clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds( - 2 * DefaultRetransmissionTime().ToMicroseconds())); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); - connection_.GetRetransmissionAlarm()->Fire(); - connection_.OnCanWrite(); -} - TEST_P(QuicConnectionTest, WriteBlockedBufferedThenSent) { BlockOnNextWrite(); writer_->set_is_write_blocked_data_buffered(true); @@ -4245,9 +4177,7 @@ TEST_P(QuicConnectionTest, RetransmitWriteBlockedAckedOriginalThenSent) { writer_->SetWritable(); connection_.OnCanWrite(); EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); - uint64_t retransmission = connection_.PtoEnabled() ? 3 : 2; - EXPECT_FALSE(QuicConnectionPeer::HasRetransmittableFrames(&connection_, - retransmission)); + EXPECT_FALSE(QuicConnectionPeer::HasRetransmittableFrames(&connection_, 3)); } TEST_P(QuicConnectionTest, AlarmsWhenWriteBlocked) { @@ -4474,85 +4404,6 @@ TEST_P(QuicConnectionTest, DontLatchUnackedPacket) { EXPECT_EQ(QuicPacketNumber(6u), stop_waiting()->least_unacked); } -TEST_P(QuicConnectionTest, TLP) { - if (connection_.PtoEnabled()) { - return; - } - 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); - - EXPECT_EQ(QuicPacketNumber(1u), writer_->header().packet_number); - // Simulate the retransmission alarm firing and sending a tlp, - // so send algorithm's OnRetransmissionTimeout is not called. - clock_.AdvanceTime(retransmission_time - clock_.Now()); - const QuicPacketNumber retransmission( - connection_.SupportsMultiplePacketNumberSpaces() ? 3 : 2); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, retransmission, _, _)); - connection_.GetRetransmissionAlarm()->Fire(); - EXPECT_EQ(retransmission, writer_->header().packet_number); - // We do not raise the high water mark yet. - EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked); -} - -TEST_P(QuicConnectionTest, RTO) { - if (connection_.PtoEnabled()) { - return; - } - connection_.SetMaxTailLossProbes(0); - - QuicTime default_retransmission_time = - clock_.ApproximateNow() + DefaultRetransmissionTime(); - SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr); - EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked); - - EXPECT_EQ(QuicPacketNumber(1u), writer_->header().packet_number); - EXPECT_EQ(default_retransmission_time, - connection_.GetRetransmissionAlarm()->deadline()); - // Simulate the retransmission alarm firing. - clock_.AdvanceTime(DefaultRetransmissionTime()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2), _, _)); - 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); -} - -// Regression test of b/133771183. -TEST_P(QuicConnectionTest, RtoWithNoDataToRetransmit) { - if (connection_.PtoEnabled()) { - return; - } - connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.SetMaxTailLossProbes(0); - - SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr); - // Connection is cwnd limited. - CongestionBlockWrites(); - // Stream gets reset. - SendRstStream(3, QUIC_ERROR_PROCESSING_STREAM, 3); - // Simulate the retransmission alarm firing. - clock_.AdvanceTime(DefaultRetransmissionTime()); - // RTO fires, but there is no packet to be RTOed. - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - connection_.GetRetransmissionAlarm()->Fire(); - EXPECT_EQ(1u, writer_->rst_stream_frames().size()); - - EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(40); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(20); - EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(false)); - EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(1); - // Receives packets 1 - 40. - for (size_t i = 1; i <= 40; ++i) { - ProcessDataPacket(i); - } -} - TEST_P(QuicConnectionTest, SendHandshakeMessages) { use_tagging_decrypter(); // A TaggingEncrypter puts kTagSize copies of the given byte (0x01 here) at @@ -4664,41 +4515,6 @@ TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) { ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_ZERO_RTT); } -TEST_P(QuicConnectionTest, TestRetransmitOrder) { - if (connection_.PtoEnabled()) { - return; - } - connection_.SetMaxTailLossProbes(0); - - QuicByteCount first_packet_size; - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) - .WillOnce(SaveArg<3>(&first_packet_size)); - - connection_.SendStreamDataWithString(3, "first_packet", 0, NO_FIN); - QuicByteCount second_packet_size; - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) - .WillOnce(SaveArg<3>(&second_packet_size)); - connection_.SendStreamDataWithString(3, "second_packet", 12, NO_FIN); - EXPECT_NE(first_packet_size, second_packet_size); - // Advance the clock by huge time to make sure packets will be retransmitted. - clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10)); - { - InSequence s; - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, first_packet_size, _)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, second_packet_size, _)); - } - connection_.GetRetransmissionAlarm()->Fire(); - - // Advance again and expect the packets to be sent again in the same order. - clock_.AdvanceTime(QuicTime::Delta::FromSeconds(20)); - { - InSequence s; - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, first_packet_size, _)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, second_packet_size, _)); - } - connection_.GetRetransmissionAlarm()->Fire(); -} - TEST_P(QuicConnectionTest, Buffer100NonDecryptablePacketsThenKeyChange) { if (connection_.SupportsMultiplePacketNumberSpaces()) { return; @@ -4753,55 +4569,7 @@ TEST_P(QuicConnectionTest, SetRTOAfterWritingToSocket) { EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); } -TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) { - if (connection_.PtoEnabled()) { - return; - } - connection_.SetMaxTailLossProbes(0); - - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); - connection_.SendStreamDataWithString(2, "foo", 0, NO_FIN); - connection_.SendStreamDataWithString(3, "bar", 0, NO_FIN); - QuicAlarm* retransmission_alarm = connection_.GetRetransmissionAlarm(); - EXPECT_TRUE(retransmission_alarm->IsSet()); - EXPECT_EQ(DefaultRetransmissionTime(), - retransmission_alarm->deadline() - clock_.Now()); - - // Advance the time right before the RTO, then receive an ack for the first - // packet to delay the RTO. - clock_.AdvanceTime(DefaultRetransmissionTime()); - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame ack = InitAckFrame(1); - ProcessAckPacket(&ack); - // Now we have an RTT sample of DefaultRetransmissionTime(500ms), - // so the RTO has increased to 2 * SRTT. - EXPECT_TRUE(retransmission_alarm->IsSet()); - EXPECT_EQ(retransmission_alarm->deadline() - clock_.Now(), - 2 * DefaultRetransmissionTime()); - - // Move forward past the original RTO and ensure the RTO is still pending. - clock_.AdvanceTime(2 * DefaultRetransmissionTime()); - - // Ensure the second packet gets retransmitted when it finally fires. - EXPECT_TRUE(retransmission_alarm->IsSet()); - EXPECT_EQ(retransmission_alarm->deadline(), clock_.ApproximateNow()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - // Manually cancel the alarm to simulate a real test. - connection_.GetRetransmissionAlarm()->Fire(); - - // The new retransmitted packet number should set the RTO to a larger value - // than previously. - EXPECT_TRUE(retransmission_alarm->IsSet()); - QuicTime next_rto_time = retransmission_alarm->deadline(); - QuicTime expected_rto_time = - connection_.sent_packet_manager().GetRetransmissionTime(); - EXPECT_EQ(next_rto_time, expected_rto_time); -} - TEST_P(QuicConnectionTest, TestQueued) { - connection_.SetMaxTailLossProbes(0); - EXPECT_EQ(0u, connection_.NumQueuedPackets()); BlockOnNextWrite(); connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN); @@ -5043,7 +4811,7 @@ TEST_P(QuicConnectionTest, ReducedPingTimeout) { EXPECT_FALSE(connection_.GetPingAlarm()->IsSet()); // Use a reduced ping timeout for this connection. - connection_.set_ping_timeout(QuicTime::Delta::FromSeconds(10)); + connection_.set_keep_alive_ping_timeout(QuicTime::Delta::FromSeconds(10)); // Advance to 5ms, and send a packet to the peer, which will set // the ping alarm. @@ -5754,84 +5522,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendDuringHandshake) { TestConnectionCloseQuicErrorCode(QUIC_NETWORK_IDLE_TIMEOUT); } -TEST_P(QuicConnectionTest, TimeoutAfterRetransmission) { - if (connection_.PtoEnabled()) { - return; - } - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - EXPECT_TRUE(connection_.connected()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - QuicConfig config; - connection_.SetFromConfig(config); - - const QuicTime start_time = clock_.Now(); - const QuicTime::Delta initial_idle_timeout = - QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1); - QuicTime default_timeout = clock_.Now() + initial_idle_timeout; - - connection_.SetMaxTailLossProbes(0); - const QuicTime default_retransmission_time = - start_time + DefaultRetransmissionTime(); - - ASSERT_LT(default_retransmission_time, default_timeout); - - // When we send a packet, the timeout will change to 5 ms + - // kInitialIdleTimeoutSecs (but it will not reschedule the alarm). - const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5); - const QuicTime send_time = start_time + five_ms; - clock_.AdvanceTime(five_ms); - ASSERT_EQ(send_time, clock_.Now()); - SendStreamDataToPeer( - GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo", - 0, FIN, nullptr); - EXPECT_EQ(default_timeout + five_ms, - connection_.GetTimeoutAlarm()->deadline()); - - // Move forward 5 ms and receive a packet, which will move the timeout - // forward 5 ms more (but will not reschedule the alarm). - const QuicTime receive_time = send_time + five_ms; - clock_.AdvanceTime(receive_time - clock_.Now()); - ASSERT_EQ(receive_time, clock_.Now()); - ProcessPacket(1); - - // Now move forward to the retransmission time and retransmit the - // packet, which should move the timeout forward again (but will not - // reschedule the alarm). - EXPECT_EQ(default_retransmission_time + five_ms, - connection_.GetRetransmissionAlarm()->deadline()); - // Simulate the retransmission alarm firing. - const QuicTime rto_time = send_time + DefaultRetransmissionTime(); - const QuicTime final_timeout = rto_time + initial_idle_timeout; - clock_.AdvanceTime(rto_time - clock_.Now()); - ASSERT_EQ(rto_time, clock_.Now()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2u), _, _)); - connection_.GetRetransmissionAlarm()->Fire(); - - // Advance to the original timeout and fire the alarm. The connection should - // timeout, and the alarm should be registered based on the time of the - // retransmission. - clock_.AdvanceTime(default_timeout - clock_.Now()); - ASSERT_EQ(default_timeout.ToDebuggingValue(), - clock_.Now().ToDebuggingValue()); - EXPECT_EQ(default_timeout, clock_.Now()); - EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); - EXPECT_TRUE(connection_.connected()); - ASSERT_EQ(final_timeout.ToDebuggingValue(), - connection_.GetTimeoutAlarm()->deadline().ToDebuggingValue()); - - // This time, we should time out. - EXPECT_CALL(visitor_, - OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1)); - clock_.AdvanceTime(final_timeout - clock_.Now()); - EXPECT_EQ(connection_.GetTimeoutAlarm()->deadline(), clock_.Now()); - EXPECT_EQ(final_timeout, clock_.Now()); - connection_.GetTimeoutAlarm()->Fire(); - EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet()); - EXPECT_FALSE(connection_.connected()); - TestConnectionCloseQuicErrorCode(QUIC_NETWORK_IDLE_TIMEOUT); -} - TEST_P(QuicConnectionTest, TimeoutAfterSendAfterHandshake) { // When the idle timeout fires, verify that by default we do not send any // connection close packets. @@ -5861,6 +5551,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendAfterHandshake) { &config, connection_.connection_id()); } connection_.SetFromConfig(config); + QuicConnectionPeer::DisableBandwidthUpdate(&connection_); const QuicTime::Delta default_idle_timeout = QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs - 1); @@ -5911,64 +5602,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendAfterHandshake) { IsError(QUIC_NETWORK_IDLE_TIMEOUT)); } -TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseAndTLP) { - if (connection_.PtoEnabled()) { - return; - } - // Same test as above, but sending TLPs causes a connection close to be sent. - EXPECT_TRUE(connection_.connected()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - QuicConfig config; - - // Create a handshake message that also enables silent close. - CryptoHandshakeMessage msg; - std::string error_details; - QuicConfig client_config; - client_config.SetInitialStreamFlowControlWindowToSend( - kInitialStreamFlowControlWindowForTest); - client_config.SetInitialSessionFlowControlWindowToSend( - kInitialSessionFlowControlWindowForTest); - client_config.SetIdleNetworkTimeout( - QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs)); - client_config.ToHandshakeMessage(&msg, connection_.transport_version()); - const QuicErrorCode error = - config.ProcessPeerHello(msg, CLIENT, &error_details); - EXPECT_THAT(error, IsQuicNoError()); - - connection_.SetFromConfig(config); - - const QuicTime::Delta default_idle_timeout = - QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs - 1); - const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5); - QuicTime default_timeout = clock_.ApproximateNow() + default_idle_timeout; - - // When we send a packet, the timeout will change to 5ms + - // kInitialIdleTimeoutSecs. - clock_.AdvanceTime(five_ms); - SendStreamDataToPeer( - GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo", - 0, FIN, nullptr); - EXPECT_EQ(default_timeout + five_ms, - connection_.GetTimeoutAlarm()->deadline()); - - // Retransmit the packet via tail loss probe. - clock_.AdvanceTime(connection_.GetRetransmissionAlarm()->deadline() - - clock_.Now()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2u), _, _)); - connection_.GetRetransmissionAlarm()->Fire(); - - // This time, we should time out and send a connection close due to the TLP. - EXPECT_CALL(visitor_, - OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1)); - clock_.AdvanceTime(connection_.GetTimeoutAlarm()->deadline() - - clock_.ApproximateNow() + five_ms); - connection_.GetTimeoutAlarm()->Fire(); - EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet()); - EXPECT_FALSE(connection_.connected()); - TestConnectionCloseQuicErrorCode(QUIC_NETWORK_IDLE_TIMEOUT); -} - TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseWithOpenStreams) { // Same test as above, but having open streams causes a connection close // to be sent. @@ -5998,6 +5631,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseWithOpenStreams) { &config, connection_.connection_id()); } connection_.SetFromConfig(config); + QuicConnectionPeer::DisableBandwidthUpdate(&connection_); const QuicTime::Delta default_idle_timeout = QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs - 1); @@ -6093,6 +5727,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) { connection_.SetNetworkTimeouts( QuicTime::Delta::Infinite(), initial_idle_timeout + QuicTime::Delta::FromSeconds(1)); + QuicConnectionPeer::DisableBandwidthUpdate(&connection_); const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5); QuicTime default_timeout = clock_.ApproximateNow() + initial_idle_timeout; @@ -6142,58 +5777,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) { TestConnectionCloseQuicErrorCode(QUIC_NETWORK_IDLE_TIMEOUT); } -TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) { - if (connection_.PtoEnabled()) { - return; - } - connection_.SetMaxTailLossProbes(2); - EXPECT_TRUE(connection_.connected()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - QuicConfig config; - QuicTagVector connection_options; - connection_options.push_back(k5RTO); - config.SetConnectionOptionsToSend(connection_options); - QuicConfigPeer::SetNegotiated(&config, true); - if (GetQuicReloadableFlag(quic_default_enable_5rto_blackhole_detection2)) { - EXPECT_CALL(visitor_, GetHandshakeState()) - .WillRepeatedly(Return(HANDSHAKE_COMPLETE)); - } - if (connection_.version().UsesTls()) { - QuicConfigPeer::SetReceivedOriginalConnectionId( - &config, connection_.connection_id()); - QuicConfigPeer::SetReceivedInitialSourceConnectionId( - &config, connection_.connection_id()); - } - connection_.SetFromConfig(config); - - // Send stream data. - SendStreamDataToPeer( - GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo", - 0, FIN, nullptr); - - // Fire the retransmission alarm 6 times, twice for TLP and 4 times for RTO. - for (int i = 0; i < 6; ++i) { - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - connection_.GetRetransmissionAlarm()->Fire(); - EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); - EXPECT_TRUE(connection_.connected()); - } - EXPECT_CALL(visitor_, OnPathDegrading()); - connection_.PathDegradingTimeout(); - - EXPECT_EQ(2u, connection_.sent_packet_manager().GetConsecutiveTlpCount()); - EXPECT_EQ(4u, connection_.sent_packet_manager().GetConsecutiveRtoCount()); - // This time, we should time out. - EXPECT_CALL(visitor_, - OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1)); - ASSERT_TRUE(connection_.BlackholeDetectionInProgress()); - connection_.GetBlackholeDetectorAlarm()->Fire(); - EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet()); - EXPECT_FALSE(connection_.connected()); - TestConnectionCloseQuicErrorCode(QUIC_TOO_MANY_RTOS); -} - TEST_P(QuicConnectionTest, SendScheduler) { // Test that if we send a packet without delay, it is not queued. QuicFramerPeer::SetPerspective(&peer_framer_, Perspective::IS_CLIENT); @@ -7095,63 +6678,6 @@ TEST_P(QuicConnectionTest, BadVersionNegotiation) { IsError(QUIC_INVALID_VERSION_NEGOTIATION_PACKET)); } -TEST_P(QuicConnectionTest, CheckSendStats) { - if (connection_.PtoEnabled()) { - return; - } - connection_.SetMaxTailLossProbes(0); - - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - connection_.SendStreamDataWithString(3, "first", 0, NO_FIN); - size_t first_packet_size = writer_->last_packet_size(); - - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - connection_.SendStreamDataWithString(5, "second", 0, NO_FIN); - size_t second_packet_size = writer_->last_packet_size(); - - // 2 retransmissions due to rto, 1 due to explicit nack. - EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3); - - // Retransmit due to RTO. - clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10)); - connection_.GetRetransmissionAlarm()->Fire(); - - // Retransmit due to explicit nacks. - QuicAckFrame nack_three = - InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}, - {QuicPacketNumber(4), QuicPacketNumber(5)}}); - - LostPacketVector lost_packets; - lost_packets.push_back( - LostPacket(QuicPacketNumber(1), kMaxOutgoingPacketSize)); - lost_packets.push_back( - LostPacket(QuicPacketNumber(3), kMaxOutgoingPacketSize)); - EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<5>(lost_packets), - Return(LossDetectionInterface::DetectionStats()))); - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - ProcessAckPacket(&nack_three); - - EXPECT_CALL(*send_algorithm_, BandwidthEstimate()) - .WillOnce(Return(QuicBandwidth::Zero())); - - const QuicConnectionStats& stats = connection_.GetStats(); - // For IETF QUIC, version is not included as the encryption level switches to - // FORWARD_SECURE in SendStreamDataWithString. - size_t save_on_version = - GetParam().version.HasIetfInvariantHeader() ? 0 : kQuicVersionSize; - EXPECT_EQ(3 * first_packet_size + 2 * second_packet_size - save_on_version, - stats.bytes_sent); - EXPECT_EQ(5u, stats.packets_sent); - EXPECT_EQ(2 * first_packet_size + second_packet_size - save_on_version, - stats.bytes_retransmitted); - EXPECT_EQ(3u, stats.packets_retransmitted); - EXPECT_EQ(1u, stats.rto_count); - EXPECT_EQ(kDefaultMaxPacketSize, stats.egress_mtu); -} - TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) { // Construct a packet with stream frame and connection close frame. QuicPacketHeader header; @@ -7404,7 +6930,7 @@ TEST_P(QuicConnectionTest, SendBlockedImmediately) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)).Times(1); EXPECT_EQ(0u, connection_.GetStats().blocked_frames_sent); - connection_.SendControlFrame(QuicFrame(QuicBlockedFrame(1, 3))); + connection_.SendControlFrame(QuicFrame(QuicBlockedFrame(1, 3, 0))); EXPECT_EQ(1u, connection_.GetStats().blocked_frames_sent); EXPECT_FALSE(connection_.HasQueuedData()); } @@ -7415,7 +6941,7 @@ TEST_P(QuicConnectionTest, FailedToSendBlockedFrames) { } MockQuicConnectionDebugVisitor debug_visitor; connection_.set_debug_visitor(&debug_visitor); - QuicBlockedFrame blocked(1, 3); + QuicBlockedFrame blocked(1, 3, 0); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0); EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)).Times(0); @@ -7431,14 +6957,19 @@ TEST_P(QuicConnectionTest, SendingUnencryptedStreamDataFails) { return; } - EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF)) - .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame)); - EXPECT_QUIC_BUG(connection_.SaveAndSendStreamData(3, {}, 0, FIN), - "Cannot send stream data with level: ENCRYPTION_INITIAL"); - EXPECT_FALSE(connection_.connected()); - EXPECT_EQ(1, connection_close_frame_count_); - EXPECT_THAT(saved_connection_close_frame_.quic_error_code, - IsError(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA)); + EXPECT_QUIC_BUG( + { + EXPECT_CALL(visitor_, + OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF)) + .WillOnce( + Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame)); + connection_.SaveAndSendStreamData(3, {}, 0, FIN); + EXPECT_FALSE(connection_.connected()); + EXPECT_EQ(1, connection_close_frame_count_); + EXPECT_THAT(saved_connection_close_frame_.quic_error_code, + IsError(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA)); + }, + "Cannot send stream data with level: ENCRYPTION_INITIAL"); } TEST_P(QuicConnectionTest, SetRetransmissionAlarmForCryptoPacket) { @@ -7643,6 +7174,150 @@ TEST_P(QuicConnectionTest, ServerRetransmittableOnWire) { connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); } +TEST_P(QuicConnectionTest, RetransmittableOnWireSendFirstPacket) { + if (!GetQuicReloadableFlag(quic_use_ping_manager2) || + !VersionHasIetfQuicFrames(connection_.version().transport_version)) { + return; + } + EXPECT_CALL(visitor_, ShouldKeepConnectionAlive()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + + const QuicTime::Delta kRetransmittableOnWireTimeout = + QuicTime::Delta::FromMilliseconds(200); + const QuicTime::Delta kTestRtt = QuicTime::Delta::FromMilliseconds(100); + + connection_.set_initial_retransmittable_on_wire_timeout( + kRetransmittableOnWireTimeout); + + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + QuicConfig config; + QuicTagVector connection_options; + connection_options.push_back(kROWF); + config.SetClientConnectionOptions(connection_options); + connection_.SetFromConfig(config); + + // Send a request. + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN); + // Receive an ACK after 1-RTT. + clock_.AdvanceTime(kTestRtt); + EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); + QuicAckFrame frame = + InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}}); + ProcessAckPacket(&frame); + ASSERT_TRUE(connection_.GetPingAlarm()->IsSet()); + EXPECT_EQ(kRetransmittableOnWireTimeout, + connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); + EXPECT_EQ(1u, writer_->packets_write_attempts()); + + // Fire retransmittable-on-wire alarm. + clock_.AdvanceTime(kRetransmittableOnWireTimeout); + connection_.GetPingAlarm()->Fire(); + EXPECT_EQ(2u, writer_->packets_write_attempts()); + // Verify alarm is set in keep-alive mode. + ASSERT_TRUE(connection_.GetPingAlarm()->IsSet()); + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), + connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); +} + +TEST_P(QuicConnectionTest, RetransmittableOnWireSendRandomBytes) { + if (!GetQuicReloadableFlag(quic_use_ping_manager2) || + !VersionHasIetfQuicFrames(connection_.version().transport_version)) { + return; + } + EXPECT_CALL(visitor_, ShouldKeepConnectionAlive()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + + const QuicTime::Delta kRetransmittableOnWireTimeout = + QuicTime::Delta::FromMilliseconds(200); + const QuicTime::Delta kTestRtt = QuicTime::Delta::FromMilliseconds(100); + + connection_.set_initial_retransmittable_on_wire_timeout( + kRetransmittableOnWireTimeout); + + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + QuicConfig config; + QuicTagVector connection_options; + connection_options.push_back(kROWR); + config.SetClientConnectionOptions(connection_options); + connection_.SetFromConfig(config); + + // Send a request. + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN); + // Receive an ACK after 1-RTT. + clock_.AdvanceTime(kTestRtt); + EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); + QuicAckFrame frame = + InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}}); + ProcessAckPacket(&frame); + ASSERT_TRUE(connection_.GetPingAlarm()->IsSet()); + EXPECT_EQ(kRetransmittableOnWireTimeout, + connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); + EXPECT_EQ(1u, writer_->packets_write_attempts()); + + // Fire retransmittable-on-wire alarm. + clock_.AdvanceTime(kRetransmittableOnWireTimeout); + // Next packet is not processable by the framer in the test writer. + ExpectNextPacketUnprocessable(); + connection_.GetPingAlarm()->Fire(); + EXPECT_EQ(2u, writer_->packets_write_attempts()); + // Verify alarm is set in keep-alive mode. + ASSERT_TRUE(connection_.GetPingAlarm()->IsSet()); + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), + connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); +} + +TEST_P(QuicConnectionTest, + RetransmittableOnWireSendRandomBytesWithWriterBlocked) { + if (!GetQuicReloadableFlag(quic_use_ping_manager2) || + !VersionHasIetfQuicFrames(connection_.version().transport_version)) { + return; + } + EXPECT_CALL(visitor_, ShouldKeepConnectionAlive()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + + const QuicTime::Delta kRetransmittableOnWireTimeout = + QuicTime::Delta::FromMilliseconds(200); + const QuicTime::Delta kTestRtt = QuicTime::Delta::FromMilliseconds(100); + + connection_.set_initial_retransmittable_on_wire_timeout( + kRetransmittableOnWireTimeout); + + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + QuicConfig config; + QuicTagVector connection_options; + connection_options.push_back(kROWR); + config.SetClientConnectionOptions(connection_options); + connection_.SetFromConfig(config); + + // Send a request. + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN); + // Receive an ACK after 1-RTT. + clock_.AdvanceTime(kTestRtt); + EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); + QuicAckFrame frame = + InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}}); + ProcessAckPacket(&frame); + ASSERT_TRUE(connection_.GetPingAlarm()->IsSet()); + EXPECT_EQ(kRetransmittableOnWireTimeout, + connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); + EXPECT_EQ(1u, writer_->packets_write_attempts()); + // Receive an out of order data packet and block the ACK packet. + BlockOnNextWrite(); + ProcessDataPacket(3); + EXPECT_EQ(2u, writer_->packets_write_attempts()); + EXPECT_EQ(1u, connection_.NumQueuedPackets()); + + // Fire retransmittable-on-wire alarm. + clock_.AdvanceTime(kRetransmittableOnWireTimeout); + connection_.GetPingAlarm()->Fire(); + // Verify the random bytes packet gets queued. + EXPECT_EQ(2u, connection_.NumQueuedPackets()); +} + // This test verifies that the connection marks path as degrading and does not // spin timer to detect path degrading when a new packet is sent on the // degraded path. @@ -7977,57 +7652,6 @@ TEST_P(QuicConnectionTest, NotBecomeApplicationLimitedDueToWriteBlock) { connection_.OnCanWrite(); } -// Test the mode in which the link is filled up with probing retransmissions if -// the connection becomes application-limited. -TEST_P(QuicConnectionTest, SendDataWhenApplicationLimited) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - EXPECT_CALL(*send_algorithm_, ShouldSendProbingPacket()) - .WillRepeatedly(Return(true)); - { - InSequence seq; - EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(true)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - EXPECT_CALL(visitor_, WillingAndAbleToWrite()) - .WillRepeatedly(Return(false)); - } - EXPECT_CALL(visitor_, SendProbingData()).WillRepeatedly([this] { - return connection_.sent_packet_manager().MaybeRetransmitOldestPacket( - PROBING_RETRANSMISSION); - }); - // Fix congestion window to be 20,000 bytes. - EXPECT_CALL(*send_algorithm_, CanSend(Ge(20000u))) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*send_algorithm_, CanSend(Lt(20000u))) - .WillRepeatedly(Return(true)); - - EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(0); - ASSERT_EQ(0u, connection_.GetStats().packets_sent); - connection_.set_fill_up_link_during_probing(true); - EXPECT_CALL(visitor_, GetHandshakeState()) - .WillRepeatedly(Return(HANDSHAKE_CONFIRMED)); - connection_.OnHandshakeComplete(); - connection_.SendStreamData3(); - - // We expect a lot of packets from a 20 kbyte window. - EXPECT_GT(connection_.GetStats().packets_sent, 10u); - // Ensure that the packets are padded. - QuicByteCount average_packet_size = - connection_.GetStats().bytes_sent / connection_.GetStats().packets_sent; - EXPECT_GT(average_packet_size, 1000u); - - // Acknowledge all packets sent, except for the last one. - QuicAckFrame ack = InitAckFrame( - connection_.sent_packet_manager().GetLargestSentPacket() - 1); - EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _)); - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - - // Ensure that since we no longer have retransmittable bytes in flight, this - // will not cause any responses to be sent. - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0); - EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(1); - ProcessAckPacket(&ack); -} - TEST_P(QuicConnectionTest, DoNotForceSendingAckOnPacketTooLarge) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); // Send an ack by simulating delayed ack alarm firing. @@ -8168,83 +7792,6 @@ TEST_P(QuicConnectionTest, ClientAlwaysSendConnectionId) { writer_->last_packet_header().destination_connection_id_included); } -TEST_P(QuicConnectionTest, SendProbingRetransmissions) { - MockQuicConnectionDebugVisitor debug_visitor; - connection_.set_debug_visitor(&debug_visitor); - - const QuicStreamId stream_id = 2; - QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); - SendStreamDataToPeer(stream_id, "bar", 3, NO_FIN, &last_packet); - SendStreamDataToPeer(stream_id, "test", 6, NO_FIN, &last_packet); - - const QuicByteCount old_bytes_in_flight = - connection_.sent_packet_manager().GetBytesInFlight(); - - // Allow 9 probing retransmissions to be sent. - { - InSequence seq; - EXPECT_CALL(*send_algorithm_, CanSend(_)) - .Times(9 * 2) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false)); - } - // Expect them retransmitted in cyclic order (foo, bar, test, foo, bar...). - QuicPacketCount sent_count = 0; - - EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)) - .WillRepeatedly(Invoke( - [this, &sent_count](QuicPacketNumber, QuicPacketLength, bool, - TransmissionType, EncryptionLevel, - const QuicFrames&, const QuicFrames&, QuicTime) { - ASSERT_EQ(1u, writer_->stream_frames().size()); - if (connection_.version().CanSendCoalescedPackets()) { - // There is a delay of sending coalesced packet, so (6, 0, 3, 6, - // 0...). - EXPECT_EQ(3 * ((sent_count + 2) % 3), - writer_->stream_frames()[0]->offset); - } else { - // Identify the frames by stream offset (0, 3, 6, 0, 3...). - EXPECT_EQ(3 * (sent_count % 3), - writer_->stream_frames()[0]->offset); - } - sent_count++; - })); - - EXPECT_CALL(*send_algorithm_, ShouldSendProbingPacket()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(visitor_, SendProbingData()).WillRepeatedly([this] { - return connection_.sent_packet_manager().MaybeRetransmitOldestPacket( - PROBING_RETRANSMISSION); - }); - - connection_.SendProbingRetransmissions(); - - // Ensure that the in-flight has increased. - const QuicByteCount new_bytes_in_flight = - connection_.sent_packet_manager().GetBytesInFlight(); - EXPECT_GT(new_bytes_in_flight, old_bytes_in_flight); -} - -// Ensure that SendProbingRetransmissions() does not retransmit anything when -// there are no outstanding packets. -TEST_P(QuicConnectionTest, - SendProbingRetransmissionsFailsWhenNothingToRetransmit) { - ASSERT_TRUE(connection_.sent_packet_manager().unacked_packets().empty()); - - MockQuicConnectionDebugVisitor debug_visitor; - connection_.set_debug_visitor(&debug_visitor); - EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)).Times(0); - EXPECT_CALL(*send_algorithm_, ShouldSendProbingPacket()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(visitor_, SendProbingData()).WillRepeatedly([this] { - return connection_.sent_packet_manager().MaybeRetransmitOldestPacket( - PROBING_RETRANSMISSION); - }); - - connection_.SendProbingRetransmissions(); -} - TEST_P(QuicConnectionTest, PingAfterLastRetransmittablePacketAcked) { const QuicTime::Delta retransmittable_on_wire_timeout = QuicTime::Delta::FromMilliseconds(50); @@ -8431,7 +7978,7 @@ TEST_P(QuicConnectionTest, BackOffRetransmittableOnWireTimeout) { // 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(), + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(AnyNumber()); @@ -8462,7 +8009,8 @@ TEST_P(QuicConnectionTest, BackOffRetransmittableOnWireTimeout) { // Verify subsequent pings are sent with timeout that is exponentially backed // off. - while (retransmittable_on_wire_timeout * 2 < connection_.ping_timeout()) { + while (retransmittable_on_wire_timeout * 2 < + QuicTime::Delta::FromSeconds(kPingTimeoutSecs)) { // Receive an ACK for the previous PING. This should set the // ping alarm with backed off retransmittable-on-wire timeout. retransmittable_on_wire_timeout = retransmittable_on_wire_timeout * 2; @@ -8483,7 +8031,7 @@ TEST_P(QuicConnectionTest, BackOffRetransmittableOnWireTimeout) { // The ping alarm is set with default ping timeout. EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); - EXPECT_EQ(connection_.ping_timeout(), + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); // Receive an ACK for the previous PING. The ping alarm is set with an @@ -8494,7 +8042,8 @@ TEST_P(QuicConnectionTest, BackOffRetransmittableOnWireTimeout) { {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}}); ProcessAckPacket(&frame); EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); - EXPECT_EQ(connection_.ping_timeout() - QuicTime::Delta::FromMilliseconds(5), + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs) - + QuicTime::Delta::FromMilliseconds(5), connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); } @@ -8526,7 +8075,7 @@ TEST_P(QuicConnectionTest, ResetBackOffRetransmitableOnWireTimeout) { // 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(), + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); // Receive an ACK of the first packet. This should set the ping alarm with @@ -8563,6 +8112,8 @@ TEST_P(QuicConnectionTest, ResetBackOffRetransmitableOnWireTimeout) { peer_creator_.packet_number() + 1); EXPECT_EQ(initial_retransmittable_on_wire_timeout, connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); + clock_.AdvanceTime(initial_retransmittable_on_wire_timeout); + connection_.GetPingAlarm()->Fire(); // Verify the count of consecutive aggressive pings is reset. for (int i = 0; i < max_aggressive_retransmittable_on_wire_ping_count; i++) { @@ -8640,7 +8191,7 @@ TEST_P(QuicConnectionTest, RetransmittableOnWirePingLimit) { // 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(), + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(AnyNumber()); @@ -8673,7 +8224,7 @@ TEST_P(QuicConnectionTest, RetransmittableOnWirePingLimit) { {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}}); ProcessAckPacket(&frame); EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); - EXPECT_EQ(connection_.ping_timeout(), + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow()); } @@ -9048,10 +8599,8 @@ TEST_P(QuicConnectionTest, ClientsResetCwndAfterConnectionMigration) { rtt_stats->set_initial_rtt(default_init_rtt * 2); EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt()); - QuicSentPacketManagerPeer::SetConsecutiveRtoCount(manager_, 1); - EXPECT_EQ(1u, manager_->GetConsecutiveRtoCount()); - QuicSentPacketManagerPeer::SetConsecutiveTlpCount(manager_, 2); - EXPECT_EQ(2u, manager_->GetConsecutiveTlpCount()); + QuicSentPacketManagerPeer::SetConsecutivePtoCount(manager_, 1); + EXPECT_EQ(1u, manager_->GetConsecutivePtoCount()); const SendAlgorithmInterface* send_algorithm = manager_->GetSendAlgorithm(); // Migrate to a new address with different IP. @@ -9061,8 +8610,7 @@ TEST_P(QuicConnectionTest, ClientsResetCwndAfterConnectionMigration) { connection_.MigratePath(kNewSelfAddress, connection_.peer_address(), &new_writer, false); EXPECT_EQ(default_init_rtt, manager_->GetRttStats()->initial_rtt()); - EXPECT_EQ(0u, manager_->GetConsecutiveRtoCount()); - EXPECT_EQ(0u, manager_->GetConsecutiveTlpCount()); + EXPECT_EQ(0u, manager_->GetConsecutivePtoCount()); EXPECT_NE(send_algorithm, manager_->GetSendAlgorithm()); } @@ -9592,14 +9140,14 @@ TEST_P(QuicConnectionTest, CoalescedPacketThatSavesFrames) { .Times(3) .WillRepeatedly([this](const QuicCryptoFrame& /*frame*/) { // QuicFrame takes ownership of the QuicBlockedFrame. - connection_.SendControlFrame(QuicFrame(QuicBlockedFrame(1, 3))); + connection_.SendControlFrame(QuicFrame(QuicBlockedFrame(1, 3, 0))); }); } else { EXPECT_CALL(visitor_, OnStreamFrame(_)) .Times(3) .WillRepeatedly([this](const QuicStreamFrame& /*frame*/) { // QuicFrame takes ownership of the QuicBlockedFrame. - connection_.SendControlFrame(QuicFrame(QuicBlockedFrame(1, 3))); + connection_.SendControlFrame(QuicFrame(QuicBlockedFrame(1, 3, 0))); }); } @@ -9665,9 +9213,8 @@ TEST_P(QuicConnectionTest, RtoAndWriteBlocked) { } // Regresstion test for b/138962304. -TEST_P(QuicConnectionTest, TlpAndWriteBlocked) { +TEST_P(QuicConnectionTest, PtoAndWriteBlocked) { EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); - connection_.SetMaxTailLossProbes(1); QuicStreamId stream_id = 2; QuicPacketNumber last_data_packet; @@ -9690,44 +9237,6 @@ TEST_P(QuicConnectionTest, TlpAndWriteBlocked) { EXPECT_EQ(1u, connection_.NumQueuedPackets()); } -// Regresstion test for b/139375344. -TEST_P(QuicConnectionTest, RtoForcesSendingPing) { - if (connection_.PtoEnabled()) { - return; - } - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.SetMaxTailLossProbes(2); - EXPECT_EQ(0u, connection_.GetStats().tlp_count); - EXPECT_EQ(0u, connection_.GetStats().rto_count); - - SendStreamDataToPeer(2, "foo", 0, NO_FIN, nullptr); - QuicTime retransmission_time = - connection_.GetRetransmissionAlarm()->deadline(); - EXPECT_NE(QuicTime::Zero(), retransmission_time); - // TLP fires. - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2), _, _)); - clock_.AdvanceTime(retransmission_time - clock_.Now()); - connection_.GetRetransmissionAlarm()->Fire(); - EXPECT_EQ(1u, connection_.GetStats().tlp_count); - EXPECT_EQ(0u, connection_.GetStats().rto_count); - EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); - - // Packet 1 gets acked. - QuicAckFrame frame = InitAckFrame(1); - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _)); - ProcessAckPacket(1, &frame); - EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); - retransmission_time = connection_.GetRetransmissionAlarm()->deadline(); - - // RTO fires, verify a PING packet gets sent because there is no data to send. - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(3), _, _)); - clock_.AdvanceTime(retransmission_time - clock_.Now()); - connection_.GetRetransmissionAlarm()->Fire(); - EXPECT_EQ(1u, connection_.GetStats().tlp_count); - EXPECT_EQ(1u, connection_.GetStats().rto_count); - EXPECT_EQ(1u, writer_->ping_frames().size()); -} - TEST_P(QuicConnectionTest, ProbeTimeout) { QuicConfig config; QuicTagVector connection_options; @@ -9792,8 +9301,6 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter6ClientPTOs) { EXPECT_CALL(visitor_, OnPathDegrading()); connection_.PathDegradingTimeout(); - EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveTlpCount()); - EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveRtoCount()); EXPECT_EQ(5u, connection_.sent_packet_manager().GetConsecutivePtoCount()); // Closes connection on 6th PTO. // May send multiple connecction close packets with multiple PN spaces. @@ -9844,8 +9351,6 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter7ClientPTOs) { EXPECT_CALL(visitor_, OnPathDegrading()); connection_.PathDegradingTimeout(); - EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveTlpCount()); - EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveRtoCount()); EXPECT_EQ(6u, connection_.sent_packet_manager().GetConsecutivePtoCount()); // Closes connection on 7th PTO. EXPECT_CALL(visitor_, @@ -9895,8 +9400,6 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter8ClientPTOs) { EXPECT_CALL(visitor_, OnPathDegrading()); connection_.PathDegradingTimeout(); - EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveTlpCount()); - EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveRtoCount()); EXPECT_EQ(7u, connection_.sent_packet_manager().GetConsecutivePtoCount()); // Closes connection on 8th PTO. EXPECT_CALL(visitor_, @@ -10200,49 +9703,6 @@ TEST_P(QuicConnectionTest, ConnectionCloseFrameType) { connection_close_frames[0].transport_close_frame_type); } -// Regression test for b/137401387 and b/138962304. -TEST_P(QuicConnectionTest, RtoPacketAsTwo) { - if (connection_.PtoEnabled()) { - return; - } - connection_.SetMaxTailLossProbes(1); - connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); - std::string stream_data(3000, 's'); - // Send packets 1 - 66 and exhaust cwnd. - for (size_t i = 0; i < 22; ++i) { - // 3 packets for each stream, the first 2 are guaranteed to be full packets. - SendStreamDataToPeer(i + 2, stream_data, 0, FIN, nullptr); - } - CongestionBlockWrites(); - - // Fires TLP. Please note, this tail loss probe has 1 byte less stream data - // compared to packet 1 because packet number length increases. - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(67), _, _)); - connection_.GetRetransmissionAlarm()->Fire(); - // Fires RTO. Please note, although packets 2 and 3 *should* be RTOed, but - // packet 2 gets RTOed to two packets because packet number length increases. - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(68), _, _)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(69), _, _)); - connection_.GetRetransmissionAlarm()->Fire(); - - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - // Resets all streams except 2 and ack packets 1 and 2. Now, packet 3 is the - // only one containing retransmittable frames. - for (size_t i = 1; i < 22; ++i) { - notifier_.OnStreamReset(i + 2, QUIC_STREAM_CANCELLED); - } - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _)); - QuicAckFrame frame = - InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(3)}}); - ProcessAckPacket(1, &frame); - CongestionUnblockWrites(); - - // Fires TLP, verify a PING gets sent because packet 3 is marked - // RTO_RETRANSMITTED. - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(70), _, _)); - connection_.GetRetransmissionAlarm()->Fire(); -} - TEST_P(QuicConnectionTest, PtoSkipsPacketNumber) { QuicConfig config; QuicTagVector connection_options; @@ -10321,69 +9781,65 @@ TEST_P(QuicConnectionTest, FailToCoalescePacket) { set_perspective(Perspective::IS_SERVER); use_tagging_decrypter(); - EXPECT_CALL(visitor_, OnHandshakePacketSent()); + auto test_body = [&] { + EXPECT_CALL(visitor_, OnHandshakePacketSent()); - if (GetQuicReloadableFlag( - quic_close_connection_if_fail_to_serialzie_coalesced_packet2)) { EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF)) .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame)); - } - ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_INITIAL); - auto test_body = [&] { - QuicConnection::ScopedPacketFlusher flusher(&connection_); - connection_.SetEncrypter(ENCRYPTION_INITIAL, - std::make_unique<TaggingEncrypter>(0x01)); - connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); - connection_.SendCryptoDataWithString("foo", 0); - // Verify this packet is on hold. - EXPECT_EQ(0u, writer_->packets_write_attempts()); - - connection_.SetEncrypter(ENCRYPTION_HANDSHAKE, - std::make_unique<TaggingEncrypter>(0x02)); - connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE); - connection_.SendCryptoDataWithString("bar", 3); - EXPECT_EQ(0u, writer_->packets_write_attempts()); + ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_INITIAL); - connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE, - std::make_unique<TaggingEncrypter>(0x03)); - connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); - SendStreamDataToPeer(2, "baz", 3, NO_FIN, nullptr); - - creator_->Flush(); - - auto& coalesced_packet = - QuicConnectionPeer::GetCoalescedPacket(&connection_); - QuicPacketLength coalesced_packet_max_length = - coalesced_packet.max_packet_length(); - QuicCoalescedPacketPeer::SetMaxPacketLength(coalesced_packet, - coalesced_packet.length()); - - // Make the coalescer's FORWARD_SECURE packet longer. - *QuicCoalescedPacketPeer::GetMutableEncryptedBuffer( - coalesced_packet, ENCRYPTION_FORWARD_SECURE) += "!!! TEST !!!"; - - QUIC_LOG(INFO) << "Reduced coalesced_packet_max_length from " - << coalesced_packet_max_length << " to " - << coalesced_packet.max_packet_length() - << ", coalesced_packet.length:" << coalesced_packet.length() - << ", coalesced_packet.packet_lengths:" - << absl::StrJoin(coalesced_packet.packet_lengths(), ":"); - }; - - EXPECT_QUIC_BUG(test_body(), "SerializeCoalescedPacket failed."); + { + QuicConnection::ScopedPacketFlusher flusher(&connection_); + connection_.SetEncrypter(ENCRYPTION_INITIAL, + std::make_unique<TaggingEncrypter>(0x01)); + connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); + connection_.SendCryptoDataWithString("foo", 0); + // Verify this packet is on hold. + EXPECT_EQ(0u, writer_->packets_write_attempts()); + + connection_.SetEncrypter(ENCRYPTION_HANDSHAKE, + std::make_unique<TaggingEncrypter>(0x02)); + connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE); + connection_.SendCryptoDataWithString("bar", 3); + EXPECT_EQ(0u, writer_->packets_write_attempts()); + + connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE, + std::make_unique<TaggingEncrypter>(0x03)); + connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); + SendStreamDataToPeer(2, "baz", 3, NO_FIN, nullptr); + + creator_->Flush(); + + auto& coalesced_packet = + QuicConnectionPeer::GetCoalescedPacket(&connection_); + QuicPacketLength coalesced_packet_max_length = + coalesced_packet.max_packet_length(); + QuicCoalescedPacketPeer::SetMaxPacketLength(coalesced_packet, + coalesced_packet.length()); + + // Make the coalescer's FORWARD_SECURE packet longer. + *QuicCoalescedPacketPeer::GetMutableEncryptedBuffer( + coalesced_packet, ENCRYPTION_FORWARD_SECURE) += "!!! TEST !!!"; + + QUIC_LOG(INFO) << "Reduced coalesced_packet_max_length from " + << coalesced_packet_max_length << " to " + << coalesced_packet.max_packet_length() + << ", coalesced_packet.length:" + << coalesced_packet.length() + << ", coalesced_packet.packet_lengths:" + << absl::StrJoin(coalesced_packet.packet_lengths(), ":"); + } - if (GetQuicReloadableFlag( - quic_close_connection_if_fail_to_serialzie_coalesced_packet2)) { EXPECT_FALSE(connection_.connected()); EXPECT_THAT(saved_connection_close_frame_.quic_error_code, IsError(QUIC_FAILED_TO_SERIALIZE_PACKET)); EXPECT_EQ(saved_connection_close_frame_.error_details, "Failed to serialize coalesced packet."); - } else { - EXPECT_TRUE(connection_.connected()); - } + }; + + EXPECT_QUIC_BUG(test_body(), "SerializeCoalescedPacket failed."); } TEST_P(QuicConnectionTest, LegacyVersionEncapsulation) { @@ -11607,40 +11063,13 @@ TEST_P(QuicConnectionTest, ClientAckDelayForAsyncPacketProcessing) { std::make_unique<TaggingEncrypter>(0x01)); connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE); // Verify HANDSHAKE packet gets processed. - if (GetQuicReloadableFlag(quic_update_ack_timeout_on_receipt_time)) { - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - } else { - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); - } + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.GetProcessUndecryptablePacketsAlarm()->Fire(); - if (GetQuicReloadableFlag(quic_update_ack_timeout_on_receipt_time)) { - // Verify immediate ACK has been sent out when flush went out of scope. - ASSERT_FALSE(connection_.HasPendingAcks()); - } else { - ASSERT_TRUE(connection_.HasPendingAcks()); - // Send ACKs. - clock_.AdvanceTime(connection_.GetAckAlarm()->deadline() - clock_.Now()); - connection_.GetAckAlarm()->Fire(); - } + // Verify immediate ACK has been sent out when flush went out of scope. + ASSERT_FALSE(connection_.HasPendingAcks()); ASSERT_FALSE(writer_->ack_frames().empty()); - if (GetQuicReloadableFlag(quic_update_ack_timeout_on_receipt_time)) { - // Verify the ack_delay_time in the sent HANDSHAKE ACK frame is 100ms. - EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), - writer_->ack_frames()[0].ack_delay_time); - ASSERT_TRUE(writer_->coalesced_packet() == nullptr); - return; - } - // Verify the ack_delay_time in the INITIAL ACK frame is 1ms. - EXPECT_EQ(QuicTime::Delta::FromMilliseconds(1), - writer_->ack_frames()[0].ack_delay_time); - // Process the coalesced HANDSHAKE packet. - ASSERT_TRUE(writer_->coalesced_packet() != nullptr); - auto packet = writer_->coalesced_packet()->Clone(); - writer_->framer()->ProcessPacket(*packet); - ASSERT_FALSE(writer_->ack_frames().empty()); - // Verify the ack_delay_time in the HANDSHAKE ACK frame includes the - // buffering time. - EXPECT_EQ(QuicTime::Delta::FromMilliseconds(101), + // Verify the ack_delay_time in the sent HANDSHAKE ACK frame is 100ms. + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), writer_->ack_frames()[0].ack_delay_time); ASSERT_TRUE(writer_->coalesced_packet() == nullptr); } @@ -11679,14 +11108,14 @@ TEST_P(QuicConnectionTest, TestingLiveness) { ASSERT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); EXPECT_FALSE(connection_.MaybeTestLiveness()); - QuicTime deadline = connection_.GetTimeoutAlarm()->deadline(); + QuicTime deadline = QuicConnectionPeer::GetIdleNetworkDeadline(&connection_); QuicTime::Delta timeout = deadline - clock_.ApproximateNow(); // Advance time to near the idle timeout. clock_.AdvanceTime(timeout - QuicTime::Delta::FromMilliseconds(1)); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); EXPECT_TRUE(connection_.MaybeTestLiveness()); // Verify idle deadline does not change. - EXPECT_EQ(deadline, connection_.GetTimeoutAlarm()->deadline()); + EXPECT_EQ(deadline, QuicConnectionPeer::GetIdleNetworkDeadline(&connection_)); } TEST_P(QuicConnectionTest, SilentIdleTimeout) { @@ -11716,6 +11145,11 @@ TEST_P(QuicConnectionTest, SilentIdleTimeout) { EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF)); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0); + if (!QuicConnectionPeer::GetBandwidthUpdateTimeout(&connection_) + .IsInfinite()) { + // Fires the bandwidth update. + connection_.GetTimeoutAlarm()->Fire(); + } connection_.GetTimeoutAlarm()->Fire(); // Verify the connection close packets get serialized and added to // termination packets list. @@ -14035,6 +13469,123 @@ TEST_P(QuicConnectionTest, EXPECT_EQ(1u, connection_.GetStats().num_validated_peer_migration); } +// Regression test of b/228645208. +TEST_P(QuicConnectionTest, NoNonProbingFrameOnAlternativePath) { + if (!connection_.connection_migration_use_new_cid()) { + return; + } + + PathProbeTestInit(Perspective::IS_SERVER); + SetClientConnectionId(TestConnectionId(1)); + connection_.CreateConnectionIdManager(); + + QuicConnectionId server_cid0 = connection_.connection_id(); + QuicConnectionId client_cid0 = connection_.client_connection_id(); + QuicConnectionId client_cid1 = TestConnectionId(2); + QuicConnectionId server_cid1; + // Sends new server CID to client. + EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_)) + .WillOnce( + Invoke([&](const QuicConnectionId& cid) { server_cid1 = cid; })); + EXPECT_CALL(visitor_, SendNewConnectionId(_)); + connection_.MaybeSendConnectionIdToClient(); + // Receives new client CID from client. + QuicNewConnectionIdFrame new_cid_frame; + new_cid_frame.connection_id = client_cid1; + new_cid_frame.sequence_number = 1u; + new_cid_frame.retire_prior_to = 0u; + connection_.OnNewConnectionIdFrame(new_cid_frame); + auto* packet_creator = QuicConnectionPeer::GetPacketCreator(&connection_); + ASSERT_EQ(packet_creator->GetDestinationConnectionId(), client_cid0); + ASSERT_EQ(packet_creator->GetSourceConnectionId(), server_cid0); + + peer_creator_.SetServerConnectionId(server_cid1); + const QuicSocketAddress kNewPeerAddress = + QuicSocketAddress(QuicIpAddress::Loopback4(), /*port=*/23456); + QuicPathFrameBuffer path_challenge_payload{0, 1, 2, 3, 4, 5, 6, 7}; + QuicFrames frames1; + frames1.push_back( + QuicFrame(QuicPathChallengeFrame(0, path_challenge_payload))); + QuicPathFrameBuffer payload; + EXPECT_CALL(*send_algorithm_, + OnPacketSent(_, _, _, _, NO_RETRANSMITTABLE_DATA)) + .Times(AtLeast(1)) + .WillOnce(Invoke([&]() { + EXPECT_EQ(kNewPeerAddress, writer_->last_write_peer_address()); + EXPECT_EQ(kPeerAddress, connection_.peer_address()); + EXPECT_EQ(kPeerAddress, connection_.effective_peer_address()); + EXPECT_FALSE(writer_->path_response_frames().empty()); + EXPECT_FALSE(writer_->path_challenge_frames().empty()); + payload = writer_->path_challenge_frames().front().data_buffer; + })); + ProcessFramesPacketWithAddresses(frames1, kSelfAddress, kNewPeerAddress, + ENCRYPTION_FORWARD_SECURE); + EXPECT_EQ(kPeerAddress, connection_.peer_address()); + EXPECT_EQ(kPeerAddress, connection_.effective_peer_address()); + EXPECT_TRUE(connection_.HasPendingPathValidation()); + const auto* default_path = QuicConnectionPeer::GetDefaultPath(&connection_); + const auto* alternative_path = + QuicConnectionPeer::GetAlternativePath(&connection_); + EXPECT_EQ(default_path->client_connection_id, client_cid0); + EXPECT_EQ(default_path->server_connection_id, server_cid0); + EXPECT_EQ(alternative_path->client_connection_id, client_cid1); + EXPECT_EQ(alternative_path->server_connection_id, server_cid1); + EXPECT_EQ(packet_creator->GetDestinationConnectionId(), client_cid0); + EXPECT_EQ(packet_creator->GetSourceConnectionId(), server_cid0); + + // Process non-probing packets on the default path. + peer_creator_.SetServerConnectionId(server_cid0); + EXPECT_CALL(visitor_, OnStreamFrame(_)).WillRepeatedly(Invoke([=]() { + EXPECT_EQ(kPeerAddress, connection_.peer_address()); + })); + // Receives packets 3 - 39 to send 19 ACK-only packets, which will force the + // connection to reach |kMaxConsecutiveNonRetransmittablePackets| while + // sending the next ACK. + for (size_t i = 3; i <= 39; ++i) { + ProcessDataPacket(i); + } + EXPECT_EQ(kPeerAddress, connection_.peer_address()); + EXPECT_EQ(kPeerAddress, connection_.effective_peer_address()); + + EXPECT_TRUE(connection_.HasPendingAcks()); + QuicTime ack_time = connection_.GetAckAlarm()->deadline(); + QuicTime path_validation_retry_time = + connection_.GetRetryTimeout(kNewPeerAddress, writer_.get()); + // Advance time to simultaneously fire path validation retry and ACK alarms. + clock_.AdvanceTime(std::max(ack_time, path_validation_retry_time) - + clock_.ApproximateNow()); + + // The 20th ACK should bundle with a WINDOW_UPDATE frame. + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()) + .WillOnce(Invoke([this]() { + connection_.SendControlFrame(QuicFrame(QuicWindowUpdateFrame(1, 0, 0))); + })); + if (GetQuicReloadableFlag(quic_not_bundle_ack_on_alternative_path)) { + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) + .WillOnce(Invoke([&]() { + EXPECT_EQ(kNewPeerAddress, writer_->last_write_peer_address()); + EXPECT_FALSE(writer_->path_challenge_frames().empty()); + // Retry path validation shouldn't bundle ACK. + EXPECT_TRUE(writer_->ack_frames().empty()); + })) + .WillOnce(Invoke([&]() { + EXPECT_EQ(kPeerAddress, writer_->last_write_peer_address()); + EXPECT_FALSE(writer_->ack_frames().empty()); + EXPECT_FALSE(writer_->window_update_frames().empty()); + })); + static_cast<TestAlarmFactory::TestAlarm*>( + QuicPathValidatorPeer::retry_timer( + QuicConnectionPeer::path_validator(&connection_))) + ->Fire(); + } else { + EXPECT_QUIC_BUG(static_cast<TestAlarmFactory::TestAlarm*>( + QuicPathValidatorPeer::retry_timer( + QuicConnectionPeer::path_validator(&connection_))) + ->Fire(), + "quic_bug_12645_2"); + } +} + TEST_P(QuicConnectionTest, ProbedOnAnotherPathAfterPeerIpAddressChangeAtServer) { PathProbeTestInit(Perspective::IS_SERVER); @@ -14486,8 +14037,7 @@ TEST_P(QuicConnectionTest, TEST_P( QuicConnectionTest, ReplacePeerIssuedConnectionIdOnBothPathsTriggeredByNewConnectionIdFrame) { - if (!version().HasIetfQuicFrames() || - !connection_.count_bytes_on_alternative_path_separately()) { + if (!version().HasIetfQuicFrames()) { return; } PathProbeTestInit(Perspective::IS_SERVER); @@ -14846,21 +14396,24 @@ TEST_P(QuicConnectionTest, LostDataThenGetAcknowledged) { QuicAckFrame ack = InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(5)}}); frames.push_back(QuicFrame(&ack)); - EXPECT_CALL(visitor_, OnConnectionMigration(_)).Times(1); - // Invoke OnCanWrite. - EXPECT_CALL(visitor_, OnStreamFrame(_)) - .WillOnce( - InvokeWithoutArgs(¬ifier_, &SimpleSessionNotifier::OnCanWrite)); QuicIpAddress ip_address; ASSERT_TRUE(ip_address.FromString("127.0.52.223")); - EXPECT_QUIC_BUG(ProcessFramesPacketWithAddresses( - frames, kSelfAddress, QuicSocketAddress(ip_address, 1000), - ENCRYPTION_FORWARD_SECURE), - "Try to write mid packet processing"); - EXPECT_EQ(1u, writer_->path_challenge_frames().size()); - // Verify stream frame will not be retransmitted. - EXPECT_TRUE(writer_->stream_frames().empty()); + EXPECT_QUIC_BUG( + { + EXPECT_CALL(visitor_, OnConnectionMigration(_)).Times(1); + EXPECT_CALL(visitor_, OnStreamFrame(_)) + .WillOnce(InvokeWithoutArgs(¬ifier_, + &SimpleSessionNotifier::OnCanWrite)); + ProcessFramesPacketWithAddresses(frames, kSelfAddress, + QuicSocketAddress(ip_address, 1000), + ENCRYPTION_FORWARD_SECURE); + EXPECT_EQ(1u, writer_->path_challenge_frames().size()); + + // Verify stream frame will not be retransmitted. + EXPECT_TRUE(writer_->stream_frames().empty()); + }, + "Try to write mid packet processing"); } TEST_P(QuicConnectionTest, PtoSendStreamData) { @@ -15282,21 +14835,12 @@ TEST_P(QuicConnectionTest, FailedToRetransmitShlo) { connection_.GetAckAlarm()->deadline()); // ACK is not throttled by amplification limit, and SHLO is bundled. Also // HANDSHAKE + 1RTT packets get coalesced. - if (GetQuicReloadableFlag(quic_flush_after_coalesce_higher_space_packets)) { - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3); - } else { - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); - } + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3); // ACK alarm fires. clock_.AdvanceTime(kAlarmGranularity); connection_.GetAckAlarm()->Fire(); - if (GetQuicReloadableFlag(quic_flush_after_coalesce_higher_space_packets)) { - // Verify 1-RTT packet is coalesced. - EXPECT_EQ(0x04040404u, writer_->final_bytes_of_last_packet()); - } else { - // Verify HANDSHAKE packet is coalesced with INITIAL ACK + SHLO. - EXPECT_EQ(0x03030303u, writer_->final_bytes_of_last_packet()); - } + // Verify 1-RTT packet is coalesced. + EXPECT_EQ(0x04040404u, writer_->final_bytes_of_last_packet()); // Only the first packet in the coalesced packet has been processed, // verify SHLO is bundled with INITIAL ACK. EXPECT_EQ(1u, writer_->ack_frames().size()); @@ -15307,16 +14851,12 @@ TEST_P(QuicConnectionTest, FailedToRetransmitShlo) { writer_->framer()->ProcessPacket(*packet); EXPECT_EQ(0u, writer_->ack_frames().size()); EXPECT_EQ(1u, writer_->crypto_frames().size()); - if (GetQuicReloadableFlag(quic_flush_after_coalesce_higher_space_packets)) { - // Process the coalesced 1-RTT packet. - ASSERT_TRUE(writer_->coalesced_packet() != nullptr); - packet = writer_->coalesced_packet()->Clone(); - writer_->framer()->ProcessPacket(*packet); - EXPECT_EQ(0u, writer_->crypto_frames().size()); - EXPECT_EQ(1u, writer_->stream_frames().size()); - } else { - ASSERT_TRUE(writer_->coalesced_packet() == nullptr); - } + // Process the coalesced 1-RTT packet. + ASSERT_TRUE(writer_->coalesced_packet() != nullptr); + packet = writer_->coalesced_packet()->Clone(); + writer_->framer()->ProcessPacket(*packet); + EXPECT_EQ(0u, writer_->crypto_frames().size()); + EXPECT_EQ(1u, writer_->stream_frames().size()); // Received INITIAL 3. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber()); @@ -15388,26 +14928,17 @@ TEST_P(QuicConnectionTest, FailedToConsumeCryptoData) { clock_.AdvanceTime(retransmission_time - clock_.Now()); connection_.GetRetransmissionAlarm()->Fire(); - if (GetQuicRestartFlag(quic_set_packet_state_if_all_data_retransmitted)) { - // Verify the retransmission is a coalesced packet with HANDSHAKE 2 and - // 1-RTT 3. - EXPECT_EQ(0x04040404u, writer_->final_bytes_of_last_packet()); - // Only the first packet in the coalesced packet has been processed. - EXPECT_EQ(1u, writer_->crypto_frames().size()); - // Process the coalesced 1-RTT packet. - ASSERT_TRUE(writer_->coalesced_packet() != nullptr); - auto packet = writer_->coalesced_packet()->Clone(); - writer_->framer()->ProcessPacket(*packet); - EXPECT_EQ(1u, writer_->stream_frames().size()); - ASSERT_TRUE(writer_->coalesced_packet() == nullptr); - } else { - // Although packet 2 has not been retransmitted, it has been marked PTOed - // and a HANDHSAKE PING gets retransmitted. - EXPECT_EQ(0x03030303u, writer_->final_bytes_of_last_packet()); - EXPECT_EQ(1u, writer_->ping_frames().size()); - EXPECT_TRUE(writer_->stream_frames().empty()); - ASSERT_TRUE(writer_->coalesced_packet() == nullptr); - } + // Verify the retransmission is a coalesced packet with HANDSHAKE 2 and + // 1-RTT 3. + EXPECT_EQ(0x04040404u, writer_->final_bytes_of_last_packet()); + // Only the first packet in the coalesced packet has been processed. + EXPECT_EQ(1u, writer_->crypto_frames().size()); + // Process the coalesced 1-RTT packet. + ASSERT_TRUE(writer_->coalesced_packet() != nullptr); + auto packet = writer_->coalesced_packet()->Clone(); + writer_->framer()->ProcessPacket(*packet); + EXPECT_EQ(1u, writer_->stream_frames().size()); + ASSERT_TRUE(writer_->coalesced_packet() == nullptr); // Verify retransmission alarm is still armed. ASSERT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); } @@ -15564,22 +15095,12 @@ TEST_P(QuicConnectionTest, NoExtraPaddingInReserializedInitial) { // Server receives INITIAL 3, this will serialzie FS 7 (stream 4, stream 8), // which will trigger a flush of a coalesced packet consists of INITIAL 4, // HS 5 and FS 6 (stream 4). - if (GetQuicReloadableFlag( - quic_close_connection_if_fail_to_serialzie_coalesced_packet2)) { - // Expect no QUIC_BUG. - ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_INITIAL); - EXPECT_EQ( - debug_visitor_sent_count, - connection_.sent_packet_manager().GetLargestSentPacket().ToUint64()); - } else { - // Expect QUIC_BUG due to extra padding. - EXPECT_QUIC_BUG( - { ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_INITIAL); }, - "Reserialize initial packet in coalescer has unexpected size"); - EXPECT_EQ( - debug_visitor_sent_count + 1, - connection_.sent_packet_manager().GetLargestSentPacket().ToUint64()); - } + + // Expect no QUIC_BUG. + ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_INITIAL); + EXPECT_EQ( + debug_visitor_sent_count, + connection_.sent_packet_manager().GetLargestSentPacket().ToUint64()); // The error only happens if after serializing the second 1RTT packet(pkt #7), // the pending padding bytes is non zero. @@ -15631,27 +15152,15 @@ TEST_P(QuicConnectionTest, ReportedAckDelayIncludesQueuingDelay) { connection_.GetProcessUndecryptablePacketsAlarm()->Fire(); ASSERT_TRUE(connection_.HasPendingAcks()); - if (GetQuicReloadableFlag(quic_update_ack_timeout_on_receipt_time)) { - EXPECT_EQ(packet_receipt_time + DefaultDelayedAckTime(), - connection_.GetAckAlarm()->deadline()); - clock_.AdvanceTime(packet_receipt_time + DefaultDelayedAckTime() - - clock_.Now()); - } else { - EXPECT_EQ(clock_.Now() + DefaultDelayedAckTime(), - connection_.GetAckAlarm()->deadline()); - clock_.AdvanceTime(DefaultDelayedAckTime()); - } + EXPECT_EQ(packet_receipt_time + DefaultDelayedAckTime(), + connection_.GetAckAlarm()->deadline()); + clock_.AdvanceTime(packet_receipt_time + DefaultDelayedAckTime() - + clock_.Now()); // Fire ACK alarm. connection_.GetAckAlarm()->Fire(); ASSERT_EQ(1u, writer_->ack_frames().size()); - if (GetQuicReloadableFlag(quic_update_ack_timeout_on_receipt_time)) { - // Verify ACK delay time does not include queuing delay. - EXPECT_EQ(DefaultDelayedAckTime(), writer_->ack_frames()[0].ack_delay_time); - } else { - // Verify ACK delay time = queuing delay + ack delay - EXPECT_EQ(DefaultDelayedAckTime() + kQueuingDelay, - writer_->ack_frames()[0].ack_delay_time); - } + // Verify ACK delay time does not include queuing delay. + EXPECT_EQ(DefaultDelayedAckTime(), writer_->ack_frames()[0].ack_delay_time); } TEST_P(QuicConnectionTest, CoalesceOneRTTPacketWithInitialAndHandshakePackets) { @@ -15716,10 +15225,6 @@ TEST_P(QuicConnectionTest, CoalesceOneRTTPacketWithInitialAndHandshakePackets) { auto packet = writer_->coalesced_packet()->Clone(); writer_->framer()->ProcessPacket(*packet); EXPECT_EQ(1u, writer_->crypto_frames().size()); - if (!GetQuicReloadableFlag(quic_flush_after_coalesce_higher_space_packets)) { - ASSERT_TRUE(writer_->coalesced_packet() == nullptr); - return; - } // Process 1-RTT packet. ASSERT_TRUE(writer_->coalesced_packet() != nullptr); packet = writer_->coalesced_packet()->Clone(); @@ -15747,16 +15252,16 @@ TEST_P(QuicConnectionTest, SendMultipleConnectionCloses) { SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); ASSERT_TRUE(connection_.BlackholeDetectionInProgress()); - // Verify BeforeConnectionCloseSent gets called twice while OnConnectionClosed - // is called once. + // Verify that BeforeConnectionCloseSent() gets called twice, + // while OnConnectionClosed() is called only once. EXPECT_CALL(visitor_, BeforeConnectionCloseSent()).Times(2); EXPECT_CALL(visitor_, OnConnectionClosed(_, _)); // Send connection close w/o closing connection. QuicConnectionPeer::SendConnectionClosePacket( &connection_, INTERNAL_ERROR, QUIC_INTERNAL_ERROR, "internal error"); - // Fire blackhole detection alarm. - EXPECT_QUIC_BUG(connection_.GetBlackholeDetectorAlarm()->Fire(), - "Already sent connection close"); + // Fire blackhole detection alarm. This will invoke + // SendConnectionClosePacket() a second time. + connection_.GetBlackholeDetectorAlarm()->Fire(); } // Regression test for b/157895910. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_constants.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_constants.h index 189179f6e9e..6f89ec1ac00 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_constants.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_constants.h @@ -181,6 +181,13 @@ const int kMaxAvailableStreamsMultiplier = 10; // create available streams entries. const int kMaxPromisedStreamsMultiplier = kMaxAvailableStreamsMultiplier - 1; +// The 1st PTO is armed with max of earliest in flight sent time + PTO +// delay and kFirstPtoSrttMultiplier * srtt from last in flight packet. +const float kFirstPtoSrttMultiplier = 1.5; + +// The multiplier of RTT variation when calculating PTO timeout. +const int kPtoRttvarMultiplier = 2; + // TCP RFC calls for 1 second RTO however Linux differs from this default and // define the minimum RTO to 200ms, we will use the same until we have data to // support a higher or lower value. @@ -300,13 +307,6 @@ QUIC_EXPORT_PRIVATE QuicPacketNumber FirstSendingPacketNumber(); QUIC_EXPORT_PRIVATE extern const char* const kEPIDGoogleFrontEnd; QUIC_EXPORT_PRIVATE extern const char* const kEPIDGoogleFrontEnd0; -// HTTP/3 Datagrams. -enum : QuicDatagramContextId { - kFirstDatagramContextIdClient = 0, - kFirstDatagramContextIdServer = 1, - kDatagramContextIdIncrement = 2, -}; - enum : uint64_t { kHttpDatagramStreamIdDivisor = 4, }; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager.cc index 64e5eecbf81..1553cc8fb8d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager.cc @@ -17,6 +17,7 @@ #include "quiche/quic/core/quic_utils.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/quic/platform/api/quic_flag_utils.h" +#include "quiche/quic/platform/api/quic_flags.h" namespace quic { @@ -81,10 +82,17 @@ void QuicControlFrameManager::WriteOrBufferWindowUpdate( QuicWindowUpdateFrame(++last_control_frame_id_, id, byte_offset))); } -void QuicControlFrameManager::WriteOrBufferBlocked(QuicStreamId id) { +void QuicControlFrameManager::WriteOrBufferBlocked( + QuicStreamId id, QuicStreamOffset byte_offset) { QUIC_DVLOG(1) << "Writing BLOCKED_FRAME"; - WriteOrBufferQuicFrame( - QuicFrame(QuicBlockedFrame(++last_control_frame_id_, id))); + if (GetQuicReloadableFlag(quic_include_offset_in_blocked_frames)) { + QUIC_RELOADABLE_FLAG_COUNT(quic_include_offset_in_blocked_frames); + WriteOrBufferQuicFrame( + QuicFrame(QuicBlockedFrame(++last_control_frame_id_, id, byte_offset))); + } else { + WriteOrBufferQuicFrame( + QuicFrame(QuicBlockedFrame(++last_control_frame_id_, id, 0))); + } } void QuicControlFrameManager::WriteOrBufferStreamsBlocked(QuicStreamCount count, @@ -266,8 +274,7 @@ void QuicControlFrameManager::OnCanWrite() { bool QuicControlFrameManager::RetransmitControlFrame(const QuicFrame& frame, TransmissionType type) { - QUICHE_DCHECK(type == PTO_RETRANSMISSION || type == RTO_RETRANSMISSION || - type == TLP_RETRANSMISSION || type == PROBING_RETRANSMISSION); + QUICHE_DCHECK(type == PTO_RETRANSMISSION); QuicControlFrameId id = GetControlFrameId(frame); if (id == kInvalidControlFrameId) { // Frame does not have a valid control frame ID, ignore it. Returns true diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager.h index b8853016d88..46a0f47e5ce 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager.h @@ -69,7 +69,7 @@ class QUIC_EXPORT_PRIVATE QuicControlFrameManager { // Tries to send a BLOCKED_FRAME. Buffers the frame if it cannot be sent // immediately. - void WriteOrBufferBlocked(QuicStreamId id); + void WriteOrBufferBlocked(QuicStreamId id, QuicStreamOffset byte_offset); // Tries to send a STREAMS_BLOCKED Frame. Buffers the frame if it cannot be // sent immediately. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager_test.cc index 821bcca8ce8..e1d2538a05f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager_test.cc @@ -72,7 +72,7 @@ class QuicControlFrameManagerTest : public QuicTest { manager_->WriteOrBufferGoAway(QUIC_PEER_GOING_AWAY, kTestStreamId, "Going away."); manager_->WriteOrBufferWindowUpdate(kTestStreamId, 100); - manager_->WriteOrBufferBlocked(kTestStreamId); + manager_->WriteOrBufferBlocked(kTestStreamId, 0); manager_->WriteOrBufferStopSending( QuicResetStreamError::FromInternal(kTestStopSendingCode), kTestStreamId); @@ -93,7 +93,7 @@ class QuicControlFrameManagerTest : public QuicTest { QuicGoAwayFrame goaway_ = {2, QUIC_PEER_GOING_AWAY, kTestStreamId, "Going away."}; QuicWindowUpdateFrame window_update_ = {3, kTestStreamId, 100}; - QuicBlockedFrame blocked_ = {4, kTestStreamId}; + QuicBlockedFrame blocked_ = {4, kTestStreamId, 0}; QuicStopSendingFrame stop_sending_ = {5, kTestStreamId, kTestStopSendingCode}; MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker.cc index aa963d54b5e..14f08e4a597 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker.cc @@ -11,9 +11,11 @@ #include "quiche/quic/core/crypto/crypto_protocol.h" #include "quiche/quic/core/crypto/crypto_utils.h" #include "quiche/quic/core/quic_session.h" +#include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_client_stats.h" #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_logging.h" +#include "quiche/common/platform/api/quiche_logging.h" namespace quic { @@ -144,6 +146,21 @@ bool QuicCryptoClientHandshaker::encryption_established() const { return encryption_established_; } +bool QuicCryptoClientHandshaker::IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel /*level*/) const { + return true; +} + +EncryptionLevel +QuicCryptoClientHandshaker::GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const { + if (space == INITIAL_DATA) { + return ENCRYPTION_INITIAL; + } + QUICHE_DCHECK(false); + return NUM_ENCRYPTION_LEVELS; +} + bool QuicCryptoClientHandshaker::one_rtt_keys_available() const { return one_rtt_keys_available_; } @@ -258,7 +275,7 @@ void QuicCryptoClientHandshaker::DoHandshakeLoop( DoInitializeServerConfigUpdate(cached); break; case STATE_NONE: - QUIC_NOTREACHED(); + QUICHE_NOTREACHED(); return; case STATE_CONNECTION_CLOSED: rv = QUIC_FAILURE; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker.h index 45d8016f935..dbbd942e709 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker.h @@ -11,6 +11,7 @@ #include "quiche/quic/core/crypto/quic_crypto_client_config.h" #include "quiche/quic/core/quic_crypto_client_stream.h" #include "quiche/quic/core/quic_server_id.h" +#include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/common/platform/api/quiche_logging.h" @@ -43,6 +44,10 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker int num_scup_messages_received() const override; std::string chlo_hash() const override; bool encryption_established() const override; + bool IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const override; + EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const override; bool one_rtt_keys_available() const override; const QuicCryptoNegotiatedParameters& crypto_negotiated_params() const override; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker_test.cc index cf5318502ed..b31ec18b981 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker_test.cc @@ -11,7 +11,7 @@ #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/test_tools/quic_test_utils.h" -namespace quic { +namespace quic::test { namespace { class TestProofHandler : public QuicCryptoClientStream::ProofHandler { @@ -214,4 +214,4 @@ TEST_P(QuicCryptoClientHandshakerTest, TestNoPaddingInFullHelloWhenDisabled) { } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.cc index 60d49ed5d98..3c6dbe767e3 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.cc @@ -164,4 +164,15 @@ SSL* QuicCryptoClientStream::GetSsl() const { return tls_handshaker_ == nullptr ? nullptr : tls_handshaker_->ssl(); } +bool QuicCryptoClientStream::IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const { + return handshaker_->IsCryptoFrameExpectedForEncryptionLevel(level); +} + +EncryptionLevel +QuicCryptoClientStream::GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const { + return handshaker_->GetEncryptionLevelToSendCryptoDataOfSpace(space); +} + } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.h index 96abfec5ab0..0a3e5e4df57 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.h @@ -17,6 +17,7 @@ #include "quiche/quic/core/quic_crypto_stream.h" #include "quiche/quic/core/quic_server_id.h" #include "quiche/quic/core/quic_session.h" +#include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_versions.h" #include "quiche/quic/platform/api/quic_export.h" @@ -169,6 +170,14 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream // for the connection. virtual bool encryption_established() const = 0; + // Returns true if receiving CRYPTO_FRAME at encryption `level` is expected. + virtual bool IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const = 0; + + // Returns the encryption level to send CRYPTO_FRAME for `space`. + virtual EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const = 0; + // Returns true once 1RTT keys are available. virtual bool one_rtt_keys_available() const = 0; @@ -283,6 +292,11 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream override; std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override; SSL* GetSsl() const override; + bool IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const override; + EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const override; + bool ExportKeyingMaterial(absl::string_view label, absl::string_view context, size_t result_len, std::string* result) override; std::string chlo_hash() const; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.cc index cca4890b31c..2bd8fbdc965 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.cc @@ -10,8 +10,10 @@ #include "absl/base/macros.h" #include "absl/strings/string_view.h" #include "openssl/sha.h" +#include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_flag_utils.h" #include "quiche/quic/platform/api/quic_testvalue.h" +#include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/quiche_text_utils.h" namespace quic { @@ -67,7 +69,6 @@ QuicCryptoServerStream::QuicCryptoServerStream( zero_rtt_attempted_(false), chlo_packet_size_(0), validate_client_hello_cb_(nullptr), - process_client_hello_cb_(nullptr), encryption_established_(false), one_rtt_keys_available_(false), one_rtt_packet_decrypted_(false), @@ -87,9 +88,10 @@ void QuicCryptoServerStream::CancelOutstandingCallbacks() { send_server_config_update_cb_->Cancel(); send_server_config_update_cb_ = nullptr; } - if (process_client_hello_cb_ != nullptr) { - process_client_hello_cb_->Cancel(); - process_client_hello_cb_ = nullptr; + if (std::shared_ptr<ProcessClientHelloCallback> cb = + process_client_hello_cb_.lock()) { + cb->Cancel(); + process_client_hello_cb_.reset(); } } @@ -113,7 +115,7 @@ void QuicCryptoServerStream::OnHandshakeMessage( } if (validate_client_hello_cb_ != nullptr || - process_client_hello_cb_ != nullptr) { + !process_client_hello_cb_.expired()) { // Already processing some other handshake message. The protocol // does not allow for clients to send multiple handshake messages // before the server has a chance to respond. @@ -127,7 +129,7 @@ void QuicCryptoServerStream::OnHandshakeMessage( std::unique_ptr<ValidateCallback> cb(new ValidateCallback(this)); QUICHE_DCHECK(validate_client_hello_cb_ == nullptr); - QUICHE_DCHECK(process_client_hello_cb_ == nullptr); + QUICHE_DCHECK(process_client_hello_cb_.expired()); validate_client_hello_cb_ = cb.get(); crypto_config_->ValidateClientHello( message, GetClientAddress(), session()->connection()->self_address(), @@ -142,12 +144,11 @@ void QuicCryptoServerStream::FinishProcessingHandshakeMessage( std::unique_ptr<ProofSource::Details> details) { // Clear the callback that got us here. QUICHE_DCHECK(validate_client_hello_cb_ != nullptr); - QUICHE_DCHECK(process_client_hello_cb_ == nullptr); + QUICHE_DCHECK(process_client_hello_cb_.expired()); validate_client_hello_cb_ = nullptr; - std::unique_ptr<ProcessClientHelloCallback> cb( - new ProcessClientHelloCallback(this, result)); - process_client_hello_cb_ = cb.get(); + auto cb = std::make_shared<ProcessClientHelloCallback>(this, result); + process_client_hello_cb_ = cb; ProcessClientHello(result, std::move(details), std::move(cb)); } @@ -159,9 +160,9 @@ void QuicCryptoServerStream:: std::unique_ptr<DiversificationNonce> diversification_nonce, std::unique_ptr<ProofSource::Details> proof_source_details) { // Clear the callback that got us here. - QUICHE_DCHECK(process_client_hello_cb_ != nullptr); + QUICHE_DCHECK(!process_client_hello_cb_.expired()); QUICHE_DCHECK(validate_client_hello_cb_ == nullptr); - process_client_hello_cb_ = nullptr; + process_client_hello_cb_.reset(); proof_source_details_ = std::move(proof_source_details); AdjustTestValue("quic::QuicCryptoServerStream::after_process_client_hello", @@ -455,7 +456,7 @@ void QuicCryptoServerStream::ProcessClientHello( ValidateClientHelloResultCallback::Result> result, std::unique_ptr<ProofSource::Details> proof_source_details, - std::unique_ptr<ProcessClientHelloResultCallback> done_cb) { + std::shared_ptr<ProcessClientHelloResultCallback> done_cb) { proof_source_details_ = std::move(proof_source_details); const CryptoHandshakeMessage& message = result->client_hello; std::string error_details; @@ -526,4 +527,22 @@ const QuicSocketAddress QuicCryptoServerStream::GetClientAddress() { SSL* QuicCryptoServerStream::GetSsl() const { return nullptr; } +bool QuicCryptoServerStream::IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel /*level*/) const { + return true; +} + +EncryptionLevel +QuicCryptoServerStream::GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const { + if (space == INITIAL_DATA) { + return ENCRYPTION_INITIAL; + } + if (space == APPLICATION_DATA) { + return ENCRYPTION_ZERO_RTT; + } + QUICHE_DCHECK(false); + return NUM_ENCRYPTION_LEVELS; +} + } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.h index 2f7fb462184..665d071d074 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.h @@ -12,6 +12,7 @@ #include "quiche/quic/core/quic_crypto_handshaker.h" #include "quiche/quic/core/quic_crypto_server_stream_base.h" #include "quiche/quic/core/quic_session.h" +#include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_export.h" namespace quic { @@ -72,6 +73,10 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream override; std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override; SSL* GetSsl() const override; + bool IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const override; + EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const override; // From QuicCryptoHandshaker void OnHandshakeMessage(const CryptoHandshakeMessage& message) override; @@ -96,7 +101,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream ValidateClientHelloResultCallback::Result> result, std::unique_ptr<ProofSource::Details> proof_source_details, - std::unique_ptr<ProcessClientHelloResultCallback> done_cb); + std::shared_ptr<ProcessClientHelloResultCallback> done_cb); // Hook that allows the server to set QuicConfig defaults just // before going through the parameter negotiation step. @@ -249,7 +254,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream // ProcessClientHello and forward it to // FinishProcessingHandshakeMessageAfterProcessClientHello. Note that this // field is mutually exclusive with validate_client_hello_cb_. - ProcessClientHelloCallback* process_client_hello_cb_; + std::weak_ptr<ProcessClientHelloCallback> process_client_hello_cb_; // The ProofSource::Details from this connection. std::unique_ptr<ProofSource::Details> proof_source_details_; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.cc index a6699820d0b..c85b9abf950 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.cc @@ -6,11 +6,14 @@ #include <string> +#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "quiche/quic/core/crypto/crypto_handshake.h" #include "quiche/quic/core/crypto/crypto_utils.h" +#include "quiche/quic/core/frames/quic_crypto_frame.h" #include "quiche/quic/core/quic_connection.h" +#include "quiche/quic/core/quic_error_codes.h" #include "quiche/quic/core/quic_session.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_utils.h" @@ -35,10 +38,7 @@ QuicCryptoStream::QuicCryptoStream(QuicSession* session) QuicVersionUsesCryptoFrames(session->transport_version()) ? CRYPTO : BIDIRECTIONAL), - substreams_{{{this, ENCRYPTION_INITIAL}, - {this, ENCRYPTION_HANDSHAKE}, - {this, ENCRYPTION_ZERO_RTT}, - {this, ENCRYPTION_FORWARD_SECURE}}} { + substreams_{{{this}, {this}, {this}}} { // The crypto stream is exempt from connection level flow control. DisableConnectionFlowControlForThisStream(); } @@ -74,9 +74,17 @@ void QuicCryptoStream::OnCryptoFrame(const QuicCryptoFrame& frame) { !QuicVersionUsesCryptoFrames(session()->transport_version())) << "Versions less than 47 shouldn't receive CRYPTO frames"; EncryptionLevel level = session()->connection()->last_decrypted_level(); - substreams_[level].sequencer.OnCryptoFrame(frame); + if (!IsCryptoFrameExpectedForEncryptionLevel(level)) { + OnUnrecoverableError( + IETF_QUIC_PROTOCOL_VIOLATION, + absl::StrCat("CRYPTO_FRAME is unexpectedly received at level ", level)); + return; + } + CryptoSubstream& substream = + substreams_[QuicUtils::GetPacketNumberSpace(level)]; + substream.sequencer.OnCryptoFrame(frame); EncryptionLevel frame_level = level; - if (substreams_[level].sequencer.NumBytesBuffered() > + if (substream.sequencer.NumBytesBuffered() > BufferSizeLimitForLevel(frame_level)) { OnUnrecoverableError(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, "Too much crypto data received"); @@ -101,7 +109,8 @@ void QuicCryptoStream::OnDataAvailable() { OnDataAvailableInSequencer(sequencer(), level); return; } - OnDataAvailableInSequencer(&substreams_[level].sequencer, level); + OnDataAvailableInSequencer( + &substreams_[QuicUtils::GetPacketNumberSpace(level)].sequencer, level); } void QuicCryptoStream::OnDataAvailableInSequencer( @@ -137,16 +146,41 @@ void QuicCryptoStream::WriteCryptoData(EncryptionLevel level, return; } const bool had_buffered_data = HasBufferedCryptoFrames(); - // Append |data| to the send buffer for this encryption level. - QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer; + QuicStreamSendBuffer* send_buffer = + &substreams_[QuicUtils::GetPacketNumberSpace(level)].send_buffer; QuicStreamOffset offset = send_buffer->stream_offset(); + + // Ensure this data does not cause the send buffer for this encryption level + // to exceed its size limit. + if (GetQuicReloadableFlag(quic_bounded_crypto_send_buffer)) { + QUIC_RELOADABLE_FLAG_COUNT(quic_bounded_crypto_send_buffer); + QUIC_BUG_IF(quic_crypto_stream_offset_lt_bytes_written, + offset < send_buffer->stream_bytes_written()); + uint64_t current_buffer_size = + offset - std::min(offset, send_buffer->stream_bytes_written()); + if (current_buffer_size > 0) { + QUIC_CODE_COUNT(quic_received_crypto_data_with_non_empty_send_buffer); + if (BufferSizeLimitForLevel(level) < + (current_buffer_size + data.length())) { + QUIC_BUG(quic_crypto_send_buffer_overflow) + << absl::StrCat("Too much data for crypto send buffer with level: ", + EncryptionLevelToString(level), + ", current_buffer_size: ", current_buffer_size, + ", data length: ", data.length()); + OnUnrecoverableError(QUIC_INTERNAL_ERROR, + "Too much data for crypto send buffer"); + return; + } + } + } + + // Append |data| to the send buffer for this encryption level. send_buffer->SaveStreamData(data); if (kMaxStreamLength - offset < data.length()) { QUIC_BUG(quic_bug_10322_2) << "Writing too much crypto handshake data"; - // TODO(nharper): Switch this to an IETF QUIC error code, possibly - // INTERNAL_ERROR? - OnUnrecoverableError(QUIC_STREAM_LENGTH_OVERFLOW, + OnUnrecoverableError(QUIC_INTERNAL_ERROR, "Writing too much crypto handshake data"); + return; } if (had_buffered_data) { // Do not try to write if there is buffered data. @@ -165,8 +199,9 @@ size_t QuicCryptoStream::BufferSizeLimitForLevel(EncryptionLevel) const { bool QuicCryptoStream::OnCryptoFrameAcked(const QuicCryptoFrame& frame, QuicTime::Delta /*ack_delay_time*/) { QuicByteCount newly_acked_length = 0; - if (!substreams_[frame.level].send_buffer.OnStreamDataAcked( - frame.offset, frame.data_length, &newly_acked_length)) { + if (!substreams_[QuicUtils::GetPacketNumberSpace(frame.level)] + .send_buffer.OnStreamDataAcked(frame.offset, frame.data_length, + &newly_acked_length)) { OnUnrecoverableError(QUIC_INTERNAL_ERROR, "Trying to ack unsent crypto data."); return false; @@ -193,9 +228,10 @@ void QuicCryptoStream::NeuterStreamDataOfEncryptionLevel( } return; } - QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer; - // TODO(nharper): Consider adding a Clear() method to QuicStreamSendBuffer to - // replace the following code. + QuicStreamSendBuffer* send_buffer = + &substreams_[QuicUtils::GetPacketNumberSpace(level)].send_buffer; + // TODO(nharper): Consider adding a Clear() method to QuicStreamSendBuffer + // to replace the following code. QuicIntervalSet<QuicStreamOffset> to_ack = send_buffer->bytes_acked(); to_ack.Complement(0, send_buffer->stream_offset()); for (const auto& interval : to_ack) { @@ -217,22 +253,12 @@ void QuicCryptoStream::OnStreamDataConsumed(QuicByteCount bytes_consumed) { QuicStream::OnStreamDataConsumed(bytes_consumed); } -namespace { - -constexpr std::array<EncryptionLevel, NUM_ENCRYPTION_LEVELS> -AllEncryptionLevels() { - return {ENCRYPTION_INITIAL, ENCRYPTION_HANDSHAKE, ENCRYPTION_ZERO_RTT, - ENCRYPTION_FORWARD_SECURE}; -} - -} // namespace - bool QuicCryptoStream::HasPendingCryptoRetransmission() const { if (!QuicVersionUsesCryptoFrames(session()->transport_version())) { return false; } - for (EncryptionLevel level : AllEncryptionLevels()) { - if (substreams_[level].send_buffer.HasPendingRetransmission()) { + for (const auto& substream : substreams_) { + if (substream.send_buffer.HasPendingRetransmission()) { return true; } } @@ -243,12 +269,15 @@ void QuicCryptoStream::WritePendingCryptoRetransmission() { QUIC_BUG_IF(quic_bug_12573_3, !QuicVersionUsesCryptoFrames(session()->transport_version())) << "Versions less than 47 don't write CRYPTO frames"; - for (EncryptionLevel level : AllEncryptionLevels()) { - QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer; + for (uint8_t i = INITIAL_DATA; i <= APPLICATION_DATA; ++i) { + auto packet_number_space = static_cast<PacketNumberSpace>(i); + QuicStreamSendBuffer* send_buffer = + &substreams_[packet_number_space].send_buffer; while (send_buffer->HasPendingRetransmission()) { auto pending = send_buffer->NextPendingRetransmission(); size_t bytes_consumed = stream_delegate()->SendCryptoData( - level, pending.length, pending.offset, HANDSHAKE_RETRANSMISSION); + GetEncryptionLevelToSendCryptoDataOfSpace(packet_number_space), + pending.length, pending.offset, HANDSHAKE_RETRANSMISSION); send_buffer->OnStreamDataRetransmitted(pending.offset, bytes_consumed); if (bytes_consumed < pending.length) { return; @@ -343,14 +372,17 @@ uint64_t QuicCryptoStream::crypto_bytes_read() const { return stream_bytes_read(); } uint64_t bytes_read = 0; - for (EncryptionLevel level : AllEncryptionLevels()) { - bytes_read += substreams_[level].sequencer.NumBytesConsumed(); + for (const CryptoSubstream& substream : substreams_) { + bytes_read += substream.sequencer.NumBytesConsumed(); } return bytes_read; } +// TODO(haoyuewang) Move this test-only method under +// quiche/quic/test_tools. uint64_t QuicCryptoStream::BytesReadOnLevel(EncryptionLevel level) const { - return substreams_[level].sequencer.NumBytesConsumed(); + return substreams_[QuicUtils::GetPacketNumberSpace(level)] + .sequencer.NumBytesConsumed(); } bool QuicCryptoStream::WriteCryptoFrame(EncryptionLevel level, @@ -360,16 +392,17 @@ bool QuicCryptoStream::WriteCryptoFrame(EncryptionLevel level, QUIC_BUG_IF(quic_bug_12573_4, !QuicVersionUsesCryptoFrames(session()->transport_version())) << "Versions less than 47 don't write CRYPTO frames (2)"; - return substreams_[level].send_buffer.WriteStreamData(offset, data_length, - writer); + return substreams_[QuicUtils::GetPacketNumberSpace(level)] + .send_buffer.WriteStreamData(offset, data_length, writer); } void QuicCryptoStream::OnCryptoFrameLost(QuicCryptoFrame* crypto_frame) { QUIC_BUG_IF(quic_bug_12573_5, !QuicVersionUsesCryptoFrames(session()->transport_version())) << "Versions less than 47 don't lose CRYPTO frames"; - substreams_[crypto_frame->level].send_buffer.OnStreamDataLost( - crypto_frame->offset, crypto_frame->data_length); + substreams_[QuicUtils::GetPacketNumberSpace(crypto_frame->level)] + .send_buffer.OnStreamDataLost(crypto_frame->offset, + crypto_frame->data_length); } bool QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame, @@ -380,7 +413,8 @@ bool QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame, QuicIntervalSet<QuicStreamOffset> retransmission( crypto_frame->offset, crypto_frame->offset + crypto_frame->data_length); QuicStreamSendBuffer* send_buffer = - &substreams_[crypto_frame->level].send_buffer; + &substreams_[QuicUtils::GetPacketNumberSpace(crypto_frame->level)] + .send_buffer; retransmission.Difference(send_buffer->bytes_acked()); if (retransmission.Empty()) { return true; @@ -388,9 +422,12 @@ bool QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame, for (const auto& interval : retransmission) { size_t retransmission_offset = interval.min(); size_t retransmission_length = interval.max() - interval.min(); + EncryptionLevel retransmission_encryption_level = + GetEncryptionLevelToSendCryptoDataOfSpace( + QuicUtils::GetPacketNumberSpace(crypto_frame->level)); size_t bytes_consumed = stream_delegate()->SendCryptoData( - crypto_frame->level, retransmission_length, retransmission_offset, - type); + retransmission_encryption_level, retransmission_length, + retransmission_offset, type); send_buffer->OnStreamDataRetransmitted(retransmission_offset, bytes_consumed); if (bytes_consumed < retransmission_length) { @@ -404,8 +441,10 @@ void QuicCryptoStream::WriteBufferedCryptoFrames() { QUIC_BUG_IF(quic_bug_12573_7, !QuicVersionUsesCryptoFrames(session()->transport_version())) << "Versions less than 47 don't use CRYPTO frames"; - for (EncryptionLevel level : AllEncryptionLevels()) { - QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer; + for (uint8_t i = INITIAL_DATA; i <= APPLICATION_DATA; ++i) { + auto packet_number_space = static_cast<PacketNumberSpace>(i); + QuicStreamSendBuffer* send_buffer = + &substreams_[packet_number_space].send_buffer; const size_t data_length = send_buffer->stream_offset() - send_buffer->stream_bytes_written(); if (data_length == 0) { @@ -413,8 +452,8 @@ void QuicCryptoStream::WriteBufferedCryptoFrames() { continue; } size_t bytes_consumed = stream_delegate()->SendCryptoData( - level, data_length, send_buffer->stream_bytes_written(), - NOT_RETRANSMISSION); + GetEncryptionLevelToSendCryptoDataOfSpace(packet_number_space), + data_length, send_buffer->stream_bytes_written(), NOT_RETRANSMISSION); send_buffer->OnStreamDataConsumed(bytes_consumed); if (bytes_consumed < data_length) { // Connection is write blocked. @@ -427,8 +466,8 @@ bool QuicCryptoStream::HasBufferedCryptoFrames() const { QUIC_BUG_IF(quic_bug_12573_8, !QuicVersionUsesCryptoFrames(session()->transport_version())) << "Versions less than 47 don't use CRYPTO frames"; - for (EncryptionLevel level : AllEncryptionLevels()) { - const QuicStreamSendBuffer& send_buffer = substreams_[level].send_buffer; + for (const CryptoSubstream& substream : substreams_) { + const QuicStreamSendBuffer& send_buffer = substream.send_buffer; QUICHE_DCHECK_GE(send_buffer.stream_offset(), send_buffer.stream_bytes_written()); if (send_buffer.stream_offset() > send_buffer.stream_bytes_written()) { @@ -449,15 +488,16 @@ bool QuicCryptoStream::IsFrameOutstanding(EncryptionLevel level, size_t offset, // the wrong transport version. return false; } - return substreams_[level].send_buffer.IsStreamDataOutstanding(offset, length); + return substreams_[QuicUtils::GetPacketNumberSpace(level)] + .send_buffer.IsStreamDataOutstanding(offset, length); } bool QuicCryptoStream::IsWaitingForAcks() const { if (!QuicVersionUsesCryptoFrames(session()->transport_version())) { return QuicStream::IsWaitingForAcks(); } - for (EncryptionLevel level : AllEncryptionLevels()) { - if (substreams_[level].send_buffer.stream_bytes_outstanding()) { + for (const CryptoSubstream& substream : substreams_) { + if (substream.send_buffer.stream_bytes_outstanding()) { return true; } } @@ -465,7 +505,7 @@ bool QuicCryptoStream::IsWaitingForAcks() const { } QuicCryptoStream::CryptoSubstream::CryptoSubstream( - QuicCryptoStream* crypto_stream, EncryptionLevel) + QuicCryptoStream* crypto_stream) : sequencer(crypto_stream), send_buffer(crypto_stream->session() ->connection() diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.h index 9e9b8702228..6d29d4b73ad 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.h @@ -236,17 +236,27 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream { virtual void OnDataAvailableInSequencer(QuicStreamSequencer* sequencer, EncryptionLevel level); - QuicStreamSequencer* GetStreamSequencerForLevel(EncryptionLevel level) { - return &substreams_[level].sequencer; + QuicStreamSequencer* GetStreamSequencerForPacketNumberSpace( + PacketNumberSpace packet_number_space) { + return &substreams_[packet_number_space].sequencer; } + // Called by OnCryptoFrame to check if a CRYPTO frame is received at an + // expected `level`. + virtual bool IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const = 0; + + // Called to determine the encryption level to send/retransmit crypto data. + virtual EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const = 0; + 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 - // across encryption levels, and a CryptoSubstream is used to manage that - // state for a particular encryption level. + // Data sent and received in CRYPTO frames is sent at multiple packet number + // spaces. Some of the state for the single logical crypto stream is split + // across packet number spaces, and a CryptoSubstream is used to manage that + // state for a particular packet number space. struct QUIC_EXPORT_PRIVATE CryptoSubstream { - CryptoSubstream(QuicCryptoStream* crypto_stream, EncryptionLevel); + CryptoSubstream(QuicCryptoStream* crypto_stream); QuicStreamSequencer sequencer; QuicStreamSendBuffer send_buffer; @@ -257,9 +267,9 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream { // TLS 1.3, which never encrypts crypto data. QuicIntervalSet<QuicStreamOffset> bytes_consumed_[NUM_ENCRYPTION_LEVELS]; - // Keeps state for data sent/received in CRYPTO frames at each encryption - // level. - std::array<CryptoSubstream, NUM_ENCRYPTION_LEVELS> substreams_; + // Keeps state for data sent/received in CRYPTO frames at each packet number + // space; + std::array<CryptoSubstream, NUM_PACKET_NUMBER_SPACES> substreams_; }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream_test.cc index 6df498301fc..f5d1f2e2fdc 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream_test.cc @@ -13,10 +13,14 @@ #include "quiche/quic/core/crypto/crypto_handshake.h" #include "quiche/quic/core/crypto/crypto_protocol.h" #include "quiche/quic/core/crypto/null_encrypter.h" +#include "quiche/quic/core/quic_error_codes.h" +#include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_utils.h" +#include "quiche/quic/platform/api/quic_expect_bug.h" #include "quiche/quic/platform/api/quic_socket_address.h" #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/test_tools/crypto_test_utils.h" +#include "quiche/quic/test_tools/quic_connection_peer.h" #include "quiche/quic/test_tools/quic_stream_peer.h" #include "quiche/quic/test_tools/quic_test_utils.h" @@ -95,6 +99,27 @@ class MockQuicCryptoStream : public QuicCryptoStream, } SSL* GetSsl() const override { return nullptr; } + bool IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const override { + return level != ENCRYPTION_ZERO_RTT; + } + + EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const override { + switch (space) { + case INITIAL_DATA: + return ENCRYPTION_INITIAL; + case HANDSHAKE_DATA: + return ENCRYPTION_HANDSHAKE; + case APPLICATION_DATA: + return QuicCryptoStream::session() + ->GetEncryptionLevelToSendApplicationData(); + default: + QUICHE_DCHECK(false); + return NUM_ENCRYPTION_LEVELS; + } + } + private: quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_; std::vector<CryptoHandshakeMessage> messages_; @@ -260,6 +285,17 @@ TEST_F(QuicCryptoStreamTest, RetransmitCryptoDataInCryptoFrames) { .WillOnce(Invoke(connection_, &MockQuicConnection::QuicConnection_SendCryptoData)); stream_->WriteCryptoData(ENCRYPTION_ZERO_RTT, data); + + // Before encryption moves to ENCRYPTION_FORWARD_SECURE, ZERO RTT data are + // retranmitted at ENCRYPTION_ZERO_RTT. + QuicCryptoFrame lost_frame = QuicCryptoFrame(ENCRYPTION_ZERO_RTT, 0, 650); + stream_->OnCryptoFrameLost(&lost_frame); + + EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 650, 0)) + .WillOnce(Invoke(connection_, + &MockQuicConnection::QuicConnection_SendCryptoData)); + stream_->WritePendingCryptoRetransmission(); + connection_->SetEncrypter( ENCRYPTION_FORWARD_SECURE, std::make_unique<NullEncrypter>(Perspective::IS_CLIENT)); @@ -267,7 +303,7 @@ TEST_F(QuicCryptoStreamTest, RetransmitCryptoDataInCryptoFrames) { EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level()); // Lost [0, 1000). - QuicCryptoFrame lost_frame(ENCRYPTION_INITIAL, 0, 1000); + lost_frame = QuicCryptoFrame(ENCRYPTION_INITIAL, 0, 1000); stream_->OnCryptoFrameLost(&lost_frame); EXPECT_TRUE(stream_->HasPendingCryptoRetransmission()); // Lost [1200, 2000). @@ -283,7 +319,7 @@ TEST_F(QuicCryptoStreamTest, RetransmitCryptoDataInCryptoFrames) { EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, 150, 1200)) .WillOnce(Invoke(connection_, &MockQuicConnection::QuicConnection_SendCryptoData)); - EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 650, 0)) + EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_FORWARD_SECURE, 650, 0)) .WillOnce(Invoke(connection_, &MockQuicConnection::QuicConnection_SendCryptoData)); stream_->WritePendingCryptoRetransmission(); @@ -527,7 +563,7 @@ TEST_F(QuicCryptoStreamTest, RetransmitStreamDataWithCryptoFrames) { stream_->OnCryptoFrameAcked(acked_frame, QuicTime::Delta::Zero())); // Retransmit only [1350, 1500). - EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 150, 0)) + EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_FORWARD_SECURE, 150, 0)) .WillOnce(Invoke(connection_, &MockQuicConnection::QuicConnection_SendCryptoData)); QuicCryptoFrame frame_to_retransmit(ENCRYPTION_ZERO_RTT, 0, 150); @@ -537,10 +573,11 @@ TEST_F(QuicCryptoStreamTest, RetransmitStreamDataWithCryptoFrames) { EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level()); // Retransmit [1350, 2700) again and all data is sent. - EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 650, 0)) + EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_FORWARD_SECURE, 650, 0)) .WillOnce(Invoke(connection_, &MockQuicConnection::QuicConnection_SendCryptoData)); - EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 200, 1150)) + EXPECT_CALL(*connection_, + SendCryptoData(ENCRYPTION_FORWARD_SECURE, 200, 1150)) .WillOnce(Invoke(connection_, &MockQuicConnection::QuicConnection_SendCryptoData)); frame_to_retransmit = QuicCryptoFrame(ENCRYPTION_ZERO_RTT, 0, 1350); @@ -617,6 +654,50 @@ TEST_F(QuicCryptoStreamTest, CryptoMessageFramingOverhead) { } } +TEST_F(QuicCryptoStreamTest, WriteCryptoDataExceedsSendBufferLimit) { + if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) { + return; + } + EXPECT_EQ(ENCRYPTION_INITIAL, connection_->encryption_level()); + int32_t buffer_limit = GetQuicFlag(FLAGS_quic_max_buffered_crypto_bytes); + + // Write data larger than the buffer limit, when there is no existing data in + // the buffer. Data is sent rather than closing the connection. + EXPECT_FALSE(stream_->HasBufferedCryptoFrames()); + int32_t over_limit = buffer_limit + 1; + EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, over_limit, 0)) + // All the data is sent, no resulting buffer. + .WillOnce(Return(over_limit)); + std::string large_data(over_limit, 'a'); + stream_->WriteCryptoData(ENCRYPTION_INITIAL, large_data); + + // Write data to the buffer up to the limit. One byte gets sent. + EXPECT_FALSE(stream_->HasBufferedCryptoFrames()); + EXPECT_CALL(*connection_, + SendCryptoData(ENCRYPTION_INITIAL, buffer_limit, over_limit)) + .WillOnce(Return(1)); + std::string data(buffer_limit, 'a'); + stream_->WriteCryptoData(ENCRYPTION_INITIAL, data); + EXPECT_TRUE(stream_->HasBufferedCryptoFrames()); + + // Write another byte that is not sent (due to there already being data in the + // buffer); send buffer is now full. + EXPECT_CALL(*connection_, SendCryptoData(_, _, _)).Times(0); + std::string data2(1, 'a'); + stream_->WriteCryptoData(ENCRYPTION_INITIAL, data2); + EXPECT_TRUE(stream_->HasBufferedCryptoFrames()); + + // Writing an additional byte to the send buffer closes the connection. + if (GetQuicReloadableFlag(quic_bounded_crypto_send_buffer)) { + QUIC_RELOADABLE_FLAG_COUNT(quic_bounded_crypto_send_buffer); + EXPECT_CALL(*connection_, CloseConnection(QUIC_INTERNAL_ERROR, _, _)); + EXPECT_QUIC_BUG( + stream_->WriteCryptoData(ENCRYPTION_INITIAL, data2), + "Too much data for crypto send buffer with level: ENCRYPTION_INITIAL, " + "current_buffer_size: 16384, data length: 1"); + } +} + TEST_F(QuicCryptoStreamTest, WriteBufferedCryptoFrames) { if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) { return; @@ -674,6 +755,20 @@ TEST_F(QuicCryptoStreamTest, LimitBufferedCryptoData) { QuicCryptoFrame(ENCRYPTION_INITIAL, offset, large_frame)); } +TEST_F(QuicCryptoStreamTest, CloseConnectionWithZeroRttCryptoFrame) { + if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) { + return; + } + + EXPECT_CALL(*connection_, + CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, _, _)); + + test::QuicConnectionPeer::SetLastDecryptedLevel(connection_, + ENCRYPTION_ZERO_RTT); + QuicStreamOffset offset = 1; + stream_->OnCryptoFrame(QuicCryptoFrame(ENCRYPTION_ZERO_RTT, offset, "data")); +} + TEST_F(QuicCryptoStreamTest, RetransmitCryptoFramesAndPartialWrite) { if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) { return; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.cc index e133bb05250..9166a931397 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.cc @@ -8,6 +8,7 @@ #include <string> #include <utility> +#include "absl/base/optimization.h" #include "absl/container/flat_hash_set.h" #include "absl/strings/string_view.h" #include "quiche/quic/core/chlo_extractor.h" @@ -147,6 +148,7 @@ class PacketCollector : public QuicPacketCreator::DelegateInterface, class StatelessConnectionTerminator { public: StatelessConnectionTerminator(QuicConnectionId server_connection_id, + QuicConnectionId original_server_connection_id, const ParsedQuicVersion version, QuicConnectionHelperInterface* helper, QuicTimeWaitListManager* time_wait_list_manager) @@ -158,7 +160,8 @@ class StatelessConnectionTerminator { creator_(server_connection_id, &framer_, &collector_), time_wait_list_manager_(time_wait_list_manager) { framer_.set_data_producer(&collector_); - framer_.SetInitialObfuscators(server_connection_id); + // Always set encrypter with original_server_connection_id. + framer_.SetInitialObfuscators(original_server_connection_id); } ~StatelessConnectionTerminator() { @@ -504,19 +507,21 @@ constexpr bool IsSourceUdpPortBlocked(uint16_t port) { 111, // Portmap. 123, // NTP, vulnerable to reflection attacks. 137, // NETBIOS Name Service, - 128, // NETBIOS Datagram Service + 138, // NETBIOS Datagram Service 161, // SNMP. 389, // CLDAP. 500, // IKE, can loop with QUIC. 1900, // SSDP, vulnerable to reflection attacks. + 3702, // WS-Discovery, vulnerable to reflection attacks. 5353, // mDNS, vulnerable to reflection attacks. + 5355, // LLMNR, vulnerable to reflection attacks. 11211, // memcache, vulnerable to reflection attacks. // This list MUST be sorted in increasing order. }; constexpr size_t num_blocked_ports = ABSL_ARRAYSIZE(blocked_ports); constexpr uint16_t highest_blocked_port = blocked_ports[num_blocked_ports - 1]; - if (QUICHE_PREDICT_TRUE(port > highest_blocked_port)) { + if (ABSL_PREDICT_TRUE(port > highest_blocked_port)) { // Early-return to skip comparisons for the majority of traffic. return false; } @@ -899,8 +904,9 @@ void QuicDispatcher::CleanUpSession(QuicConnectionId server_connection_id, // This serializes a connection close termination packet and adds the // connection to the time wait list. StatelessConnectionTerminator terminator( - server_connection_id, connection->version(), helper_.get(), - time_wait_list_manager_.get()); + server_connection_id, + connection->GetOriginalDestinationConnectionId(), + connection->version(), helper_.get(), time_wait_list_manager_.get()); terminator.CloseConnection( QUIC_HANDSHAKE_FAILED, "Connection is closed by server before handshake confirmed", @@ -1135,9 +1141,9 @@ void QuicDispatcher::StatelesslyTerminateConnection( << version << ", error_code:" << error_code << ", error_details:" << error_details; - StatelessConnectionTerminator terminator(server_connection_id, version, - helper_.get(), - time_wait_list_manager_.get()); + StatelessConnectionTerminator terminator( + server_connection_id, server_connection_id, version, helper_.get(), + time_wait_list_manager_.get()); // This also adds the connection to time wait list. terminator.CloseConnection( error_code, error_details, format != GOOGLE_QUIC_PACKET, @@ -1311,7 +1317,7 @@ void QuicDispatcher::ProcessChlo(ParsedClientHello parsed_chlo, std::unique_ptr<QuicSession> session = CreateQuicSession( packet_info->destination_connection_id, packet_info->self_address, packet_info->peer_address, alpn, packet_info->version, parsed_chlo); - if (QUIC_PREDICT_FALSE(session == nullptr)) { + if (ABSL_PREDICT_FALSE(session == nullptr)) { QUIC_BUG(quic_bug_10287_8) << "CreateQuicSession returned nullptr for " << packet_info->destination_connection_id << " from " @@ -1319,7 +1325,9 @@ void QuicDispatcher::ProcessChlo(ParsedClientHello parsed_chlo, << " ALPN \"" << alpn << "\" version " << packet_info->version; return; } - if (original_connection_id != packet_info->destination_connection_id) { + const bool replaced_connection_id = + original_connection_id != packet_info->destination_connection_id; + if (replaced_connection_id) { session->connection()->SetOriginalDestinationConnectionId( original_connection_id); } @@ -1340,8 +1348,11 @@ void QuicDispatcher::ProcessChlo(ParsedClientHello parsed_chlo, } session_ptr = insertion_result.first->second.get(); std::list<BufferedPacket> packets = - buffered_packets_.DeliverPackets(packet_info->destination_connection_id) - .buffered_packets; + buffered_packets_.DeliverPackets(original_connection_id).buffered_packets; + if (replaced_connection_id && !packets.empty()) { + QUIC_CODE_COUNT( + quic_delivered_buffered_packets_to_connection_with_replaced_id); + } // Process CHLO at first. session_ptr->ProcessUdpPacket(packet_info->self_address, packet_info->peer_address, packet_info->packet); @@ -1390,7 +1401,6 @@ void QuicDispatcher::MaybeResetPacketsWithNoVersion( // recently. if (recent_stateless_reset_addresses_.contains(packet_info.peer_address)) { QUIC_CODE_COUNT(quic_donot_send_reset_repeatedly); - QUICHE_DCHECK(use_recent_reset_addresses_); return; } if (packet_info.form != GOOGLE_QUIC_PACKET) { @@ -1410,24 +1420,21 @@ void QuicDispatcher::MaybeResetPacketsWithNoVersion( return; } } - if (use_recent_reset_addresses_) { - QUIC_RESTART_FLAG_COUNT(quic_use_recent_reset_addresses); - // Do not send a stateless reset if there are too many stateless reset - // addresses. - if (recent_stateless_reset_addresses_.size() >= - GetQuicFlag(FLAGS_quic_max_recent_stateless_reset_addresses)) { - QUIC_CODE_COUNT(quic_too_many_recent_reset_addresses); - return; - } - if (recent_stateless_reset_addresses_.empty()) { - clear_stateless_reset_addresses_alarm_->Update( - helper()->GetClock()->ApproximateNow() + - QuicTime::Delta::FromMilliseconds(GetQuicFlag( - FLAGS_quic_recent_stateless_reset_addresses_lifetime_ms)), - QuicTime::Delta::Zero()); - } - recent_stateless_reset_addresses_.emplace(packet_info.peer_address); + // Do not send a stateless reset if there are too many stateless reset + // addresses. + if (recent_stateless_reset_addresses_.size() >= + GetQuicFlag(FLAGS_quic_max_recent_stateless_reset_addresses)) { + QUIC_CODE_COUNT(quic_too_many_recent_reset_addresses); + return; + } + if (recent_stateless_reset_addresses_.empty()) { + clear_stateless_reset_addresses_alarm_->Update( + helper()->GetClock()->ApproximateNow() + + QuicTime::Delta::FromMilliseconds(GetQuicFlag( + FLAGS_quic_recent_stateless_reset_addresses_lifetime_ms)), + QuicTime::Delta::Zero()); } + recent_stateless_reset_addresses_.emplace(packet_info.peer_address); time_wait_list_manager()->SendPublicReset( packet_info.self_address, packet_info.peer_address, diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.h index 74ac6947b55..f53df8b2447 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.h @@ -467,9 +467,6 @@ class QUIC_NO_EXPORT QuicDispatcher // If true, change expected_server_connection_id_length_ to be the received // destination connection ID length of all IETF long headers. bool should_update_expected_server_connection_id_length_; - - const bool use_recent_reset_addresses_ = - GetQuicRestartFlag(quic_use_recent_reset_addresses); }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher_test.cc index 3dad09673a2..e5e6ea2c14e 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher_test.cc @@ -490,7 +490,8 @@ class QuicDispatcherTestBase : public QuicTestWithParam<ParsedQuicVersion> { ProcessFirstFlight(version, client_address, connection_id); } - void TestTlsMultiPacketClientHello(bool add_reordering); + void TestTlsMultiPacketClientHello(bool add_reordering, + bool long_connection_id); void TestVersionNegotiationForUnknownVersionInvalidShortInitialConnectionId( const QuicConnectionId& server_connection_id, @@ -560,14 +561,23 @@ TEST_P(QuicDispatcherTestAllVersions, TlsClientHelloCreatesSession) { } void QuicDispatcherTestBase::TestTlsMultiPacketClientHello( - bool add_reordering) { + bool add_reordering, bool long_connection_id) { if (!version_.UsesTls()) { return; } SetAddressToken("857293462398"); QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - QuicConnectionId server_connection_id = TestConnectionId(); + QuicConnectionId original_connection_id, new_connection_id; + if (long_connection_id) { + original_connection_id = QuicConnectionId( + {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}); + new_connection_id = + QuicConnectionId({0x6c, 0x6b, 0x4b, 0xad, 0x8d, 0x00, 0x24, 0xd8}); + } else { + original_connection_id = TestConnectionId(); + new_connection_id = original_connection_id; + } QuicConfig client_config = DefaultQuicConfig(); // Add a 2000-byte custom parameter to increase the length of the CHLO. constexpr auto kCustomParameterId = @@ -576,7 +586,7 @@ void QuicDispatcherTestBase::TestTlsMultiPacketClientHello( client_config.custom_transport_parameters_to_send()[kCustomParameterId] = kCustomParameterValue; std::vector<std::unique_ptr<QuicReceivedPacket>> packets = - GetFirstFlightOfPackets(version_, client_config, server_connection_id, + GetFirstFlightOfPackets(version_, client_config, original_connection_id, EmptyQuicConnectionId(), TestClientCryptoConfig()); ASSERT_EQ(packets.size(), 2u); @@ -585,11 +595,12 @@ void QuicDispatcherTestBase::TestTlsMultiPacketClientHello( } // Processing the first packet should not create a new session. - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection( - ReceivedPacketInfoConnectionIdEquals(server_connection_id))); + EXPECT_CALL( + *dispatcher_, + ShouldCreateOrBufferPacketForConnection( + ReceivedPacketInfoConnectionIdEquals(original_connection_id))); ProcessReceivedPacket(std::move(packets[0]), client_address, version_, - server_connection_id); + original_connection_id); EXPECT_EQ(dispatcher_->NumSessions(), 0u) << "No session should be created before the rest of the CHLO arrives."; @@ -597,10 +608,10 @@ void QuicDispatcherTestBase::TestTlsMultiPacketClientHello( // Processing the second packet should create the new session. EXPECT_CALL( *dispatcher_, - CreateQuicSession(server_connection_id, _, client_address, + CreateQuicSession(new_connection_id, _, client_address, Eq(ExpectedAlpn()), _, Eq(ParsedClientHelloForTest()))) .WillOnce(Return(ByMove(CreateSession( - dispatcher_.get(), config_, server_connection_id, client_address, + dispatcher_.get(), config_, new_connection_id, client_address, &mock_helper_, &mock_alarm_factory_, &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)))); EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), @@ -608,16 +619,29 @@ void QuicDispatcherTestBase::TestTlsMultiPacketClientHello( .Times(2); ProcessReceivedPacket(std::move(packets[1]), client_address, version_, - server_connection_id); + original_connection_id); EXPECT_EQ(dispatcher_->NumSessions(), 1u); } TEST_P(QuicDispatcherTestAllVersions, TlsMultiPacketClientHello) { - TestTlsMultiPacketClientHello(/*add_reordering=*/false); + TestTlsMultiPacketClientHello(/*add_reordering=*/false, + /*long_connection_id=*/false); } TEST_P(QuicDispatcherTestAllVersions, TlsMultiPacketClientHelloWithReordering) { - TestTlsMultiPacketClientHello(/*add_reordering=*/true); + TestTlsMultiPacketClientHello(/*add_reordering=*/true, + /*long_connection_id=*/false); +} + +TEST_P(QuicDispatcherTestAllVersions, TlsMultiPacketClientHelloWithLongId) { + TestTlsMultiPacketClientHello(/*add_reordering=*/false, + /*long_connection_id=*/true); +} + +TEST_P(QuicDispatcherTestAllVersions, + TlsMultiPacketClientHelloWithReorderingAndLongId) { + TestTlsMultiPacketClientHello(/*add_reordering=*/true, + /*long_connection_id=*/true); } TEST_P(QuicDispatcherTestAllVersions, LegacyVersionEncapsulation) { @@ -979,15 +1003,10 @@ TEST_P(QuicDispatcherTestAllVersions, LimitResetsToSameClientAddress) { QuicSocketAddress client_address3(QuicIpAddress::Loopback6(), 1); QuicConnectionId connection_id = TestConnectionId(1); - if (GetQuicRestartFlag(quic_use_recent_reset_addresses)) { - // Verify only one reset is sent to the address, although multiple packets - // are received. - EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _)) - .Times(1); - } else { - EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _)) - .Times(3); - } + // Verify only one reset is sent to the address, although multiple packets + // are received. + EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _)) + .Times(1); ProcessPacket(client_address, connection_id, /*has_version_flag=*/false, "data"); ProcessPacket(client_address, connection_id, /*has_version_flag=*/false, @@ -1024,43 +1043,25 @@ TEST_P(QuicDispatcherTestAllVersions, const QuicTime expected_deadline = mock_helper_.GetClock()->Now() + QuicTime::Delta::FromMilliseconds(kTestLifeTimeMs); - if (GetQuicRestartFlag(quic_use_recent_reset_addresses)) { - ASSERT_TRUE(GetClearResetAddressesAlarm()->IsSet()); - EXPECT_EQ(expected_deadline, GetClearResetAddressesAlarm()->deadline()); - } else { - EXPECT_FALSE(GetClearResetAddressesAlarm()->IsSet()); - } + ASSERT_TRUE(GetClearResetAddressesAlarm()->IsSet()); + EXPECT_EQ(expected_deadline, GetClearResetAddressesAlarm()->deadline()); // Received no version packet 2 after 5ms. mock_helper_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); ProcessPacket(client_address2, connection_id, /*has_version_flag=*/false, "data"); - if (GetQuicRestartFlag(quic_use_recent_reset_addresses)) { - ASSERT_TRUE(GetClearResetAddressesAlarm()->IsSet()); - // Verify deadline does not change. - EXPECT_EQ(expected_deadline, GetClearResetAddressesAlarm()->deadline()); - } else { - EXPECT_FALSE(GetClearResetAddressesAlarm()->IsSet()); - } - if (GetQuicRestartFlag(quic_use_recent_reset_addresses)) { - // Verify reset gets throttled since there are too many recent addresses. - EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _)) - .Times(0); - } else { - EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _)) - .Times(1); - } + ASSERT_TRUE(GetClearResetAddressesAlarm()->IsSet()); + // Verify deadline does not change. + EXPECT_EQ(expected_deadline, GetClearResetAddressesAlarm()->deadline()); + // Verify reset gets throttled since there are too many recent addresses. + EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _)) + .Times(0); ProcessPacket(client_address3, connection_id, /*has_version_flag=*/false, "data"); mock_helper_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); - if (GetQuicRestartFlag(quic_use_recent_reset_addresses)) { - GetClearResetAddressesAlarm()->Fire(); - EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _)) - .Times(2); - } else { - EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _)) - .Times(3); - } + GetClearResetAddressesAlarm()->Fire(); + EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _)) + .Times(2); ProcessPacket(client_address, connection_id, /*has_version_flag=*/false, "data"); ProcessPacket(client_address2, connection_id, /*has_version_flag=*/false, @@ -2161,20 +2162,23 @@ TEST_P(QuicDispatcherWriteBlockedListTest, PerConnectionWriterBlocked) { TEST_P(QuicDispatcherWriteBlockedListTest, RemoveConnectionFromWriteBlockedListWhenDeletingSessions) { - dispatcher_->OnConnectionClosed(connection1()->connection_id(), - QUIC_PACKET_WRITE_ERROR, "Closed by test.", - ConnectionCloseSource::FROM_SELF); - - SetBlocked(); - - ASSERT_FALSE(dispatcher_->HasPendingWrites()); - SetBlocked(); - dispatcher_->OnWriteBlocked(connection1()); - ASSERT_TRUE(dispatcher_->HasPendingWrites()); - - EXPECT_QUIC_BUG(dispatcher_->DeleteSessions(), - "QuicConnection was in WriteBlockedList before destruction"); - MarkSession1Deleted(); + EXPECT_QUIC_BUG( + { + dispatcher_->OnConnectionClosed( + connection1()->connection_id(), QUIC_PACKET_WRITE_ERROR, + "Closed by test.", ConnectionCloseSource::FROM_SELF); + + SetBlocked(); + + ASSERT_FALSE(dispatcher_->HasPendingWrites()); + SetBlocked(); + dispatcher_->OnWriteBlocked(connection1()); + ASSERT_TRUE(dispatcher_->HasPendingWrites()); + + dispatcher_->DeleteSessions(); + MarkSession1Deleted(); + }, + "QuicConnection was in WriteBlockedList before destruction"); } class QuicDispatcherSupportMultipleConnectionIdPerConnectionTest diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_epoll_clock_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_epoll_clock_test.cc index e501fc41b65..617230f9c93 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_epoll_clock_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_epoll_clock_test.cc @@ -44,70 +44,6 @@ TEST_F(QuicEpollClockTest, NowInUsec) { EXPECT_EQ(1000005, (clock.Now() - QuicTime::Zero()).ToMicroseconds()); } -TEST_F(QuicEpollClockTest, CalibrateRealEpollClock) { - QuicEpollServer epoll_server; - - QuicEpollClock uncalibrated_clock(&epoll_server); - QuicEpollClock calibrated_clock(&epoll_server); - EXPECT_TRUE(calibrated_clock.ComputeCalibrationOffset().IsZero()); - - for (int i = 0; i < 100; ++i) { - QuicWallTime wallnow = uncalibrated_clock.WallNow(); - EXPECT_EQ(uncalibrated_clock.ConvertWallTimeToQuicTime(wallnow), - calibrated_clock.ConvertWallTimeToQuicTime(wallnow)); - } -} - -// ClockWithOffset is a clock whose offset(WallNow() - Now() at any instant) is -// given at construction time. -class ClockWithOffset : public QuicEpollClock { - public: - ClockWithOffset(QuicEpollServer* epoll_server, QuicTime::Delta offset) - : QuicEpollClock(epoll_server), offset_(offset) {} - - QuicTime Now() const override { return QuicEpollClock::Now() - offset_; } - - // QuicEpollClock disables ConvertWallTimeToQuicTime since it always have a - // zero offset. We need to re-enable it here in order to test the calibration - // and conversion code in QuicClock. - QuicTime ConvertWallTimeToQuicTime( - const QuicWallTime& walltime) const override { - return QuicClock::ConvertWallTimeToQuicTime(walltime); - } - - private: - QuicTime::Delta offset_; -}; - -TEST_F(QuicEpollClockTest, CalibrateClockWithOffset) { - QuicEpollServer epoll_server; - - for (const QuicTime::Delta& offset : {QuicTime::Delta::FromSeconds(5000), - QuicTime::Delta::FromSeconds(-8000)}) { - ClockWithOffset clock(&epoll_server, offset); - ASSERT_EQ(offset, clock.ComputeCalibrationOffset()) - << "offset (us): " << offset.ToMicroseconds(); - // Test fails without this. - clock.SetCalibrationOffset(offset); - - QuicWallTime last_walltime = clock.WallNow(); - QuicTime last_time = clock.ConvertWallTimeToQuicTime(last_walltime); - - for (int i = 0; i < 1e5; ++i) { - QuicWallTime wallnow = clock.WallNow(); - QuicTime now = clock.ConvertWallTimeToQuicTime(wallnow); - - if (wallnow.IsAfter(last_walltime)) { - ASSERT_LT(0, (now - last_time).ToMicroseconds()) - << "offset (us): " << offset.ToMicroseconds(); - - last_walltime = wallnow; - last_time = now; - } - } - } -} - TEST_F(QuicEpollClockTest, MonotonicityWithRealEpollClock) { QuicEpollServer epoll_server; QuicEpollClock clock(&epoll_server); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_epoll_connection_helper.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_epoll_connection_helper.h index a4247709ab3..dfc26491def 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_epoll_connection_helper.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_epoll_connection_helper.h @@ -19,7 +19,7 @@ #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/platform/api/quic_epoll.h" -#include "quiche/quic/platform/api/quic_stream_buffer_allocator.h" +#include "quiche/common/platform/api/quiche_stream_buffer_allocator.h" #include "quiche/common/simple_buffer_allocator.h" namespace quic { @@ -48,7 +48,7 @@ class QUIC_EXPORT_PRIVATE QuicEpollConnectionHelper QuicRandom* random_generator_; // Set up allocators. They take up minimal memory before use. // Allocator for stream send buffers. - QuicStreamBufferAllocator stream_buffer_allocator_; + quiche::QuicheStreamBufferAllocator stream_buffer_allocator_; quiche::SimpleBufferAllocator simple_buffer_allocator_; QuicAllocator allocator_type_; }; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h index 12cac822d2b..0fbff267b5b 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h @@ -6,121 +6,109 @@ #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) +QUIC_FLAG(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) +QUIC_FLAG(quic_reloadable_flag_quic_testonly_default_false, false) // A testonly reloadable flag that will always default to true. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_testonly_default_true, true) +QUIC_FLAG(quic_reloadable_flag_quic_testonly_default_true, true) // A testonly restart flag that will always default to false. -QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_false, false) +QUIC_FLAG(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) +QUIC_FLAG(quic_restart_flag_quic_testonly_default_true, 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) QUIC connections will use a lower minimum for trusted initial rtt, 2) When TRTT is received, QUIC server sessions will mark the initial rtt from CachedNetworkParameters as trusted. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_lower_min_for_trusted_irtt, true) -// If true, QUIC connection will be closed if it fails to serialize a coalesced packet. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_close_connection_if_fail_to_serialzie_coalesced_packet2, true) +QUIC_FLAG(quic_reloadable_flag_quic_bbr2_no_probe_up_exit_if_no_queue, 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) +QUIC_FLAG(quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false) // 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. -QUIC_FLAG(FLAGS_quic_restart_flag_quic_tls_server_support_client_cert, true) +QUIC_FLAG(quic_restart_flag_quic_support_release_time_for_gso, false) +// If true, TlsHandshaker::AdvanceHandshake will check if connection is closed after SSL_do_handshake. +QUIC_FLAG(quic_reloadable_flag_quic_tls_handshaker_check_connection_closed, 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) +QUIC_FLAG(quic_reloadable_flag_quic_abort_qpack_on_stream_reset, 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) +QUIC_FLAG(quic_reloadable_flag_quic_can_send_ack_frequency, true) // If true, allow client to enable BBRv2 on server via connection option \'B2ON\'. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allow_client_enabled_bbr_v2, true) +QUIC_FLAG(quic_reloadable_flag_quic_allow_client_enabled_bbr_v2, true) // If true, close read side but not write side in QuicSpdyStream::OnStreamReset(). -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_on_stream_reset, true) -// If true, consolidate more logic into SetRetransmissionAlarm to ensure the logic is applied consistently. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_simplify_set_retransmission_alarm, true) -// If true, default on PTO which unifies TLP + RTO loss recovery. -QUIC_FLAG(FLAGS_quic_restart_flag_quic_default_on_pto2, true) +QUIC_FLAG(quic_reloadable_flag_quic_fix_on_stream_reset, true) +// If true, close the connection if a crypto send buffer exceeds its size limit. +QUIC_FLAG(quic_reloadable_flag_quic_bounded_crypto_send_buffer, false) +// If true, consider original connection ID as active before handshake completes. +QUIC_FLAG(quic_reloadable_flag_quic_consider_original_connection_id_as_active_pre_handshake, true) // If true, default-enable 5RTO blachole detection. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true) +QUIC_FLAG(quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true) +// If true, deliver INITIAL packets before other types of packets in QuicBufferedPacketStore. +QUIC_FLAG(quic_reloadable_flag_quic_deliver_initial_packets_first, true) // If true, disable QUIC version Q043. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q043, false) +QUIC_FLAG(quic_reloadable_flag_quic_disable_version_q043, false) // If true, disable QUIC version Q046. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q046, false) +QUIC_FLAG(quic_reloadable_flag_quic_disable_version_q046, false) // If true, disable QUIC version Q050. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q050, false) +QUIC_FLAG(quic_reloadable_flag_quic_disable_version_q050, false) // If true, disable QUIC version h3 (RFCv1). -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_rfcv1, false) +QUIC_FLAG(quic_reloadable_flag_quic_disable_version_rfcv1, false) // If true, disable QUIC version h3-29. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_draft_29, false) +QUIC_FLAG(quic_reloadable_flag_quic_disable_version_draft_29, false) // If true, disable blackhole detection on server side. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_server_blackhole_detection, false) +QUIC_FLAG(quic_reloadable_flag_quic_disable_server_blackhole_detection, false) +// If true, disable resumption when receiving NRES connection option. +QUIC_FLAG(quic_reloadable_flag_quic_enable_disable_resumption, true) // If true, discard INITIAL packet if the key has been dropped. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_discard_initial_packet_with_key_dropped, 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) +QUIC_FLAG(quic_reloadable_flag_quic_discard_initial_packet_with_key_dropped, true) +// If true, do not bundle ACK while sending PATH_CHALLENGE on alternative path. +QUIC_FLAG(quic_reloadable_flag_quic_not_bundle_ack_on_alternative_path, 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 creator after coalesce packet of higher space. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_flush_after_coalesce_higher_space_packets, true) +QUIC_FLAG(quic_reloadable_flag_quic_enable_server_on_wire_ping, true) // If true, flush pending frames as well as pending padding bytes on connection migration. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_flush_pending_frames_and_padding_bytes_on_migration, true) +QUIC_FLAG(quic_reloadable_flag_quic_flush_pending_frames_and_padding_bytes_on_migration, true) // If true, ietf connection migration is no longer conditioned on connection option RVCM. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_remove_connection_migration_connection_option_v2, false) -// If true, ignore incoming MAX_PUSH_ID frames (expect for enforcing frame type rules). -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ignore_max_push_id, true) +QUIC_FLAG(quic_reloadable_flag_quic_remove_connection_migration_connection_option_v2, false) +// If true, include offset in QUIC STREAM_DATA_BLOCKED and DATA_BLOCKED frames. +QUIC_FLAG(quic_reloadable_flag_quic_include_offset_in_blocked_frames, false) // If true, include stream information in idle timeout connection close detail. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true) -// If true, limit the size of HPACK encoder dynamic table to 16 kB. Only affects gQUIC; QPACK encoder dynamic table size used in IETF QUIC is already bounded. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_limit_encoder_dynamic_table_size, true) +QUIC_FLAG(quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true) // If true, quic server will send ENABLE_CONNECT_PROTOCOL setting and and endpoint will validate required request/response headers and extended CONNECT mechanism and update code counts of valid/invalid headers. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_verify_request_headers_2, true) -// If true, record addresses that server has sent reset to recently, and do not send reset if the address lives in the set. -QUIC_FLAG(FLAGS_quic_restart_flag_quic_use_recent_reset_addresses, true) +QUIC_FLAG(quic_reloadable_flag_quic_verify_request_headers_2, true) // If true, reject or send error response code upon receiving invalid request or response headers. This flag depends on --gfe2_reloadable_flag_quic_verify_request_headers_2. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_act_upon_invalid_header, false) +QUIC_FLAG(quic_reloadable_flag_quic_act_upon_invalid_header, false) // If true, require handshake confirmation for QUIC connections, functionally disabling 0-rtt handshakes. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_require_handshake_confirmation, false) +QUIC_FLAG(quic_reloadable_flag_quic_require_handshake_confirmation, false) // 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, true) -// If true, servers drop received packets with changed server address. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_drop_packets_with_changed_server_address, true) +QUIC_FLAG(quic_reloadable_flag_quic_retire_cid_on_reverse_path_validation_failure, true) +// If true, server sends bandwidth eastimate when network is idle for a while. +QUIC_FLAG(quic_restart_flag_quic_enable_sending_bandwidth_estimate_when_network_idle, true) // If true, set burst token to 2 in cwnd bootstrapping experiment. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_bursts, false) +QUIC_FLAG(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, update ACK timeout based on packet receipt time rather than now. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_update_ack_timeout_on_receipt_time, true) +QUIC_FLAG(quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time, false) // 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) +QUIC_FLAG(quic_reloadable_flag_quic_default_to_bbr_v2, false) +// If true, use PING manager to manage the PING alarm. +QUIC_FLAG(quic_reloadable_flag_quic_use_ping_manager2, true) // If true, use new connection ID in connection migration. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2, true) +QUIC_FLAG(quic_reloadable_flag_quic_connection_migration_use_new_cid_v2, true) // If true, uses conservative cwnd gain and pacing gain when cwnd gets bootstrapped. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false) -// If true, validate that peer owns the new address once the server detects peer migration or is probed from that address, and also apply anti-amplification limit while sending to that address. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path3, true) -// If true, when a packet is forced retransmitted, only set packet state if all data gets retransmitted. -QUIC_FLAG(FLAGS_quic_restart_flag_quic_set_packet_state_if_all_data_retransmitted, true) +QUIC_FLAG(quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false) // 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) +QUIC_FLAG(quic_reloadable_flag_quic_bbr2_startup_probe_up_loss_events, true) // When true, defaults to BBR congestion control instead of Cubic. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr, false) +QUIC_FLAG(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, true) +QUIC_FLAG(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) +QUIC_FLAG(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) +QUIC_FLAG(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) +QUIC_FLAG(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. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_startup_extra_acked, true) +QUIC_FLAG(quic_reloadable_flag_quic_bbr2_startup_extra_acked, true) // When true, the B207 connection option causes BBR2 to exit STARTUP if a persistent queue of 2*BDP has existed for the entire round. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_exit_startup_on_persistent_queue2, true) +QUIC_FLAG(quic_reloadable_flag_quic_bbr2_exit_startup_on_persistent_queue2, true) // When true, the BBQ0 connection option causes QUIC BBR2 to add bytes_acked to probe_up_acked if the connection hasn\'t been app-limited since inflight_hi was utilized. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_add_bytes_acked_after_inflight_hi_limited, true) +QUIC_FLAG(quic_reloadable_flag_quic_bbr2_add_bytes_acked_after_inflight_hi_limited, true) // When true, the BBR4 copt sets the extra_acked window to 20 RTTs and BBR5 sets it to 40 RTTs. -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_extra_acked_window, true) +QUIC_FLAG(quic_reloadable_flag_quic_bbr2_extra_acked_window, true) #endif diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.cc index 47d3c28cf03..4acdd513f3f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.cc @@ -232,10 +232,10 @@ void QuicFlowController::UpdateReceiveWindowOffsetAndSendWindowUpdate( SendWindowUpdate(); } -bool QuicFlowController::ShouldSendBlocked() { +void QuicFlowController::MaybeSendBlocked() { if (SendWindowSize() != 0 || last_blocked_send_window_offset_ >= send_window_offset_) { - return false; + return; } QUIC_DLOG(INFO) << ENDPOINT << LogLabel() << " is flow control blocked. " << "Send window: " << SendWindowSize() @@ -247,7 +247,7 @@ bool QuicFlowController::ShouldSendBlocked() { // Keep track of when we last sent a BLOCKED frame so that we only send one // at a given send offset. last_blocked_send_window_offset_ = send_window_offset_; - return true; + session_->SendBlocked(id_, last_blocked_send_window_offset_); } bool QuicFlowController::UpdateSendWindowOffset( diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.h index 7f68ff5c44c..eaf660a8d2f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.h @@ -78,8 +78,8 @@ class QUIC_EXPORT_PRIVATE QuicFlowController QuicByteCount receive_window_size() const { return receive_window_size_; } - // Returns whether a BLOCKED frame should be sent. - bool ShouldSendBlocked(); + // Sends a BLOCKED frame if needed. + void MaybeSendBlocked(); // Returns true if flow control send limits have been reached. bool IsBlocked() const; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller_test.cc index 20cb5994489..567b120e682 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller_test.cc @@ -18,6 +18,7 @@ using testing::_; using testing::Invoke; +using testing::StrictMock; namespace quic { namespace test { @@ -43,7 +44,7 @@ class QuicFlowControllerTest : public QuicTest { connection_->SetEncrypter( ENCRYPTION_FORWARD_SECURE, std::make_unique<NullEncrypter>(connection_->perspective())); - session_ = std::make_unique<MockQuicSession>(connection_); + session_ = std::make_unique<StrictMock<MockQuicSession>>(connection_); flow_controller_ = std::make_unique<QuicFlowController>( session_.get(), stream_id_, /*is_connection_flow_controller*/ false, send_window_, receive_window_, kStreamReceiveWindowLimit, @@ -58,7 +59,7 @@ class QuicFlowControllerTest : public QuicTest { MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; MockQuicConnection* connection_; - std::unique_ptr<MockQuicSession> session_; + std::unique_ptr<StrictMock<MockQuicSession>> session_; MockFlowController session_flow_controller_; bool should_auto_tune_receive_window_ = false; }; @@ -81,7 +82,8 @@ TEST_F(QuicFlowControllerTest, SendingBytes) { EXPECT_EQ(0u, flow_controller_->SendWindowSize()); // BLOCKED frame should get sent. - EXPECT_TRUE(flow_controller_->ShouldSendBlocked()); + EXPECT_CALL(*session_, SendBlocked(_, _)).Times(1); + flow_controller_->MaybeSendBlocked(); // Update the send window, and verify this has unblocked. EXPECT_TRUE(flow_controller_->UpdateSendWindowOffset(2 * send_window_)); @@ -93,13 +95,16 @@ TEST_F(QuicFlowControllerTest, SendingBytes) { EXPECT_EQ(send_window_, flow_controller_->SendWindowSize()); // Try to send more bytes, violating flow control. - EXPECT_CALL(*connection_, - CloseConnection(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA, _, _)); EXPECT_QUIC_BUG( - flow_controller_->AddBytesSent(send_window_ * 10), + { + EXPECT_CALL( + *connection_, + CloseConnection(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA, _, _)); + flow_controller_->AddBytesSent(send_window_ * 10); + EXPECT_TRUE(flow_controller_->IsBlocked()); + EXPECT_EQ(0u, flow_controller_->SendWindowSize()); + }, absl::StrCat("Trying to send an extra ", send_window_ * 10, " bytes")); - EXPECT_TRUE(flow_controller_->IsBlocked()); - EXPECT_EQ(0u, flow_controller_->SendWindowSize()); } TEST_F(QuicFlowControllerTest, ReceivingBytes) { @@ -164,14 +169,16 @@ TEST_F(QuicFlowControllerTest, OnlySendBlockedFrameOncePerOffset) { EXPECT_EQ(0u, flow_controller_->SendWindowSize()); // BLOCKED frame should get sent. - EXPECT_TRUE(flow_controller_->ShouldSendBlocked()); + EXPECT_CALL(*session_, SendBlocked(_, _)).Times(1); + flow_controller_->MaybeSendBlocked(); // BLOCKED frame should not get sent again until our send offset changes. - EXPECT_FALSE(flow_controller_->ShouldSendBlocked()); - EXPECT_FALSE(flow_controller_->ShouldSendBlocked()); - EXPECT_FALSE(flow_controller_->ShouldSendBlocked()); - EXPECT_FALSE(flow_controller_->ShouldSendBlocked()); - EXPECT_FALSE(flow_controller_->ShouldSendBlocked()); + EXPECT_CALL(*session_, SendBlocked(_, _)).Times(0); + flow_controller_->MaybeSendBlocked(); + flow_controller_->MaybeSendBlocked(); + flow_controller_->MaybeSendBlocked(); + flow_controller_->MaybeSendBlocked(); + flow_controller_->MaybeSendBlocked(); // Update the send window, then send enough bytes to block again. EXPECT_TRUE(flow_controller_->UpdateSendWindowOffset(2 * send_window_)); @@ -182,7 +189,8 @@ TEST_F(QuicFlowControllerTest, OnlySendBlockedFrameOncePerOffset) { EXPECT_EQ(0u, flow_controller_->SendWindowSize()); // BLOCKED frame should get sent as send offset has changed. - EXPECT_TRUE(flow_controller_->ShouldSendBlocked()); + EXPECT_CALL(*session_, SendBlocked(_, _)).Times(1); + flow_controller_->MaybeSendBlocked(); } TEST_F(QuicFlowControllerTest, ReceivingBytesFastIncreasesFlowWindow) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc index b0f5018b40b..b6b0c5bab51 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc @@ -3121,6 +3121,8 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader, // static bool QuicFramer::IsIetfFrameTypeExpectedForEncryptionLevel( uint64_t frame_type, EncryptionLevel level) { + // IETF_CRYPTO is allowed for any level here and is separately checked in + // QuicCryptoStream::OnCryptoFrame. switch (level) { case ENCRYPTION_INITIAL: case ENCRYPTION_HANDSHAKE: @@ -3132,7 +3134,7 @@ bool QuicFramer::IsIetfFrameTypeExpectedForEncryptionLevel( case ENCRYPTION_ZERO_RTT: return !(frame_type == IETF_ACK || frame_type == IETF_ACK_ECN || frame_type == IETF_ACK_RECEIVE_TIMESTAMPS || - frame_type == IETF_CRYPTO || frame_type == IETF_HANDSHAKE_DONE || + frame_type == IETF_HANDSHAKE_DONE || frame_type == IETF_NEW_TOKEN || frame_type == IETF_PATH_RESPONSE || frame_type == IETF_RETIRE_CONNECTION_ID); @@ -5699,7 +5701,7 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame, ++num_ack_blocks_written; } if (num_ack_blocks_written >= num_ack_blocks) { - if (QUIC_PREDICT_FALSE(num_ack_blocks_written != num_ack_blocks)) { + if (ABSL_PREDICT_FALSE(num_ack_blocks_written != num_ack_blocks)) { QUIC_BUG(quic_bug_10850_85) << "Wrote " << num_ack_blocks_written << ", expected to write " << num_ack_blocks; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_framer_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_framer_test.cc index 77515102a35..9b022a2eff5 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_framer_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_framer_test.cc @@ -10446,11 +10446,14 @@ TEST_P(QuicFramerTest, EncryptEmptyPacket) { /*retry_token_length=*/0, VARIABLE_LENGTH_INTEGER_LENGTH_0); char buffer[kMaxOutgoingPacketSize]; size_t encrypted_length = 1; - EXPECT_QUIC_BUG(encrypted_length = framer_.EncryptPayload( - ENCRYPTION_INITIAL, kPacketNumber, *packet, buffer, - kMaxOutgoingPacketSize), - "packet is shorter than associated data length"); - EXPECT_EQ(0u, encrypted_length); + EXPECT_QUIC_BUG( + { + encrypted_length = + framer_.EncryptPayload(ENCRYPTION_INITIAL, kPacketNumber, *packet, + buffer, kMaxOutgoingPacketSize); + EXPECT_EQ(0u, encrypted_length); + }, + "packet is shorter than associated data length"); } TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector.cc index edb54836703..a5bd8ad208f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector.cc @@ -5,7 +5,10 @@ #include "quiche/quic/core/quic_idle_network_detector.h" #include "quiche/quic/core/quic_constants.h" +#include "quiche/quic/core/quic_time.h" #include "quiche/quic/platform/api/quic_flag_utils.h" +#include "quiche/quic/platform/api/quic_flags.h" +#include "quiche/common/platform/api/quiche_logging.h" namespace quic { @@ -36,10 +39,18 @@ QuicIdleNetworkDetector::QuicIdleNetworkDetector( time_of_last_received_packet_(now), time_of_first_packet_sent_after_receiving_(QuicTime::Zero()), idle_network_timeout_(QuicTime::Delta::Infinite()), + bandwidth_update_timeout_(QuicTime::Delta::Infinite()), alarm_(alarm_factory->CreateAlarm( arena->New<AlarmDelegate>(this, context), arena)) {} void QuicIdleNetworkDetector::OnAlarm() { + if (!bandwidth_update_timeout_.IsInfinite()) { + QUICHE_DCHECK(handshake_timeout_.IsInfinite()); + bandwidth_update_timeout_ = QuicTime::Delta::Infinite(); + SetAlarm(); + delegate_->OnBandwidthUpdateTimeout(); + return; + } if (handshake_timeout_.IsInfinite()) { delegate_->OnIdleNetworkDetected(); return; @@ -60,6 +71,15 @@ void QuicIdleNetworkDetector::SetTimeouts( QuicTime::Delta handshake_timeout, QuicTime::Delta idle_network_timeout) { handshake_timeout_ = handshake_timeout; idle_network_timeout_ = idle_network_timeout; + bandwidth_update_timeout_ = QuicTime::Delta::Infinite(); + + if (GetQuicRestartFlag( + quic_enable_sending_bandwidth_estimate_when_network_idle) && + handshake_timeout_.IsInfinite()) { + QUIC_RESTART_FLAG_COUNT_N( + quic_enable_sending_bandwidth_estimate_when_network_idle, 1, 3); + bandwidth_update_timeout_ = idle_network_timeout_ * 0.5; + } SetAlarm(); } @@ -68,6 +88,7 @@ void QuicIdleNetworkDetector::StopDetection() { alarm_->PermanentCancel(); handshake_timeout_ = QuicTime::Delta::Infinite(); idle_network_timeout_ = QuicTime::Delta::Infinite(); + handshake_timeout_ = QuicTime::Delta::Infinite(); stopped_ = true; } @@ -115,6 +136,9 @@ void QuicIdleNetworkDetector::SetAlarm() { new_deadline = idle_network_deadline; } } + if (!bandwidth_update_timeout_.IsInfinite()) { + new_deadline = std::min(new_deadline, GetBandwidthUpdateDeadline()); + } alarm_->Update(new_deadline, kAlarmGranularity); } @@ -141,4 +165,9 @@ QuicTime QuicIdleNetworkDetector::GetIdleNetworkDeadline() const { return last_network_activity_time() + idle_network_timeout_; } +QuicTime QuicIdleNetworkDetector::GetBandwidthUpdateDeadline() const { + QUICHE_DCHECK(!bandwidth_update_timeout_.IsInfinite()); + return last_network_activity_time() + bandwidth_update_timeout_; +} + } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector.h index 0b5a20e1639..ca431482545 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector.h @@ -34,6 +34,9 @@ class QUIC_EXPORT_PRIVATE QuicIdleNetworkDetector { // Called when idle network has been detected. virtual void OnIdleNetworkDetected() = 0; + + // Called when bandwidth update alarms. + virtual void OnBandwidthUpdateTimeout() = 0; }; QuicIdleNetworkDetector(Delegate* delegate, QuicTime now, @@ -73,6 +76,10 @@ class QUIC_EXPORT_PRIVATE QuicIdleNetworkDetector { QuicTime::Delta idle_network_timeout() const { return idle_network_timeout_; } + QuicTime::Delta bandwidth_update_timeout() const { + return bandwidth_update_timeout_; + } + QuicTime GetIdleNetworkDeadline() const; private: @@ -83,13 +90,15 @@ class QUIC_EXPORT_PRIVATE QuicIdleNetworkDetector { void MaybeSetAlarmOnSentPacket(QuicTime::Delta pto_delay); + QuicTime GetBandwidthUpdateDeadline() const; + Delegate* delegate_; // Not owned. // Start time of the detector, handshake deadline = start_time_ + // handshake_timeout_. const QuicTime start_time_; - // Handshake timeout. Infinit means handshake has completed. + // Handshake timeout. Infinite means handshake has completed. QuicTime::Delta handshake_timeout_; // Time that last packet is received for this connection. Initialized to @@ -102,9 +111,12 @@ class QUIC_EXPORT_PRIVATE QuicIdleNetworkDetector { // Initialized to 0. QuicTime time_of_first_packet_sent_after_receiving_; - // Idle network timeout. Infinit means no idle network timeout. + // Idle network timeout. Infinite means no idle network timeout. QuicTime::Delta idle_network_timeout_; + // Bandwidth update timeout. Infinite means no bandwidth update timeout. + QuicTime::Delta bandwidth_update_timeout_; + QuicArenaScopedPtr<QuicAlarm> alarm_; bool shorter_idle_timeout_on_sent_packet_ = false; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector_test.cc index 31aa8b490ba..9105ec9e4ae 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector_test.cc @@ -5,7 +5,9 @@ #include "quiche/quic/core/quic_idle_network_detector.h" #include "quiche/quic/core/quic_one_block_arena.h" +#include "quiche/quic/core/quic_time.h" #include "quiche/quic/platform/api/quic_expect_bug.h" +#include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/test_tools/quic_test_utils.h" @@ -25,6 +27,7 @@ class MockDelegate : public QuicIdleNetworkDetector::Delegate { public: MOCK_METHOD(void, OnHandshakeTimeout, (), (override)); MOCK_METHOD(void, OnIdleNetworkDetected, (), (override)); + MOCK_METHOD(void, OnBandwidthUpdateTimeout, (), (override)); }; class QuicIdleNetworkDetectorTest : public QuicTest { @@ -90,6 +93,8 @@ TEST_F(QuicIdleNetworkDetectorTest, /*handshake_timeout=*/QuicTime::Delta::FromSeconds(30), /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(20)); EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(20), + alarm_->deadline()); // Handshake completes in 200ms. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(200)); @@ -97,11 +102,30 @@ TEST_F(QuicIdleNetworkDetectorTest, detector_->SetTimeouts( /*handshake_timeout=*/QuicTime::Delta::Infinite(), /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(600)); - EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(600), + if (!GetQuicRestartFlag( + quic_enable_sending_bandwidth_estimate_when_network_idle)) { + EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(600), + alarm_->deadline()); + + // No network activity for 600s. + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(600)); + EXPECT_CALL(delegate_, OnIdleNetworkDetected()); + alarm_->Fire(); + return; + } + + EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(300), + alarm_->deadline()); + + // No network activity for 300s. + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(300)); + EXPECT_CALL(delegate_, OnBandwidthUpdateTimeout()); + alarm_->Fire(); + EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(300), alarm_->deadline()); // No network activity for 600s. - clock_.AdvanceTime(QuicTime::Delta::FromSeconds(600)); + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(300)); EXPECT_CALL(delegate_, OnIdleNetworkDetected()); alarm_->Fire(); } @@ -115,11 +139,16 @@ TEST_F(QuicIdleNetworkDetectorTest, EXPECT_TRUE(alarm_->IsSet()); // Handshake completes in 200ms. + const bool enable_sending_bandwidth_estimate_when_network_idle = + GetQuicRestartFlag( + quic_enable_sending_bandwidth_estimate_when_network_idle); clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(200)); detector_->OnPacketReceived(clock_.Now()); detector_->SetTimeouts( /*handshake_timeout=*/QuicTime::Delta::Infinite(), - /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(600)); + enable_sending_bandwidth_estimate_when_network_idle + ? QuicTime::Delta::FromSeconds(1200) + : QuicTime::Delta::FromSeconds(600)); EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(600), alarm_->deadline()); @@ -133,22 +162,46 @@ TEST_F(QuicIdleNetworkDetectorTest, // Sent another packet after 200ms clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(200)); detector_->OnPacketSent(clock_.Now(), QuicTime::Delta::Zero()); - // Verify idle network deadline does not extend. + // Verify network deadline does not extend. EXPECT_EQ(packet_sent_time + QuicTime::Delta::FromSeconds(600), alarm_->deadline()); - // No network activity for 600s. + if (!enable_sending_bandwidth_estimate_when_network_idle) { + // No network activity for 600s. + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(600) - + QuicTime::Delta::FromMilliseconds(200)); + EXPECT_CALL(delegate_, OnIdleNetworkDetected()); + alarm_->Fire(); + return; + } + + // Bandwidth update times out after no network activity for 600s. clock_.AdvanceTime(QuicTime::Delta::FromSeconds(600) - QuicTime::Delta::FromMilliseconds(200)); + EXPECT_CALL(delegate_, OnBandwidthUpdateTimeout()); + alarm_->Fire(); + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(packet_sent_time + QuicTime::Delta::FromSeconds(1200), + alarm_->deadline()); + + // Network idle time out after no network activity for 1200s. + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1200) - + QuicTime::Delta::FromMilliseconds(600)); EXPECT_CALL(delegate_, OnIdleNetworkDetected()); alarm_->Fire(); } TEST_F(QuicIdleNetworkDetectorTest, ShorterIdleTimeoutOnSentPacket) { detector_->enable_shorter_idle_timeout_on_sent_packet(); + QuicTime::Delta idle_network_timeout = QuicTime::Delta::Zero(); + if (GetQuicRestartFlag( + quic_enable_sending_bandwidth_estimate_when_network_idle)) { + idle_network_timeout = QuicTime::Delta::FromSeconds(60); + } else { + idle_network_timeout = QuicTime::Delta::FromSeconds(30); + } detector_->SetTimeouts( - /*handshake_timeout=*/QuicTime::Delta::Infinite(), - /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(30)); + /*handshake_timeout=*/QuicTime::Delta::Infinite(), idle_network_timeout); EXPECT_TRUE(alarm_->IsSet()); const QuicTime deadline = alarm_->deadline(); EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(30), deadline); @@ -175,7 +228,7 @@ TEST_F(QuicIdleNetworkDetectorTest, ShorterIdleTimeoutOnSentPacket) { EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(30), alarm_->deadline()); - // Send a packet near timeout.. + // Send a packet near timeout. clock_.AdvanceTime(QuicTime::Delta::FromSeconds(29)); detector_->OnPacketSent(clock_.Now(), QuicTime::Delta::FromSeconds(2)); EXPECT_TRUE(alarm_->IsSet()); @@ -194,6 +247,35 @@ TEST_F(QuicIdleNetworkDetectorTest, NoAlarmAfterStopped) { EXPECT_FALSE(alarm_->IsSet()); } +TEST_F(QuicIdleNetworkDetectorTest, + ResetBandwidthTimeoutWhenHandshakeTimeoutIsSet) { + if (!GetQuicRestartFlag( + quic_enable_sending_bandwidth_estimate_when_network_idle)) { + return; + } + detector_->SetTimeouts( + /*handshake_timeout=*/QuicTime::Delta::Infinite(), + /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(20)); + // The deadline is set based on the bandwidth timeout. + EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(10), + alarm_->deadline()); + + detector_->SetTimeouts( + /*handshake_timeout=*/QuicTime::Delta::FromSeconds(15), + /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(20)); + // Bandwidth timeout is reset and the deadline is set based on the handshake + // timeout. + EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(15), + alarm_->deadline()); + + detector_->SetTimeouts( + /*handshake_timeout=*/QuicTime::Delta::Infinite(), + /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(20)); + // The deadline is set based on the bandwidth timeout. + EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(10), + alarm_->deadline()); +} + } // namespace } // namespace test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_interval_deque.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_interval_deque.h index eff9f63a4db..ed13e7a44df 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_interval_deque.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_interval_deque.h @@ -137,7 +137,7 @@ class QuicIntervalDequePeer; // // cached_index -> 1 // // container -> {{2, [25, 30)}, {3, [35, 50)}} -template <class T, class C = QUIC_NO_EXPORT quiche::QuicheCircularDeque<T>> +template <class T, class C = quiche::QuicheCircularDeque<T>> class QUIC_NO_EXPORT QuicIntervalDeque { public: class QUIC_NO_EXPORT Iterator { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_interval_set.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_interval_set.h index 7e2b11bda6d..7de036219e1 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_interval_set.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_interval_set.h @@ -60,8 +60,8 @@ #include <vector> #include "quiche/quic/core/quic_interval.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_logging.h" +#include "quiche/common/platform/api/quiche_containers.h" namespace quic { @@ -85,7 +85,7 @@ class QUIC_NO_EXPORT QuicIntervalSet { bool operator()(T&& point, const value_type& a) const; }; - using Set = QuicSmallOrderedSet<value_type, IntervalLess>; + using Set = quiche::QuicheSmallOrderedSet<value_type, IntervalLess>; public: using const_iterator = typename Set::const_iterator; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_one_block_arena.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_one_block_arena.h index 4bebebea565..cb44217b034 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_one_block_arena.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_one_block_arena.h @@ -12,6 +12,7 @@ #include <cstdint> +#include "absl/base/optimization.h" #include "quiche/quic/core/quic_arena_scoped_ptr.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" @@ -37,7 +38,7 @@ class QUIC_EXPORT_PRIVATE QuicOneBlockArena { << "Object is too large for the arena."; static_assert(alignof(T) > 1, "Objects added to the arena must be at least 2B aligned."); - if (QUIC_PREDICT_FALSE(offset_ > ArenaSize - AlignedSize<T>())) { + if (ABSL_PREDICT_FALSE(offset_ > ArenaSize - AlignedSize<T>())) { QUIC_BUG(quic_bug_10593_1) << "Ran out of space in QuicOneBlockArena at " << this << ", max size was " << ArenaSize << ", failing request was " @@ -69,7 +70,7 @@ class QUIC_EXPORT_PRIVATE QuicOneBlockArena { // QuicConnections currently use around 1KB of polymorphic types which would // ordinarily be on the heap. Instead, store them inline in an arena. -using QuicConnectionArena = QuicOneBlockArena<1152>; +using QuicConnectionArena = QuicOneBlockArena<1280>; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_one_block_arena_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_one_block_arena_test.cc index 89c774d2955..5c1079b7730 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_one_block_arena_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_one_block_arena_test.cc @@ -6,12 +6,11 @@ #include <cstdint> -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_expect_bug.h" #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/test_tools/quic_test_utils.h" -namespace quic { +namespace quic::test { namespace { static const uint32_t kMaxAlign = 8; @@ -57,4 +56,4 @@ TEST_F(QuicOneBlockArenaTest, NoOverlaps) { } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.cc index c84556ceb66..66c7d14f94a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.cc @@ -511,8 +511,7 @@ size_t QuicPacketCreator::ReserializeInitialPacketInCoalescedPacket( << "Attempt to serialize empty ENCRYPTION_INITIAL packet in coalesced " "packet"; - if (close_connection_if_fail_to_serialzie_coalesced_packet_ && - HasPendingFrames()) { + if (HasPendingFrames()) { QUIC_BUG(quic_packet_creator_unexpected_queued_frames) << "Unexpected queued frames: " << GetPendingFramesInfo(); return 0; @@ -549,15 +548,8 @@ size_t QuicPacketCreator::ReserializeInitialPacketInCoalescedPacket( } } - if (close_connection_if_fail_to_serialzie_coalesced_packet_) { - QUIC_RELOADABLE_FLAG_COUNT_N( - quic_close_connection_if_fail_to_serialzie_coalesced_packet2, 1, 2); - } - - if (!SerializePacket( - QuicOwnedPacketBuffer(buffer, nullptr), buffer_len, - /*allow_padding=*/ - !close_connection_if_fail_to_serialzie_coalesced_packet_)) { + if (!SerializePacket(QuicOwnedPacketBuffer(buffer, nullptr), buffer_len, + /*allow_padding=*/false)) { return 0; } const size_t encrypted_length = packet_.encrypted_length; @@ -1883,10 +1875,6 @@ void QuicPacketCreator::MaybeAddPadding() { return; } - if (packet_.transmission_type == PROBING_RETRANSMISSION) { - needs_full_padding_ = true; - } - if (packet_.fate == COALESCE || packet_.fate == LEGACY_VERSION_ENCAPSULATE) { // Do not add full padding if the packet is going to be coalesced or // encapsulated. @@ -2084,7 +2072,7 @@ size_t QuicPacketCreator::MinPlaintextPacketSize( // 1.3 is used, unittests still use NullEncrypter/NullDecrypter (and other // test crypters) which also only use 12 byte tags. // - // TODO(nharper): Set this based on the handshake protocol in use. + // TODO(b/234061734): Set this based on the handshake protocol in use. return 7; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.h index bc792e17afb..51446ba3e0d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.h @@ -485,10 +485,6 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator { const QuicSocketAddress& peer_address() const { return packet_.peer_address; } - bool close_connection_if_fail_to_serialzie_coalesced_packet() const { - return close_connection_if_fail_to_serialzie_coalesced_packet_; - } - private: friend class test::QuicPacketCreatorPeer; @@ -692,10 +688,6 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator { // Whether to attempt protecting initial packets with chaos. bool chaos_protection_enabled_; - - const bool close_connection_if_fail_to_serialzie_coalesced_packet_ = - GetQuicReloadableFlag( - quic_close_connection_if_fail_to_serialzie_coalesced_packet2); }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator_test.cc index b2233268982..c9f8ecccfe4 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator_test.cc @@ -1549,11 +1549,13 @@ TEST_P(QuicPacketCreatorTest, AddUnencryptedStreamDataClosesConnection) { } creator_.set_encryption_level(ENCRYPTION_INITIAL); - EXPECT_CALL(delegate_, OnUnrecoverableError(_, _)); QuicStreamFrame stream_frame(GetNthClientInitiatedStreamId(0), /*fin=*/false, 0u, absl::string_view()); EXPECT_QUIC_BUG( - creator_.AddFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION), + { + EXPECT_CALL(delegate_, OnUnrecoverableError(_, _)); + creator_.AddFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION); + }, "Cannot send stream data with level: ENCRYPTION_INITIAL"); } @@ -1564,11 +1566,13 @@ TEST_P(QuicPacketCreatorTest, SendStreamDataWithEncryptionHandshake) { } creator_.set_encryption_level(ENCRYPTION_HANDSHAKE); - EXPECT_CALL(delegate_, OnUnrecoverableError(_, _)); QuicStreamFrame stream_frame(GetNthClientInitiatedStreamId(0), /*fin=*/false, 0u, absl::string_view()); EXPECT_QUIC_BUG( - creator_.AddFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION), + { + EXPECT_CALL(delegate_, OnUnrecoverableError(_, _)); + creator_.AddFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION); + }, "Cannot send stream data with level: ENCRYPTION_HANDSHAKE"); } @@ -1932,16 +1936,16 @@ TEST_P(QuicPacketCreatorTest, PacketTransmissionType) { EXPECT_TRUE(creator_.AddFrame(ack_frame, LOSS_RETRANSMISSION)); ASSERT_EQ(serialized_packet_, nullptr); - EXPECT_TRUE(creator_.AddFrame(stream_frame, RTO_RETRANSMISSION)); + EXPECT_TRUE(creator_.AddFrame(stream_frame, PTO_RETRANSMISSION)); ASSERT_EQ(serialized_packet_, nullptr); - EXPECT_TRUE(creator_.AddFrame(padding_frame, TLP_RETRANSMISSION)); + EXPECT_TRUE(creator_.AddFrame(padding_frame, LOSS_RETRANSMISSION)); creator_.FlushCurrentPacket(); ASSERT_TRUE(serialized_packet_->encrypted_buffer); // The last retransmittable frame on packet is a stream frame, the packet's // transmission type should be the same as the stream frame's. - EXPECT_EQ(serialized_packet_->transmission_type, RTO_RETRANSMISSION); + EXPECT_EQ(serialized_packet_->transmission_type, PTO_RETRANSMISSION); DeleteSerializedPacket(); } @@ -2563,12 +2567,15 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest, delegate_.SetCanWriteAnything(); const std::string data(10000, '?'); EXPECT_CALL(delegate_, OnSerializedPacket(_)).Times(0); - EXPECT_CALL(delegate_, OnUnrecoverableError(_, _)); - EXPECT_QUIC_BUG(creator_.ConsumeDataFastPath( - QuicUtils::GetFirstBidirectionalStreamId( - framer_.transport_version(), Perspective::IS_CLIENT), - data), - ""); + EXPECT_QUIC_BUG( + { + EXPECT_CALL(delegate_, OnUnrecoverableError(_, _)); + creator_.ConsumeDataFastPath( + QuicUtils::GetFirstBidirectionalStreamId( + framer_.transport_version(), Perspective::IS_CLIENT), + data); + }, + ""); } TEST_F(QuicPacketCreatorMultiplePacketsTest, AddControlFrame_OnlyAckWritable) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.cc new file mode 100644 index 00000000000..da7c42305c1 --- /dev/null +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.cc @@ -0,0 +1,162 @@ +// 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. + +#include "quiche/quic/core/quic_ping_manager.h" + +namespace quic { + +namespace { + +// Maximum shift used to calculate retransmittable on wire timeout. For 200ms +// initial retransmittable on wire delay, this would get a maximum of 200ms * (1 +// << 10) = 204.8s +const int kMaxRetransmittableOnWireDelayShift = 10; + +class AlarmDelegate : public QuicAlarm::DelegateWithContext { + public: + explicit AlarmDelegate(QuicPingManager* manager, + QuicConnectionContext* context) + : QuicAlarm::DelegateWithContext(context), manager_(manager) {} + AlarmDelegate(const AlarmDelegate&) = delete; + AlarmDelegate& operator=(const AlarmDelegate&) = delete; + + void OnAlarm() override { manager_->OnAlarm(); } + + private: + QuicPingManager* manager_; +}; + +} // namespace + +QuicPingManager::QuicPingManager(Perspective perspective, Delegate* delegate, + QuicConnectionArena* arena, + QuicAlarmFactory* alarm_factory, + QuicConnectionContext* context) + : perspective_(perspective), + delegate_(delegate), + alarm_(alarm_factory->CreateAlarm( + arena->New<AlarmDelegate>(this, context), arena)) {} + +void QuicPingManager::SetAlarm(QuicTime now, bool should_keep_alive, + bool has_in_flight_packets) { + UpdateDeadlines(now, should_keep_alive, has_in_flight_packets); + const QuicTime earliest_deadline = GetEarliestDeadline(); + if (!earliest_deadline.IsInitialized()) { + alarm_->Cancel(); + return; + } + if (earliest_deadline == keep_alive_deadline_) { + // Use 1s granularity for keep-alive time. + alarm_->Update(earliest_deadline, QuicTime::Delta::FromSeconds(1)); + return; + } + alarm_->Update(earliest_deadline, kAlarmGranularity); +} + +void QuicPingManager::OnAlarm() { + const QuicTime earliest_deadline = GetEarliestDeadline(); + if (!earliest_deadline.IsInitialized()) { + QUIC_BUG(quic_ping_manager_alarm_fires_unexpectedly) + << "QuicPingManager alarm fires unexpectedly."; + return; + } + // Please note, alarm does not get re-armed here, and we are relying on caller + // to SetAlarm later. + if (earliest_deadline == retransmittable_on_wire_deadline_) { + retransmittable_on_wire_deadline_ = QuicTime::Zero(); + if (GetQuicFlag( + FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count) != + 0) { + ++consecutive_retransmittable_on_wire_count_; + } + ++retransmittable_on_wire_count_; + delegate_->OnRetransmittableOnWireTimeout(); + return; + } + if (earliest_deadline == keep_alive_deadline_) { + keep_alive_deadline_ = QuicTime::Zero(); + delegate_->OnKeepAliveTimeout(); + } +} + +void QuicPingManager::Stop() { + alarm_->PermanentCancel(); + retransmittable_on_wire_deadline_ = QuicTime::Zero(); + keep_alive_deadline_ = QuicTime::Zero(); +} + +void QuicPingManager::UpdateDeadlines(QuicTime now, bool should_keep_alive, + bool has_in_flight_packets) { + // Reset keep-alive deadline given it will be set later (with left edge + // |now|). + keep_alive_deadline_ = QuicTime::Zero(); + if (perspective_ == Perspective::IS_SERVER && + initial_retransmittable_on_wire_timeout_.IsInfinite()) { + // The PING alarm exists to support two features: + // 1) clients send PINGs every 15s to prevent NAT timeouts, + // 2) both clients and servers can send retransmittable on the wire PINGs + // (ROWP) while ShouldKeepConnectionAlive is true and there is no packets in + // flight. + QUICHE_DCHECK(!retransmittable_on_wire_deadline_.IsInitialized()); + return; + } + if (!should_keep_alive) { + // Don't send a ping unless the application (ie: HTTP/3) says to, usually + // because it is expecting a response from the peer. + retransmittable_on_wire_deadline_ = QuicTime::Zero(); + return; + } + if (perspective_ == Perspective::IS_CLIENT) { + // Clients send 15s PINGs to avoid NATs from timing out. + keep_alive_deadline_ = now + keep_alive_timeout_; + } + if (initial_retransmittable_on_wire_timeout_.IsInfinite() || + has_in_flight_packets || + retransmittable_on_wire_count_ > + GetQuicFlag(FLAGS_quic_max_retransmittable_on_wire_ping_count)) { + // No need to set retransmittable-on-wire timeout. + retransmittable_on_wire_deadline_ = QuicTime::Zero(); + return; + } + + QUICHE_DCHECK_LT(initial_retransmittable_on_wire_timeout_, + keep_alive_timeout_); + QuicTime::Delta retransmittable_on_wire_timeout = + initial_retransmittable_on_wire_timeout_; + const int max_aggressive_retransmittable_on_wire_count = + GetQuicFlag(FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count); + QUICHE_DCHECK_LE(0, max_aggressive_retransmittable_on_wire_count); + if (consecutive_retransmittable_on_wire_count_ > + max_aggressive_retransmittable_on_wire_count) { + // Exponentially back off the timeout if the number of consecutive + // retransmittable on wire pings has exceeds the allowance. + int shift = std::min(consecutive_retransmittable_on_wire_count_ - + max_aggressive_retransmittable_on_wire_count, + kMaxRetransmittableOnWireDelayShift); + retransmittable_on_wire_timeout = + initial_retransmittable_on_wire_timeout_ * (1 << shift); + } + if (retransmittable_on_wire_deadline_.IsInitialized() && + retransmittable_on_wire_deadline_ < + now + retransmittable_on_wire_timeout) { + // Alarm is set to an earlier time. Do not postpone it. + return; + } + retransmittable_on_wire_deadline_ = now + retransmittable_on_wire_timeout; +} + +QuicTime QuicPingManager::GetEarliestDeadline() const { + QuicTime earliest_deadline = QuicTime::Zero(); + for (QuicTime t : {retransmittable_on_wire_deadline_, keep_alive_deadline_}) { + if (!t.IsInitialized()) { + continue; + } + if (!earliest_deadline.IsInitialized() || t < earliest_deadline) { + earliest_deadline = t; + } + } + return earliest_deadline; +} + +} // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.h new file mode 100644 index 00000000000..d88dac26f36 --- /dev/null +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.h @@ -0,0 +1,108 @@ +// 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. + +#ifndef QUICHE_QUIC_CORE_QUIC_PING_MANAGER_H_ +#define QUICHE_QUIC_CORE_QUIC_PING_MANAGER_H_ + +#include "quiche/quic/core/quic_alarm.h" +#include "quiche/quic/core/quic_alarm_factory.h" +#include "quiche/quic/core/quic_constants.h" +#include "quiche/quic/core/quic_one_block_arena.h" +#include "quiche/quic/core/quic_time.h" +#include "quiche/quic/platform/api/quic_export.h" + +namespace quic { + +namespace test { +class QuicConnectionPeer; +class QuicPingManagerPeer; +} // namespace test + +// QuicPingManager manages an alarm that has two modes: +// 1) keep-alive. When alarm fires, send packet to extend idle timeout to keep +// connection alive. +// 2) retransmittable-on-wire. When alarm fires, send packets to detect path +// degrading (used in IP/port migrations). +class QUIC_EXPORT_PRIVATE QuicPingManager { + public: + // Interface that get notified when |alarm_| fires. + class QUIC_EXPORT_PRIVATE Delegate { + public: + virtual ~Delegate() {} + + // Called when alarm fires in keep-alive mode. + virtual void OnKeepAliveTimeout() = 0; + // Called when alarm fires in retransmittable-on-wire mode. + virtual void OnRetransmittableOnWireTimeout() = 0; + }; + + QuicPingManager(Perspective perspective, Delegate* delegate, + QuicConnectionArena* arena, QuicAlarmFactory* alarm_factory, + QuicConnectionContext* context); + + // Called to set |alarm_|. + void SetAlarm(QuicTime now, bool should_keep_alive, + bool has_in_flight_packets); + + // Called when |alarm_| fires. + void OnAlarm(); + + // Called to stop |alarm_| permanently. + void Stop(); + + void set_keep_alive_timeout(QuicTime::Delta keep_alive_timeout) { + QUICHE_DCHECK(!alarm_->IsSet()); + keep_alive_timeout_ = keep_alive_timeout; + } + + void set_initial_retransmittable_on_wire_timeout( + QuicTime::Delta retransmittable_on_wire_timeout) { + QUICHE_DCHECK(!alarm_->IsSet()); + initial_retransmittable_on_wire_timeout_ = retransmittable_on_wire_timeout; + } + + void reset_consecutive_retransmittable_on_wire_count() { + consecutive_retransmittable_on_wire_count_ = 0; + } + + private: + friend class test::QuicConnectionPeer; + friend class test::QuicPingManagerPeer; + + // Update |retransmittable_on_wire_deadline_| and |keep_alive_deadline_|. + void UpdateDeadlines(QuicTime now, bool should_keep_alive, + bool has_in_flight_packets); + + // Get earliest deadline of |retransmittable_on_wire_deadline_| and + // |keep_alive_deadline_|. Returns 0 if both deadlines are not initialized. + QuicTime GetEarliestDeadline() const; + + Perspective perspective_; + + Delegate* delegate_; // Not owned. + + // Initial timeout for how long the wire can have no retransmittable packets. + QuicTime::Delta initial_retransmittable_on_wire_timeout_ = + QuicTime::Delta::Infinite(); + + // Indicates how many consecutive retransmittable-on-wire has been armed + // (since last reset). + int consecutive_retransmittable_on_wire_count_ = 0; + + // Indicates how many retransmittable-on-wire has been armed in total. + int retransmittable_on_wire_count_ = 0; + + QuicTime::Delta keep_alive_timeout_ = + QuicTime::Delta::FromSeconds(kPingTimeoutSecs); + + QuicTime retransmittable_on_wire_deadline_ = QuicTime::Zero(); + + QuicTime keep_alive_deadline_ = QuicTime::Zero(); + + QuicArenaScopedPtr<QuicAlarm> alarm_; +}; + +} // namespace quic + +#endif // QUICHE_QUIC_CORE_QUIC_PING_MANAGER_H_ diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager_test.cc new file mode 100644 index 00000000000..509022b6181 --- /dev/null +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_ping_manager_test.cc @@ -0,0 +1,429 @@ +// 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. + +#include "quiche/quic/core/quic_ping_manager.h" + +#include "quiche/quic/core/quic_one_block_arena.h" +#include "quiche/quic/platform/api/quic_test.h" +#include "quiche/quic/test_tools/quic_test_utils.h" + +namespace quic { +namespace test { + +class QuicPingManagerPeer { + public: + static QuicAlarm* GetAlarm(QuicPingManager* manager) { + return manager->alarm_.get(); + } + + static void SetPerspective(QuicPingManager* manager, + Perspective perspective) { + manager->perspective_ = perspective; + } +}; + +namespace { + +const bool kShouldKeepAlive = true; +const bool kHasInflightPackets = true; + +class MockDelegate : public QuicPingManager::Delegate { + public: + MOCK_METHOD(void, OnKeepAliveTimeout, (), (override)); + MOCK_METHOD(void, OnRetransmittableOnWireTimeout, (), (override)); +}; + +class QuicPingManagerTest : public QuicTest { + public: + QuicPingManagerTest() + : manager_(Perspective::IS_CLIENT, &delegate_, &arena_, &alarm_factory_, + /*context=*/nullptr), + alarm_(static_cast<MockAlarmFactory::TestAlarm*>( + QuicPingManagerPeer::GetAlarm(&manager_))) { + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); + } + + protected: + testing::StrictMock<MockDelegate> delegate_; + MockClock clock_; + QuicConnectionArena arena_; + MockAlarmFactory alarm_factory_; + QuicPingManager manager_; + MockAlarmFactory::TestAlarm* alarm_; +}; + +TEST_F(QuicPingManagerTest, KeepAliveTimeout) { + EXPECT_FALSE(alarm_->IsSet()); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + // Set alarm with in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), + alarm_->deadline() - clock_.ApproximateNow()); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + // Reset alarm with no in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + // Verify the deadline is set slightly less than 15 seconds in the future, + // because of the 1s alarm granularity. + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs) - + QuicTime::Delta::FromMilliseconds(5), + alarm_->deadline() - clock_.ApproximateNow()); + + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(kPingTimeoutSecs)); + EXPECT_CALL(delegate_, OnKeepAliveTimeout()); + alarm_->Fire(); + EXPECT_FALSE(alarm_->IsSet()); + // Reset alarm with in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + + // Verify alarm is not armed if !kShouldKeepAlive. + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + manager_.SetAlarm(clock_.ApproximateNow(), !kShouldKeepAlive, + kHasInflightPackets); + EXPECT_FALSE(alarm_->IsSet()); +} + +TEST_F(QuicPingManagerTest, CustomizedKeepAliveTimeout) { + EXPECT_FALSE(alarm_->IsSet()); + + // Set customized keep-alive timeout. + manager_.set_keep_alive_timeout(QuicTime::Delta::FromSeconds(10)); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + // Set alarm with in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(QuicTime::Delta::FromSeconds(10), + alarm_->deadline() - clock_.ApproximateNow()); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + // Set alarm with no in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + // The deadline is set slightly less than 10 seconds in the future, because + // of the 1s alarm granularity. + EXPECT_EQ( + QuicTime::Delta::FromSeconds(10) - QuicTime::Delta::FromMilliseconds(5), + alarm_->deadline() - clock_.ApproximateNow()); + + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10)); + EXPECT_CALL(delegate_, OnKeepAliveTimeout()); + alarm_->Fire(); + EXPECT_FALSE(alarm_->IsSet()); + // Reset alarm with in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + + // Verify alarm is not armed if !kShouldKeepAlive. + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + manager_.SetAlarm(clock_.ApproximateNow(), !kShouldKeepAlive, + kHasInflightPackets); + EXPECT_FALSE(alarm_->IsSet()); +} + +TEST_F(QuicPingManagerTest, RetransmittableOnWireTimeout) { + const QuicTime::Delta kRtransmittableOnWireTimeout = + QuicTime::Delta::FromMilliseconds(50); + manager_.set_initial_retransmittable_on_wire_timeout( + kRtransmittableOnWireTimeout); + + EXPECT_FALSE(alarm_->IsSet()); + + // Set alarm with in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + // Verify alarm is in keep-alive mode. + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), + alarm_->deadline() - clock_.ApproximateNow()); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + // Set alarm with no in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + // Verify alarm is in retransmittable-on-wire mode. + EXPECT_EQ(kRtransmittableOnWireTimeout, + alarm_->deadline() - clock_.ApproximateNow()); + + clock_.AdvanceTime(kRtransmittableOnWireTimeout); + EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout()); + alarm_->Fire(); + EXPECT_FALSE(alarm_->IsSet()); + // Reset alarm with in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + // Verify the alarm is in keep-alive mode. + ASSERT_TRUE(alarm_->IsSet()); + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), + alarm_->deadline() - clock_.ApproximateNow()); +} + +TEST_F(QuicPingManagerTest, RetransmittableOnWireTimeoutExponentiallyBackOff) { + const int kMaxAggressiveRetransmittableOnWireCount = 5; + SetQuicFlag(FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count, + kMaxAggressiveRetransmittableOnWireCount); + const QuicTime::Delta initial_retransmittable_on_wire_timeout = + QuicTime::Delta::FromMilliseconds(200); + manager_.set_initial_retransmittable_on_wire_timeout( + initial_retransmittable_on_wire_timeout); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + EXPECT_FALSE(alarm_->IsSet()); + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + // Verify alarm is in keep-alive mode. + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), + alarm_->deadline() - clock_.ApproximateNow()); + + // Verify no exponential backoff on the first few retransmittable on wire + // timeouts. + for (int i = 0; i <= kMaxAggressiveRetransmittableOnWireCount; ++i) { + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + // Reset alarm with no in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + // Verify alarm is in retransmittable-on-wire mode. + EXPECT_EQ(initial_retransmittable_on_wire_timeout, + alarm_->deadline() - clock_.ApproximateNow()); + clock_.AdvanceTime(initial_retransmittable_on_wire_timeout); + EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout()); + alarm_->Fire(); + EXPECT_FALSE(alarm_->IsSet()); + // Reset alarm with in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + } + + QuicTime::Delta retransmittable_on_wire_timeout = + initial_retransmittable_on_wire_timeout; + + // Verify subsequent retransmittable-on-wire timeout is exponentially backed + // off. + while (retransmittable_on_wire_timeout * 2 < + QuicTime::Delta::FromSeconds(kPingTimeoutSecs)) { + retransmittable_on_wire_timeout = retransmittable_on_wire_timeout * 2; + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(retransmittable_on_wire_timeout, + alarm_->deadline() - clock_.ApproximateNow()); + + clock_.AdvanceTime(retransmittable_on_wire_timeout); + EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout()); + alarm_->Fire(); + EXPECT_FALSE(alarm_->IsSet()); + // Reset alarm with in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + } + + // Verify alarm is in keep-alive mode. + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), + alarm_->deadline() - clock_.ApproximateNow()); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + // Reset alarm with no in flight packets + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + // Verify alarm is in keep-alive mode because retransmittable-on-wire deadline + // is later. + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs) - + QuicTime::Delta::FromMilliseconds(5), + alarm_->deadline() - clock_.ApproximateNow()); + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(kPingTimeoutSecs) - + QuicTime::Delta::FromMilliseconds(5)); + EXPECT_CALL(delegate_, OnKeepAliveTimeout()); + alarm_->Fire(); + EXPECT_FALSE(alarm_->IsSet()); +} + +TEST_F(QuicPingManagerTest, + ResetRetransmitableOnWireTimeoutExponentiallyBackOff) { + const int kMaxAggressiveRetransmittableOnWireCount = 3; + SetQuicFlag(FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count, + kMaxAggressiveRetransmittableOnWireCount); + const QuicTime::Delta initial_retransmittable_on_wire_timeout = + QuicTime::Delta::FromMilliseconds(200); + manager_.set_initial_retransmittable_on_wire_timeout( + initial_retransmittable_on_wire_timeout); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + EXPECT_FALSE(alarm_->IsSet()); + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + // Verify alarm is in keep-alive mode. + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), + alarm_->deadline() - clock_.ApproximateNow()); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + // Verify alarm is in retransmittable-on-wire mode. + EXPECT_EQ(initial_retransmittable_on_wire_timeout, + alarm_->deadline() - clock_.ApproximateNow()); + + EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout()); + clock_.AdvanceTime(initial_retransmittable_on_wire_timeout); + alarm_->Fire(); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(initial_retransmittable_on_wire_timeout, + alarm_->deadline() - clock_.ApproximateNow()); + + manager_.reset_consecutive_retransmittable_on_wire_count(); + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_EQ(initial_retransmittable_on_wire_timeout, + alarm_->deadline() - clock_.ApproximateNow()); + EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout()); + clock_.AdvanceTime(initial_retransmittable_on_wire_timeout); + alarm_->Fire(); + + for (int i = 0; i < kMaxAggressiveRetransmittableOnWireCount; i++) { + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(initial_retransmittable_on_wire_timeout, + alarm_->deadline() - clock_.ApproximateNow()); + clock_.AdvanceTime(initial_retransmittable_on_wire_timeout); + EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout()); + alarm_->Fire(); + // Reset alarm with in flight packets. + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + // Advance 5ms to receive next packet. + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + } + + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(initial_retransmittable_on_wire_timeout * 2, + alarm_->deadline() - clock_.ApproximateNow()); + + clock_.AdvanceTime(2 * initial_retransmittable_on_wire_timeout); + EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout()); + alarm_->Fire(); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + manager_.reset_consecutive_retransmittable_on_wire_count(); + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(initial_retransmittable_on_wire_timeout, + alarm_->deadline() - clock_.ApproximateNow()); +} + +TEST_F(QuicPingManagerTest, RetransmittableOnWireLimit) { + static constexpr int kMaxRetransmittableOnWirePingCount = 3; + SetQuicFlag(FLAGS_quic_max_retransmittable_on_wire_ping_count, + kMaxRetransmittableOnWirePingCount); + static constexpr QuicTime::Delta initial_retransmittable_on_wire_timeout = + QuicTime::Delta::FromMilliseconds(200); + static constexpr QuicTime::Delta kShortDelay = + QuicTime::Delta::FromMilliseconds(5); + ASSERT_LT(kShortDelay * 10, initial_retransmittable_on_wire_timeout); + manager_.set_initial_retransmittable_on_wire_timeout( + initial_retransmittable_on_wire_timeout); + + clock_.AdvanceTime(kShortDelay); + EXPECT_FALSE(alarm_->IsSet()); + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), + alarm_->deadline() - clock_.ApproximateNow()); + + for (int i = 0; i <= kMaxRetransmittableOnWirePingCount; i++) { + clock_.AdvanceTime(kShortDelay); + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(initial_retransmittable_on_wire_timeout, + alarm_->deadline() - clock_.ApproximateNow()); + clock_.AdvanceTime(initial_retransmittable_on_wire_timeout); + EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout()); + alarm_->Fire(); + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + } + + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + // Verify alarm is in keep-alive mode. + EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), + alarm_->deadline() - clock_.ApproximateNow()); + clock_.AdvanceTime(QuicTime::Delta::FromSeconds(kPingTimeoutSecs)); + EXPECT_CALL(delegate_, OnKeepAliveTimeout()); + alarm_->Fire(); + EXPECT_FALSE(alarm_->IsSet()); +} + +TEST_F(QuicPingManagerTest, MaxRetransmittableOnWireDelayShift) { + QuicPingManagerPeer::SetPerspective(&manager_, Perspective::IS_SERVER); + const int kMaxAggressiveRetransmittableOnWireCount = 3; + SetQuicFlag(FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count, + kMaxAggressiveRetransmittableOnWireCount); + const QuicTime::Delta initial_retransmittable_on_wire_timeout = + QuicTime::Delta::FromMilliseconds(200); + manager_.set_initial_retransmittable_on_wire_timeout( + initial_retransmittable_on_wire_timeout); + + for (int i = 0; i <= kMaxAggressiveRetransmittableOnWireCount; i++) { + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + EXPECT_EQ(initial_retransmittable_on_wire_timeout, + alarm_->deadline() - clock_.ApproximateNow()); + clock_.AdvanceTime(initial_retransmittable_on_wire_timeout); + EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout()); + alarm_->Fire(); + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + kHasInflightPackets); + } + for (int i = 1; i <= 20; ++i) { + manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive, + !kHasInflightPackets); + EXPECT_TRUE(alarm_->IsSet()); + if (i <= 10) { + EXPECT_EQ(initial_retransmittable_on_wire_timeout * (1 << i), + alarm_->deadline() - clock_.ApproximateNow()); + } else { + // Verify shift is capped. + EXPECT_EQ(initial_retransmittable_on_wire_timeout * (1 << 10), + alarm_->deadline() - clock_.ApproximateNow()); + } + clock_.AdvanceTime(alarm_->deadline() - clock_.ApproximateNow()); + EXPECT_CALL(delegate_, OnRetransmittableOnWireTimeout()); + alarm_->Fire(); + } +} + +} // namespace + +} // namespace test +} // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc index 213f6ba59fc..bb7b87d349e 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc @@ -267,24 +267,9 @@ void QuicReceivedPacketManager::MaybeUpdateAckTimeout( return; } - QuicTime ack_timeout_base = now; - const bool quic_update_ack_timeout_on_receipt_time = - GetQuicReloadableFlag(quic_update_ack_timeout_on_receipt_time); - if (quic_update_ack_timeout_on_receipt_time) { - if (last_packet_receipt_time <= now) { - QUIC_CODE_COUNT(quic_update_ack_timeout_on_receipt_time); - ack_timeout_base = last_packet_receipt_time; - } else { - QUIC_CODE_COUNT(quic_update_ack_timeout_on_now); - ack_timeout_base = now; - } - } - QuicTime updated_ack_time = - ack_timeout_base + - GetMaxAckDelay(last_received_packet_number, *rtt_stats); - if (quic_update_ack_timeout_on_receipt_time) { - updated_ack_time = std::max(now, updated_ack_time); - } + const QuicTime updated_ack_time = std::max( + now, std::min(last_packet_receipt_time, now) + + GetMaxAckDelay(last_received_packet_number, *rtt_stats)); if (!ack_timeout_.IsInitialized() || ack_timeout_ > updated_ack_time) { ack_timeout_ = updated_ack_time; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager_test.cc index 65cfa867d53..c4537076a19 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager_test.cc @@ -650,13 +650,8 @@ TEST_F(QuicReceivedPacketManagerTest, UpdateAckTimeoutOnPacketReceiptTime) { kInstigateAck, QuicPacketNumber(3), /*last_packet_receipt_time=*/packet_receipt_time3, clock_.ApproximateNow(), &rtt_stats_); - if (GetQuicReloadableFlag(quic_update_ack_timeout_on_receipt_time)) { - // Make sure ACK timeout is based on receipt time. - CheckAckTimeout(packet_receipt_time3 + kDelayedAckTime); - } else { - // Make sure ACK timeout is based on now. - CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); - } + // Make sure ACK timeout is based on receipt time. + CheckAckTimeout(packet_receipt_time3 + kDelayedAckTime); RecordPacketReceipt(4, clock_.ApproximateNow()); MaybeUpdateAckTimeout(kInstigateAck, 4); @@ -677,13 +672,8 @@ TEST_F(QuicReceivedPacketManagerTest, kInstigateAck, QuicPacketNumber(3), /*last_packet_receipt_time=*/packet_receipt_time3, clock_.ApproximateNow(), &rtt_stats_); - if (GetQuicReloadableFlag(quic_update_ack_timeout_on_receipt_time)) { - // Given 100ms > ack delay, verify immediate ACK. - CheckAckTimeout(clock_.ApproximateNow()); - } else { - // Make sure ACK timeout is based on now. - CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime); - } + // Given 100ms > ack delay, verify immediate ACK. + CheckAckTimeout(clock_.ApproximateNow()); } } // namespace diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.cc index 47377e13a67..10835830bfb 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.cc @@ -30,13 +30,6 @@ namespace quic { namespace { static const int64_t kDefaultRetransmissionTimeMs = 500; -static const int64_t kMaxRetransmissionTimeMs = 60000; -// Maximum number of exponential backoffs used for RTO timeouts. -static const size_t kMaxRetransmissions = 10; -// Maximum number of packets retransmitted upon an RTO. -static const size_t kMaxRetransmissionsOnTimeout = 2; -// The path degrading delay is the sum of this number of consecutive RTO delays. -const size_t kNumRetransmissionDelaysForPathDegradingDelay = 2; // Ensure the handshake timer isnt't faster than 10ms. // This limits the tenth retransmitted packet to 10s after the initial CHLO. @@ -46,13 +39,14 @@ static const int64_t kMinHandshakeTimeoutMs = 10; // per draft RFC draft-dukkipati-tcpm-tcp-loss-probe. static const size_t kDefaultMaxTailLossProbes = 2; +// The multiplier for calculating PTO timeout before any RTT sample is +// available. +static const float kPtoMultiplierWithoutRttSamples = 3; + // Returns true of retransmissions of the specified type should retransmit // the frames directly (as opposed to resulting in a loss notification). inline bool ShouldForceRetransmission(TransmissionType transmission_type) { return transmission_type == HANDSHAKE_RETRANSMISSION || - transmission_type == TLP_RETRANSMISSION || - transmission_type == PROBING_RETRANSMISSION || - transmission_type == RTO_RETRANSMISSION || transmission_type == PTO_RETRANSMISSION; } @@ -81,56 +75,25 @@ QuicSentPacketManager::QuicSentPacketManager( network_change_visitor_(nullptr), initial_congestion_window_(kInitialCongestionWindow), loss_algorithm_(&uber_loss_algorithm_), - consecutive_rto_count_(0), - consecutive_tlp_count_(0), consecutive_crypto_retransmission_count_(0), pending_timer_transmission_count_(0), - max_tail_loss_probes_(kDefaultMaxTailLossProbes), - max_rto_packets_(kMaxRetransmissionsOnTimeout), using_pacing_(false), - use_new_rto_(false), conservative_handshake_retransmits_(false), - min_tlp_timeout_( - QuicTime::Delta::FromMilliseconds(kMinTailLossProbeTimeoutMs)), - min_rto_timeout_( - QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs)), largest_mtu_acked_(0), handshake_finished_(false), peer_max_ack_delay_( QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)), rtt_updated_(false), acked_packets_iter_(last_ack_frame_.packets.rbegin()), - pto_enabled_(GetQuicRestartFlag(quic_default_on_pto2)), - max_probe_packets_per_pto_(2), consecutive_pto_count_(0), handshake_mode_disabled_(false), - skip_packet_number_for_pto_(false), - always_include_max_ack_delay_for_pto_timeout_(true), - pto_exponential_backoff_start_point_(0), - pto_rttvar_multiplier_(4), - num_tlp_timeout_ptos_(0), handshake_packet_acked_(false), zero_rtt_packet_acked_(false), one_rtt_packet_acked_(false), - first_pto_srtt_multiplier_(0), - use_standard_deviation_for_pto_(false), - pto_multiplier_without_rtt_samples_(3), num_ptos_for_path_degrading_(kNumProbeTimeoutsForPathDegradingDelay), ignore_pings_(false), ignore_ack_delay_(false) { SetSendAlgorithm(congestion_control_type); - if (pto_enabled_) { - QUIC_RESTART_FLAG_COUNT_N(quic_default_on_pto2, 1, 2); - // TODO(fayang): change the default values when deprecating - // quic_default_on_pto2. - // Default to 1 packet per PTO and skip a packet number. Arm the 1st PTO - // with max of earliest in flight sent time + PTO delay and 1.5 * srtt from - // last in flight packet. - max_probe_packets_per_pto_ = 1; - skip_packet_number_for_pto_ = true; - first_pto_srtt_multiplier_ = 1.5; - pto_rttvar_multiplier_ = 2; - } } QuicSentPacketManager::~QuicSentPacketManager() {} @@ -167,82 +130,18 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) { if (config.HasClientSentConnectionOption(kMAD0, perspective)) { ignore_ack_delay_ = true; } - if (config.HasClientSentConnectionOption(kMAD2, perspective)) { - // Set the minimum to the alarm granularity. - min_tlp_timeout_ = kAlarmGranularity; + + if (config.HasClientRequestedIndependentOption(kPDP1, perspective)) { + num_ptos_for_path_degrading_ = 1; } - if (config.HasClientSentConnectionOption(kMAD3, perspective)) { - // Set the minimum to the alarm granularity. - min_rto_timeout_ = kAlarmGranularity; + if (config.HasClientRequestedIndependentOption(kPDP2, perspective)) { + num_ptos_for_path_degrading_ = 2; } - - if (!GetQuicRestartFlag(quic_default_on_pto2)) { - if (config.HasClientSentConnectionOption(k2PTO, perspective)) { - pto_enabled_ = true; - } - if (config.HasClientSentConnectionOption(k1PTO, perspective)) { - pto_enabled_ = true; - max_probe_packets_per_pto_ = 1; - } - - if (config.HasClientSentConnectionOption(kPTOS, perspective)) { - if (!pto_enabled_) { - QUIC_PEER_BUG(quic_peer_bug_12552_1) - << "PTO is not enabled when receiving PTOS connection option."; - pto_enabled_ = true; - max_probe_packets_per_pto_ = 1; - } - skip_packet_number_for_pto_ = true; - } - if (pto_enabled_) { - if (config.HasClientSentConnectionOption(kPTOA, perspective)) { - always_include_max_ack_delay_for_pto_timeout_ = false; - } - if (config.HasClientSentConnectionOption(kPEB1, perspective)) { - StartExponentialBackoffAfterNthPto(1); - } - if (config.HasClientSentConnectionOption(kPEB2, perspective)) { - StartExponentialBackoffAfterNthPto(2); - } - if (config.HasClientSentConnectionOption(kPVS1, perspective)) { - pto_rttvar_multiplier_ = 2; - } - if (config.HasClientSentConnectionOption(kPAG1, perspective)) { - QUIC_CODE_COUNT(one_aggressive_pto); - num_tlp_timeout_ptos_ = 1; - } - if (config.HasClientSentConnectionOption(kPAG2, perspective)) { - QUIC_CODE_COUNT(two_aggressive_ptos); - num_tlp_timeout_ptos_ = 2; - } - if (config.HasClientSentConnectionOption(kPLE1, perspective)) { - first_pto_srtt_multiplier_ = 0.5; - } else if (config.HasClientSentConnectionOption(kPLE2, perspective)) { - first_pto_srtt_multiplier_ = 1.5; - } - if (config.HasClientSentConnectionOption(kAPTO, perspective)) { - pto_multiplier_without_rtt_samples_ = 1.5; - } - if (config.HasClientSentConnectionOption(kPSDA, perspective)) { - use_standard_deviation_for_pto_ = true; - rtt_stats_.EnableStandardDeviationCalculation(); - } - } + if (config.HasClientRequestedIndependentOption(kPDP3, perspective)) { + num_ptos_for_path_degrading_ = 3; } - - if (pto_enabled_) { - if (config.HasClientRequestedIndependentOption(kPDP1, perspective)) { - num_ptos_for_path_degrading_ = 1; - } - if (config.HasClientRequestedIndependentOption(kPDP2, perspective)) { - num_ptos_for_path_degrading_ = 2; - } - if (config.HasClientRequestedIndependentOption(kPDP3, perspective)) { - num_ptos_for_path_degrading_ = 3; - } - if (config.HasClientRequestedIndependentOption(kPDP5, perspective)) { - num_ptos_for_path_degrading_ = 5; - } + if (config.HasClientRequestedIndependentOption(kPDP5, perspective)) { + num_ptos_for_path_degrading_ = 5; } // Configure congestion control. @@ -296,19 +195,6 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) { } using_pacing_ = !GetQuicFlag(FLAGS_quic_disable_pacing_for_perf_tests); - - if (config.HasClientSentConnectionOption(kNTLP, perspective)) { - max_tail_loss_probes_ = 0; - } - if (config.HasClientSentConnectionOption(k1TLP, perspective)) { - max_tail_loss_probes_ = 1; - } - if (config.HasClientSentConnectionOption(k1RTO, perspective)) { - max_rto_packets_ = 1; - } - if (config.HasClientSentConnectionOption(kNRTO, perspective)) { - use_new_rto_ = true; - } // Configure loss detection. if (config.HasClientRequestedIndependentOption(kILD0, perspective)) { uber_loss_algorithm_.SetReorderingShift(kDefaultIetfLossDelayShift); @@ -396,39 +282,21 @@ 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 (use_lower_min_irtt()) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_lower_min_for_trusted_irtt, 2, 2); - if (!rtt.IsZero()) { - if (params.is_rtt_trusted) { - // Always set initial rtt if it's trusted. - SetInitialRtt(rtt, /*trusted=*/true); - } else if (rtt_stats_.initial_rtt() == - QuicTime::Delta::FromMilliseconds(kInitialRttMs)) { - // Only set initial rtt if we are using the default. This avoids - // overwriting a trusted initial rtt by an untrusted one. - SetInitialRtt(rtt, /*trusted=*/false); - } - } - } else { - if (!rtt.IsZero()) { + if (!rtt.IsZero()) { + if (params.is_rtt_trusted) { + // Always set initial rtt if it's trusted. + SetInitialRtt(rtt, /*trusted=*/true); + } else if (rtt_stats_.initial_rtt() == + QuicTime::Delta::FromMilliseconds(kInitialRttMs)) { + // Only set initial rtt if we are using the default. This avoids + // overwriting a trusted initial rtt by an untrusted one. SetInitialRtt(rtt, /*trusted=*/false); } } + const QuicByteCount old_cwnd = send_algorithm_->GetCongestionWindow(); if (GetQuicReloadableFlag(quic_conservative_bursts) && using_pacing_ && !bandwidth.IsZero()) { @@ -470,10 +338,6 @@ void QuicSentPacketManager::PostProcessNewlyAckedPackets( unacked_packets_.NotifyAggregatedStreamFrameAcked( last_ack_frame_.ack_delay_time); InvokeLossDetection(ack_receive_time); - // Ignore losses in RTO mode. - if (consecutive_rto_count_ > 0 && !use_new_rto_) { - packets_lost_.clear(); - } MaybeInvokeCongestionEvent(rtt_updated, prior_bytes_in_flight, ack_receive_time); unacked_packets_.RemoveObsoletePackets(); @@ -486,33 +350,13 @@ void QuicSentPacketManager::PostProcessNewlyAckedPackets( // Anytime we are making forward progress and have a new RTT estimate, reset // the backoff counters. if (rtt_updated) { - if (consecutive_rto_count_ > 0) { - // If the ack acknowledges data sent prior to the RTO, - // the RTO was spurious. - if (LargestAcked(ack_frame) < first_rto_transmission_) { - // Replace SRTT with latest_rtt and increase the variance to prevent - // a spurious RTO from happening again. - rtt_stats_.ExpireSmoothedMetrics(); - } else { - if (!use_new_rto_) { - send_algorithm_->OnRetransmissionTimeout(true); - } - } - } - // Records the max consecutive RTO or PTO before forward progress has been - // made. - if (consecutive_rto_count_ > + // Records the max consecutive PTO before forward progress has been made. + if (consecutive_pto_count_ > stats_->max_consecutive_rto_with_forward_progress) { stats_->max_consecutive_rto_with_forward_progress = - consecutive_rto_count_; - } else if (consecutive_pto_count_ > - stats_->max_consecutive_rto_with_forward_progress) { - stats_->max_consecutive_rto_with_forward_progress = consecutive_pto_count_; } // Reset all retransmit counters any time a new packet is acked. - consecutive_rto_count_ = 0; - consecutive_tlp_count_ = 0; consecutive_pto_count_ = 0; consecutive_crypto_retransmission_count_ = 0; } @@ -619,39 +463,9 @@ void QuicSentPacketManager::NeuterHandshakePackets() { bool QuicSentPacketManager::ShouldAddMaxAckDelay( PacketNumberSpace space) const { - QUICHE_DCHECK(pto_enabled_); - if (supports_multiple_packet_number_spaces() && space != APPLICATION_DATA) { - // When the PTO is armed for Initial or Handshake packet number spaces, - // the max_ack_delay is 0. - return false; - } - if (always_include_max_ack_delay_for_pto_timeout_) { - return true; - } - if (!unacked_packets_ - .GetLargestSentRetransmittableOfPacketNumberSpace(APPLICATION_DATA) - .IsInitialized() || - unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace( - APPLICATION_DATA) < - FirstSendingPacketNumber() + kMinReceivedBeforeAckDecimation - 1) { - // Peer is doing TCP style acking. Expect an immediate ACK if more than 1 - // packet are outstanding. - if (unacked_packets_.packets_in_flight() >= - kDefaultRetransmittablePacketsBeforeAck) { - return false; - } - } else if (unacked_packets_.packets_in_flight() >= - kMaxRetransmittablePacketsBeforeAck) { - // Peer is doing ack decimation. Expect an immediate ACK if >= 10 - // packets are outstanding. - return false; - } - if (skip_packet_number_for_pto_ && consecutive_pto_count_ > 0) { - // An immediate ACK is expected when doing PTOS. Please note, this will miss - // cases when PTO fires and turns out to be spurious. - return false; - } - return true; + // Do not include max_ack_delay when PTO is armed for Initial or Handshake + // packet number spaces. + return !supports_multiple_packet_number_spaces() || space == APPLICATION_DATA; } QuicTime QuicSentPacketManager::GetEarliestPacketSentTimeForPto( @@ -680,38 +494,30 @@ void QuicSentPacketManager::MarkForRetransmission( QuicPacketNumber packet_number, TransmissionType transmission_type) { QuicTransmissionInfo* transmission_info = unacked_packets_.GetMutableTransmissionInfo(packet_number); - // A previous RTO retransmission may cause connection close; packets without - // retransmittable frames can be marked for loss retransmissions. + // Packets without retransmittable frames can only be marked for loss + // retransmission. QUIC_BUG_IF(quic_bug_12552_2, transmission_type != LOSS_RETRANSMISSION && - transmission_type != RTO_RETRANSMISSION && !unacked_packets_.HasRetransmittableFrames( *transmission_info)) << "packet number " << packet_number << " transmission_type: " << transmission_type << " transmission_info " << transmission_info->DebugString(); - // Handshake packets should never be sent as probing retransmissions. - QUICHE_DCHECK(!transmission_info->has_crypto_handshake || - transmission_type != PROBING_RETRANSMISSION); if (ShouldForceRetransmission(transmission_type)) { - const bool retransmitted = unacked_packets_.RetransmitFrames( - QuicFrames(transmission_info->retransmittable_frames), - transmission_type); - if (GetQuicRestartFlag(quic_set_packet_state_if_all_data_retransmitted)) { - QUIC_RESTART_FLAG_COUNT(quic_set_packet_state_if_all_data_retransmitted); - if (!retransmitted) { - // Do not set packet state if the data is not fully retransmitted. - // This should only happen if packet payload size decreases which can be - // caused by: - // 1) connection tries to opportunistically retransmit data - // when sending a packet of a different packet number space, or - // 2) path MTU decreases, or - // 3) packet header size increases (e.g., packet number length - // increases). - QUIC_CODE_COUNT(quic_retransmit_frames_failed); - return; - } - QUIC_CODE_COUNT(quic_retransmit_frames_succeeded); + if (!unacked_packets_.RetransmitFrames( + QuicFrames(transmission_info->retransmittable_frames), + transmission_type)) { + // Do not set packet state if the data is not fully retransmitted. + // This should only happen if packet payload size decreases which can be + // caused by: + // 1) connection tries to opportunistically retransmit data + // when sending a packet of a different packet number space, or + // 2) path MTU decreases, or + // 3) packet header size increases (e.g., packet number length + // increases). + QUIC_CODE_COUNT(quic_retransmit_frames_failed); + return; } + QUIC_CODE_COUNT(quic_retransmit_frames_succeeded); } else { unacked_packets_.NotifyFramesLost(*transmission_info, transmission_type); @@ -914,17 +720,6 @@ QuicSentPacketManager::OnRetransmissionTimeout() { MaybeInvokeCongestionEvent(false, prior_in_flight, now); return LOSS_MODE; } - case TLP_MODE: - ++stats_->tlp_count; - ++consecutive_tlp_count_; - pending_timer_transmission_count_ = 1; - // TLPs prefer sending new data instead of retransmitting data, so - // give the connection a chance to write before completing the TLP. - return TLP_MODE; - case RTO_MODE: - ++stats_->rto_count; - RetransmitRtoPackets(); - return RTO_MODE; case PTO_MODE: QUIC_DVLOG(1) << ENDPOINT << "PTO mode"; ++stats_->pto_count; @@ -932,7 +727,7 @@ QuicSentPacketManager::OnRetransmissionTimeout() { ++stats_->crypto_retransmit_count; } ++consecutive_pto_count_; - pending_timer_transmission_count_ = max_probe_packets_per_pto_; + pending_timer_transmission_count_ = 1; return PTO_MODE; } QUIC_BUG(quic_bug_10750_3) @@ -972,17 +767,6 @@ void QuicSentPacketManager::RetransmitCryptoPackets() { } } -bool QuicSentPacketManager::MaybeRetransmitTailLossProbe() { - QUICHE_DCHECK(!pto_enabled_); - if (pending_timer_transmission_count_ == 0) { - return false; - } - if (!MaybeRetransmitOldestPacket(TLP_RETRANSMISSION)) { - return false; - } - return true; -} - bool QuicSentPacketManager::MaybeRetransmitOldestPacket(TransmissionType type) { if (!unacked_packets_.empty()) { QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked(); @@ -1007,47 +791,7 @@ bool QuicSentPacketManager::MaybeRetransmitOldestPacket(TransmissionType type) { return false; } -void QuicSentPacketManager::RetransmitRtoPackets() { - QUICHE_DCHECK(!pto_enabled_); - QUIC_BUG_IF(quic_bug_12552_3, pending_timer_transmission_count_ > 0) - << "Retransmissions already queued:" << pending_timer_transmission_count_; - // Mark two packets for retransmission. - std::vector<QuicPacketNumber> retransmissions; - if (!unacked_packets_.empty()) { - QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked(); - QuicPacketNumber largest_sent_packet = - unacked_packets_.largest_sent_packet(); - for (; packet_number <= largest_sent_packet; ++packet_number) { - QuicTransmissionInfo* transmission_info = - unacked_packets_.GetMutableTransmissionInfo(packet_number); - if (transmission_info->state == OUTSTANDING && - unacked_packets_.HasRetransmittableFrames(*transmission_info) && - pending_timer_transmission_count_ < max_rto_packets_) { - QUICHE_DCHECK(transmission_info->in_flight); - retransmissions.push_back(packet_number); - ++pending_timer_transmission_count_; - } - } - } - if (pending_timer_transmission_count_ > 0) { - if (consecutive_rto_count_ == 0) { - first_rto_transmission_ = unacked_packets_.largest_sent_packet() + 1; - } - ++consecutive_rto_count_; - } - for (QuicPacketNumber retransmission : retransmissions) { - MarkForRetransmission(retransmission, RTO_RETRANSMISSION); - } - if (retransmissions.empty()) { - QUIC_BUG_IF(quic_bug_12552_4, pending_timer_transmission_count_ != 0); - // No packets to be RTO retransmitted, raise up a credit to allow - // connection to send. - QUIC_CODE_COUNT(no_packets_to_be_rto_retransmitted); - pending_timer_transmission_count_ = 1; - } -} - -void QuicSentPacketManager::MaybeSendProbePackets() { +void QuicSentPacketManager::MaybeSendProbePacket() { if (pending_timer_transmission_count_ == 0) { return; } @@ -1093,42 +837,9 @@ void QuicSentPacketManager::MaybeSendProbePackets() { // It is possible that there is not enough outstanding data for probing. } -void QuicSentPacketManager::AdjustPendingTimerTransmissions() { - if (pending_timer_transmission_count_ < max_probe_packets_per_pto_) { - // There are packets sent already, clear credit. - pending_timer_transmission_count_ = 0; - return; - } - // No packet gets sent, leave 1 credit to allow data to be write eventually. - pending_timer_transmission_count_ = 1; -} - void QuicSentPacketManager::EnableIetfPtoAndLossDetection() { - if (pto_enabled_) { - QUIC_RESTART_FLAG_COUNT_N(quic_default_on_pto2, 2, 2); - // Disable handshake mode. - handshake_mode_disabled_ = true; - return; - } - if (GetQuicRestartFlag(quic_default_on_pto2)) { - QUIC_BUG(pto_not_enabled) - << "PTO is not enabled while quic_default_on_pto2 is true"; - return; - } - pto_enabled_ = true; + // Disable handshake mode. handshake_mode_disabled_ = true; - // Default to 1 packet per PTO and skip a packet number. Arm the 1st PTO - // with max of earliest in flight sent time + PTO delay and 1.5 * srtt from - // last in flight packet. - max_probe_packets_per_pto_ = 1; - skip_packet_number_for_pto_ = true; - first_pto_srtt_multiplier_ = 1.5; - pto_rttvar_multiplier_ = 2; -} - -void QuicSentPacketManager::StartExponentialBackoffAfterNthPto( - size_t exponential_backoff_start_point) { - pto_exponential_backoff_start_point_ = exponential_backoff_start_point; } void QuicSentPacketManager::RetransmitDataOfSpaceIfAny( @@ -1171,15 +882,7 @@ QuicSentPacketManager::GetRetransmissionMode() const { if (loss_algorithm_->GetLossTimeout() != QuicTime::Zero()) { return LOSS_MODE; } - if (pto_enabled_) { - return PTO_MODE; - } - if (consecutive_tlp_count_ < max_tail_loss_probes_) { - if (unacked_packets_.HasUnackedRetransmittableFrames()) { - return TLP_MODE; - } - } - return RTO_MODE; + return PTO_MODE; } void QuicSentPacketManager::InvokeLossDetection(QuicTime time) { @@ -1283,49 +986,18 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const { // Do not set the timer if there is any credit left. return QuicTime::Zero(); } - PacketNumberSpace packet_number_space; - if (!simplify_set_retransmission_alarm_ && - supports_multiple_packet_number_spaces() && - unacked_packets_.perspective() == Perspective::IS_SERVER && - !GetEarliestPacketSentTimeForPto(&packet_number_space).IsInitialized()) { - // Do not set the timer on the server side if the only in flight packets are - // half RTT data. - return QuicTime::Zero(); - } switch (GetRetransmissionMode()) { case HANDSHAKE_MODE: return unacked_packets_.GetLastCryptoPacketSentTime() + GetCryptoRetransmissionDelay(); case LOSS_MODE: return loss_algorithm_->GetLossTimeout(); - case TLP_MODE: { - QUICHE_DCHECK(!pto_enabled_); - // TODO(ianswett): When CWND is available, it would be preferable to - // set the timer based on the earliest retransmittable packet. - // Base the updated timer on the send time of the last packet. - const QuicTime sent_time = - unacked_packets_.GetLastInFlightPacketSentTime(); - const QuicTime tlp_time = sent_time + GetTailLossProbeDelay(); - // Ensure the TLP timer never gets set to a time in the past. - return std::max(clock_->ApproximateNow(), tlp_time); - } - case RTO_MODE: { - QUICHE_DCHECK(!pto_enabled_); - // The RTO is based on the first outstanding packet. - const QuicTime sent_time = - unacked_packets_.GetLastInFlightPacketSentTime(); - QuicTime rto_time = sent_time + GetRetransmissionDelay(); - // Wait for TLP packets to be acked before an RTO fires. - QuicTime tlp_time = sent_time + GetTailLossProbeDelay(); - return std::max(tlp_time, rto_time); - } case PTO_MODE: { if (!supports_multiple_packet_number_spaces()) { - if (first_pto_srtt_multiplier_ > 0 && - unacked_packets_.HasInFlightPackets() && + if (unacked_packets_.HasInFlightPackets() && consecutive_pto_count_ == 0) { // Arm 1st PTO with earliest in flight sent time, and make sure at - // least first_pto_srtt_multiplier_ * RTT has been passed since last + // least kFirstPtoSrttMultiplier * RTT has been passed since last // in flight packet. return std::max( clock_->ApproximateNow(), @@ -1333,7 +1005,7 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const { ->sent_time + GetProbeTimeoutDelay(NUM_PACKET_NUMBER_SPACES), unacked_packets_.GetLastInFlightPacketSentTime() + - first_pto_srtt_multiplier_ * + kFirstPtoSrttMultiplier * rtt_stats_.SmoothedOrInitialRtt())); } // Ensure PTO never gets set to a time in the past. @@ -1351,22 +1023,21 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const { // Arm PTO from now if there is no in flight packets. earliest_right_edge = clock_->ApproximateNow(); } - if (first_pto_srtt_multiplier_ > 0 && - packet_number_space == APPLICATION_DATA && + if (packet_number_space == APPLICATION_DATA && consecutive_pto_count_ == 0) { const QuicTransmissionInfo* first_application_info = unacked_packets_.GetFirstInFlightTransmissionInfoOfSpace( APPLICATION_DATA); if (first_application_info != nullptr) { // Arm 1st PTO with earliest in flight sent time, and make sure at - // least first_pto_srtt_multiplier_ * RTT has been passed since last + // least kFirstPtoSrttMultiplier * RTT has been passed since last // in flight packet. Only do this for application data. return std::max( clock_->ApproximateNow(), std::max( first_application_info->sent_time + GetProbeTimeoutDelay(packet_number_space), - earliest_right_edge + first_pto_srtt_multiplier_ * + earliest_right_edge + kFirstPtoSrttMultiplier * rtt_stats_.SmoothedOrInitialRtt())); } } @@ -1380,18 +1051,14 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const { } const QuicTime::Delta QuicSentPacketManager::GetPathDegradingDelay() const { - if (pto_enabled_) { - QUICHE_DCHECK_GT(num_ptos_for_path_degrading_, 0); - return num_ptos_for_path_degrading_ * GetPtoDelay(); - } - return GetNConsecutiveRetransmissionTimeoutDelay( - max_tail_loss_probes_ + kNumRetransmissionDelaysForPathDegradingDelay); + QUICHE_DCHECK_GT(num_ptos_for_path_degrading_, 0); + return num_ptos_for_path_degrading_ * GetPtoDelay(); } const QuicTime::Delta QuicSentPacketManager::GetNetworkBlackholeDelay( int8_t num_rtos_for_blackhole_detection) const { return GetNConsecutiveRetransmissionTimeoutDelay( - max_tail_loss_probes_ + num_rtos_for_blackhole_detection); + kDefaultMaxTailLossProbes + num_rtos_for_blackhole_detection); } QuicTime::Delta QuicSentPacketManager::GetMtuReductionDelay( @@ -1418,75 +1085,22 @@ const QuicTime::Delta QuicSentPacketManager::GetCryptoRetransmissionDelay() delay_ms << consecutive_crypto_retransmission_count_); } -const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const { - QuicTime::Delta srtt = rtt_stats_.SmoothedOrInitialRtt(); - 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 - // expression assumed QUIC did the same. - return std::max(2 * srtt, 1.5 * srtt + (min_rto_timeout_ * 0.5)); - } - return std::max(min_tlp_timeout_, 2 * srtt); -} - -const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const { - QuicTime::Delta retransmission_delay = QuicTime::Delta::Zero(); - if (rtt_stats_.smoothed_rtt().IsZero()) { - // We are in the initial state, use default timeout values. - retransmission_delay = - QuicTime::Delta::FromMilliseconds(kDefaultRetransmissionTimeMs); - } else { - retransmission_delay = - rtt_stats_.smoothed_rtt() + 4 * rtt_stats_.mean_deviation(); - if (retransmission_delay < min_rto_timeout_) { - retransmission_delay = min_rto_timeout_; - } - } - - // Calculate exponential back off. - retransmission_delay = - retransmission_delay * - (1 << std::min<size_t>(consecutive_rto_count_, kMaxRetransmissions)); - - if (retransmission_delay.ToMilliseconds() > kMaxRetransmissionTimeMs) { - return QuicTime::Delta::FromMilliseconds(kMaxRetransmissionTimeMs); - } - return retransmission_delay; -} - const QuicTime::Delta QuicSentPacketManager::GetProbeTimeoutDelay( PacketNumberSpace space) const { - QUICHE_DCHECK(pto_enabled_); if (rtt_stats_.smoothed_rtt().IsZero()) { // Respect kMinHandshakeTimeoutMs to avoid a potential amplification attack. QUIC_BUG_IF(quic_bug_12552_6, rtt_stats_.initial_rtt().IsZero()); - return std::max( - pto_multiplier_without_rtt_samples_ * rtt_stats_.initial_rtt(), - QuicTime::Delta::FromMilliseconds(kMinHandshakeTimeoutMs)) * + return std::max(kPtoMultiplierWithoutRttSamples * rtt_stats_.initial_rtt(), + QuicTime::Delta::FromMilliseconds(kMinHandshakeTimeoutMs)) * (1 << consecutive_pto_count_); } - const QuicTime::Delta rtt_var = use_standard_deviation_for_pto_ - ? rtt_stats_.GetStandardOrMeanDeviation() - : rtt_stats_.mean_deviation(); QuicTime::Delta pto_delay = rtt_stats_.smoothed_rtt() + - std::max(pto_rttvar_multiplier_ * rtt_var, kAlarmGranularity) + + std::max(kPtoRttvarMultiplier * rtt_stats_.mean_deviation(), + kAlarmGranularity) + (ShouldAddMaxAckDelay(space) ? peer_max_ack_delay_ : QuicTime::Delta::Zero()); - pto_delay = - pto_delay * (1 << (consecutive_pto_count_ - - std::min(consecutive_pto_count_, - pto_exponential_backoff_start_point_))); - if (consecutive_pto_count_ < num_tlp_timeout_ptos_) { - // Make first n PTOs similar to TLPs. - if (pto_delay > 2 * rtt_stats_.smoothed_rtt()) { - QUIC_CODE_COUNT(quic_delayed_pto); - pto_delay = std::max(kAlarmGranularity, 2 * rtt_stats_.smoothed_rtt()); - } else { - QUIC_CODE_COUNT(quic_faster_pto); - } - } - return pto_delay; + return pto_delay * (1 << consecutive_pto_count_); } QuicTime::Delta QuicSentPacketManager::GetSlowStartDuration() const { @@ -1529,8 +1143,6 @@ void QuicSentPacketManager::SetSendAlgorithm( std::unique_ptr<SendAlgorithmInterface> QuicSentPacketManager::OnConnectionMigration(bool reset_send_algorithm) { - consecutive_rto_count_ = 0; - consecutive_tlp_count_ = 0; consecutive_pto_count_ = 0; rtt_stats_.OnConnectionMigration(); if (!reset_send_algorithm) { @@ -1787,13 +1399,16 @@ QuicSentPacketManager::GetNConsecutiveRetransmissionTimeoutDelay( QuicTime::Delta total_delay = QuicTime::Delta::Zero(); const QuicTime::Delta srtt = rtt_stats_.SmoothedOrInitialRtt(); int num_tlps = - std::min(num_timeouts, static_cast<int>(max_tail_loss_probes_)); + std::min(num_timeouts, static_cast<int>(kDefaultMaxTailLossProbes)); num_timeouts -= 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))); + const QuicTime::Delta tlp_delay = std::max( + 2 * srtt, + unacked_packets_.HasMultipleInFlightPackets() + ? QuicTime::Delta::FromMilliseconds(kMinTailLossProbeTimeoutMs) + : (1.5 * srtt + + (QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs) * + 0.5))); total_delay = total_delay + num_tlps * tlp_delay; } if (num_timeouts == 0) { @@ -1803,7 +1418,9 @@ QuicSentPacketManager::GetNConsecutiveRetransmissionTimeoutDelay( const QuicTime::Delta retransmission_delay = rtt_stats_.smoothed_rtt().IsZero() ? QuicTime::Delta::FromMilliseconds(kDefaultRetransmissionTimeMs) - : std::max(srtt + 4 * rtt_stats_.mean_deviation(), min_rto_timeout_); + : std::max( + srtt + 4 * rtt_stats_.mean_deviation(), + QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs)); total_delay = total_delay + ((1 << num_timeouts) - 1) * retransmission_delay; return total_delay; } @@ -1824,8 +1441,7 @@ bool QuicSentPacketManager::IsLessThanThreePTOs(QuicTime::Delta timeout) const { } QuicTime::Delta QuicSentPacketManager::GetPtoDelay() const { - return pto_enabled_ ? GetProbeTimeoutDelay(APPLICATION_DATA) - : GetRetransmissionDelay(); + return GetProbeTimeoutDelay(APPLICATION_DATA); } void QuicSentPacketManager::OnAckFrequencyFrameSent( diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.h index a476f41aa54..f0a6bc6ded7 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.h @@ -25,7 +25,6 @@ #include "quiche/quic/core/quic_transmission_info.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_unacked_packet_map.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/common/quiche_circular_deque.h" @@ -110,10 +109,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { // The retransmission timer is a single timer which switches modes depending // upon connection state. enum RetransmissionTimeoutMode { - // A conventional TCP style RTO. - RTO_MODE, - // A tail loss probe. By default, QUIC sends up to two before RTOing. - TLP_MODE, // Retransmission of handshake packets prior to handshake completion. HANDSHAKE_MODE, // Re-invoke the loss detection when a packet is not acked before the @@ -176,10 +171,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { void OnConfigNegotiated(); void OnConnectionClosed(); - // Retransmits the oldest pending packet there is still a tail loss probe - // pending. Invoked after OnRetransmissionTimeout. - bool MaybeRetransmitTailLossProbe(); - // Retransmits the oldest pending packet. bool MaybeRetransmitOldestPacket(TransmissionType type); @@ -375,10 +366,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { bool InSlowStart() const { return send_algorithm_->InSlowStart(); } - size_t GetConsecutiveRtoCount() const { return consecutive_rto_count_; } - - size_t GetConsecutiveTlpCount() const { return consecutive_tlp_count_; } - size_t GetConsecutivePtoCount() const { return consecutive_pto_count_; } void OnApplicationLimited(); @@ -410,7 +397,9 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { void set_peer_max_ack_delay(QuicTime::Delta peer_max_ack_delay) { // The delayed ack time should never be more than one half the min RTO time. - QUICHE_DCHECK_LE(peer_max_ack_delay, (min_rto_timeout_ * 0.5)); + QUICHE_DCHECK_LE( + peer_max_ack_delay, + (QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs) * 0.5)); peer_max_ack_delay_ = peer_max_ack_delay; } @@ -432,21 +421,13 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { // Setting the send algorithm once the connection is underway is dangerous. void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm); - // Sends up to max_probe_packets_per_pto_ probe packets. - void MaybeSendProbePackets(); - - // Called to adjust pending_timer_transmission_count_ accordingly. - void AdjustPendingTimerTransmissions(); + // Sends one probe packet. + void MaybeSendProbePacket(); // Called to disable HANDSHAKE_MODE, and only PTO and LOSS modes are used. // Also enable IETF loss detection. void EnableIetfPtoAndLossDetection(); - // Called to set the start point of doing exponential backoff when calculating - // PTO timeout. - void StartExponentialBackoffAfterNthPto( - size_t exponential_backoff_start_point); - // Called to retransmit in flight packet of |space| if any. void RetransmitDataOfSpaceIfAny(PacketNumberSpace space); @@ -460,14 +441,8 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { return unacked_packets_.supports_multiple_packet_number_spaces(); } - bool pto_enabled() const { return pto_enabled_; } - bool handshake_mode_disabled() const { return handshake_mode_disabled_; } - bool skip_packet_number_for_pto() const { - return skip_packet_number_for_pto_; - } - bool zero_rtt_packet_acked() const { return zero_rtt_packet_acked_; } bool one_rtt_packet_acked() const { return one_rtt_packet_acked_; } @@ -489,12 +464,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { // kMinUntrustedInitialRoundTripTimeUs if not |trusted|. void SetInitialRtt(QuicTime::Delta rtt, bool trusted); - bool use_lower_min_irtt() const { return use_lower_min_irtt_; } - - bool simplify_set_retransmission_alarm() const { - return simplify_set_retransmission_alarm_; - } - private: friend class test::QuicConnectionPeer; friend class test::QuicSentPacketManagerPeer; @@ -505,21 +474,9 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { // Retransmits all crypto stream packets. void RetransmitCryptoPackets(); - // Retransmits two packets for an RTO and removes any non-retransmittable - // packets from flight. - void RetransmitRtoPackets(); - // Returns the timeout for retransmitting crypto handshake packets. const QuicTime::Delta GetCryptoRetransmissionDelay() const; - // Calls GetTailLossProbeDelay() with values from the current state of this - // packet manager as its params. - const QuicTime::Delta GetTailLossProbeDelay() const; - - // Calls GetRetransmissionDelay() with values from the current state of this - // packet manager as its params. - const QuicTime::Delta GetRetransmissionDelay() const; - // Returns the probe timeout. const QuicTime::Delta GetProbeTimeoutDelay(PacketNumberSpace space) const; @@ -581,6 +538,7 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { // A helper function to return total delay of |num_timeouts| retransmission // timeout with TLP and RTO mode. + // TODO(fayang): remove this method and calculate blackhole delay by PTO. QuicTime::Delta GetNConsecutiveRetransmissionTimeoutDelay( int num_timeouts) const; @@ -619,32 +577,14 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { LossDetectionInterface* loss_algorithm_; UberLossAlgorithm uber_loss_algorithm_; - // Tracks the first RTO packet. If any packet before that packet gets acked, - // it indicates the RTO was spurious and should be reversed(F-RTO). - QuicPacketNumber first_rto_transmission_; - // Number of times the RTO timer has fired in a row without receiving an ack. - size_t consecutive_rto_count_; - // Number of times the tail loss probe has been sent. - size_t consecutive_tlp_count_; // Number of times the crypto handshake has been retransmitted. size_t consecutive_crypto_retransmission_count_; - // Number of pending transmissions of TLP, RTO, or crypto packets. + // Number of pending transmissions of PTO or crypto packets. size_t pending_timer_transmission_count_; - // Maximum number of tail loss probes to send before firing an RTO. - size_t max_tail_loss_probes_; - // Maximum number of packets to send upon RTO. - QuicPacketCount max_rto_packets_; - // If true, send the TLP at 0.5 RTT. + 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. - bool use_new_rto_; // If true, use a more conservative handshake retransmission policy. bool conservative_handshake_retransmits_; - // The minimum TLP timeout. - QuicTime::Delta min_tlp_timeout_; - // The minimum RTO. - QuicTime::Delta min_rto_timeout_; // Vectors packets acked and lost as a result of the last congestion event. AckedPacketVector packets_acked_; @@ -703,36 +643,12 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { // OnAckRangeStart, and gradually moves in OnAckRange.. PacketNumberQueue::const_reverse_iterator acked_packets_iter_; - // Indicates whether PTO mode has been enabled. PTO mode unifies TLP and RTO - // modes. - bool pto_enabled_; - - // Maximum number of probes to send when PTO fires. - size_t max_probe_packets_per_pto_; - // Number of times the PTO timer has fired in a row without receiving an ack. size_t consecutive_pto_count_; // True if HANDSHAKE mode has been disabled. bool handshake_mode_disabled_; - // If true, skip packet number before sending the last PTO retransmission. - bool skip_packet_number_for_pto_; - - // If true, always include peer_max_ack_delay_ when calculating PTO timeout. - bool always_include_max_ack_delay_for_pto_timeout_; - - // When calculating PTO timeout, the start point of doing exponential backoff. - // For example, 0 : always do exponential backoff. n : do exponential backoff - // since nth PTO. - size_t pto_exponential_backoff_start_point_; - - // The multiplier of rttvar when calculating PTO timeout. - int pto_rttvar_multiplier_; - - // Number of PTOs similar to TLPs. - size_t num_tlp_timeout_ptos_; - // True if any ENCRYPTION_HANDSHAKE packet gets acknowledged. bool handshake_packet_acked_; @@ -742,18 +658,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { // True if any 1-RTT packet gets acknowledged. bool one_rtt_packet_acked_; - // If > 0, arm the 1st PTO with max of earliest in flight sent time + PTO - // delay and multiplier * srtt from last in flight packet. - float first_pto_srtt_multiplier_; - - // If true, use standard deviation (instead of mean deviation) when - // calculating PTO timeout. - bool use_standard_deviation_for_pto_; - - // The multiplier for caculating PTO timeout before any RTT sample is - // available. - float pto_multiplier_without_rtt_samples_; - // The number of PTOs needed for path degrading alarm. If equals to 0, the // traditional path degrading mechanism will be used. int num_ptos_for_path_degrading_; @@ -764,13 +668,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager { // Whether to ignore the ack_delay in received ACKs. bool ignore_ack_delay_; - - // Latched value of --quic_use_lower_min_for_trusted_irtt. - bool use_lower_min_irtt_ = - GetQuicReloadableFlag(quic_use_lower_min_for_trusted_irtt); - - const bool simplify_set_retransmission_alarm_ = - GetQuicReloadableFlag(quic_simplify_set_retransmission_alarm); }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager_test.cc index 24485e2d97c..8c8076b43e5 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager_test.cc @@ -98,8 +98,6 @@ class QuicSentPacketManagerTest : public QuicTest { send_algorithm_(new StrictMock<MockSendAlgorithm>), network_change_visitor_(new StrictMock<MockNetworkChangeVisitor>) { QuicSentPacketManagerPeer::SetSendAlgorithm(&manager_, send_algorithm_); - // Disable tail loss probes for most tests. - QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 0); // Advance the time 1s so the send times are never QuicTime::Zero. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000)); manager_.SetNetworkChangeVisitor(network_change_visitor_.get()); @@ -202,7 +200,7 @@ class QuicSentPacketManagerTest : public QuicTest { void RetransmitAndSendPacket(uint64_t old_packet_number, uint64_t new_packet_number) { RetransmitAndSendPacket(old_packet_number, new_packet_number, - TLP_RETRANSMISSION); + PTO_RETRANSMISSION); } void RetransmitAndSendPacket(uint64_t old_packet_number, @@ -210,9 +208,7 @@ class QuicSentPacketManagerTest : public QuicTest { TransmissionType transmission_type) { bool is_lost = false; if (transmission_type == HANDSHAKE_RETRANSMISSION || - transmission_type == TLP_RETRANSMISSION || - transmission_type == RTO_RETRANSMISSION || - transmission_type == PROBING_RETRANSMISSION) { + transmission_type == PTO_RETRANSMISSION) { EXPECT_CALL(notifier_, RetransmitFrames(_, _)) .WillOnce(WithArgs<1>( Invoke([this, new_packet_number](TransmissionType type) { @@ -316,25 +312,6 @@ class QuicSentPacketManagerTest : public QuicTest { NO_RETRANSMITTABLE_DATA, true); } - void EnablePto(QuicTag tag) { - QuicConfig config; - QuicTagVector options; - options.push_back(tag); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - EXPECT_TRUE(manager_.pto_enabled()); - } - - int GetPtoRttvarMultiplier() { - if (GetQuicRestartFlag(quic_default_on_pto2) || - manager_.handshake_mode_disabled()) { - return 2; - } - return 4; - } - quiche::SimpleBufferAllocator allocator_; QuicSentPacketManager manager_; MockClock clock_; @@ -393,7 +370,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) { return RetransmitDataPacket(2, type); }))); QuicSentPacketManagerPeer::MarkForRetransmission(&manager_, 1, - TLP_RETRANSMISSION); + PTO_RETRANSMISSION); // Ack 1. ExpectAck(1); manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(), @@ -415,7 +392,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenStopRetransmittingBeforeSend) { SendDataPacket(1); EXPECT_CALL(notifier_, RetransmitFrames(_, _)).WillRepeatedly(Return(true)); QuicSentPacketManagerPeer::MarkForRetransmission(&manager_, 1, - TLP_RETRANSMISSION); + PTO_RETRANSMISSION); EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false)); @@ -552,7 +529,7 @@ TEST_F(QuicSentPacketManagerTest, TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) { StrictMock<MockDebugDelegate> debug_delegate; - EXPECT_CALL(debug_delegate, OnSpuriousPacketRetransmission(TLP_RETRANSMISSION, + EXPECT_CALL(debug_delegate, OnSpuriousPacketRetransmission(PTO_RETRANSMISSION, kDefaultLength)) .Times(1); manager_.SetDebugDelegate(&debug_delegate); @@ -831,155 +808,6 @@ TEST_F(QuicSentPacketManagerTest, RttZeroDelta) { EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt()); } -TEST_F(QuicSentPacketManagerTest, TailLossProbeTimeout) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2); - - // Send 1 packet. - SendDataPacket(1); - - // The first tail loss probe retransmits 1 packet. - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(2, type); - }))); - manager_.MaybeRetransmitTailLossProbe(); - - // The second tail loss probe retransmits 1 packet. - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(3, type); - }))); - manager_.MaybeRetransmitTailLossProbe(); - EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false)); - EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now())); - - // Ack the third and ensure the first two are still pending. - ExpectAck(3); - - manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1), - ENCRYPTION_INITIAL)); - - EXPECT_TRUE(manager_.HasInFlightPackets()); - - // Acking two more packets will lose both of them due to nacks. - SendDataPacket(4); - SendDataPacket(5); - uint64_t acked[] = {4, 5}; - uint64_t lost[] = {1, 2}; - ExpectAcksAndLosses(true, acked, ABSL_ARRAYSIZE(acked), lost, - ABSL_ARRAYSIZE(lost)); - // Frames in all packets are acked. - EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false)); - // Notify session that stream frame in packets 1 and 2 get lost although - // they are not outstanding. - EXPECT_CALL(notifier_, OnFrameLost(_)).Times(2); - manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(2), - ENCRYPTION_INITIAL)); - - EXPECT_FALSE(manager_.HasInFlightPackets()); - EXPECT_EQ(2u, stats_.tlp_count); - EXPECT_EQ(0u, stats_.rto_count); -} - -TEST_F(QuicSentPacketManagerTest, TailLossProbeThenRTO) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2); - - // Send 100 packets. - const size_t kNumSentPackets = 100; - for (size_t i = 1; i <= kNumSentPackets; ++i) { - SendDataPacket(i); - } - QuicTime rto_packet_time = clock_.Now(); - // Advance the time. - clock_.AdvanceTime(manager_.GetRetransmissionTime() - clock_.Now()); - - // The first tail loss probe retransmits 1 packet. - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(101, type); - }))); - manager_.MaybeRetransmitTailLossProbe(); - EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false)); - EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now())); - clock_.AdvanceTime(manager_.GetRetransmissionTime() - clock_.Now()); - - // The second tail loss probe retransmits 1 packet. - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(102, type); - }))); - EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe()); - EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false)); - EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now())); - - // Ensure the RTO is set based on the correct packet. - rto_packet_time = clock_.Now(); - EXPECT_EQ(rto_packet_time + QuicTime::Delta::FromMilliseconds(500), - manager_.GetRetransmissionTime()); - - // Advance the time enough to ensure all packets are RTO'd. - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000)); - - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .Times(2) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(103, type); - }))) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(104, type); - }))); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(2u, stats_.tlp_count); - EXPECT_EQ(1u, stats_.rto_count); - EXPECT_EQ(0u, stats_.max_consecutive_rto_with_forward_progress); - // There are 2 RTO retransmissions. - EXPECT_EQ(104 * kDefaultLength, manager_.GetBytesInFlight()); - QuicPacketNumber largest_acked = QuicPacketNumber(103); - EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); - EXPECT_CALL(*send_algorithm_, - OnCongestionEvent( - true, _, _, Pointwise(PacketNumberEq(), {largest_acked}), _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - // Although frames in packet 3 gets acked, it would be kept for another - // RTT. - EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true)); - // Packets [1, 102] are lost, although stream frame in packet 3 is not - // outstanding. - EXPECT_CALL(notifier_, OnFrameLost(_)).Times(102); - manager_.OnAckFrameStart(QuicPacketNumber(103), QuicTime::Delta::Infinite(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(103), QuicPacketNumber(104)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1), - ENCRYPTION_INITIAL)); - // All packets before 103 should be lost. - // Packet 104 is still in flight. - EXPECT_EQ(1000u, manager_.GetBytesInFlight()); - EXPECT_EQ(1u, stats_.max_consecutive_rto_with_forward_progress); -} - TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeout) { // Send 2 crypto packets and 3 data packets. const size_t kNumSentCryptoPackets = 2; @@ -1137,225 +965,6 @@ TEST_F(QuicSentPacketManagerTest, VerifyRetransmittablePackets(nullptr, 0); } -TEST_F(QuicSentPacketManagerTest, RetransmissionTimeout) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - StrictMock<MockDebugDelegate> debug_delegate; - manager_.SetDebugDelegate(&debug_delegate); - - // Send 100 packets. - const size_t kNumSentPackets = 100; - for (size_t i = 1; i <= kNumSentPackets; ++i) { - SendDataPacket(i); - } - - EXPECT_FALSE(manager_.MaybeRetransmitTailLossProbe()); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .Times(2) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(101, type); - }))) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(102, type); - }))); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(102 * kDefaultLength, manager_.GetBytesInFlight()); - - // Ack a retransmission. - // Ensure no packets are lost. - QuicPacketNumber largest_acked = QuicPacketNumber(102); - EXPECT_CALL(*send_algorithm_, - OnCongestionEvent(true, _, _, - Pointwise(PacketNumberEq(), {largest_acked}), - /*lost_packets=*/IsEmpty())); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); - // RTO's use loss detection instead of immediately declaring retransmitted - // packets lost. - for (int i = 1; i <= 99; ++i) { - EXPECT_CALL(debug_delegate, - OnPacketLoss(QuicPacketNumber(i), _, LOSS_RETRANSMISSION, _)); - } - EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true)); - // Packets [1, 99] are considered as lost, although stream frame in packet - // 2 is not outstanding. - EXPECT_CALL(notifier_, OnFrameLost(_)).Times(99); - manager_.OnAckFrameStart(QuicPacketNumber(102), QuicTime::Delta::Zero(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(102), QuicPacketNumber(103)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1), - ENCRYPTION_INITIAL)); -} - -TEST_F(QuicSentPacketManagerTest, RetransmissionTimeoutOnePacket) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - // Set the 1RTO connection option. - QuicConfig client_config; - QuicTagVector options; - options.push_back(k1RTO); - QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); - client_config.SetConnectionOptionsToSend(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()) - .WillRepeatedly(Return(10 * kDefaultTCPMSS)); - manager_.SetFromConfig(client_config); - EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true)); - - StrictMock<MockDebugDelegate> debug_delegate; - manager_.SetDebugDelegate(&debug_delegate); - - // Send 100 packets. - const size_t kNumSentPackets = 100; - for (size_t i = 1; i <= kNumSentPackets; ++i) { - SendDataPacket(i); - } - - EXPECT_FALSE(manager_.MaybeRetransmitTailLossProbe()); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .Times(1) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(101, type); - }))); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(101 * kDefaultLength, manager_.GetBytesInFlight()); -} - -TEST_F(QuicSentPacketManagerTest, NewRetransmissionTimeout) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicConfig client_config; - QuicTagVector options; - options.push_back(kNRTO); - QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); - client_config.SetConnectionOptionsToSend(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()) - .WillRepeatedly(Return(10 * kDefaultTCPMSS)); - manager_.SetFromConfig(client_config); - EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_)); - EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true)); - - // Send 100 packets. - const size_t kNumSentPackets = 100; - for (size_t i = 1; i <= kNumSentPackets; ++i) { - SendDataPacket(i); - } - - EXPECT_FALSE(manager_.MaybeRetransmitTailLossProbe()); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .Times(2) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(101, type); - }))) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(102, type); - }))); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(102 * kDefaultLength, manager_.GetBytesInFlight()); - - // Ack a retransmission and expect no call to OnRetransmissionTimeout. - // This will include packets in the lost packet map. - QuicPacketNumber largest_acked = QuicPacketNumber(102); - EXPECT_CALL(*send_algorithm_, - OnCongestionEvent(true, _, _, - Pointwise(PacketNumberEq(), {largest_acked}), - /*lost_packets=*/Not(IsEmpty()))); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true)); - // Packets [1, 99] are considered as lost, although stream frame in packet - // 2 is not outstanding. - EXPECT_CALL(notifier_, OnFrameLost(_)).Times(99); - manager_.OnAckFrameStart(QuicPacketNumber(102), QuicTime::Delta::Zero(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(102), QuicPacketNumber(103)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1), - ENCRYPTION_INITIAL)); -} - -TEST_F(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - // Send 1 packet. - SendDataPacket(1); - - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(2, type); - }))); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight()); - - // Rto a second time. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(3, type); - }))); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(3 * kDefaultLength, manager_.GetBytesInFlight()); - - // Ack a retransmission and ensure OnRetransmissionTimeout is called. - EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); - ExpectAck(2); - manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Zero(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1), - ENCRYPTION_INITIAL)); - - // The original packet and newest should be outstanding. - EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight()); -} - -TEST_F(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - // Send 1 packet. - SendDataPacket(1); - - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(2, type); - }))); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight()); - - // Rto a second time. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(3, type); - }))); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(3 * kDefaultLength, manager_.GetBytesInFlight()); - - // Ack a retransmission and ensure OnRetransmissionTimeout is called. - EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); - ExpectAck(3); - manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Zero(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1), - ENCRYPTION_INITIAL)); - - // The first two packets should still be outstanding. - EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight()); -} - TEST_F(QuicSentPacketManagerTest, GetTransmissionTime) { EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime()); } @@ -1448,199 +1057,6 @@ TEST_F(QuicSentPacketManagerTest, EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); } -TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeTailLossProbe) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2); - SendDataPacket(1); - SendDataPacket(2); - - // Check the min. - RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); - rtt_stats->set_initial_rtt(QuicTime::Delta::FromMilliseconds(1)); - EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromMilliseconds(10), - manager_.GetRetransmissionTime()); - - // Test with a standard smoothed RTT. - rtt_stats->set_initial_rtt(QuicTime::Delta::FromMilliseconds(100)); - QuicTime::Delta srtt = rtt_stats->initial_rtt(); - QuicTime::Delta expected_tlp_delay = 2 * srtt; - QuicTime expected_time = clock_.Now() + expected_tlp_delay; - EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); - - // 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) { - return RetransmitDataPacket(3, type); - }))); - EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe()); - EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false)); - EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now())); - - expected_time = clock_.Now() + expected_tlp_delay; - EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); -} - -TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); - rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100), - QuicTime::Delta::Zero(), QuicTime::Zero()); - - SendDataPacket(1); - SendDataPacket(2); - SendDataPacket(3); - SendDataPacket(4); - - QuicTime::Delta expected_rto_delay = - rtt_stats->smoothed_rtt() + 4 * rtt_stats->mean_deviation(); - QuicTime expected_time = clock_.Now() + expected_rto_delay; - EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); - - // Retransmit the packet by invoking the retransmission timeout. - clock_.AdvanceTime(expected_rto_delay); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .Times(2) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(5, type); - }))) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(6, type); - }))); - manager_.OnRetransmissionTimeout(); - // All previous packets are inflight, plus two rto retransmissions. - EXPECT_EQ(6 * kDefaultLength, manager_.GetBytesInFlight()); - - // The delay should double the second time. - expected_time = clock_.Now() + expected_rto_delay + expected_rto_delay; - // Once we always base the timer on the right edge, leaving the older packets - // in flight doesn't change the timeout. - EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); - - // Ack a packet before the first RTO and ensure the RTO timeout returns to the - // original value and OnRetransmissionTimeout is not called or reverted. - uint64_t acked[] = {1, 2}; - ExpectAcksAndLosses(true, acked, ABSL_ARRAYSIZE(acked), nullptr, 0); - manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Zero(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1), - ENCRYPTION_INITIAL)); - EXPECT_EQ(4 * kDefaultLength, manager_.GetBytesInFlight()); - - // Wait 2RTTs from now for the RTO, since it's the max of the RTO time - // and the TLP time. In production, there would always be two TLP's first. - // Since retransmission was spurious, smoothed_rtt_ is expired, and replaced - // by the latest RTT sample of 500ms. - expected_time = clock_.Now() + QuicTime::Delta::FromMilliseconds(1000); - // Once we always base the timer on the right edge, leaving the older packets - // in flight doesn't change the timeout. - EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); -} - -TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMin) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - SendDataPacket(1); - // Provide a 1ms RTT sample. - const_cast<RttStats*>(manager_.GetRttStats()) - ->UpdateRtt(QuicTime::Delta::FromMilliseconds(1), QuicTime::Delta::Zero(), - QuicTime::Zero()); - QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(200); - - // If the delay is smaller than the min, ensure it exponentially backs off - // from the min. - for (int i = 0; i < 5; ++i) { - EXPECT_EQ(delay, - QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_)); - delay = delay + delay; - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this, i](TransmissionType type) { - return RetransmitDataPacket(i + 2, type); - }))); - manager_.OnRetransmissionTimeout(); - } -} - -TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMax) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - SendDataPacket(1); - // Provide a 60s RTT sample. - const_cast<RttStats*>(manager_.GetRttStats()) - ->UpdateRtt(QuicTime::Delta::FromSeconds(60), QuicTime::Delta::Zero(), - QuicTime::Zero()); - - EXPECT_EQ(QuicTime::Delta::FromSeconds(60), - QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayExponentialBackoff) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - SendDataPacket(1); - QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(500); - - // Delay should back off exponentially. - for (int i = 0; i < 5; ++i) { - EXPECT_EQ(delay, - QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_)); - delay = delay + delay; - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this, i](TransmissionType type) { - return RetransmitDataPacket(i + 2, type); - }))); - manager_.OnRetransmissionTimeout(); - } -} - -TEST_F(QuicSentPacketManagerTest, RetransmissionDelay) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); - const int64_t kRttMs = 250; - const int64_t kDeviationMs = 5; - - rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs), - QuicTime::Delta::Zero(), clock_.Now()); - - // Initial value is to set the median deviation to half of the initial rtt, - // the median in then multiplied by a factor of 4 and finally the smoothed rtt - // is added which is the initial rtt. - QuicTime::Delta expected_delay = - QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4); - EXPECT_EQ(expected_delay, - QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_)); - - for (int i = 0; i < 100; ++i) { - // Run to make sure that we converge. - rtt_stats->UpdateRtt( - QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs), - QuicTime::Delta::Zero(), clock_.Now()); - rtt_stats->UpdateRtt( - QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs), - QuicTime::Delta::Zero(), clock_.Now()); - } - expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4); - - EXPECT_NEAR(kRttMs, rtt_stats->smoothed_rtt().ToMilliseconds(), 1); - EXPECT_NEAR(expected_delay.ToMilliseconds(), - QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_) - .ToMilliseconds(), - 1); -} - TEST_F(QuicSentPacketManagerTest, GetLossDelay) { auto loss_algorithm = std::make_unique<MockLossAlgorithm>(); QuicSentPacketManagerPeer::SetLossAlgorithm(&manager_, loss_algorithm.get()); @@ -1868,214 +1284,6 @@ TEST_F(QuicSentPacketManagerTest, NegotiateClientCongestionControlFromOptions) { ->GetCongestionControlType()); } -TEST_F(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtServer) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicConfig config; - QuicTagVector options; - - options.push_back(kMAD2); - 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); - // Set the initial RTT to 1us. - QuicSentPacketManagerPeer::GetRttStats(&manager_)->set_initial_rtt( - QuicTime::Delta::FromMicroseconds(1)); - // The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(200ms). - EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002), - QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_)); - - // Send two packets, and the TLP should be 1ms. - QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMilliseconds(1); - SendDataPacket(1); - SendDataPacket(2); - EXPECT_EQ(expected_tlp_delay, - QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtClient) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicConfig client_config; - QuicTagVector options; - - options.push_back(kMAD2); - QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); - client_config.SetConnectionOptionsToSend(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(client_config); - // Set the initial RTT to 1us. - QuicSentPacketManagerPeer::GetRttStats(&manager_)->set_initial_rtt( - QuicTime::Delta::FromMicroseconds(1)); - // The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(200ms). - EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002), - QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_)); - // Send two packets, and the TLP should be 1ms. - QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMilliseconds(1); - SendDataPacket(1); - SendDataPacket(2); - EXPECT_EQ(expected_tlp_delay, - QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtServer) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicConfig config; - QuicTagVector options; - - options.push_back(kMAD3); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - manager_.SetFromConfig(config); - // Provide one RTT measurement, because otherwise we use the default of 500ms. - RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); - rtt_stats->UpdateRtt(QuicTime::Delta::FromMicroseconds(1), - QuicTime::Delta::Zero(), QuicTime::Zero()); - QuicTime::Delta expected_rto_delay = QuicTime::Delta::FromMilliseconds(1); - EXPECT_EQ(expected_rto_delay, - QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_)); - // The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(0ms). - QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMicroseconds(502); - EXPECT_EQ(expected_tlp_delay, - QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtClient) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicConfig client_config; - QuicTagVector options; - - options.push_back(kMAD3); - 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); - // Provide one RTT measurement, because otherwise we use the default of 500ms. - RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); - rtt_stats->UpdateRtt(QuicTime::Delta::FromMicroseconds(1), - QuicTime::Delta::Zero(), QuicTime::Zero()); - QuicTime::Delta expected_rto_delay = QuicTime::Delta::FromMilliseconds(1); - EXPECT_EQ(expected_rto_delay, - QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_)); - // The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(0ms). - QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMicroseconds(502); - EXPECT_EQ(expected_tlp_delay, - QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtServer) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicConfig config; - QuicTagVector options; - - options.push_back(kNTLP); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - manager_.SetFromConfig(config); - EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtClient) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicConfig client_config; - QuicTagVector options; - - options.push_back(kNTLP); - 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_EQ(0u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, Negotiate1TLPFromOptionsAtServer) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicConfig config; - QuicTagVector options; - - options.push_back(k1TLP); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - manager_.SetFromConfig(config); - EXPECT_EQ(1u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, Negotiate1TLPFromOptionsAtClient) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicConfig client_config; - QuicTagVector options; - - options.push_back(k1TLP); - 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_EQ(1u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtServer) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - EXPECT_FALSE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_)); - QuicConfig config; - QuicTagVector options; - - options.push_back(kNRTO); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - manager_.SetFromConfig(config); - EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_)); -} - -TEST_F(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtClient) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - EXPECT_FALSE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_)); - QuicConfig client_config; - QuicTagVector options; - - options.push_back(kNRTO); - 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::GetUseNewRto(&manager_)); -} - TEST_F(QuicSentPacketManagerTest, UseInitialRoundTripTimeToSend) { QuicTime::Delta initial_rtt = QuicTime::Delta::FromMilliseconds(325); EXPECT_NE(initial_rtt, manager_.GetRttStats()->smoothed_rtt()); @@ -2116,18 +1324,15 @@ TEST_F(QuicSentPacketManagerTest, ConnectionMigrationUnspecifiedChange) { rtt_stats->set_initial_rtt(default_init_rtt * 2); EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt()); - QuicSentPacketManagerPeer::SetConsecutiveRtoCount(&manager_, 1); - EXPECT_EQ(1u, manager_.GetConsecutiveRtoCount()); - QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, 2); - EXPECT_EQ(2u, manager_.GetConsecutiveTlpCount()); + QuicSentPacketManagerPeer::SetConsecutivePtoCount(&manager_, 1); + EXPECT_EQ(1u, manager_.GetConsecutivePtoCount()); EXPECT_CALL(*send_algorithm_, OnConnectionMigration()); EXPECT_EQ(nullptr, manager_.OnConnectionMigration(/*reset_send_algorithm=*/false)); EXPECT_EQ(default_init_rtt, rtt_stats->initial_rtt()); - EXPECT_EQ(0u, manager_.GetConsecutiveRtoCount()); - EXPECT_EQ(0u, manager_.GetConsecutiveTlpCount()); + EXPECT_EQ(0u, manager_.GetConsecutivePtoCount()); } // Tests that ResetCongestionControlUponPeerAddressChange() resets send @@ -2142,10 +1347,8 @@ TEST_F(QuicSentPacketManagerTest, rtt_stats->set_initial_rtt(default_init_rtt * 2); EXPECT_EQ(2 * default_init_rtt, rtt_stats->initial_rtt()); - QuicSentPacketManagerPeer::SetConsecutiveRtoCount(&manager_, 1); - EXPECT_EQ(1u, manager_.GetConsecutiveRtoCount()); - QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, 2); - EXPECT_EQ(2u, manager_.GetConsecutiveTlpCount()); + QuicSentPacketManagerPeer::SetConsecutivePtoCount(&manager_, 1); + EXPECT_EQ(1u, manager_.GetConsecutivePtoCount()); SendDataPacket(1, ENCRYPTION_FORWARD_SECURE); @@ -2161,8 +1364,7 @@ TEST_F(QuicSentPacketManagerTest, EXPECT_EQ(old_send_algorithm->GetCongestionControlType(), manager_.GetSendAlgorithm()->GetCongestionControlType()); EXPECT_EQ(default_init_rtt, rtt_stats->initial_rtt()); - EXPECT_EQ(0u, manager_.GetConsecutiveRtoCount()); - EXPECT_EQ(0u, manager_.GetConsecutiveTlpCount()); + EXPECT_EQ(0u, manager_.GetConsecutivePtoCount()); // Packets sent earlier shouldn't be regarded as in flight. EXPECT_EQ(0u, BytesInFlight()); @@ -2245,8 +1447,7 @@ TEST_F(QuicSentPacketManagerTest, EXPECT_EQ(old_send_algorithm->GetCongestionControlType(), manager_.GetSendAlgorithm()->GetCongestionControlType()); EXPECT_EQ(default_init_rtt, rtt_stats->initial_rtt()); - EXPECT_EQ(0u, manager_.GetConsecutiveRtoCount()); - EXPECT_EQ(0u, manager_.GetConsecutiveTlpCount()); + EXPECT_EQ(0u, manager_.GetConsecutivePtoCount()); EXPECT_EQ(0u, BytesInFlight()); EXPECT_TRUE(manager_.GetRttStats()->latest_rtt().IsZero()); @@ -2317,8 +1518,7 @@ TEST_F(QuicSentPacketManagerTest, old_send_algorithm = manager_.OnConnectionMigration(/*reset_send_algorithm=*/true); EXPECT_EQ(default_init_rtt, rtt_stats->initial_rtt()); - EXPECT_EQ(0u, manager_.GetConsecutiveRtoCount()); - EXPECT_EQ(0u, manager_.GetConsecutiveTlpCount()); + EXPECT_EQ(0u, manager_.GetConsecutivePtoCount()); EXPECT_EQ(0u, BytesInFlight()); EXPECT_TRUE(manager_.GetRttStats()->latest_rtt().IsZero()); @@ -2622,94 +1822,7 @@ TEST_F(QuicSentPacketManagerTest, ENCRYPTION_HANDSHAKE)); } -// Regression test for b/133771183. -TEST_F(QuicSentPacketManagerTest, PacketInLimbo) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2); - // Send SHLO. - SendCryptoPacket(1); - // Send data packet. - SendDataPacket(2, ENCRYPTION_FORWARD_SECURE); - // Send Ack Packet. - SendAckPacket(3, 1, ENCRYPTION_FORWARD_SECURE); - // Retransmit SHLO. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce( - InvokeWithoutArgs([this]() { return RetransmitCryptoPacket(4); })); - manager_.OnRetransmissionTimeout(); - - // Successfully decrypt a forward secure packet. - manager_.SetHandshakeConfirmed(); - EXPECT_CALL(notifier_, HasUnackedCryptoData()).WillRepeatedly(Return(false)); - // Send Ack packet. - SendAckPacket(5, 2, ENCRYPTION_FORWARD_SECURE); - - // Retransmission alarm fires. - manager_.OnRetransmissionTimeout(); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(6, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeRetransmitTailLossProbe(); - - // Received Ack of packets 1, 3 and 4. - uint64_t acked[] = {1, 3, 4}; - ExpectAcksAndLosses(true, acked, ABSL_ARRAYSIZE(acked), nullptr, 0); - manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(5)); - manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1), - ENCRYPTION_INITIAL)); - - uint64_t acked2[] = {5, 6}; - uint64_t loss[] = {2}; - // Verify packet 2 is detected lost. - EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1); - ExpectAcksAndLosses(true, acked2, ABSL_ARRAYSIZE(acked2), loss, - ABSL_ARRAYSIZE(loss)); - manager_.OnAckFrameStart(QuicPacketNumber(6), QuicTime::Delta::Infinite(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(7)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(2), - ENCRYPTION_INITIAL)); -} - -TEST_F(QuicSentPacketManagerTest, RtoFiresNoPacketToRetransmit) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - // Send 10 packets. - for (size_t i = 1; i <= 10; ++i) { - SendDataPacket(i); - } - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .Times(2) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(11, type); - }))) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(12, type); - }))); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(1u, stats_.rto_count); - EXPECT_EQ(0u, manager_.pending_timer_transmission_count()); - - // RTO fires again, but there is no packet to be RTO retransmitted. - EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false)); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)).Times(0); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(2u, stats_.rto_count); - // Verify a credit is raised up. - EXPECT_EQ(1u, manager_.pending_timer_transmission_count()); -} - TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeout) { - EnablePto(k2PTO); EXPECT_CALL(*send_algorithm_, PacingRate(_)) .WillRepeatedly(Return(QuicBandwidth::Zero())); EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) @@ -2722,7 +1835,7 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeout) { SendDataPacket(1, ENCRYPTION_FORWARD_SECURE); // Verify PTO is correctly set. QuicTime::Delta expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); QuicTime packet1_sent_time = clock_.Now(); EXPECT_EQ(clock_.Now() + expected_pto_delay, @@ -2730,12 +1843,8 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeout) { clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10)); SendDataPacket(2, ENCRYPTION_FORWARD_SECURE); - // Verify PTO is correctly set based on sent time of packet 2. - QuicTime deadline = clock_.Now() + expected_pto_delay; - if (GetQuicRestartFlag(quic_default_on_pto2)) { - // Verify PTO is set based on left edge. - deadline = packet1_sent_time + expected_pto_delay; - } + // Verify PTO is set based on left edge. + QuicTime deadline = packet1_sent_time + expected_pto_delay; EXPECT_EQ(deadline, manager_.GetRetransmissionTime()); EXPECT_EQ(0u, stats_.pto_count); @@ -2746,23 +1855,11 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeout) { EXPECT_EQ(1u, stats_.pto_count); EXPECT_EQ(0u, stats_.max_consecutive_rto_with_forward_progress); - if (GetQuicRestartFlag(quic_default_on_pto2)) { - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE); - }))); - } else { - // Verify two probe packets get sent. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .Times(2) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE); - }))) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(4, type, ENCRYPTION_FORWARD_SECURE); - }))); - } - manager_.MaybeSendProbePackets(); + EXPECT_CALL(notifier_, RetransmitFrames(_, _)) + .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { + return RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE); + }))); + manager_.MaybeSendProbePacket(); // Verify PTO period gets set to twice the current value. QuicTime sent_time = clock_.Now(); EXPECT_EQ(sent_time + expected_pto_delay * 2, @@ -2779,7 +1876,7 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeout) { ENCRYPTION_FORWARD_SECURE)); expected_pto_delay = rtt_stats->SmoothedOrInitialRtt() + - std::max(GetPtoRttvarMultiplier() * rtt_stats->mean_deviation(), + std::max(kPtoRttvarMultiplier * rtt_stats->mean_deviation(), QuicTime::Delta::FromMilliseconds(1)) + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); @@ -2789,7 +1886,6 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeout) { } TEST_F(QuicSentPacketManagerTest, SendOneProbePacket) { - EnablePto(k1PTO); EXPECT_CALL(*send_algorithm_, PacingRate(_)) .WillRepeatedly(Return(QuicBandwidth::Zero())); EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) @@ -2806,13 +1902,10 @@ TEST_F(QuicSentPacketManagerTest, SendOneProbePacket) { QuicTime::Delta srtt = rtt_stats->smoothed_rtt(); // Verify PTO period is correctly set. QuicTime::Delta expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); - QuicTime deadline = clock_.Now() + expected_pto_delay; - if (GetQuicRestartFlag(quic_default_on_pto2)) { - // Verify PTO is set based on left edge. - deadline = packet1_sent_time + expected_pto_delay; - } + // Verify PTO is set based on left edge. + QuicTime deadline = packet1_sent_time + expected_pto_delay; EXPECT_EQ(deadline, manager_.GetRetransmissionTime()); // Invoke PTO. @@ -2825,7 +1918,7 @@ TEST_F(QuicSentPacketManagerTest, SendOneProbePacket) { .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { return RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE); }))); - manager_.MaybeSendProbePackets(); + manager_.MaybeSendProbePacket(); } TEST_F(QuicSentPacketManagerTest, DisableHandshakeModeClient) { @@ -2883,269 +1976,7 @@ TEST_F(QuicSentPacketManagerTest, DisableHandshakeModeServer) { EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime()); } -TEST_F(QuicSentPacketManagerTest, PtoTimeoutIncludesMaxAckDelay) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - EnablePto(k1PTO); - // Use PTOS and PTOA. - QuicConfig config; - QuicTagVector options; - options.push_back(kPTOS); - options.push_back(kPTOA); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - EXPECT_TRUE(manager_.skip_packet_number_for_pto()); - EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true)); - - EXPECT_CALL(*send_algorithm_, PacingRate(_)) - .WillRepeatedly(Return(QuicBandwidth::Zero())); - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillRepeatedly(Return(10 * kDefaultTCPMSS)); - 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(); - - SendDataPacket(1, ENCRYPTION_FORWARD_SECURE); - QuicTime packet1_sent_time = clock_.Now(); - // Verify PTO is correctly set and ack delay is included. - QuicTime::Delta expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + - QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); - EXPECT_EQ(clock_.Now() + expected_pto_delay, - manager_.GetRetransmissionTime()); - - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10)); - SendDataPacket(2, ENCRYPTION_FORWARD_SECURE); - // Verify PTO is correctly set based on sent time of packet 2 but ack delay is - // not included as an immediate ACK is expected. - expected_pto_delay = expected_pto_delay - QuicTime::Delta::FromMilliseconds( - kDefaultDelayedAckTimeMs); - QuicTime deadline = clock_.Now() + expected_pto_delay; - if (GetQuicRestartFlag(quic_default_on_pto2)) { - deadline = packet1_sent_time + expected_pto_delay; - } - EXPECT_EQ(deadline, manager_.GetRetransmissionTime()); - EXPECT_EQ(0u, stats_.pto_count); - - // Invoke PTO. - clock_.AdvanceTime(deadline - clock_.Now()); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_EQ(1u, stats_.pto_count); - - // Verify 1 probe packets get sent and packet number gets skipped. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(4, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeSendProbePackets(); - // Verify PTO period gets set to twice the current value. Also, ack delay is - // not included. - QuicTime sent_time = clock_.Now(); - EXPECT_EQ(sent_time + expected_pto_delay * 2, - manager_.GetRetransmissionTime()); - - // Received ACK for packets 1 and 2. - uint64_t acked[] = {1, 2}; - ExpectAcksAndLosses(true, acked, ABSL_ARRAYSIZE(acked), nullptr, 0); - manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1), - ENCRYPTION_FORWARD_SECURE)); - expected_pto_delay = - rtt_stats->SmoothedOrInitialRtt() + - std::max(GetPtoRttvarMultiplier() * rtt_stats->mean_deviation(), - QuicTime::Delta::FromMilliseconds(1)) + - QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); - - // Verify PTO is correctly re-armed based on sent time of packet 4. Because of - // PTOS turns out to be spurious, ACK delay is included. - EXPECT_EQ(sent_time + expected_pto_delay, manager_.GetRetransmissionTime()); - - // Received ACK for packets 4. - ExpectAck(4); - manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(4), QuicPacketNumber(5)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(4), - ENCRYPTION_FORWARD_SECURE)); - EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime()); - // Send more packets, such that peer will do ack decimation. - std::vector<uint64_t> acked2; - for (size_t i = 5; i <= 100; ++i) { - SendDataPacket(i, ENCRYPTION_FORWARD_SECURE); - acked2.push_back(i); - } - // Received ACK for all sent packets. - ExpectAcksAndLosses(true, &acked2[0], acked2.size(), nullptr, 0); - manager_.OnAckFrameStart(QuicPacketNumber(100), QuicTime::Delta::Infinite(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(5), QuicPacketNumber(101)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(100), - ENCRYPTION_FORWARD_SECURE)); - - expected_pto_delay = - rtt_stats->SmoothedOrInitialRtt() + - std::max(GetPtoRttvarMultiplier() * rtt_stats->mean_deviation(), - QuicTime::Delta::FromMilliseconds(1)) + - QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); - for (size_t i = 101; i < 110; i++) { - SendDataPacket(i, ENCRYPTION_FORWARD_SECURE); - // Verify PTO timeout includes ACK delay as there are less than 10 packets - // outstanding. - EXPECT_EQ(clock_.Now() + expected_pto_delay, - manager_.GetRetransmissionTime()); - } - expected_pto_delay = expected_pto_delay - QuicTime::Delta::FromMilliseconds( - kDefaultDelayedAckTimeMs); - SendDataPacket(110, ENCRYPTION_FORWARD_SECURE); - // Verify ACK delay is excluded. - EXPECT_EQ(clock_.Now() + expected_pto_delay, - manager_.GetRetransmissionTime()); -} - -TEST_F(QuicSentPacketManagerTest, StartExponentialBackoffSince2ndPto) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - EnablePto(k2PTO); - QuicConfig config; - QuicTagVector options; - options.push_back(kPEB2); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - - EXPECT_CALL(*send_algorithm_, PacingRate(_)) - .WillRepeatedly(Return(QuicBandwidth::Zero())); - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillRepeatedly(Return(10 * kDefaultTCPMSS)); - 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(); - - SendDataPacket(1, ENCRYPTION_FORWARD_SECURE); - QuicTime packet1_sent_time = clock_.Now(); - // Verify PTO is correctly set. - QuicTime::Delta expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + - QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); - EXPECT_EQ(packet1_sent_time + expected_pto_delay, - manager_.GetRetransmissionTime()); - - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10)); - SendDataPacket(2, ENCRYPTION_FORWARD_SECURE); - // Verify PTO is correctly set based on sent time of packet 2. - QuicTime deadline = clock_.Now() + expected_pto_delay; - if (GetQuicRestartFlag(quic_default_on_pto2)) { - // Verify PTO is set based on left edge. - deadline = packet1_sent_time + expected_pto_delay; - } - EXPECT_EQ(deadline, manager_.GetRetransmissionTime()); - EXPECT_EQ(0u, stats_.pto_count); - - // Invoke PTO. - clock_.AdvanceTime(deadline - clock_.Now()); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_EQ(1u, stats_.pto_count); - - // Verify two probe packets get sent. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .Times(2) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE); - }))) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(4, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeSendProbePackets(); - // Verify no exponential backoff. - EXPECT_EQ(clock_.Now() + expected_pto_delay, - manager_.GetRetransmissionTime()); - - // Invoke 2nd PTO. - clock_.AdvanceTime(expected_pto_delay); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_EQ(2u, stats_.pto_count); - - // Verify two probe packets get sent. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .Times(2) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(5, type, ENCRYPTION_FORWARD_SECURE); - }))) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(6, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeSendProbePackets(); - // Verify still no exponential backoff. - EXPECT_EQ(clock_.Now() + expected_pto_delay, - manager_.GetRetransmissionTime()); - - // Invoke 3rd PTO. - clock_.AdvanceTime(expected_pto_delay); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_EQ(3u, stats_.pto_count); - - // Verify two probe packets get sent. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .Times(2) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(7, type, ENCRYPTION_FORWARD_SECURE); - }))) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(8, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeSendProbePackets(); - // Verify exponential backoff starts. - EXPECT_EQ(clock_.Now() + expected_pto_delay * 2, - manager_.GetRetransmissionTime()); - - // Invoke 4th PTO. - clock_.AdvanceTime(expected_pto_delay * 2); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_EQ(4u, stats_.pto_count); - - // Verify two probe packets get sent. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .Times(2) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(9, type, ENCRYPTION_FORWARD_SECURE); - }))) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(10, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeSendProbePackets(); - // Verify exponential backoff continues. - EXPECT_EQ(clock_.Now() + expected_pto_delay * 4, - manager_.GetRetransmissionTime()); -} - TEST_F(QuicSentPacketManagerTest, PtoTimeoutRttVarMultiple) { - EnablePto(k1PTO); - // Use 2 * rttvar - QuicConfig config; - QuicTagVector options; - options.push_back(kPVS1); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - EXPECT_CALL(*send_algorithm_, PacingRate(_)) .WillRepeatedly(Return(QuicBandwidth::Zero())); EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) @@ -3158,172 +1989,12 @@ TEST_F(QuicSentPacketManagerTest, PtoTimeoutRttVarMultiple) { SendDataPacket(1, ENCRYPTION_FORWARD_SECURE); // Verify PTO is correctly set based on 2 times rtt var. QuicTime::Delta expected_pto_delay = - srtt + 2 * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); EXPECT_EQ(clock_.Now() + expected_pto_delay, manager_.GetRetransmissionTime()); } -// Regression test for b/143962153 -TEST_F(QuicSentPacketManagerTest, RtoNotInFlightPacket) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2); - // Send SHLO. - QuicStreamFrame crypto_frame(1, false, 0, absl::string_view()); - SendCryptoPacket(1); - // Send data packet. - SendDataPacket(2, ENCRYPTION_FORWARD_SECURE); - - // Successfully decrypt a forward secure packet. - EXPECT_CALL(notifier_, OnFrameAcked(_, _, _)).Times(1); - manager_.SetHandshakeConfirmed(); - - // 1st TLP. - manager_.OnRetransmissionTimeout(); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeRetransmitTailLossProbe(); - - // 2nd TLP. - manager_.OnRetransmissionTimeout(); - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(4, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeRetransmitTailLossProbe(); - - // RTO retransmits SHLO although it is not in flight. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<0>(Invoke([&crypto_frame](const QuicFrames& frames) { - EXPECT_EQ(1u, frames.size()); - EXPECT_NE(crypto_frame, frames[0].stream_frame); - return true; - }))); - manager_.OnRetransmissionTimeout(); -} - -TEST_F(QuicSentPacketManagerTest, Aggressive1Pto) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - EnablePto(k1PTO); - // Let the first PTO be aggressive. - QuicConfig config; - QuicTagVector options; - options.push_back(kPTOS); - options.push_back(kPAG1); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - - EXPECT_CALL(*send_algorithm_, PacingRate(_)) - .WillRepeatedly(Return(QuicBandwidth::Zero())); - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillRepeatedly(Return(10 * kDefaultTCPMSS)); - 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(); - SendDataPacket(1, ENCRYPTION_FORWARD_SECURE); - // Verify PTO is correctly set. - QuicTime::Delta expected_pto_delay = 2 * srtt; - EXPECT_EQ(clock_.Now() + expected_pto_delay, - manager_.GetRetransmissionTime()); - - // Invoke PTO. - clock_.AdvanceTime(expected_pto_delay); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_EQ(1u, stats_.pto_count); - - // Verify 1 probe packets get sent and packet number gets skipped. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeSendProbePackets(); - - // Verify PTO period gets set correctly. - QuicTime sent_time = clock_.Now(); - expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + - QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); - EXPECT_EQ(sent_time + expected_pto_delay * 2, - manager_.GetRetransmissionTime()); -} - -TEST_F(QuicSentPacketManagerTest, Aggressive2Ptos) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - EnablePto(k1PTO); - // Let the first PTO be aggressive. - QuicConfig config; - QuicTagVector options; - options.push_back(kPTOS); - options.push_back(kPAG2); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - - EXPECT_CALL(*send_algorithm_, PacingRate(_)) - .WillRepeatedly(Return(QuicBandwidth::Zero())); - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillRepeatedly(Return(10 * kDefaultTCPMSS)); - 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(); - SendDataPacket(1, ENCRYPTION_FORWARD_SECURE); - // Verify PTO is correctly set. - QuicTime::Delta expected_pto_delay = 2 * srtt; - EXPECT_EQ(clock_.Now() + expected_pto_delay, - manager_.GetRetransmissionTime()); - - // Invoke PTO. - clock_.AdvanceTime(expected_pto_delay); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_EQ(1u, stats_.pto_count); - - // Verify 1 probe packets get sent and packet number gets skipped. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeSendProbePackets(); - - // Verify PTO period gets set correctly. - EXPECT_EQ(clock_.Now() + expected_pto_delay, - manager_.GetRetransmissionTime()); - - // Invoke 2nd PTO. - clock_.AdvanceTime(expected_pto_delay); - manager_.OnRetransmissionTimeout(); - EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now())); - EXPECT_EQ(2u, stats_.pto_count); - - // Verify 1 probe packets get sent and packet number gets skipped. - EXPECT_CALL(notifier_, RetransmitFrames(_, _)) - .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { - return RetransmitDataPacket(5, type, ENCRYPTION_FORWARD_SECURE); - }))); - manager_.MaybeSendProbePackets(); - expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + - QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); - - // Verify PTO period gets set correctly. - EXPECT_EQ(clock_.Now() + expected_pto_delay * 4, - manager_.GetRetransmissionTime()); -} - TEST_F(QuicSentPacketManagerTest, IW10ForUpAndDown) { QuicConfig config; QuicTagVector options; @@ -3339,7 +2010,6 @@ TEST_F(QuicSentPacketManagerTest, IW10ForUpAndDown) { TEST_F(QuicSentPacketManagerTest, ClientMultiplePacketNumberSpacePtoTimeout) { manager_.EnableMultiplePacketNumberSpacesSupport(); - EnablePto(k1PTO); EXPECT_CALL(*send_algorithm_, PacingRate(_)) .WillRepeatedly(Return(QuicBandwidth::Zero())); EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) @@ -3354,7 +2024,7 @@ TEST_F(QuicSentPacketManagerTest, ClientMultiplePacketNumberSpacePtoTimeout) { SendDataPacket(1, ENCRYPTION_INITIAL); // Verify PTO is correctly set. QuicTime::Delta expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::Zero(); EXPECT_EQ(clock_.Now() + expected_pto_delay, manager_.GetRetransmissionTime()); @@ -3381,7 +2051,7 @@ TEST_F(QuicSentPacketManagerTest, ClientMultiplePacketNumberSpacePtoTimeout) { .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { return RetransmitDataPacket(3, type, ENCRYPTION_HANDSHAKE); }))); - manager_.MaybeSendProbePackets(); + manager_.MaybeSendProbePacket(); // Verify PTO period gets set to twice the current value. const QuicTime packet3_sent_time = clock_.Now(); EXPECT_EQ(packet3_sent_time + expected_pto_delay * 2, @@ -3417,7 +2087,7 @@ TEST_F(QuicSentPacketManagerTest, ClientMultiplePacketNumberSpacePtoTimeout) { SendDataPacket(7, ENCRYPTION_HANDSHAKE); expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation(); + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation(); // Verify PTO timeout is now based on packet 7. EXPECT_EQ(packet7_sent_time + expected_pto_delay * 2, manager_.GetRetransmissionTime()); @@ -3427,7 +2097,7 @@ TEST_F(QuicSentPacketManagerTest, ClientMultiplePacketNumberSpacePtoTimeout) { // Forward progress has been made, verify PTO counter gets reset. PTO timeout // is armed by left edge. expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); EXPECT_EQ(packet4_sent_time + expected_pto_delay, manager_.GetRetransmissionTime()); @@ -3435,7 +2105,6 @@ TEST_F(QuicSentPacketManagerTest, ClientMultiplePacketNumberSpacePtoTimeout) { TEST_F(QuicSentPacketManagerTest, ServerMultiplePacketNumberSpacePtoTimeout) { manager_.EnableMultiplePacketNumberSpacesSupport(); - EnablePto(k1PTO); EXPECT_CALL(*send_algorithm_, PacingRate(_)) .WillRepeatedly(Return(QuicBandwidth::Zero())); EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) @@ -3450,7 +2119,7 @@ TEST_F(QuicSentPacketManagerTest, ServerMultiplePacketNumberSpacePtoTimeout) { const QuicTime packet1_sent_time = clock_.Now(); // Verify PTO is correctly set. QuicTime::Delta expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::Zero(); EXPECT_EQ(packet1_sent_time + expected_pto_delay, manager_.GetRetransmissionTime()); @@ -3485,7 +2154,7 @@ TEST_F(QuicSentPacketManagerTest, ServerMultiplePacketNumberSpacePtoTimeout) { // Discard handshake keys. manager_.SetHandshakeConfirmed(); expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); // Verify PTO timeout is now based on packet 3 as handshake is // complete/confirmed. @@ -3494,17 +2163,6 @@ TEST_F(QuicSentPacketManagerTest, ServerMultiplePacketNumberSpacePtoTimeout) { } TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge) { - EnablePto(k1PTO); - // Use PTOS and PLE1. - QuicConfig config; - QuicTagVector options; - options.push_back(kPTOS); - options.push_back(kPLE1); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - EXPECT_TRUE(manager_.skip_packet_number_for_pto()); EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true)); EXPECT_CALL(*send_algorithm_, PacingRate(_)) .WillRepeatedly(Return(QuicBandwidth::Zero())); @@ -3518,7 +2176,7 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge) { SendDataPacket(1, ENCRYPTION_FORWARD_SECURE); // Verify PTO is correctly set. QuicTime::Delta expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); const QuicTime packet1_sent_time = clock_.Now(); EXPECT_EQ(packet1_sent_time + expected_pto_delay, @@ -3541,7 +2199,7 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge) { .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { return RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE); }))); - manager_.MaybeSendProbePackets(); + manager_.MaybeSendProbePacket(); // Verify PTO period gets set to twice the current value and based on packet3. QuicTime packet3_sent_time = clock_.Now(); EXPECT_EQ(packet3_sent_time + expected_pto_delay * 2, @@ -3558,7 +2216,7 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge) { ENCRYPTION_FORWARD_SECURE)); expected_pto_delay = rtt_stats->SmoothedOrInitialRtt() + - std::max(GetPtoRttvarMultiplier() * rtt_stats->mean_deviation(), + std::max(kPtoRttvarMultiplier * rtt_stats->mean_deviation(), QuicTime::Delta::FromMilliseconds(1)) + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); @@ -3568,17 +2226,6 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge) { } TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge2) { - EnablePto(k1PTO); - // Use PTOS and PLE2. - QuicConfig config; - QuicTagVector options; - options.push_back(kPTOS); - options.push_back(kPLE2); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - EXPECT_TRUE(manager_.skip_packet_number_for_pto()); EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true)); EXPECT_CALL(*send_algorithm_, PacingRate(_)) .WillRepeatedly(Return(QuicBandwidth::Zero())); @@ -3592,7 +2239,7 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge2) { SendDataPacket(1, ENCRYPTION_FORWARD_SECURE); // Verify PTO is correctly set. QuicTime::Delta expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); const QuicTime packet1_sent_time = clock_.Now(); EXPECT_EQ(packet1_sent_time + expected_pto_delay, @@ -3603,7 +2250,7 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge2) { expected_pto_delay.ToMilliseconds() - 10)); SendDataPacket(2, ENCRYPTION_FORWARD_SECURE); // Verify PTO expands to packet 2 sent time + 1.5 * srtt. - expected_pto_delay = 1.5 * rtt_stats->smoothed_rtt(); + expected_pto_delay = kFirstPtoSrttMultiplier * rtt_stats->smoothed_rtt(); EXPECT_EQ(clock_.Now() + expected_pto_delay, manager_.GetRetransmissionTime()); EXPECT_EQ(0u, stats_.pto_count); @@ -3618,11 +2265,11 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge2) { .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) { return RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE); }))); - manager_.MaybeSendProbePackets(); + manager_.MaybeSendProbePacket(); // Verify PTO period gets set to twice the expected value and based on // packet3 (right edge). expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); QuicTime packet3_sent_time = clock_.Now(); EXPECT_EQ(packet3_sent_time + expected_pto_delay * 2, @@ -3639,7 +2286,7 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge2) { ENCRYPTION_FORWARD_SECURE)); expected_pto_delay = rtt_stats->SmoothedOrInitialRtt() + - std::max(GetPtoRttvarMultiplier() * rtt_stats->mean_deviation(), + std::max(kPtoRttvarMultiplier * rtt_stats->mean_deviation(), QuicTime::Delta::FromMilliseconds(1)) + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); @@ -3649,61 +2296,9 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge2) { manager_.GetRetransmissionTime()); } -TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutUsingStandardDeviation) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - EnablePto(k1PTO); - // Use PTOS and PSDA. - QuicConfig config; - QuicTagVector options; - options.push_back(kPTOS); - options.push_back(kPSDA); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - EXPECT_TRUE(manager_.skip_packet_number_for_pto()); - EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true)); - EXPECT_CALL(*send_algorithm_, PacingRate(_)) - .WillRepeatedly(Return(QuicBandwidth::Zero())); - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillRepeatedly(Return(10 * kDefaultTCPMSS)); - RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); - rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100), - QuicTime::Delta::Zero(), QuicTime::Zero()); - rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(50), - QuicTime::Delta::Zero(), QuicTime::Zero()); - rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(50), - QuicTime::Delta::Zero(), QuicTime::Zero()); - rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(75), - QuicTime::Delta::Zero(), QuicTime::Zero()); - QuicTime::Delta srtt = rtt_stats->smoothed_rtt(); - - SendDataPacket(1, ENCRYPTION_FORWARD_SECURE); - // Verify PTO is correctly set using standard deviation. - QuicTime::Delta expected_pto_delay = - srtt + - GetPtoRttvarMultiplier() * rtt_stats->GetStandardOrMeanDeviation() + - QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); - EXPECT_EQ(clock_.Now() + expected_pto_delay, - manager_.GetRetransmissionTime()); -} - TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdgeMultiplePacketNumberSpaces) { manager_.EnableMultiplePacketNumberSpacesSupport(); - EnablePto(k1PTO); - // Use PTOS and PLE1. - QuicConfig config; - QuicTagVector options; - options.push_back(kPTOS); - options.push_back(kPLE1); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - EXPECT_TRUE(manager_.skip_packet_number_for_pto()); EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true)); EXPECT_CALL(*send_algorithm_, PacingRate(_)) .WillRepeatedly(Return(QuicBandwidth::Zero())); @@ -3719,7 +2314,7 @@ TEST_F(QuicSentPacketManagerTest, const QuicTime packet1_sent_time = clock_.Now(); // Verify PTO is correctly set. QuicTime::Delta expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::Zero(); EXPECT_EQ(packet1_sent_time + expected_pto_delay, manager_.GetRetransmissionTime()); @@ -3756,7 +2351,7 @@ TEST_F(QuicSentPacketManagerTest, // Verify PTO timeout is now based on packet 3 as handshake is // complete/confirmed. expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); EXPECT_EQ(packet3_sent_time + expected_pto_delay, manager_.GetRetransmissionTime()); @@ -3771,17 +2366,6 @@ TEST_F(QuicSentPacketManagerTest, TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge2MultiplePacketNumberSpaces) { manager_.EnableMultiplePacketNumberSpacesSupport(); - EnablePto(k1PTO); - // Use PTOS and PLE2. - QuicConfig config; - QuicTagVector options; - options.push_back(kPTOS); - options.push_back(kPLE2); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - EXPECT_TRUE(manager_.skip_packet_number_for_pto()); EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true)); EXPECT_CALL(*send_algorithm_, PacingRate(_)) .WillRepeatedly(Return(QuicBandwidth::Zero())); @@ -3797,7 +2381,7 @@ TEST_F(QuicSentPacketManagerTest, const QuicTime packet1_sent_time = clock_.Now(); // Verify PTO is correctly set. QuicTime::Delta expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::Zero(); EXPECT_EQ(packet1_sent_time + expected_pto_delay, manager_.GetRetransmissionTime()); @@ -3834,7 +2418,7 @@ TEST_F(QuicSentPacketManagerTest, // Verify PTO timeout is now based on packet 3 as handshake is // complete/confirmed. expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); EXPECT_EQ(packet3_sent_time + expected_pto_delay, manager_.GetRetransmissionTime()); @@ -3844,7 +2428,7 @@ TEST_F(QuicSentPacketManagerTest, expected_pto_delay.ToMilliseconds() - 10)); SendDataPacket(5, ENCRYPTION_FORWARD_SECURE); // Verify PTO timeout expands to packet 5 sent time + 1.5 * srtt. - EXPECT_EQ(clock_.Now() + 1.5 * rtt_stats->smoothed_rtt(), + EXPECT_EQ(clock_.Now() + kFirstPtoSrttMultiplier * rtt_stats->smoothed_rtt(), manager_.GetRetransmissionTime()); } @@ -3908,56 +2492,7 @@ TEST_F(QuicSentPacketManagerTest, NoPacketThresholdDetectionForRuntPackets) { QuicSentPacketManagerPeer::UsePacketThresholdForRuntPackets(&manager_)); } -TEST_F(QuicSentPacketManagerTest, GetPathDegradingDelayNonPto) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2); - // Before RTT sample is available. - // 2 TLPs + 2 RTOs. - QuicTime::Delta expected_delay = QuicTime::Delta::Zero(); - for (size_t i = 0; i < 2; ++i) { - QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, i); - expected_delay = - expected_delay + - QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_); - } - for (size_t i = 0; i < 2; ++i) { - QuicSentPacketManagerPeer::SetConsecutiveRtoCount(&manager_, i); - expected_delay = - expected_delay + - QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_); - } - EXPECT_EQ(expected_delay, manager_.GetPathDegradingDelay()); - - expected_delay = QuicTime::Delta::Zero(); - QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, 0); - QuicSentPacketManagerPeer::SetConsecutiveRtoCount(&manager_, 0); - - // After RTT sample is available. - RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); - rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100), - QuicTime::Delta::Zero(), QuicTime::Zero()); - // 2 TLPs + 2 RTOs. - for (size_t i = 0; i < 2; ++i) { - QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, i); - expected_delay = - expected_delay + - QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_); - } - for (size_t i = 0; i < 2; ++i) { - QuicSentPacketManagerPeer::SetConsecutiveRtoCount(&manager_, i); - expected_delay = - expected_delay + - QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_); - } - EXPECT_EQ(expected_delay, manager_.GetPathDegradingDelay()); -} - TEST_F(QuicSentPacketManagerTest, GetPathDegradingDelayDefaultPTO) { - if (!GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); QuicTime::Delta expected_delay = 4 * manager_.GetPtoDelay(); EXPECT_EQ(expected_delay, manager_.GetPathDegradingDelay()); @@ -3965,34 +2500,26 @@ TEST_F(QuicSentPacketManagerTest, GetPathDegradingDelayDefaultPTO) { TEST_F(QuicSentPacketManagerTest, GetPathDegradingDelayUsing2PTO) { QuicConfig client_config; - QuicTagVector options; - options.push_back(k1PTO); QuicTagVector client_options; client_options.push_back(kPDP2); QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); - client_config.SetConnectionOptionsToSend(options); client_config.SetClientConnectionOptions(client_options); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); manager_.SetFromConfig(client_config); - EXPECT_TRUE(manager_.pto_enabled()); QuicTime::Delta expected_delay = 2 * manager_.GetPtoDelay(); EXPECT_EQ(expected_delay, manager_.GetPathDegradingDelay()); } TEST_F(QuicSentPacketManagerTest, GetPathDegradingDelayUsing1PTO) { QuicConfig client_config; - QuicTagVector options; - options.push_back(k1PTO); QuicTagVector client_options; client_options.push_back(kPDP1); QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); - client_config.SetConnectionOptionsToSend(options); client_config.SetClientConnectionOptions(client_options); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); manager_.SetFromConfig(client_config); - EXPECT_TRUE(manager_.pto_enabled()); QuicTime::Delta expected_delay = 1 * manager_.GetPtoDelay(); EXPECT_EQ(expected_delay, manager_.GetPathDegradingDelay()); } @@ -4068,10 +2595,7 @@ TEST_F(QuicSentPacketManagerTest, ExponentialBackoffWithNoRttMeasurement) { EXPECT_CALL(notifier_, RetransmitFrames(_, _)) .WillOnce( WithArgs<1>(Invoke([this]() { return RetransmitCryptoPacket(3); }))); - manager_.MaybeSendProbePackets(); - if (GetQuicRestartFlag(quic_default_on_pto2)) { - manager_.AdjustPendingTimerTransmissions(); - } + manager_.MaybeSendProbePacket(); // Verify exponential backoff of the PTO timeout. EXPECT_EQ(clock_.Now() + 2 * expected_pto_delay, manager_.GetRetransmissionTime()); @@ -4098,10 +2622,7 @@ TEST_F(QuicSentPacketManagerTest, PtoDelayWithTinyInitialRtt) { EXPECT_CALL(notifier_, RetransmitFrames(_, _)) .WillOnce( WithArgs<1>(Invoke([this]() { return RetransmitCryptoPacket(3); }))); - manager_.MaybeSendProbePackets(); - if (GetQuicRestartFlag(quic_default_on_pto2)) { - manager_.AdjustPendingTimerTransmissions(); - } + manager_.MaybeSendProbePacket(); // Verify exponential backoff of the PTO timeout. EXPECT_EQ(clock_.Now() + 2 * expected_pto_delay, manager_.GetRetransmissionTime()); @@ -4135,7 +2656,7 @@ TEST_F(QuicSentPacketManagerTest, HandshakeAckCausesInitialKeyDropping) { // Verify nothing to probe (and connection will send PING for current // encryption level). EXPECT_CALL(notifier_, RetransmitFrames(_, _)).Times(0); - manager_.MaybeSendProbePackets(); + manager_.MaybeSendProbePacket(); } // Regression test for b/156487311 @@ -4171,59 +2692,12 @@ TEST_F(QuicSentPacketManagerTest, ClearLastInflightPacketsSentTime) { RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); const QuicTime::Delta pto_delay = rtt_stats->smoothed_rtt() + - GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::Zero(); // Verify PTO is armed based on handshake data. EXPECT_EQ(packet2_sent_time + pto_delay, manager_.GetRetransmissionTime()); } -// Regression test for b/157895910. -TEST_F(QuicSentPacketManagerTest, EarliestSentTimeNotInitializedWhenPtoFires) { - if (GetQuicReloadableFlag(quic_simplify_set_retransmission_alarm)) { - return; - } - manager_.EnableMultiplePacketNumberSpacesSupport(); - EXPECT_CALL(*send_algorithm_, PacingRate(_)) - .WillRepeatedly(Return(QuicBandwidth::Zero())); - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillRepeatedly(Return(10 * kDefaultTCPMSS)); - - // Send INITIAL 1. - SendDataPacket(1, ENCRYPTION_INITIAL); - - // Send HANDSHAKE packets. - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10)); - SendDataPacket(2, ENCRYPTION_HANDSHAKE); - SendDataPacket(3, ENCRYPTION_HANDSHAKE); - SendDataPacket(4, ENCRYPTION_HANDSHAKE); - - // Send half RTT packet. - SendDataPacket(5, ENCRYPTION_FORWARD_SECURE); - - // Received ACK for INITIAL packet 1. - ExpectAck(1); - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(90)); - manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1), - ENCRYPTION_INITIAL)); - - // Received ACK for HANDSHAKE packets. - uint64_t acked[] = {2, 3, 4}; - ExpectAcksAndLosses(true, acked, ABSL_ARRAYSIZE(acked), nullptr, 0); - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(90)); - manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(), - clock_.Now()); - manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(5)); - EXPECT_EQ(PACKETS_NEWLY_ACKED, - manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(4), - ENCRYPTION_HANDSHAKE)); - // Verify PTO will not be armed. - EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime()); -} - TEST_F(QuicSentPacketManagerTest, MaybeRetransmitInitialData) { manager_.EnableMultiplePacketNumberSpacesSupport(); EXPECT_CALL(*send_algorithm_, PacingRate(_)) @@ -4246,7 +2720,7 @@ TEST_F(QuicSentPacketManagerTest, MaybeRetransmitInitialData) { SendDataPacket(3, ENCRYPTION_HANDSHAKE); // Verify PTO is correctly set based on packet 1. QuicTime::Delta expected_pto_delay = - srtt + GetPtoRttvarMultiplier() * rtt_stats->mean_deviation() + + srtt + kPtoRttvarMultiplier * rtt_stats->mean_deviation() + QuicTime::Delta::Zero(); EXPECT_EQ(packet1_sent_time + expected_pto_delay, manager_.GetRetransmissionTime()); @@ -4274,33 +2748,6 @@ TEST_F(QuicSentPacketManagerTest, MaybeRetransmitInitialData) { manager_.GetRetransmissionTime()); } -TEST_F(QuicSentPacketManagerTest, - AggressivePtoBeforeAnyRttSamplesAreAvailable) { - if (GetQuicRestartFlag(quic_default_on_pto2)) { - return; - } - manager_.EnableMultiplePacketNumberSpacesSupport(); - EXPECT_CALL(*send_algorithm_, PacingRate(_)) - .WillRepeatedly(Return(QuicBandwidth::Zero())); - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillRepeatedly(Return(10 * kDefaultTCPMSS)); - RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); - - QuicConfig config; - QuicTagVector options; - options.push_back(kAPTO); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(config); - - // Send INITIAL 1. - SendDataPacket(1, ENCRYPTION_INITIAL); - // Verify retransmission timeout is expected. - EXPECT_EQ(clock_.Now() + 1.5 * rtt_stats->initial_rtt(), - manager_.GetRetransmissionTime()); -} - TEST_F(QuicSentPacketManagerTest, SendPathChallengeAndGetAck) { QuicPacketNumber packet_number(1); EXPECT_CALL(*send_algorithm_, diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_server_id_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_server_id_test.cc index c4e5368f895..226a5176222 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_server_id_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_server_id_test.cc @@ -8,7 +8,7 @@ #include "quiche/quic/platform/api/quic_test.h" -namespace quic { +namespace quic::test { namespace { @@ -121,4 +121,4 @@ TEST_F(QuicServerIdTest, Equals) { } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session.cc index 8868fc59e42..d29760062ad 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session.cc @@ -543,7 +543,7 @@ void QuicSession::OnBlockedFrame(const QuicBlockedFrame& frame) { // streams: if we have a large window then maybe something // had gone wrong with the flow control accounting. QUIC_DLOG(INFO) << ENDPOINT << "Received BLOCKED frame with stream id: " - << frame.stream_id; + << frame.stream_id << ", offset: " << frame.offset; } bool QuicSession::CheckStreamNotBusyLooping(QuicStream* stream, @@ -692,14 +692,6 @@ void QuicSession::OnCanWrite() { } } -bool QuicSession::SendProbingData() { - if (connection()->sent_packet_manager().MaybeRetransmitOldestPacket( - PROBING_RETRANSMISSION)) { - return true; - } - return false; -} - bool QuicSession::WillingAndAbleToWrite() const { // Schedule a write when: // 1) control frame manager has pending or new control frames, or @@ -939,8 +931,8 @@ void QuicSession::SendGoAway(QuicErrorCode error_code, reason); } -void QuicSession::SendBlocked(QuicStreamId id) { - control_frame_manager_.WriteOrBufferBlocked(id); +void QuicSession::SendBlocked(QuicStreamId id, QuicStreamOffset byte_offset) { + control_frame_manager_.WriteOrBufferBlocked(id, byte_offset); } void QuicSession::SendWindowUpdate(QuicStreamId id, @@ -1002,11 +994,7 @@ void QuicSession::OnStreamClosed(QuicStreamId stream_id) { closed_streams_clean_up_alarm_->Set( connection_->clock()->ApproximateNow()); } - QUIC_BUG_IF( - 364846171_1, - connection_->packet_creator().HasPendingStreamFramesOfStream(stream_id)) - << "Stream " << stream_id - << " gets closed while there are pending frames."; + connection_->QuicBugIfHasPendingFrames(stream_id); } if (!stream->HasReceivedFinalOffset()) { @@ -1562,7 +1550,7 @@ bool QuicSession::OnNewDecryptionKeyAvailable( bool set_alternative_decrypter, bool latch_once_used) { if (connection_->version().handshake_protocol == PROTOCOL_TLS1_3 && !connection()->framer().HasEncrypterOfEncryptionLevel( - QuicUtils::GetEncryptionLevel( + QuicUtils::GetEncryptionLevelToSendAckofSpace( QuicUtils::GetPacketNumberSpace(level)))) { // This should never happen because connection should never decrypt a packet // while an ACK for it cannot be encrypted. @@ -2177,9 +2165,7 @@ void QuicSession::MaybeCloseZombieStream(QuicStreamId id) { } // Do not retransmit data of a closed stream. streams_with_pending_retransmission_.erase(id); - QUIC_BUG_IF(364846171_2, - connection_->packet_creator().HasPendingStreamFramesOfStream(id)) - << "Stream " << id << " gets closed while there are pending frames."; + connection_->QuicBugIfHasPendingFrames(id); } QuicStream* QuicSession::GetStream(QuicStreamId id) const { @@ -2285,10 +2271,7 @@ bool QuicSession::RetransmitFrames(const QuicFrames& frames, continue; } if (frame.type == CRYPTO_FRAME) { - const bool data_retransmitted = - GetMutableCryptoStream()->RetransmitData(frame.crypto_frame, type); - if (GetQuicRestartFlag(quic_set_packet_state_if_all_data_retransmitted) && - !data_retransmitted) { + if (!GetMutableCryptoStream()->RetransmitData(frame.crypto_frame, type)) { return false; } continue; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session.h index 3051cf60133..7bdcaa95f4d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session.h @@ -138,7 +138,6 @@ class QUIC_EXPORT_PRIVATE QuicSession const QuicSocketAddress& peer_address, bool is_connectivity_probe) override; void OnCanWrite() override; - bool SendProbingData() override; void OnCongestionWindowChange(QuicTime /*now*/) override {} void OnConnectionMigration(AddressChangeType /*type*/) override {} // Adds a connection level WINDOW_UPDATE frame. @@ -173,6 +172,7 @@ class QUIC_EXPORT_PRIVATE QuicSession const QuicSocketAddress& /*address*/) const override { return false; } + void OnBandwidthUpdateTimeout() override {} // QuicStreamFrameDataProducer WriteStreamDataResult WriteStreamData(QuicStreamId id, @@ -265,7 +265,7 @@ class QUIC_EXPORT_PRIVATE QuicSession virtual void SendGoAway(QuicErrorCode error_code, const std::string& reason); // Sends a BLOCKED frame. - virtual void SendBlocked(QuicStreamId id); + virtual void SendBlocked(QuicStreamId id, QuicStreamOffset byte_offset); // Sends a WINDOW_UPDATE frame. virtual void SendWindowUpdate(QuicStreamId id, QuicStreamOffset byte_offset); @@ -616,9 +616,6 @@ class QUIC_EXPORT_PRIVATE QuicSession virtual QuicSSLConfig GetSSLConfig() const { return QuicSSLConfig(); } - // Latched value of flag --quic_tls_server_support_client_cert. - bool support_client_cert() const { return support_client_cert_; } - // Try converting all pending streams to normal streams. void ProcessAllPendingStreams(); @@ -1005,9 +1002,6 @@ class QUIC_EXPORT_PRIVATE QuicSession // Whether BoringSSL randomizes the order of TLS extensions. bool permutes_tls_extensions_ = true; - - const bool support_client_cert_ = - GetQuicRestartFlag(quic_tls_server_support_client_cert); }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session_test.cc index ddda101d33c..9b90c4f169f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_session_test.cc @@ -38,6 +38,7 @@ #include "quiche/quic/test_tools/quic_stream_peer.h" #include "quiche/quic/test_tools/quic_stream_send_buffer_peer.h" #include "quiche/quic/test_tools/quic_test_utils.h" +#include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/quiche_mem_slice_storage.h" using spdy::kV3HighestPriority; @@ -181,6 +182,26 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker { SSL* GetSsl() const override { return nullptr; } + bool IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const override { + return level != ENCRYPTION_ZERO_RTT; + } + + EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const override { + switch (space) { + case INITIAL_DATA: + return ENCRYPTION_INITIAL; + case HANDSHAKE_DATA: + return ENCRYPTION_HANDSHAKE; + case APPLICATION_DATA: + return ENCRYPTION_FORWARD_SECURE; + default: + QUICHE_DCHECK(false); + return NUM_ENCRYPTION_LEVELS; + } + } + private: using QuicCryptoStream::session; @@ -2483,7 +2504,7 @@ TEST_P(QuicSessionTestServer, RetransmitFrames) { EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _, _)) .WillOnce(Return(true)); EXPECT_CALL(*send_algorithm, OnApplicationLimited(_)); - session_.RetransmitFrames(frames, TLP_RETRANSMISSION); + session_.RetransmitFrames(frames, PTO_RETRANSMISSION); } // Regression test of b/110082001. @@ -2954,7 +2975,11 @@ TEST_P(QuicSessionTestServer, WriteBufferedCryptoFrames) { EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, 350, 1000)) .WillOnce(Return(350)); - EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 1350, 0)) + EXPECT_CALL( + *connection_, + SendCryptoData(crypto_stream->GetEncryptionLevelToSendCryptoDataOfSpace( + QuicUtils::GetPacketNumberSpace(ENCRYPTION_ZERO_RTT)), + 1350, 0)) .WillOnce(Return(1350)); session_.OnCanWrite(); EXPECT_FALSE(session_.HasPendingHandshake()); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc index 7d1a9ddf49d..dcbb02acd22 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc @@ -150,7 +150,7 @@ void PendingStream::AddBytesConsumed(QuicByteCount bytes) { void PendingStream::ResetWithError(QuicResetStreamError /*error*/) { // Currently PendingStream is only read-unidirectional. It shouldn't send // Reset. - QUIC_NOTREACHED(); + QUICHE_NOTREACHED(); } void PendingStream::OnUnrecoverableError(QuicErrorCode error, @@ -741,15 +741,12 @@ void QuicStream::MaybeSendBlocked() { << ENDPOINT << "MaybeSendBlocked called on stream without flow control"; return; } - if (flow_controller_->ShouldSendBlocked()) { - session_->SendBlocked(id_); - } + flow_controller_->MaybeSendBlocked(); if (!stream_contributes_to_connection_flow_control_) { return; } - if (connection_flow_controller_->ShouldSendBlocked()) { - session_->SendBlocked(QuicUtils::GetInvalidStreamId(transport_version())); - } + connection_flow_controller_->MaybeSendBlocked(); + // If the stream is blocked by connection-level flow control but not by // stream-level flow control, add the stream to the write blocked list so that // the stream will be given a chance to write when a connection-level @@ -1139,8 +1136,7 @@ void QuicStream::OnStreamFrameLost(QuicStreamOffset offset, bool QuicStream::RetransmitStreamData(QuicStreamOffset offset, QuicByteCount data_length, bool fin, TransmissionType type) { - QUICHE_DCHECK(type == PTO_RETRANSMISSION || type == RTO_RETRANSMISSION || - type == TLP_RETRANSMISSION || type == PROBING_RETRANSMISSION); + QUICHE_DCHECK(type == PTO_RETRANSMISSION); if (HasDeadlinePassed()) { OnDeadlinePassed(); return true; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer.cc index 03fd99035d1..fa7684106ab 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer.cc @@ -292,6 +292,11 @@ QuicStreamOffset QuicStreamSequencer::NumBytesConsumed() const { return buffered_frames_.BytesConsumed(); } +bool QuicStreamSequencer::IsAllDataAvailable() const { + QUICHE_DCHECK_LE(NumBytesConsumed() + NumBytesBuffered(), close_offset_); + return NumBytesConsumed() + NumBytesBuffered() >= close_offset_; +} + const std::string QuicStreamSequencer::DebugString() const { // clang-format off return absl::StrCat("QuicStreamSequencer:", diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer.h index e201cc14067..9953c7555f3 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer.h @@ -139,6 +139,10 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencer { // Number of bytes has been consumed. QuicStreamOffset NumBytesConsumed() const; + // Returns true if all of the data within the stream up until the FIN is + // available. + bool IsAllDataAvailable() const; + QuicStreamOffset close_offset() const { return close_offset_; } int num_frames_received() const { return num_frames_received_; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer_test.cc index 0e57b094825..3ac6d88ba8d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer_test.cc @@ -223,8 +223,10 @@ TEST_F(QuicStreamSequencerTest, BlockedThenFullFrameConsumed) { ConsumeData(3); })); EXPECT_FALSE(sequencer_->IsClosed()); + EXPECT_FALSE(sequencer_->IsAllDataAvailable()); OnFinFrame(3, "def"); EXPECT_TRUE(sequencer_->IsClosed()); + EXPECT_TRUE(sequencer_->IsAllDataAvailable()); } TEST_F(QuicStreamSequencerTest, BlockedThenFullFrameAndFinConsumed) { @@ -239,6 +241,7 @@ TEST_F(QuicStreamSequencerTest, BlockedThenFullFrameAndFinConsumed) { ConsumeData(3); })); EXPECT_FALSE(sequencer_->IsClosed()); + EXPECT_TRUE(sequencer_->IsAllDataAvailable()); sequencer_->SetUnblocked(); EXPECT_TRUE(sequencer_->IsClosed()); EXPECT_EQ(0u, NumBufferedBytes()); @@ -260,6 +263,7 @@ TEST_F(QuicStreamSequencerTest, EmptyFinFrame) { OnFinFrame(0, ""); EXPECT_EQ(0u, NumBufferedBytes()); EXPECT_EQ(0u, sequencer_->NumBytesConsumed()); + EXPECT_TRUE(sequencer_->IsAllDataAvailable()); } TEST_F(QuicStreamSequencerTest, PartialFrameConsumed) { @@ -560,11 +564,14 @@ TEST_F(QuicStreamSequencerTest, MarkConsumedError) { // Now, attempt to mark consumed more data than was readable and expect the // stream to be closed. - EXPECT_CALL(stream_, ResetWithError(QuicResetStreamError::FromInternal( - QUIC_ERROR_PROCESSING_STREAM))); - EXPECT_QUIC_BUG(sequencer_->MarkConsumed(4), - "Invalid argument to MarkConsumed." - " expect to consume: 4, but not enough bytes available."); + EXPECT_QUIC_BUG( + { + EXPECT_CALL(stream_, ResetWithError(QuicResetStreamError::FromInternal( + QUIC_ERROR_PROCESSING_STREAM))); + sequencer_->MarkConsumed(4); + }, + "Invalid argument to MarkConsumed." + " expect to consume: 4, but not enough bytes available."); } TEST_F(QuicStreamSequencerTest, MarkConsumedWithMissingPacket) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_test.cc index dad793f936f..51b25a5f322 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_stream_test.cc @@ -480,9 +480,13 @@ TEST_P(QuicStreamTest, WriteOrBufferDataReachStreamLimit) { .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); stream_->WriteOrBufferData(data, false, nullptr); EXPECT_TRUE(session_->HasUnackedStreamData()); - EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _)); - EXPECT_QUIC_BUG(stream_->WriteOrBufferData("a", false, nullptr), - "Write too many data via stream"); + EXPECT_QUIC_BUG( + { + EXPECT_CALL(*connection_, + CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _)); + stream_->WriteOrBufferData("a", false, nullptr); + }, + "Write too many data via stream"); } TEST_P(QuicStreamTest, ConnectionCloseAfterStreamClose) { @@ -789,11 +793,14 @@ TEST_P(QuicStreamTest, OnStreamFrameUpperLimit) { TEST_P(QuicStreamTest, StreamTooLong) { Initialize(); - EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _)) - .Times(1); QuicStreamFrame stream_frame(stream_->id(), false, kMaxStreamLength, "."); EXPECT_QUIC_PEER_BUG( - stream_->OnStreamFrame(stream_frame), + { + EXPECT_CALL(*connection_, + CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _)) + .Times(1); + stream_->OnStreamFrame(stream_frame); + }, absl::StrCat("Receive stream frame on stream ", stream_->id(), " reaches max stream length")); } @@ -1237,9 +1244,13 @@ TEST_P(QuicStreamTest, WritevDataReachStreamLimit) { quiche::QuicheMemSliceStorage storage2( &iov2, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(), 1024); - EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _)); - EXPECT_QUIC_BUG(stream_->WriteMemSlices(storage2.ToSpan(), false), - "Write too many data via stream"); + EXPECT_QUIC_BUG( + { + EXPECT_CALL(*connection_, + CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _)); + stream_->WriteMemSlices(storage2.ToSpan(), false); + }, + "Write too many data via stream"); } TEST_P(QuicStreamTest, WriteMemSlices) { @@ -1328,9 +1339,13 @@ TEST_P(QuicStreamTest, WriteMemSlicesReachStreamLimit) { EXPECT_EQ(5u, consumed.bytes_consumed); quiche::QuicheMemSlice slice2 = MemSliceFromString("6"); - EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _)); - EXPECT_QUIC_BUG(stream_->WriteMemSlice(std::move(slice2), false), - "Write too many data via stream"); + EXPECT_QUIC_BUG( + { + EXPECT_CALL(*connection_, + CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _)); + stream_->WriteMemSlice(std::move(slice2), false); + }, + "Write too many data via stream"); } TEST_P(QuicStreamTest, StreamDataGetAckedMultipleTimes) { @@ -1510,8 +1525,7 @@ TEST_P(QuicStreamTest, MarkConnectionLevelWriteBlockedOnWindowUpdateFrame) { EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); - EXPECT_CALL(*session_, WriteControlFrame(_, _)) - .WillOnce(Invoke(&ClearControlFrameWithTransmissionType)); + EXPECT_CALL(*session_, SendBlocked(_, _)).Times(1); std::string data(1024, '.'); stream->WriteOrBufferData(data, false, nullptr); EXPECT_FALSE(HasWriteBlockedStreams()); @@ -1544,8 +1558,7 @@ TEST_P(QuicStreamTest, std::string data(100, '.'); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); - EXPECT_CALL(*session_, WriteControlFrame(_, _)) - .WillOnce(Invoke(&ClearControlFrameWithTransmissionType)); + EXPECT_CALL(*session_, SendBlocked(_, _)).Times(1); stream->WriteOrBufferData(data, false, nullptr); EXPECT_FALSE(HasWriteBlockedStreams()); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_trace_visitor_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_trace_visitor_test.cc index 9e255b97182..5584ebe65e4 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_trace_visitor_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_trace_visitor_test.cc @@ -11,7 +11,7 @@ #include "quiche/quic/test_tools/simulator/simulator.h" #include "quiche/quic/test_tools/simulator/switch.h" -namespace quic { +namespace quic::test { namespace { const QuicByteCount kTransferSize = 1000 * kMaxOutgoingPacketSize; @@ -181,4 +181,4 @@ TEST_F(QuicTraceVisitorTest, EncryptionLevels) { } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_types.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_types.cc index 389477bf598..62760c9678d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_types.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_types.cc @@ -214,10 +214,7 @@ std::string TransmissionTypeToString(TransmissionType transmission_type) { RETURN_STRING_LITERAL(HANDSHAKE_RETRANSMISSION); RETURN_STRING_LITERAL(ALL_ZERO_RTT_RETRANSMISSION); RETURN_STRING_LITERAL(LOSS_RETRANSMISSION); - RETURN_STRING_LITERAL(RTO_RETRANSMISSION); - RETURN_STRING_LITERAL(TLP_RETRANSMISSION); RETURN_STRING_LITERAL(PTO_RETRANSMISSION); - RETURN_STRING_LITERAL(PROBING_RETRANSMISSION); RETURN_STRING_LITERAL(PATH_RETRANSMISSION); RETURN_STRING_LITERAL(ALL_INITIAL_RETRANSMISSION); default: diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_types.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_types.h index b136708e4ff..c79633c70ea 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_types.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_types.h @@ -28,13 +28,6 @@ using QuicPacketLength = uint16_t; using QuicControlFrameId = uint32_t; using QuicMessageId = uint32_t; -// TODO(b/181256914) replace QuicDatagramStreamId with QuicStreamId once we -// remove support for draft-ietf-masque-h3-datagram-00 in favor of later drafts. -using QuicDatagramStreamId = uint64_t; -using QuicDatagramContextId = uint64_t; -// Note that for draft-ietf-masque-h3-datagram-00, we represent the flow ID as a -// QuicDatagramStreamId. - // IMPORTANT: IETF QUIC defines stream IDs and stream counts as being unsigned // 62-bit numbers. However, we have decided to only support up to 2^32-1 streams // in order to reduce the size of data structures such as QuicStreamFrame @@ -187,10 +180,7 @@ enum TransmissionType : int8_t { ALL_ZERO_RTT_RETRANSMISSION, // Retransmits all packets encrypted with 0-RTT // key. LOSS_RETRANSMISSION, // Retransmits due to loss detection. - RTO_RETRANSMISSION, // Retransmits due to retransmit time out. - TLP_RETRANSMISSION, // Tail loss probes. PTO_RETRANSMISSION, // Retransmission due to probe timeout. - PROBING_RETRANSMISSION, // Retransmission in order to probe bandwidth. PATH_RETRANSMISSION, // Retransmission proactively due to underlying // network change. ALL_INITIAL_RETRANSMISSION, // Retransmit all packets encrypted with INITIAL @@ -552,14 +542,8 @@ enum SentPacketState : uint8_t { HANDSHAKE_RETRANSMITTED, // This packet is considered as lost, this is used for LOST_RETRANSMISSION. LOST, - // This packet has been retransmitted when TLP fires. - TLP_RETRANSMITTED, - // This packet has been retransmitted when RTO fires. - RTO_RETRANSMITTED, // This packet has been retransmitted when PTO fires. PTO_RETRANSMITTED, - // This packet has been retransmitted for probing purpose. - PROBE_RETRANSMITTED, // This packet is sent on a different path or is a PING only packet. // Do not update RTT stats and congestion control if the packet is the // largest_acked of an incoming ACK. @@ -842,6 +826,8 @@ QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, QUIC_EXPORT_PRIVATE std::string KeyUpdateReasonString(KeyUpdateReason reason); +using QuicSignatureAlgorithmVector = absl::InlinedVector<uint16_t, 8>; + // QuicSSLConfig contains configurations to be applied on a SSL object, which // overrides the configurations in SSL_CTX. struct QUIC_NO_EXPORT QuicSSLConfig { @@ -852,7 +838,7 @@ struct QUIC_NO_EXPORT QuicSSLConfig { absl::optional<bool> disable_ticket_support; // If set, used to configure the SSL object with // SSL_set_signing_algorithm_prefs. - absl::optional<absl::InlinedVector<uint16_t, 8>> signing_algorithm_prefs; + absl::optional<QuicSignatureAlgorithmVector> signing_algorithm_prefs; // Client certificate mode for mTLS support. Only used at server side. ClientCertMode client_cert_mode = ClientCertMode::kNone; }; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_udp_socket_posix.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_udp_socket_posix.cc index c1ce940a7b5..c77d560c640 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_udp_socket_posix.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_udp_socket_posix.cc @@ -9,6 +9,7 @@ #include <sys/socket.h> #include <sys/types.h> +#include "absl/base/optimization.h" #include "quiche/quic/core/quic_udp_socket.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/quic/platform/api/quic_udp_socket_platform_api.h" @@ -413,13 +414,13 @@ void QuicUdpSocketApi::ReadPacket(QuicUdpSocketFd fd, return; } - if (QUIC_PREDICT_FALSE(hdr.msg_flags & MSG_CTRUNC)) { + if (ABSL_PREDICT_FALSE(hdr.msg_flags & MSG_CTRUNC)) { QUIC_BUG(quic_bug_10751_3) << "Control buffer too small. size:" << control_buffer.buffer_len; return; } - if (QUIC_PREDICT_FALSE(hdr.msg_flags & MSG_TRUNC) || + if (ABSL_PREDICT_FALSE(hdr.msg_flags & MSG_TRUNC) || // Normally "bytes_read > packet_buffer.buffer_len" implies the MSG_TRUNC // bit is set, but it is not the case if tested with config=android_arm64. static_cast<size_t>(bytes_read) > packet_buffer.buffer_len) { @@ -502,14 +503,14 @@ size_t QuicUdpSocketApi::ReadMultiplePackets(QuicUdpSocketFd fd, } msghdr& hdr = hdrs[i].msg_hdr; - if (QUIC_PREDICT_FALSE(hdr.msg_flags & MSG_CTRUNC)) { + if (ABSL_PREDICT_FALSE(hdr.msg_flags & MSG_CTRUNC)) { QUIC_BUG(quic_bug_10751_4) << "Control buffer too small. size:" << (*results)[i].control_buffer.buffer_len << ", need:" << hdr.msg_controllen; continue; } - if (QUIC_PREDICT_FALSE(hdr.msg_flags & MSG_TRUNC)) { + if (ABSL_PREDICT_FALSE(hdr.msg_flags & MSG_TRUNC)) { QUIC_LOG_FIRST_N(WARNING, 100) << "Received truncated QUIC packet: buffer size:" << (*results)[i].packet_buffer.buffer_len diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_unacked_packet_map_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_unacked_packet_map_test.cc index 3acb13a1c79..fc8ea983f95 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_unacked_packet_map_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_unacked_packet_map_test.cc @@ -402,8 +402,8 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitFourTimes) { std::vector<uint64_t> retransmittable2 = {1, 3}; VerifyRetransmittablePackets(&retransmittable2[0], retransmittable2.size()); - // TLP 3 (formerly 1) as 4, and don't remove 1 from unacked. - RetransmitAndSendPacket(3, 4, TLP_RETRANSMISSION); + // PTO 3 (formerly 1) as 4, and don't remove 1 from unacked. + RetransmitAndSendPacket(3, 4, PTO_RETRANSMISSION); SerializedPacket packet5(CreateRetransmittablePacket(5)); unacked_packets_.AddSentPacket(&packet5, NOT_RETRANSMISSION, now_, true, true); @@ -551,7 +551,7 @@ TEST_P(QuicUnackedPacketMapTest, CannotAggregateAckedControlFrames) { QuicWindowUpdateFrame window_update(1, 5, 100); QuicStreamFrame stream_frame1(3, false, 0, 100); QuicStreamFrame stream_frame2(3, false, 100, 100); - QuicBlockedFrame blocked(2, 5); + QuicBlockedFrame blocked(2, 5, 0); QuicGoAwayFrame go_away(3, QUIC_PEER_GOING_AWAY, 5, "Going away."); QuicTransmissionInfo info1; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils.cc index fcda2e6fa6e..fdfce7ef4b8 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils.cc @@ -170,10 +170,7 @@ const char* QuicUtils::SentPacketStateToString(SentPacketState state) { RETURN_STRING_LITERAL(NEUTERED); RETURN_STRING_LITERAL(HANDSHAKE_RETRANSMITTED); RETURN_STRING_LITERAL(LOST); - RETURN_STRING_LITERAL(TLP_RETRANSMITTED); - RETURN_STRING_LITERAL(RTO_RETRANSMITTED); RETURN_STRING_LITERAL(PTO_RETRANSMITTED); - RETURN_STRING_LITERAL(PROBE_RETRANSMITTED); RETURN_STRING_LITERAL(NOT_CONTRIBUTING_RTT); } return "INVALID_SENT_PACKET_STATE"; @@ -289,14 +286,8 @@ SentPacketState QuicUtils::RetransmissionTypeToPacketState( return HANDSHAKE_RETRANSMITTED; case LOSS_RETRANSMISSION: return LOST; - case TLP_RETRANSMISSION: - return TLP_RETRANSMITTED; - case RTO_RETRANSMISSION: - return RTO_RETRANSMITTED; case PTO_RETRANSMISSION: return PTO_RETRANSMITTED; - case PROBING_RETRANSMISSION: - return PROBE_RETRANSMITTED; case PATH_RETRANSMISSION: return NOT_CONTRIBUTING_RTT; case ALL_INITIAL_RETRANSMISSION: @@ -601,7 +592,7 @@ PacketNumberSpace QuicUtils::GetPacketNumberSpace( } // static -EncryptionLevel QuicUtils::GetEncryptionLevel( +EncryptionLevel QuicUtils::GetEncryptionLevelToSendAckofSpace( PacketNumberSpace packet_number_space) { switch (packet_number_space) { case INITIAL_DATA: diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils.h index 202dc4ba323..2d4d5e889f1 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils.h @@ -209,8 +209,8 @@ class QUIC_EXPORT_PRIVATE QuicUtils { static PacketNumberSpace GetPacketNumberSpace( EncryptionLevel encryption_level); - // Determines encryption level to send packets in |packet_number_space|. - static EncryptionLevel GetEncryptionLevel( + // Determines encryption level to send ACK in |packet_number_space|. + static EncryptionLevel GetEncryptionLevelToSendAckofSpace( PacketNumberSpace packet_number_space); // Get the maximum value for a V99/IETF QUIC stream count. If a count diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils_test.cc index 19ce4462e49..835cb977a3e 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_utils_test.cc @@ -129,14 +129,8 @@ TEST_F(QuicUtilsTest, RetransmissionTypeToPacketState) { EXPECT_EQ(LOST, state); } else if (i == ALL_ZERO_RTT_RETRANSMISSION) { EXPECT_EQ(UNACKABLE, state); - } else if (i == TLP_RETRANSMISSION) { - EXPECT_EQ(TLP_RETRANSMITTED, state); - } else if (i == RTO_RETRANSMISSION) { - EXPECT_EQ(RTO_RETRANSMITTED, state); } else if (i == PTO_RETRANSMISSION) { EXPECT_EQ(PTO_RETRANSMITTED, state); - } else if (i == PROBING_RETRANSMISSION) { - EXPECT_EQ(PROBE_RETRANSMITTED, state); } else if (i == PATH_RETRANSMISSION) { EXPECT_EQ(NOT_CONTRIBUTING_RTT, state); } else if (i == ALL_INITIAL_RETRANSMISSION) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_versions_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_versions_test.cc index 5dbfdd07ddf..58bab07c21a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_versions_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_versions_test.cc @@ -8,7 +8,6 @@ #include "quiche/quic/platform/api/quic_expect_bug.h" #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_logging.h" -#include "quiche/quic/platform/api/quic_mock_log.h" #include "quiche/quic/platform/api/quic_test.h" namespace quic { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_write_blocked_list.h b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_write_blocked_list.h index 8aa355e253c..3020c22b2fd 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/quic_write_blocked_list.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/quic_write_blocked_list.h @@ -13,7 +13,6 @@ #include "quiche/http2/core/priority_write_scheduler.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_flags.h" diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.cc index 90a9d7419be..36edcacc28d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.cc @@ -236,8 +236,7 @@ bool TlsClientHandshaker::SetTransportParameters() { session()->connection()->OnTransportParametersSent(params); std::vector<uint8_t> param_bytes; - return SerializeTransportParameters(session()->connection()->version(), - params, ¶m_bytes) && + return SerializeTransportParameters(params, ¶m_bytes) && SSL_set_quic_transport_params(ssl(), param_bytes.data(), param_bytes.size()) == 1; } @@ -357,6 +356,24 @@ bool TlsClientHandshaker::encryption_established() const { return encryption_established_; } +bool TlsClientHandshaker::IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const { + return level != ENCRYPTION_ZERO_RTT; +} + +EncryptionLevel TlsClientHandshaker::GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const { + switch (space) { + case INITIAL_DATA: + return ENCRYPTION_INITIAL; + case HANDSHAKE_DATA: + return ENCRYPTION_HANDSHAKE; + default: + QUICHE_DCHECK(false); + return NUM_ENCRYPTION_LEVELS; + } +} + bool TlsClientHandshaker::one_rtt_keys_available() const { return state_ >= HANDSHAKE_COMPLETE; } @@ -425,7 +442,7 @@ void TlsClientHandshaker::OnNewTokenReceived(absl::string_view token) { void TlsClientHandshaker::SetWriteSecret( EncryptionLevel level, const SSL_CIPHER* cipher, - const std::vector<uint8_t>& write_secret) { + absl::Span<const uint8_t> write_secret) { if (is_connection_closed()) { return; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.h b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.h index 15727e1d0e0..06581b54db4 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.h @@ -54,6 +54,10 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker // From QuicCryptoClientStream::HandshakerInterface and TlsHandshaker bool encryption_established() const override; + bool IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const override; + EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const override; bool one_rtt_keys_available() const override; const QuicCryptoNegotiatedParameters& crypto_negotiated_params() const override; @@ -70,7 +74,7 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker void OnHandshakeDoneReceived() override; void OnNewTokenReceived(absl::string_view token) override; void SetWriteSecret(EncryptionLevel level, const SSL_CIPHER* cipher, - const std::vector<uint8_t>& write_secret) override; + absl::Span<const uint8_t> write_secret) override; // Override to drop initial keys if trying to write ENCRYPTION_HANDSHAKE data. void WriteMessage(EncryptionLevel level, absl::string_view data) override; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker_test.cc index 91593d6e265..a1d5984dd1f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker_test.cc @@ -577,18 +577,22 @@ TEST_P(TlsClientHandshakerTest, ClientSendsNoSNI) { TEST_P(TlsClientHandshakerTest, ClientSendingTooManyALPNs) { std::string long_alpn(250, 'A'); - EXPECT_CALL(*session_, GetAlpnsToOffer()) - .WillOnce(testing::Return(std::vector<std::string>({ - long_alpn + "1", - long_alpn + "2", - long_alpn + "3", - long_alpn + "4", - long_alpn + "5", - long_alpn + "6", - long_alpn + "7", - long_alpn + "8", - }))); - EXPECT_QUIC_BUG(stream()->CryptoConnect(), "Failed to set ALPN"); + EXPECT_QUIC_BUG( + { + EXPECT_CALL(*session_, GetAlpnsToOffer()) + .WillOnce(testing::Return(std::vector<std::string>({ + long_alpn + "1", + long_alpn + "2", + long_alpn + "3", + long_alpn + "4", + long_alpn + "5", + long_alpn + "6", + long_alpn + "7", + long_alpn + "8", + }))); + stream()->CryptoConnect(); + }, + "Failed to set ALPN"); } TEST_P(TlsClientHandshakerTest, ServerRequiresCustomALPN) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.cc index 6f4f4ffbef7..0449c6779ae 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.cc @@ -85,7 +85,7 @@ bool TlsHandshaker::ProcessInput(absl::string_view input, } void TlsHandshaker::AdvanceHandshake() { - if (is_connection_closed_) { + if (is_connection_closed()) { return; } if (GetHandshakeState() >= HANDSHAKE_COMPLETE) { @@ -101,6 +101,13 @@ void TlsHandshaker::AdvanceHandshake() { QUIC_VLOG(1) << ENDPOINT << "Continuing handshake"; int rv = SSL_do_handshake(ssl()); + if (GetQuicReloadableFlag(quic_tls_handshaker_check_connection_closed) && + is_connection_closed()) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_tls_handshaker_check_connection_closed, 1, + 2); + return; + } + // If SSL_do_handshake return success(1) and we are in early data, it is // possible that we have provided ServerHello to BoringSSL but it hasn't been // processed. Retry SSL_do_handshake once will advance the handshake more in @@ -109,6 +116,14 @@ void TlsHandshaker::AdvanceHandshake() { if (rv == 1 && SSL_in_early_data(ssl())) { OnEnterEarlyData(); rv = SSL_do_handshake(ssl()); + + if (GetQuicReloadableFlag(quic_tls_handshaker_check_connection_closed) && + is_connection_closed()) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_tls_handshaker_check_connection_closed, + 2, 2); + return; + } + QUIC_VLOG(1) << ENDPOINT << "SSL_do_handshake returned when entering early data. After " << "retry, rv=" << rv @@ -120,7 +135,7 @@ void TlsHandshaker::AdvanceHandshake() { // SSL_in_early_data should be false. // // In either case, it should not both return 1 and stay in early data. - if (rv == 1 && SSL_in_early_data(ssl()) && !is_connection_closed_) { + if (rv == 1 && SSL_in_early_data(ssl()) && !is_connection_closed()) { QUIC_BUG(quic_handshaker_stay_in_early_data) << "The original and the retry of SSL_do_handshake both returned " "success and in early data"; @@ -139,7 +154,7 @@ void TlsHandshaker::AdvanceHandshake() { return; } if (ShouldCloseConnectionOnUnexpectedError(ssl_error) && - !is_connection_closed_) { + !is_connection_closed()) { QUIC_VLOG(1) << "SSL_do_handshake failed; SSL_get_error returns " << ssl_error; ERR_print_errors_fp(stderr); @@ -235,7 +250,7 @@ enum ssl_verify_result_t TlsHandshaker::VerifyCert(uint8_t* out_alert) { void TlsHandshaker::SetWriteSecret(EncryptionLevel level, const SSL_CIPHER* cipher, - const std::vector<uint8_t>& write_secret) { + absl::Span<const uint8_t> write_secret) { QUIC_DVLOG(1) << ENDPOINT << "SetWriteSecret level=" << level; std::unique_ptr<QuicEncrypter> encrypter = QuicEncrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); @@ -252,7 +267,7 @@ void TlsHandshaker::SetWriteSecret(EncryptionLevel level, header_protection_key.size())); if (level == ENCRYPTION_FORWARD_SECURE) { QUICHE_DCHECK(latest_write_secret_.empty()); - latest_write_secret_ = write_secret; + latest_write_secret_.assign(write_secret.begin(), write_secret.end()); one_rtt_write_header_protection_key_ = header_protection_key; } handshaker_delegate_->OnNewEncryptionKeyAvailable(level, @@ -261,7 +276,7 @@ void TlsHandshaker::SetWriteSecret(EncryptionLevel level, bool TlsHandshaker::SetReadSecret(EncryptionLevel level, const SSL_CIPHER* cipher, - const std::vector<uint8_t>& read_secret) { + absl::Span<const uint8_t> read_secret) { QUIC_DVLOG(1) << ENDPOINT << "SetReadSecret level=" << level; std::unique_ptr<QuicDecrypter> decrypter = QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); @@ -278,7 +293,7 @@ bool TlsHandshaker::SetReadSecret(EncryptionLevel level, header_protection_key.size())); if (level == ENCRYPTION_FORWARD_SECURE) { QUICHE_DCHECK(latest_read_secret_.empty()); - latest_read_secret_ = read_secret; + latest_read_secret_.assign(read_secret.begin(), read_secret.end()); one_rtt_read_header_protection_key_ = header_protection_key; } return handshaker_delegate_->OnNewDecryptionKeyAvailable( diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.h b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.h index ddd44c67fb8..d2e0ee487ba 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_handshaker.h @@ -138,14 +138,14 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate, // traffic secrets and application traffic secrets. The provided write secret // must be used with the provided cipher suite |cipher|. void SetWriteSecret(EncryptionLevel level, const SSL_CIPHER* cipher, - const std::vector<uint8_t>& write_secret) override; + absl::Span<const uint8_t> write_secret) override; // SetReadSecret is similar to SetWriteSecret, except that it is used for // decrypting messages. SetReadSecret at a particular level is always called // after SetWriteSecret for that level, except for ENCRYPTION_ZERO_RTT, where // the EncryptionLevel for SetWriteSecret is ENCRYPTION_FORWARD_SECURE. bool SetReadSecret(EncryptionLevel level, const SSL_CIPHER* cipher, - const std::vector<uint8_t>& read_secret) override; + absl::Span<const uint8_t> read_secret) override; // WriteMessage is called when there is |data| from the TLS stack ready for // the QUIC stack to write in a crypto frame. The data must be transmitted at diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc index ce63767bad3..c9781ccb583 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc @@ -185,9 +185,8 @@ TlsServerHandshaker::TlsServerHandshaker( crypto_negotiated_params_(new QuicCryptoNegotiatedParameters), tls_connection_(crypto_config->ssl_ctx(), this, session->GetSSLConfig()), crypto_config_(crypto_config) { - QUIC_DVLOG(1) << "TlsServerHandshaker: support_client_cert:" - << session->support_client_cert() - << ", client_cert_mode initial value: " << client_cert_mode(); + QUIC_DVLOG(1) << "TlsServerHandshaker: client_cert_mode initial value: " + << client_cert_mode(); QUICHE_DCHECK_EQ(PROTOCOL_TLS1_3, session->connection()->version().handshake_protocol); @@ -528,8 +527,7 @@ TlsServerHandshaker::SetTransportParameters() { { // Ensure |server_params_bytes| is not accessed out of the scope. std::vector<uint8_t> server_params_bytes; - if (!SerializeTransportParameters(session()->connection()->version(), - server_params, &server_params_bytes) || + if (!SerializeTransportParameters(server_params, &server_params_bytes) || SSL_set_quic_transport_params(ssl(), server_params_bytes.data(), server_params_bytes.size()) != 1) { return result; @@ -557,7 +555,7 @@ TlsServerHandshaker::SetTransportParameters() { void TlsServerHandshaker::SetWriteSecret( EncryptionLevel level, const SSL_CIPHER* cipher, - const std::vector<uint8_t>& write_secret) { + absl::Span<const uint8_t> write_secret) { if (is_connection_closed()) { return; } @@ -612,13 +610,6 @@ QuicAsyncStatus TlsServerHandshaker::VerifyCertChain( const std::vector<std::string>& /*certs*/, std::string* /*error_details*/, std::unique_ptr<ProofVerifyDetails>* /*details*/, uint8_t* /*out_alert*/, std::unique_ptr<ProofVerifierCallback> /*callback*/) { - if (!session()->support_client_cert()) { - QUIC_BUG(quic_bug_10341_5) - << "Client certificates are not yet supported on the server"; - return QUIC_FAILURE; - } - - QUIC_RESTART_FLAG_COUNT_N(quic_tls_server_support_client_cert, 2, 2); QUIC_DVLOG(1) << "VerifyCertChain returning success"; // No real verification here. A subclass can override this function to verify @@ -751,9 +742,8 @@ ssl_ticket_aead_result_t TlsServerHandshaker::SessionTicketOpen( } if (!ticket_decryption_callback_) { - ticket_decryption_callback_ = new DecryptCallback(this); - proof_source_->GetTicketCrypter()->Decrypt( - in, std::unique_ptr<DecryptCallback>(ticket_decryption_callback_)); + ticket_decryption_callback_ = std::make_shared<DecryptCallback>(this); + proof_source_->GetTicketCrypter()->Decrypt(in, ticket_decryption_callback_); // Decrypt can run the callback synchronously. In that case, the callback // will clear the ticket_decryption_callback_ pointer, and instead of @@ -981,13 +971,13 @@ void TlsServerHandshaker::OnSelectCertificateDone( ticket_encryption_key_ = std::string(ticket_encryption_key); select_cert_status_ = QUIC_FAILURE; cert_matched_sni_ = cert_matched_sni; - if (session()->support_client_cert()) { - if (delayed_ssl_config.client_cert_mode.has_value()) { - tls_connection_.SetClientCertMode(*delayed_ssl_config.client_cert_mode); - QUIC_DVLOG(1) << "client_cert_mode after cert selection: " - << client_cert_mode(); - } + + if (delayed_ssl_config.client_cert_mode.has_value()) { + tls_connection_.SetClientCertMode(*delayed_ssl_config.client_cert_mode); + QUIC_DVLOG(1) << "client_cert_mode after cert selection: " + << client_cert_mode(); } + if (ok) { if (chain && !chain->certs.empty()) { tls_connection_.SetCertChain(chain->ToCryptoBuffers().value); @@ -1134,4 +1124,24 @@ TlsServerHandshaker::SetApplicationSettings(absl::string_view alpn) { SSL* TlsServerHandshaker::GetSsl() const { return ssl(); } +bool TlsServerHandshaker::IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const { + return level != ENCRYPTION_ZERO_RTT; +} + +EncryptionLevel TlsServerHandshaker::GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const { + switch (space) { + case INITIAL_DATA: + return ENCRYPTION_INITIAL; + case HANDSHAKE_DATA: + return ENCRYPTION_HANDSHAKE; + case APPLICATION_DATA: + return ENCRYPTION_FORWARD_SECURE; + default: + QUICHE_DCHECK(false); + return NUM_ENCRYPTION_LEVELS; + } +} + } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h index 6385eda3c9b..05b63ae9663 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h @@ -71,6 +71,10 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker bool ExportKeyingMaterial(absl::string_view label, absl::string_view context, size_t result_len, std::string* result) override; SSL* GetSsl() const override; + bool IsCryptoFrameExpectedForEncryptionLevel( + EncryptionLevel level) const override; + EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const override; // From QuicCryptoServerStreamBase and TlsHandshaker ssl_early_data_reason_t EarlyDataReason() const override; @@ -87,7 +91,7 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker override; std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override; void SetWriteSecret(EncryptionLevel level, const SSL_CIPHER* cipher, - const std::vector<uint8_t>& write_secret) override; + absl::Span<const uint8_t> write_secret) override; // Called with normalized SNI hostname as |hostname|. Return value will be // sent in an ACCEPT_CH frame in the TLS ALPS extension, unless empty. @@ -321,7 +325,7 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker // |ticket_decryption_callback_| points to the non-owned callback that was // passed to ProofSource::TicketCrypter::Decrypt but hasn't finished running // yet. - DecryptCallback* ticket_decryption_callback_ = nullptr; + std::shared_ptr<DecryptCallback> ticket_decryption_callback_; // |decrypted_session_ticket_| contains the decrypted session ticket after the // callback has run but before it is passed to BoringSSL. std::vector<uint8_t> decrypted_session_ticket_; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker_test.cc index 34ec60c1654..e652f052c75 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker_test.cc @@ -924,11 +924,7 @@ TEST_P(TlsServerHandshakerTest, RequestClientCert) { CompleteCryptoHandshake(); ExpectHandshakeSuccessful(); - if (GetQuicRestartFlag(quic_tls_server_support_client_cert)) { - EXPECT_TRUE(server_handshaker_->received_client_cert()); - } else { - EXPECT_FALSE(server_handshaker_->received_client_cert()); - } + EXPECT_TRUE(server_handshaker_->received_client_cert()); } TEST_P(TlsServerHandshakerTest, RequestClientCertByDelayedSslConfig) { @@ -950,11 +946,7 @@ TEST_P(TlsServerHandshakerTest, RequestClientCertByDelayedSslConfig) { CompleteCryptoHandshake(); ExpectHandshakeSuccessful(); - if (GetQuicRestartFlag(quic_tls_server_support_client_cert)) { - EXPECT_TRUE(server_handshaker_->received_client_cert()); - } else { - EXPECT_FALSE(server_handshaker_->received_client_cert()); - } + EXPECT_TRUE(server_handshaker_->received_client_cert()); } TEST_P(TlsServerHandshakerTest, RequestClientCert_NoCert) { @@ -983,12 +975,7 @@ TEST_P(TlsServerHandshakerTest, RequestAndRequireClientCert) { CompleteCryptoHandshake(); ExpectHandshakeSuccessful(); - - if (GetQuicRestartFlag(quic_tls_server_support_client_cert)) { - EXPECT_TRUE(server_handshaker_->received_client_cert()); - } else { - EXPECT_FALSE(server_handshaker_->received_client_cert()); - } + EXPECT_TRUE(server_handshaker_->received_client_cert()); } TEST_P(TlsServerHandshakerTest, RequestAndRequireClientCertByDelayedSslConfig) { @@ -1010,11 +997,7 @@ TEST_P(TlsServerHandshakerTest, RequestAndRequireClientCertByDelayedSslConfig) { CompleteCryptoHandshake(); ExpectHandshakeSuccessful(); - if (GetQuicRestartFlag(quic_tls_server_support_client_cert)) { - EXPECT_TRUE(server_handshaker_->received_client_cert()); - } else { - EXPECT_FALSE(server_handshaker_->received_client_cert()); - } + EXPECT_TRUE(server_handshaker_->received_client_cert()); } TEST_P(TlsServerHandshakerTest, RequestAndRequireClientCert_NoCert) { @@ -1025,10 +1008,9 @@ TEST_P(TlsServerHandshakerTest, RequestAndRequireClientCert_NoCert) { /*compute_signature_action=*/FakeProofSourceHandle::Action:: DELEGATE_SYNC); - if (GetQuicRestartFlag(quic_tls_server_support_client_cert)) { - EXPECT_CALL(*server_connection_, - CloseConnection(QUIC_TLS_CERTIFICATE_REQUIRED, _, _, _)); - } + EXPECT_CALL(*server_connection_, + CloseConnection(QUIC_TLS_CERTIFICATE_REQUIRED, _, _, _)); + AdvanceHandshakeWithFakeClient(); AdvanceHandshakeWithFakeClient(); EXPECT_FALSE(server_handshaker_->received_client_cert()); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/uber_received_packet_manager_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/core/uber_received_packet_manager_test.cc index 030e55c4cac..ad62d8fe2a8 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/uber_received_packet_manager_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/core/uber_received_packet_manager_test.cc @@ -33,6 +33,20 @@ const QuicTime::Delta kMinRttMs = QuicTime::Delta::FromMilliseconds(40); const QuicTime::Delta kDelayedAckTime = QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); +EncryptionLevel GetEncryptionLevel(PacketNumberSpace packet_number_space) { + switch (packet_number_space) { + case INITIAL_DATA: + return ENCRYPTION_INITIAL; + case HANDSHAKE_DATA: + return ENCRYPTION_HANDSHAKE; + case APPLICATION_DATA: + return ENCRYPTION_FORWARD_SECURE; + default: + QUICHE_DCHECK(false); + return NUM_ENCRYPTION_LEVELS; + } +} + class UberReceivedPacketManagerTest : public QuicTest { protected: UberReceivedPacketManagerTest() { @@ -108,7 +122,7 @@ class UberReceivedPacketManagerTest : public QuicTest { continue; } manager_->ResetAckStates( - QuicUtils::GetEncryptionLevel(static_cast<PacketNumberSpace>(i))); + GetEncryptionLevel(static_cast<PacketNumberSpace>(i))); } } @@ -544,15 +558,9 @@ TEST_F(UberReceivedPacketManagerTest, CheckAckTimeout(clock_.ApproximateNow()); EXPECT_TRUE(HasPendingAck()); - if (GetQuicReloadableFlag(quic_update_ack_timeout_on_receipt_time)) { - // Verify ACK delay is based on packet receipt time. - CheckAckTimeout(clock_.ApproximateNow() - - QuicTime::Delta::FromMilliseconds(11) + kDelayedAckTime); - } else { - // Delayed ack is scheduled. - CheckAckTimeout(clock_.ApproximateNow() - - QuicTime::Delta::FromMilliseconds(1) + kDelayedAckTime); - } + // Verify ACK delay is based on packet receipt time. + CheckAckTimeout(clock_.ApproximateNow() - + QuicTime::Delta::FromMilliseconds(11) + kDelayedAckTime); } } // namespace diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc index 8fd5e52d63a..2d686dfad08 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc @@ -29,9 +29,9 @@ DEFINE_QUICHE_COMMAND_LINE_FLAG( bool, disable_certificate_verification, false, "If true, don't verify the server certificate."); -DEFINE_QUICHE_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, currently only valid value is \"open\"."); namespace quic { @@ -54,14 +54,16 @@ int RunMasqueClient(int argc, char* argv[]) { } const bool disable_certificate_verification = - GetQuicFlag(FLAGS_disable_certificate_verification); + quiche::GetQuicheCommandLineFlag(FLAGS_disable_certificate_verification); QuicEpollServer epoll_server; std::string uri_template = urls[0]; if (!absl::StrContains(uri_template, '/')) { - // Allow passing in authority instead of URI template. + // If an authority is passed in instead of a URI template, use the default + // URI template. uri_template = - absl::StrCat("https://", uri_template, "/{target_host}/{target_port}/"); + absl::StrCat("https://", uri_template, + "/.well-known/masque/udp/{target_host}/{target_port}/"); } url::Parsed parsed_uri_template; url::ParseStandardURL(uri_template.c_str(), uri_template.length(), @@ -82,10 +84,8 @@ int RunMasqueClient(int argc, char* argv[]) { proof_verifier = CreateDefaultProofVerifier(host); } MasqueMode masque_mode = MasqueMode::kOpen; - std::string mode_string = GetQuicFlag(FLAGS_masque_mode); - if (mode_string == "legacy") { - masque_mode = MasqueMode::kLegacy; - } else if (!mode_string.empty() && mode_string != "open") { + std::string mode_string = quiche::GetQuicheCommandLineFlag(FLAGS_masque_mode); + if (!mode_string.empty() && mode_string != "open") { std::cerr << "Invalid masque_mode \"" << mode_string << "\"" << std::endl; return 1; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc index fc6da5acccd..28ba839f758 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc @@ -4,12 +4,14 @@ #include "quiche/quic/masque/masque_client_session.h" +#include <cstring> #include <string> #include "absl/algorithm/container.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" #include "url/url_canon.h" #include "quiche/quic/core/http/spdy_utils.h" #include "quiche/quic/core/quic_data_reader.h" @@ -30,42 +32,7 @@ MasqueClientSession::MasqueClientSession( crypto_config, push_promise_index), masque_mode_(masque_mode), uri_template_(uri_template), - owner_(owner), - compression_engine_(this) {} - -void MasqueClientSession::OnMessageReceived(absl::string_view message) { - if (masque_mode_ == MasqueMode::kLegacy) { - QUIC_DVLOG(1) << "Received DATAGRAM frame of length " << message.length(); - QuicConnectionId client_connection_id, server_connection_id; - QuicSocketAddress target_server_address; - std::vector<char> packet; - bool version_present; - if (!compression_engine_.DecompressDatagram( - message, &client_connection_id, &server_connection_id, - &target_server_address, &packet, &version_present)) { - return; - } - - auto connection_id_registration = - client_connection_id_registrations_.find(client_connection_id); - if (connection_id_registration == - client_connection_id_registrations_.end()) { - QUIC_DLOG(ERROR) << "MasqueClientSession failed to dispatch " - << client_connection_id; - return; - } - EncapsulatedClientSession* encapsulated_client_session = - connection_id_registration->second; - encapsulated_client_session->ProcessPacket( - absl::string_view(packet.data(), packet.size()), target_server_address); - - QUIC_DVLOG(1) << "Sent " << packet.size() << " bytes to connection for " - << client_connection_id; - return; - } - QUICHE_DCHECK_EQ(masque_mode_, MasqueMode::kOpen); - QuicSpdySession::OnMessageReceived(message); -} + owner_(owner) {} void MasqueClientSession::OnMessageAcked(QuicMessageId message_id, QuicTime /*receive_timestamp*/) { @@ -157,10 +124,7 @@ MasqueClientSession::GetOrCreateConnectUdpClientState( headers[":scheme"] = scheme; headers[":authority"] = authority; headers[":path"] = canonicalized_path; - headers["connect-udp-version"] = "6"; - if (http_datagram_support() == HttpDatagramSupport::kDraft00) { - SpdyUtils::AddDatagramFlowIdHeader(&headers, stream->id()); - } + headers["connect-udp-version"] = "12"; size_t bytes_sent = stream->SendRequest(std::move(headers), /*body=*/"", /*fin=*/false); if (bytes_sent == 0) { @@ -168,24 +132,14 @@ MasqueClientSession::GetOrCreateConnectUdpClientState( return nullptr; } - absl::optional<QuicDatagramContextId> context_id; - connect_udp_client_states_.push_back( - ConnectUdpClientState(stream, encapsulated_client_session, this, - context_id, target_server_address)); + connect_udp_client_states_.push_back(ConnectUdpClientState( + stream, encapsulated_client_session, this, target_server_address)); return &connect_udp_client_states_.back(); } void MasqueClientSession::SendPacket( - QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, absl::string_view packet, - const QuicSocketAddress& target_server_address, + absl::string_view packet, const QuicSocketAddress& target_server_address, EncapsulatedClientSession* encapsulated_client_session) { - if (masque_mode_ == MasqueMode::kLegacy) { - compression_engine_.CompressAndSendPacket(packet, client_connection_id, - server_connection_id, - target_server_address); - return; - } const ConnectUdpClientState* connect_udp = GetOrCreateConnectUdpClientState( target_server_address, encapsulated_client_session); if (connect_udp == nullptr) { @@ -193,55 +147,25 @@ void MasqueClientSession::SendPacket( return; } - MessageStatus message_status = SendHttp3Datagram( - connect_udp->stream()->id(), connect_udp->context_id(), packet); + std::string http_payload; + http_payload.resize(1 + packet.size()); + http_payload[0] = 0; + memcpy(&http_payload[1], packet.data(), packet.size()); + MessageStatus message_status = + SendHttp3Datagram(connect_udp->stream()->id(), http_payload); QUIC_DVLOG(1) << "Sent packet to " << target_server_address << " compressed with stream ID " << connect_udp->stream()->id() - << " context ID " - << (connect_udp->context_id().has_value() - ? absl::StrCat(connect_udp->context_id().value()) - : "none") << " and got message status " << MessageStatusToString(message_status); } -void MasqueClientSession::RegisterConnectionId( - QuicConnectionId client_connection_id, +void MasqueClientSession::CloseConnectUdpStream( EncapsulatedClientSession* encapsulated_client_session) { - QUIC_DLOG(INFO) << "Registering " << client_connection_id - << " to encapsulated client"; - QUICHE_DCHECK( - client_connection_id_registrations_.find(client_connection_id) == - client_connection_id_registrations_.end() || - client_connection_id_registrations_[client_connection_id] == - encapsulated_client_session); - client_connection_id_registrations_[client_connection_id] = - encapsulated_client_session; -} - -void MasqueClientSession::UnregisterConnectionId( - QuicConnectionId client_connection_id, - EncapsulatedClientSession* encapsulated_client_session) { - QUIC_DLOG(INFO) << "Unregistering " << client_connection_id; - if (masque_mode_ == MasqueMode::kLegacy) { - if (client_connection_id_registrations_.find(client_connection_id) != - client_connection_id_registrations_.end()) { - client_connection_id_registrations_.erase(client_connection_id); - owner_->UnregisterClientConnectionId(client_connection_id); - compression_engine_.UnregisterClientConnectionId(client_connection_id); - } - return; - } - for (auto it = connect_udp_client_states_.begin(); it != connect_udp_client_states_.end();) { if (it->encapsulated_client_session() == encapsulated_client_session) { - QUIC_DLOG(INFO) << "Removing state for stream ID " << it->stream()->id() - << " context ID " - << (it->context_id().has_value() - ? absl::StrCat(it->context_id().value()) - : "none"); + QUIC_DLOG(INFO) << "Removing state for stream ID " << it->stream()->id(); auto* stream = it->stream(); it = connect_udp_client_states_.erase(it); if (!stream->write_side_closed()) { @@ -279,10 +203,7 @@ void MasqueClientSession::OnStreamClosed(QuicStreamId stream_id) { it != connect_udp_client_states_.end();) { if (it->stream()->id() == stream_id) { QUIC_DLOG(INFO) << "Stream " << stream_id - << " was closed, removing state for context ID " - << (it->context_id().has_value() - ? absl::StrCat(it->context_id().value()) - : "none"); + << " was closed, removing state"; auto* encapsulated_client_session = it->encapsulated_client_session(); it = connect_udp_client_states_.erase(it); encapsulated_client_session->CloseConnection( @@ -316,24 +237,18 @@ MasqueClientSession::ConnectUdpClientState::ConnectUdpClientState( QuicSpdyClientStream* stream, EncapsulatedClientSession* encapsulated_client_session, MasqueClientSession* masque_session, - absl::optional<QuicDatagramContextId> context_id, const QuicSocketAddress& target_server_address) : stream_(stream), encapsulated_client_session_(encapsulated_client_session), masque_session_(masque_session), - context_id_(context_id), target_server_address_(target_server_address) { QUICHE_DCHECK_NE(masque_session_, nullptr); - this->stream()->RegisterHttp3DatagramRegistrationVisitor(this); - this->stream()->RegisterHttp3DatagramContextId( - this->context_id(), DatagramFormatType::UDP_PAYLOAD, - /*format_additional_data=*/absl::string_view(), this); + this->stream()->RegisterHttp3DatagramVisitor(this); } MasqueClientSession::ConnectUdpClientState::~ConnectUdpClientState() { if (stream() != nullptr) { - stream()->UnregisterHttp3DatagramContextId(context_id()); - stream()->UnregisterHttp3DatagramRegistrationVisitor(); + stream()->UnregisterHttp3DatagramVisitor(); } } @@ -348,88 +263,33 @@ MasqueClientSession::ConnectUdpClientState::operator=( stream_ = other.stream_; encapsulated_client_session_ = other.encapsulated_client_session_; masque_session_ = other.masque_session_; - context_id_ = other.context_id_; target_server_address_ = other.target_server_address_; other.stream_ = nullptr; if (stream() != nullptr) { - stream()->MoveHttp3DatagramRegistration(this); - stream()->MoveHttp3DatagramContextIdRegistration(context_id(), this); + stream()->ReplaceHttp3DatagramVisitor(this); } return *this; } void MasqueClientSession::ConnectUdpClientState::OnHttp3Datagram( - QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id, - absl::string_view payload) { + QuicStreamId stream_id, absl::string_view payload) { QUICHE_DCHECK_EQ(stream_id, stream()->id()); - QUICHE_DCHECK(context_id == context_id_); - encapsulated_client_session_->ProcessPacket(payload, target_server_address_); - QUIC_DVLOG(1) << "Sent " << payload.size() - << " bytes to connection for stream ID " << stream_id - << " context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) - : "none"); -} - -void MasqueClientSession::ConnectUdpClientState::OnContextReceived( - QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id, - DatagramFormatType format_type, absl::string_view format_additional_data) { - if (stream_id != stream_->id()) { - QUIC_BUG(MASQUE client bad datagram context registration) - << "Registered stream ID " << stream_id << ", expected " - << stream_->id(); - return; - } - if (format_type != DatagramFormatType::UDP_PAYLOAD) { - QUIC_DLOG(INFO) << "Ignoring unexpected datagram format type " - << DatagramFormatTypeToString(format_type); - return; - } - if (!format_additional_data.empty()) { - QUIC_DLOG(ERROR) - << "Received non-empty format additional data for context ID " - << (context_id_.has_value() ? context_id_.value() : 0) - << " on stream ID " << stream()->id(); - masque_session_->ResetStream(stream()->id(), QUIC_STREAM_CANCELLED); - return; - } - if (context_id != context_id_) { - QUIC_DLOG(INFO) - << "Ignoring unexpected context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) : "none") - << " instead of " - << (context_id_.has_value() ? absl::StrCat(context_id_.value()) - : "none") - << " on stream ID " << stream_->id(); - return; - } - // Do nothing since the client registers first and we currently ignore - // extensions. -} - -void MasqueClientSession::ConnectUdpClientState::OnContextClosed( - QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id, - ContextCloseCode close_code, absl::string_view close_details) { - if (stream_id != stream_->id()) { - QUIC_BUG(MASQUE client bad datagram context registration) - << "Closed context on stream ID " << stream_id << ", expected " - << stream_->id(); + QuicDataReader reader(payload); + uint64_t context_id; + if (!reader.ReadVarInt62(&context_id)) { + QUIC_DLOG(ERROR) << "Failed to read context ID"; return; } - if (context_id != context_id_) { - QUIC_DLOG(INFO) - << "Ignoring unexpected close of context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) : "none") - << " instead of " - << (context_id_.has_value() ? absl::StrCat(context_id_.value()) - : "none") - << " on stream ID " << stream_->id(); + if (context_id != 0) { + QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID " + << context_id; return; } - QUIC_DLOG(INFO) << "Received datagram context close with close code " - << close_code << " close details \"" << close_details - << "\" on stream ID " << stream_->id() << ", closing stream"; - masque_session_->ResetStream(stream_->id(), QUIC_STREAM_CANCELLED); + absl::string_view http_payload = reader.ReadRemainingPayload(); + encapsulated_client_session_->ProcessPacket(http_payload, + target_server_address_); + QUIC_DVLOG(1) << "Sent " << http_payload.size() + << " bytes to connection for stream ID " << stream_id; } } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.h b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.h index 07673c32aaf..66c7e2ee35a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.h @@ -10,7 +10,6 @@ #include "absl/container/flat_hash_map.h" #include "absl/strings/string_view.h" #include "quiche/quic/core/http/quic_spdy_client_session.h" -#include "quiche/quic/masque/masque_compression_engine.h" #include "quiche/quic/masque/masque_utils.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_socket_address.h" @@ -30,10 +29,6 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession { public: virtual ~Owner() {} - // Notifies the owner that the client connection ID is no longer in use. - virtual void UnregisterClientConnectionId( - QuicConnectionId client_connection_id) = 0; - // Notifies the owner that a settings frame has been received. virtual void OnSettingsReceived() = 0; }; @@ -70,7 +65,6 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession { MasqueClientSession& operator=(const MasqueClientSession&) = delete; // From QuicSession. - void OnMessageReceived(absl::string_view message) override; void OnMessageAcked(QuicMessageId message_id, QuicTime receive_timestamp) override; void OnMessageLost(QuicMessageId message_id) override; @@ -82,33 +76,18 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession { bool OnSettingsFrame(const SettingsFrame& frame) override; // Send encapsulated packet. - void SendPacket(QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - absl::string_view packet, + void SendPacket(absl::string_view packet, const QuicSocketAddress& target_server_address, EncapsulatedClientSession* encapsulated_client_session); - // Register encapsulated client. This allows clients that are encapsulated - // within this MASQUE session to indicate they own a given client connection - // ID so incoming packets with that connection ID are routed back to them. - // Callers must not register a second different |encapsulated_client_session| - // with the same |client_connection_id|. Every call must be matched with a - // call to UnregisterConnectionId. - void RegisterConnectionId( - QuicConnectionId client_connection_id, - EncapsulatedClientSession* encapsulated_client_session); - - // Unregister encapsulated client. |client_connection_id| must match a - // value previously passed to RegisterConnectionId. - void UnregisterConnectionId( - QuicConnectionId client_connection_id, + // Close CONNECT-UDP stream tied to this encapsulated client session. + void CloseConnectUdpStream( EncapsulatedClientSession* encapsulated_client_session); private: // State that the MasqueClientSession keeps for each CONNECT-UDP request. class QUIC_NO_EXPORT ConnectUdpClientState - : public QuicSpdyStream::Http3DatagramRegistrationVisitor, - public QuicSpdyStream::Http3DatagramVisitor { + : public QuicSpdyStream::Http3DatagramVisitor { public: // |stream| and |encapsulated_client_session| must be valid for the lifetime // of the ConnectUdpClientState. @@ -116,7 +95,6 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession { QuicSpdyClientStream* stream, EncapsulatedClientSession* encapsulated_client_session, MasqueClientSession* masque_session, - absl::optional<QuicDatagramContextId> context_id, const QuicSocketAddress& target_server_address); ~ConnectUdpClientState(); @@ -131,38 +109,23 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession { EncapsulatedClientSession* encapsulated_client_session() const { return encapsulated_client_session_; } - absl::optional<QuicDatagramContextId> context_id() const { - return context_id_; - } const QuicSocketAddress& target_server_address() const { return target_server_address_; } // From QuicSpdyStream::Http3DatagramVisitor. void OnHttp3Datagram(QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, absl::string_view payload) override; - // From QuicSpdyStream::Http3DatagramRegistrationVisitor. - void OnContextReceived(QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - DatagramFormatType format_type, - absl::string_view format_additional_data) override; - void OnContextClosed(QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - ContextCloseCode close_code, - absl::string_view close_details) override; - private: QuicSpdyClientStream* stream_; // Unowned. EncapsulatedClientSession* encapsulated_client_session_; // Unowned. MasqueClientSession* masque_session_; // Unowned. - absl::optional<QuicDatagramContextId> context_id_; QuicSocketAddress target_server_address_; }; HttpDatagramSupport LocalHttpDatagramSupport() override { - return HttpDatagramSupport::kDraft00And04; + return HttpDatagramSupport::kDraft09; } const ConnectUdpClientState* GetOrCreateConnectUdpClientState( @@ -172,11 +135,7 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession { MasqueMode masque_mode_; std::string uri_template_; std::list<ConnectUdpClientState> connect_udp_client_states_; - absl::flat_hash_map<QuicConnectionId, EncapsulatedClientSession*, - QuicConnectionIdHash> - client_connection_id_registrations_; Owner* owner_; // Unowned; - MasqueCompressionEngine compression_engine_; }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_compression_engine.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_compression_engine.cc deleted file mode 100644 index 3d057407c5c..00000000000 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_compression_engine.cc +++ /dev/null @@ -1,526 +0,0 @@ -// Copyright 2019 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 "quiche/quic/masque/masque_compression_engine.h" - -#include <cstdint> - -#include "absl/strings/string_view.h" -#include "quiche/quic/core/quic_data_reader.h" -#include "quiche/quic/core/quic_data_writer.h" -#include "quiche/quic/core/quic_framer.h" -#include "quiche/quic/core/quic_session.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_containers.h" -#include "quiche/common/platform/api/quiche_mem_slice.h" -#include "quiche/common/quiche_buffer_allocator.h" -#include "quiche/common/quiche_text_utils.h" - -namespace quic { - -namespace { -// |kFlowId0| is used to indicate creation of a new compression context. -const QuicDatagramStreamId kFlowId0 = 0; - -enum MasqueAddressFamily : uint8_t { - MasqueAddressFamilyIPv4 = 4, - MasqueAddressFamilyIPv6 = 6, -}; - -} // namespace - -MasqueCompressionEngine::MasqueCompressionEngine( - QuicSpdySession* masque_session) - : masque_session_(masque_session), - next_available_flow_id_( - masque_session_->perspective() == Perspective::IS_CLIENT ? 0 : 1) {} - -QuicDatagramStreamId MasqueCompressionEngine::FindOrCreateCompressionContext( - QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address, bool client_connection_id_present, - bool server_connection_id_present, bool* validated) { - QuicDatagramStreamId flow_id = kFlowId0; - *validated = false; - for (const auto& kv : contexts_) { - const MasqueCompressionContext& context = kv.second; - if (context.server_address != server_address) { - continue; - } - if (client_connection_id_present && - context.client_connection_id != client_connection_id) { - continue; - } - if (server_connection_id_present && - context.server_connection_id != server_connection_id) { - continue; - } - - flow_id = kv.first; - QUICHE_DCHECK_NE(flow_id, kFlowId0); - *validated = context.validated; - QUIC_DVLOG(1) << "Compressing using " << (*validated ? "" : "un") - << "validated flow_id " << flow_id << " to " - << context.server_address << " client " - << context.client_connection_id << " server " - << context.server_connection_id; - break; - } - - if (flow_id != kFlowId0) { - // Found a compression context, use it. - return flow_id; - } - - // Create new compression context. - next_available_flow_id_ += 2; - flow_id = next_available_flow_id_; - QUIC_DVLOG(1) << "Compression assigning new flow_id " << flow_id << " to " - << server_address << " client " << client_connection_id - << " server " << server_connection_id; - MasqueCompressionContext context; - context.client_connection_id = client_connection_id; - context.server_connection_id = server_connection_id; - context.server_address = server_address; - contexts_[flow_id] = context; - - return flow_id; -} - -bool MasqueCompressionEngine::WriteCompressedPacketToSlice( - QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address, - QuicConnectionId destination_connection_id, - QuicConnectionId source_connection_id, QuicDatagramStreamId flow_id, - bool validated, uint8_t first_byte, bool long_header, - QuicDataReader* reader, QuicDataWriter* writer) { - if (validated) { - QUIC_DVLOG(1) << "Compressing using validated flow_id " << flow_id; - if (!writer->WriteVarInt62(flow_id)) { - QUIC_BUG(quic_bug_10981_1) << "Failed to write flow_id"; - return false; - } - } else { - QUIC_DVLOG(1) << "Compressing using unvalidated flow_id " << flow_id; - if (!writer->WriteVarInt62(kFlowId0)) { - QUIC_BUG(quic_bug_10981_2) << "Failed to write kFlowId0"; - return false; - } - if (!writer->WriteVarInt62(flow_id)) { - QUIC_BUG(quic_bug_10981_3) << "Failed to write flow_id"; - return false; - } - if (!writer->WriteLengthPrefixedConnectionId(client_connection_id)) { - QUIC_BUG(quic_bug_10981_4) << "Failed to write client_connection_id"; - return false; - } - if (!writer->WriteLengthPrefixedConnectionId(server_connection_id)) { - QUIC_BUG(quic_bug_10981_5) << "Failed to write server_connection_id"; - return false; - } - if (!writer->WriteUInt16(server_address.port())) { - QUIC_BUG(quic_bug_10981_6) << "Failed to write port"; - return false; - } - QuicIpAddress peer_ip = server_address.host(); - QUICHE_DCHECK(peer_ip.IsInitialized()); - std::string peer_ip_bytes = peer_ip.ToPackedString(); - QUICHE_DCHECK(!peer_ip_bytes.empty()); - uint8_t address_id; - if (peer_ip.address_family() == IpAddressFamily::IP_V6) { - address_id = MasqueAddressFamilyIPv6; - if (peer_ip_bytes.length() != QuicIpAddress::kIPv6AddressSize) { - QUIC_BUG(quic_bug_10981_7) << "Bad IPv6 length " << server_address; - return false; - } - } else if (peer_ip.address_family() == IpAddressFamily::IP_V4) { - address_id = MasqueAddressFamilyIPv4; - if (peer_ip_bytes.length() != QuicIpAddress::kIPv4AddressSize) { - QUIC_BUG(quic_bug_10981_8) << "Bad IPv4 length " << server_address; - return false; - } - } else { - QUIC_BUG(quic_bug_10981_9) - << "Unexpected server_address " << server_address; - return false; - } - if (!writer->WriteUInt8(address_id)) { - QUIC_BUG(quic_bug_10981_10) << "Failed to write address_id"; - return false; - } - if (!writer->WriteStringPiece(peer_ip_bytes)) { - QUIC_BUG(quic_bug_10981_11) << "Failed to write IP address"; - return false; - } - } - if (!writer->WriteUInt8(first_byte)) { - QUIC_BUG(quic_bug_10981_12) << "Failed to write first_byte"; - return false; - } - if (long_header) { - QuicVersionLabel version_label; - if (!reader->ReadUInt32(&version_label)) { - QUIC_DLOG(ERROR) << "Failed to read version"; - return false; - } - if (!writer->WriteUInt32(version_label)) { - QUIC_BUG(quic_bug_10981_13) << "Failed to write version"; - return false; - } - QuicConnectionId packet_destination_connection_id, - packet_source_connection_id; - if (!reader->ReadLengthPrefixedConnectionId( - &packet_destination_connection_id) || - !reader->ReadLengthPrefixedConnectionId(&packet_source_connection_id)) { - QUIC_DLOG(ERROR) << "Failed to parse long header connection IDs"; - return false; - } - if (packet_destination_connection_id != destination_connection_id) { - QUIC_DLOG(ERROR) << "Long header packet's destination_connection_id " - << packet_destination_connection_id - << " does not match expected " - << destination_connection_id; - return false; - } - if (packet_source_connection_id != source_connection_id) { - QUIC_DLOG(ERROR) << "Long header packet's source_connection_id " - << packet_source_connection_id - << " does not match expected " << source_connection_id; - return false; - } - } else { - QuicConnectionId packet_destination_connection_id; - if (!reader->ReadConnectionId(&packet_destination_connection_id, - destination_connection_id.length())) { - QUIC_DLOG(ERROR) - << "Failed to read short header packet's destination_connection_id"; - return false; - } - if (packet_destination_connection_id != destination_connection_id) { - QUIC_DLOG(ERROR) << "Short header packet's destination_connection_id " - << packet_destination_connection_id - << " does not match expected " - << destination_connection_id; - return false; - } - } - absl::string_view packet_payload = reader->ReadRemainingPayload(); - if (!writer->WriteStringPiece(packet_payload)) { - QUIC_BUG(quic_bug_10981_14) << "Failed to write packet_payload"; - return false; - } - return true; -} - -void MasqueCompressionEngine::CompressAndSendPacket( - absl::string_view packet, QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address) { - QUIC_DVLOG(2) << "Compressing client " << client_connection_id << " server " - << server_connection_id << "\n" - << quiche::QuicheTextUtils::HexDump(packet); - QUICHE_DCHECK(server_address.IsInitialized()); - if (packet.empty()) { - QUIC_BUG(quic_bug_10981_15) << "Tried to send empty packet"; - return; - } - QuicDataReader reader(packet.data(), packet.length()); - uint8_t first_byte; - if (!reader.ReadUInt8(&first_byte)) { - QUIC_BUG(quic_bug_10981_16) << "Failed to read first_byte"; - return; - } - const bool long_header = (first_byte & FLAGS_LONG_HEADER) != 0; - bool client_connection_id_present = true, server_connection_id_present = true; - QuicConnectionId destination_connection_id, source_connection_id; - if (masque_session_->perspective() == Perspective::IS_SERVER) { - destination_connection_id = client_connection_id; - source_connection_id = server_connection_id; - if (!long_header) { - server_connection_id_present = false; - } - } else { - destination_connection_id = server_connection_id; - source_connection_id = client_connection_id; - if (!long_header) { - client_connection_id_present = false; - } - } - - bool validated = false; - QuicDatagramStreamId flow_id = FindOrCreateCompressionContext( - client_connection_id, server_connection_id, server_address, - client_connection_id_present, server_connection_id_present, &validated); - - size_t slice_length = packet.length() - destination_connection_id.length(); - if (long_header) { - slice_length -= sizeof(uint8_t) * 2 + source_connection_id.length(); - } - if (validated) { - slice_length += QuicDataWriter::GetVarInt62Len(flow_id); - } else { - slice_length += QuicDataWriter::GetVarInt62Len(kFlowId0) + - QuicDataWriter::GetVarInt62Len(flow_id) + sizeof(uint8_t) + - client_connection_id.length() + sizeof(uint8_t) + - server_connection_id.length() + - sizeof(server_address.port()) + sizeof(uint8_t) + - server_address.host().ToPackedString().length(); - } - quiche::QuicheBuffer buffer( - masque_session_->connection()->helper()->GetStreamSendBufferAllocator(), - slice_length); - QuicDataWriter writer(buffer.size(), buffer.data()); - - if (!WriteCompressedPacketToSlice( - client_connection_id, server_connection_id, server_address, - destination_connection_id, source_connection_id, flow_id, validated, - first_byte, long_header, &reader, &writer)) { - return; - } - - MessageResult message_result = - masque_session_->SendMessage(quiche::QuicheMemSlice(std::move(buffer))); - - QUIC_DVLOG(1) << "Sent packet compressed with flow ID " << flow_id - << " and got message result " << message_result; -} - -bool MasqueCompressionEngine::ParseCompressionContext( - QuicDataReader* reader, MasqueCompressionContext* context) { - QuicDatagramStreamId new_flow_id; - if (!reader->ReadVarInt62(&new_flow_id)) { - QUIC_DLOG(ERROR) << "Could not read new_flow_id"; - return false; - } - QuicConnectionId new_client_connection_id; - if (!reader->ReadLengthPrefixedConnectionId(&new_client_connection_id)) { - QUIC_DLOG(ERROR) << "Could not read new_client_connection_id"; - return false; - } - QuicConnectionId new_server_connection_id; - if (!reader->ReadLengthPrefixedConnectionId(&new_server_connection_id)) { - QUIC_DLOG(ERROR) << "Could not read new_server_connection_id"; - return false; - } - uint16_t port; - if (!reader->ReadUInt16(&port)) { - QUIC_DLOG(ERROR) << "Could not read port"; - return false; - } - uint8_t address_id; - if (!reader->ReadUInt8(&address_id)) { - QUIC_DLOG(ERROR) << "Could not read address_id"; - return false; - } - size_t ip_bytes_length; - if (address_id == MasqueAddressFamilyIPv6) { - ip_bytes_length = QuicIpAddress::kIPv6AddressSize; - } else if (address_id == MasqueAddressFamilyIPv4) { - ip_bytes_length = QuicIpAddress::kIPv4AddressSize; - } else { - QUIC_DLOG(ERROR) << "Unknown address_id " << static_cast<int>(address_id); - return false; - } - char ip_bytes[QuicIpAddress::kMaxAddressSize]; - if (!reader->ReadBytes(ip_bytes, ip_bytes_length)) { - QUIC_DLOG(ERROR) << "Could not read IP address"; - return false; - } - QuicIpAddress ip_address; - ip_address.FromPackedString(ip_bytes, ip_bytes_length); - if (!ip_address.IsInitialized()) { - QUIC_BUG(quic_bug_10981_17) << "Failed to parse IP address"; - return false; - } - QuicSocketAddress new_server_address = QuicSocketAddress(ip_address, port); - auto context_pair = contexts_.find(new_flow_id); - if (context_pair == contexts_.end()) { - context->client_connection_id = new_client_connection_id; - context->server_connection_id = new_server_connection_id; - context->server_address = new_server_address; - context->validated = true; - contexts_[new_flow_id] = *context; - QUIC_DVLOG(1) << "Registered new flow_id " << new_flow_id << " to " - << new_server_address << " client " - << new_client_connection_id << " server " - << new_server_connection_id; - } else { - *context = context_pair->second; - if (context->client_connection_id != new_client_connection_id) { - QUIC_LOG(ERROR) - << "Received incorrect context registration for existing flow_id " - << new_flow_id << " mismatched client " - << context->client_connection_id << " " << new_client_connection_id; - return false; - } - if (context->server_connection_id != new_server_connection_id) { - QUIC_LOG(ERROR) - << "Received incorrect context registration for existing flow_id " - << new_flow_id << " mismatched server " - << context->server_connection_id << " " << new_server_connection_id; - return false; - } - if (context->server_address != new_server_address) { - QUIC_LOG(ERROR) - << "Received incorrect context registration for existing flow_id " - << new_flow_id << " mismatched server " << context->server_address - << " " << new_server_address; - return false; - } - if (!context->validated) { - context->validated = true; - contexts_[new_flow_id] = *context; - QUIC_DLOG(INFO) << "Successfully validated remotely-unvalidated flow_id " - << new_flow_id << " to " << new_server_address - << " client " << new_client_connection_id << " server " - << new_server_connection_id; - } else { - QUIC_DVLOG(1) << "Decompressing using incoming locally-validated " - "remotely-unvalidated flow_id " - << new_flow_id << " to " << new_server_address << " client " - << new_client_connection_id << " server " - << new_server_connection_id; - } - } - return true; -} - -bool MasqueCompressionEngine::WriteDecompressedPacket( - QuicDataReader* reader, const MasqueCompressionContext& context, - std::vector<char>* packet, bool* version_present) { - QuicConnectionId destination_connection_id, source_connection_id; - if (masque_session_->perspective() == Perspective::IS_SERVER) { - destination_connection_id = context.server_connection_id; - source_connection_id = context.client_connection_id; - } else { - destination_connection_id = context.client_connection_id; - source_connection_id = context.server_connection_id; - } - - size_t packet_length = - reader->BytesRemaining() + destination_connection_id.length(); - uint8_t first_byte; - if (!reader->ReadUInt8(&first_byte)) { - QUIC_DLOG(ERROR) << "Failed to read first_byte"; - return false; - } - *version_present = (first_byte & FLAGS_LONG_HEADER) != 0; - if (*version_present) { - packet_length += sizeof(uint8_t) * 2 + source_connection_id.length(); - } - *packet = std::vector<char>(packet_length); - QuicDataWriter writer(packet->size(), packet->data()); - if (!writer.WriteUInt8(first_byte)) { - QUIC_BUG(quic_bug_10981_18) << "Failed to write first_byte"; - return false; - } - if (*version_present) { - QuicVersionLabel version_label; - if (!reader->ReadUInt32(&version_label)) { - QUIC_DLOG(ERROR) << "Failed to read version"; - return false; - } - if (!writer.WriteUInt32(version_label)) { - QUIC_BUG(quic_bug_10981_19) << "Failed to write version"; - return false; - } - if (!writer.WriteLengthPrefixedConnectionId(destination_connection_id)) { - QUIC_BUG(quic_bug_10981_20) - << "Failed to write long header destination_connection_id"; - return false; - } - if (!writer.WriteLengthPrefixedConnectionId(source_connection_id)) { - QUIC_BUG(quic_bug_10981_21) - << "Failed to write long header source_connection_id"; - return false; - } - } else { - if (!writer.WriteConnectionId(destination_connection_id)) { - QUIC_BUG(quic_bug_10981_22) - << "Failed to write short header destination_connection_id"; - return false; - } - } - absl::string_view payload = reader->ReadRemainingPayload(); - if (!writer.WriteStringPiece(payload)) { - QUIC_BUG(quic_bug_10981_23) << "Failed to write payload"; - return false; - } - return true; -} - -bool MasqueCompressionEngine::DecompressDatagram( - absl::string_view datagram, QuicConnectionId* client_connection_id, - QuicConnectionId* server_connection_id, QuicSocketAddress* server_address, - std::vector<char>* packet, bool* version_present) { - QUIC_DVLOG(1) << "Decompressing DATAGRAM frame of length " - << datagram.length(); - QuicDataReader reader(datagram); - QuicDatagramStreamId flow_id; - if (!reader.ReadVarInt62(&flow_id)) { - QUIC_DLOG(ERROR) << "Could not read flow_id"; - return false; - } - MasqueCompressionContext context; - if (flow_id == kFlowId0) { - if (!ParseCompressionContext(&reader, &context)) { - return false; - } - } else { - auto context_pair = contexts_.find(flow_id); - if (context_pair == contexts_.end()) { - QUIC_DLOG(ERROR) << "Received unknown flow_id " << flow_id; - return false; - } - context = context_pair->second; - - if (!context.validated) { - context.validated = true; - contexts_[flow_id] = context; - QUIC_DLOG(INFO) << "Successfully validated remotely-validated flow_id " - << flow_id << " to " << context.server_address - << " client " << context.client_connection_id - << " server " << context.server_connection_id; - } else { - QUIC_DVLOG(1) << "Decompressing using incoming locally-validated " - "remotely-validated flow_id " - << flow_id << " to " << context.server_address << " client " - << context.client_connection_id << " server " - << context.server_connection_id; - } - } - - if (!WriteDecompressedPacket(&reader, context, packet, version_present)) { - return false; - } - - *server_address = context.server_address; - *client_connection_id = context.client_connection_id; - *server_connection_id = context.server_connection_id; - - QUIC_DVLOG(2) << "Decompressed client " << context.client_connection_id - << " server " << context.server_connection_id << "\n" - << quiche::QuicheTextUtils::HexDump( - absl::string_view(packet->data(), packet->size())); - - return true; -} - -void MasqueCompressionEngine::UnregisterClientConnectionId( - QuicConnectionId client_connection_id) { - std::vector<QuicDatagramStreamId> flow_ids_to_remove; - for (const auto& kv : contexts_) { - const MasqueCompressionContext& context = kv.second; - if (context.client_connection_id == client_connection_id) { - flow_ids_to_remove.push_back(kv.first); - } - } - for (QuicDatagramStreamId flow_id : flow_ids_to_remove) { - contexts_.erase(flow_id); - } -} - -} // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_compression_engine.h b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_compression_engine.h deleted file mode 100644 index 8c09de25f25..00000000000 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_compression_engine.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2019 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_MASQUE_MASQUE_COMPRESSION_ENGINE_H_ -#define QUICHE_QUIC_MASQUE_MASQUE_COMPRESSION_ENGINE_H_ - -#include "absl/container/flat_hash_map.h" -#include "absl/strings/string_view.h" -#include "quiche/quic/core/http/quic_spdy_session.h" -#include "quiche/quic/core/quic_connection_id.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/platform/api/quic_containers.h" -#include "quiche/quic/platform/api/quic_export.h" -#include "quiche/quic/platform/api/quic_socket_address.h" - -namespace quic { - -// MASQUE compression engine used by client and servers. -// This class allows converting QUIC packets into a compressed form suitable -// for sending over QUIC DATAGRAM frames. It leverages a flow identifier at the -// start of each datagram to indicate which compression context was used to -// compress this packet, or to create new compression contexts. -// Compression contexts contain client and server connection IDs and the -// server's IP and port. This allows compressing that information in most -// packets without requiring access to the cryptographic keys of the end-to-end -// encapsulated session. When the flow identifier is 0, the DATAGRAM contains -// all the contents of the compression context. When the flow identifier is -// non-zero, those fields are removed so the encapsulated QUIC packet is -// transmitted without connection IDs and reassembled by the peer on -// decompression. This only needs to contain the HTTP server's IP address since -// the client's IP address is not visible to the HTTP server. - -class QUIC_NO_EXPORT MasqueCompressionEngine { - public: - // Caller must ensure that |masque_session| has a lifetime longer than the - // newly constructed MasqueCompressionEngine. - explicit MasqueCompressionEngine(QuicSpdySession* masque_session); - - // Disallow copy and assign. - MasqueCompressionEngine(const MasqueCompressionEngine&) = delete; - MasqueCompressionEngine& operator=(const MasqueCompressionEngine&) = delete; - - // Compresses packet and sends it in a DATAGRAM frame over a MASQUE session. - // When used from MASQUE client to MASQUE server, the MASQUE server will then - // send the packet to the provided |server_address|. - // When used from MASQUE server to MASQUE client, the MASQUE client will then - // hand off the uncompressed packet to an encapsulated session that will treat - // it as having come from the provided |server_address|. - // The connection IDs are the one used by the encapsulated |packet|. - void CompressAndSendPacket(absl::string_view packet, - QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address); - - // Decompresses received DATAGRAM frame contents from |datagram| and places - // them in |packet|. Reverses the transformation from CompressAndSendPacket. - // The connection IDs are the one used by the encapsulated |packet|. - // |server_address| will be filled with the |server_address| passed to - // CompressAndSendPacket. |version_present| will contain whether the - // encapsulated |packet| contains a Version field. - bool DecompressDatagram(absl::string_view datagram, - QuicConnectionId* client_connection_id, - QuicConnectionId* server_connection_id, - QuicSocketAddress* server_address, - std::vector<char>* packet, bool* version_present); - - // Clears all entries referencing |client_connection_id| from the - // compression table. - void UnregisterClientConnectionId(QuicConnectionId client_connection_id); - - private: - struct QUIC_NO_EXPORT MasqueCompressionContext { - QuicConnectionId client_connection_id; - QuicConnectionId server_connection_id; - QuicSocketAddress server_address; - bool validated = false; - }; - - // Finds or creates a new compression context to use during compression. - // |client_connection_id_present| and |server_connection_id_present| indicate - // whether the corresponding connection ID is present in the current packet. - // |validated| will contain whether the compression context that matches - // these arguments is currently validated or not. - QuicDatagramStreamId FindOrCreateCompressionContext( - QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address, - bool client_connection_id_present, bool server_connection_id_present, - bool* validated); - - // Writes compressed packet to |slice| during compression. - bool WriteCompressedPacketToSlice(QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address, - QuicConnectionId destination_connection_id, - QuicConnectionId source_connection_id, - QuicDatagramStreamId flow_id, - bool validated, uint8_t first_byte, - bool long_header, QuicDataReader* reader, - QuicDataWriter* writer); - - // Parses compression context from flow ID 0 during decompression. - bool ParseCompressionContext(QuicDataReader* reader, - MasqueCompressionContext* context); - - // Writes decompressed packet to |packet| during decompression. - bool WriteDecompressedPacket(QuicDataReader* reader, - const MasqueCompressionContext& context, - std::vector<char>* packet, - bool* version_present); - - QuicSpdySession* masque_session_; // Unowned. - absl::flat_hash_map<QuicDatagramStreamId, MasqueCompressionContext> contexts_; - QuicDatagramStreamId next_available_flow_id_; -}; - -} // namespace quic - -#endif // QUICHE_QUIC_MASQUE_MASQUE_COMPRESSION_ENGINE_H_ diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_dispatcher.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_dispatcher.cc index 6db6f8ce009..d0440a6cd14 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_dispatcher.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_dispatcher.cc @@ -38,50 +38,11 @@ std::unique_ptr<QuicSession> MasqueDispatcher::CreateQuicSession( ParsedQuicVersionVector{version}); auto session = std::make_unique<MasqueServerSession>( - masque_mode_, config(), GetSupportedVersions(), connection, this, this, + masque_mode_, config(), GetSupportedVersions(), connection, this, epoll_server_, session_helper(), crypto_config(), compressed_certs_cache(), masque_server_backend_); session->Initialize(); return session; } -bool MasqueDispatcher::OnFailedToDispatchPacket( - const ReceivedPacketInfo& packet_info) { - auto connection_id_registration = client_connection_id_registrations_.find( - packet_info.destination_connection_id); - if (connection_id_registration == client_connection_id_registrations_.end()) { - QUIC_DLOG(INFO) << "MasqueDispatcher failed to dispatch " << packet_info; - return false; - } - MasqueServerSession* masque_server_session = - connection_id_registration->second; - masque_server_session->HandlePacketFromServer(packet_info); - return true; -} - -void MasqueDispatcher::RegisterClientConnectionId( - QuicConnectionId client_connection_id, - MasqueServerSession* masque_server_session) { - QUIC_DLOG(INFO) << "Registering encapsulated " << client_connection_id - << " to MASQUE session " - << masque_server_session->connection_id(); - - // Make sure we don't try to overwrite an existing registration with a - // different session. - QUIC_BUG_IF(quic_bug_12013_1, - client_connection_id_registrations_.find(client_connection_id) != - client_connection_id_registrations_.end() && - client_connection_id_registrations_[client_connection_id] != - masque_server_session) - << "Overwriting existing registration for " << client_connection_id; - client_connection_id_registrations_[client_connection_id] = - masque_server_session; -} - -void MasqueDispatcher::UnregisterClientConnectionId( - QuicConnectionId client_connection_id) { - QUIC_DLOG(INFO) << "Unregistering " << client_connection_id; - client_connection_id_registrations_.erase(client_connection_id); -} - } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_dispatcher.h b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_dispatcher.h index 90d319cee0a..b5ef5bb22ed 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_dispatcher.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_dispatcher.h @@ -17,8 +17,7 @@ namespace quic { // QUIC dispatcher that handles new MASQUE connections and can proxy traffic // between MASQUE clients and QUIC servers. -class QUIC_NO_EXPORT MasqueDispatcher : public QuicSimpleDispatcher, - public MasqueServerSession::Visitor { +class QUIC_NO_EXPORT MasqueDispatcher : public QuicSimpleDispatcher { public: explicit MasqueDispatcher( MasqueMode masque_mode, const QuicConfig* config, @@ -41,25 +40,10 @@ class QUIC_NO_EXPORT MasqueDispatcher : public QuicSimpleDispatcher, const ParsedQuicVersion& version, const quic::ParsedClientHello& parsed_chlo) override; - bool OnFailedToDispatchPacket(const ReceivedPacketInfo& packet_info) override; - - // From MasqueServerSession::Visitor. - void RegisterClientConnectionId( - QuicConnectionId client_connection_id, - MasqueServerSession* masque_server_session) override; - - void UnregisterClientConnectionId( - QuicConnectionId client_connection_id) override; - private: MasqueMode masque_mode_; QuicEpollServer* epoll_server_; // Unowned. MasqueServerBackend* masque_server_backend_; // Unowned. - // Mapping from client connection IDs to server sessions, allows routing - // incoming packets to the right MASQUE connection. - absl::flat_hash_map<QuicConnectionId, MasqueServerSession*, - QuicConnectionIdHash> - client_connection_id_registrations_; }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_client_session.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_client_session.cc index 988b51170d9..077430fa6a9 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_client_session.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_client_session.cc @@ -33,8 +33,7 @@ void MasqueEncapsulatedClientSession::CloseConnection( void MasqueEncapsulatedClientSession::OnConnectionClosed( const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) { QuicSpdyClientSession::OnConnectionClosed(frame, source); - masque_client_session_->UnregisterConnectionId( - connection()->client_connection_id(), this); + masque_client_session_->CloseConnectUdpStream(this); } } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_epoll_client.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_epoll_client.cc index 41dde4ecf5f..242d26594d0 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_epoll_client.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_epoll_client.cc @@ -29,9 +29,7 @@ class MasquePacketWriter : public QuicPacketWriter { << " bytes to " << peer_address; absl::string_view packet(buffer, buf_len); client_->masque_client()->masque_client_session()->SendPacket( - client_->session()->connection()->client_connection_id(), - client_->session()->connection()->connection_id(), packet, peer_address, - client_->masque_encapsulated_client_session()); + packet, peer_address, client_->masque_encapsulated_client_session()); return WriteResult(WRITE_STATUS_OK, buf_len); } @@ -93,8 +91,8 @@ MasqueEncapsulatedEpollClient::MasqueEncapsulatedEpollClient( masque_client_(masque_client) {} MasqueEncapsulatedEpollClient::~MasqueEncapsulatedEpollClient() { - masque_client_->masque_client_session()->UnregisterConnectionId( - client_connection_id_, masque_encapsulated_client_session()); + masque_client_->masque_client_session()->CloseConnectUdpStream( + masque_encapsulated_client_session()); } std::unique_ptr<QuicSession> @@ -113,13 +111,4 @@ MasqueEncapsulatedEpollClient::masque_encapsulated_client_session() { return static_cast<MasqueEncapsulatedClientSession*>(QuicClient::session()); } -QuicConnectionId MasqueEncapsulatedEpollClient::GetClientConnectionId() { - if (client_connection_id_.IsEmpty()) { - client_connection_id_ = QuicUtils::CreateRandomConnectionId(); - masque_client_->masque_client_session()->RegisterConnectionId( - client_connection_id_, masque_encapsulated_client_session()); - } - return client_connection_id_; -} - } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_epoll_client.h b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_epoll_client.h index cbe1bcd3450..2b98652755a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_epoll_client.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_epoll_client.h @@ -32,8 +32,6 @@ class QUIC_NO_EXPORT MasqueEncapsulatedEpollClient : public QuicClient { const ParsedQuicVersionVector& supported_versions, QuicConnection* connection) override; - QuicConnectionId GetClientConnectionId() override; - // MASQUE client that this client is encapsulated in. MasqueEpollClient* masque_client() { return masque_client_; } @@ -42,7 +40,6 @@ class QUIC_NO_EXPORT MasqueEncapsulatedEpollClient : public QuicClient { private: MasqueEpollClient* masque_client_; // Unowned. - QuicConnectionId client_connection_id_; }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.cc index 6d6470bc099..705ea15cd95 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.cc @@ -91,36 +91,6 @@ std::unique_ptr<MasqueEpollClient> MasqueEpollClient::Create( return nullptr; } - if (masque_client->masque_mode() == MasqueMode::kLegacy) { - // Construct the legacy mode init request. - spdy::Http2HeaderBlock header_block; - header_block[":method"] = "POST"; - header_block[":scheme"] = "https"; - header_block[":authority"] = masque_client->authority(); - header_block[":path"] = "/.well-known/masque/init"; - std::string body = "foo"; - - // Make sure to store the response, for later output. - masque_client->set_store_response(true); - - // Send the MASQUE init command. - masque_client->SendRequestAndWaitForResponse(header_block, body, - /*fin=*/true); - - if (!masque_client->connected()) { - QUIC_LOG(ERROR) - << "MASQUE init request caused connection failure. Error: " - << QuicErrorCodeToString(masque_client->session()->error()); - return nullptr; - } - - const int response_code = masque_client->latest_response_code(); - if (response_code != 200) { - QUIC_LOG(ERROR) << "MASQUE init request failed with HTTP response code " - << response_code; - return nullptr; - } - } return masque_client; } @@ -133,22 +103,4 @@ bool MasqueEpollClient::WaitUntilSettingsReceived() { return connected() && settings_received_; } -void MasqueEpollClient::UnregisterClientConnectionId( - QuicConnectionId client_connection_id) { - std::string body(client_connection_id.data(), client_connection_id.length()); - - // Construct a GET or POST request for supplied URL. - spdy::Http2HeaderBlock header_block; - header_block[":method"] = "POST"; - header_block[":scheme"] = "https"; - header_block[":authority"] = authority(); - header_block[":path"] = "/.well-known/masque/unregister"; - - // Make sure to store the response, for later output. - set_store_response(true); - - // Send the MASQUE unregister command. - SendRequest(header_block, body, /*fin=*/true); -} - } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.h b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.h index 7b36bf68faa..7eff270ee4e 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_epoll_client.h @@ -38,9 +38,6 @@ class QUIC_NO_EXPORT MasqueEpollClient : public QuicClient, // From MasqueClientSession::Owner. void OnSettingsReceived() override; - // Send a MASQUE client connection ID unregister command to the server. - void UnregisterClientConnectionId( - QuicConnectionId client_connection_id) override; MasqueMode masque_mode() const { return masque_mode_; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.cc index 8dfe8b8452e..b42a055c56c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.cc @@ -20,7 +20,6 @@ MasqueServerBackend::MasqueServerBackend(MasqueMode masque_mode, bool MasqueServerBackend::MaybeHandleMasqueRequest( const spdy::Http2HeaderBlock& request_headers, - const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) { auto method_pair = request_headers.find(":method"); if (method_pair == request_headers.end()) { @@ -29,34 +28,11 @@ bool MasqueServerBackend::MaybeHandleMasqueRequest( } absl::string_view method = method_pair->second; std::string masque_path = ""; - if (masque_mode_ == MasqueMode::kLegacy) { - auto path_pair = request_headers.find(":path"); - auto scheme_pair = request_headers.find(":scheme"); - if (path_pair == request_headers.end() || - scheme_pair == request_headers.end()) { - // This request is missing required headers. - return false; - } - absl::string_view path = path_pair->second; - absl::string_view scheme = scheme_pair->second; - if (scheme != "https" || method != "POST" || request_body.empty()) { - // MASQUE requests MUST be a non-empty https POST. - return false; - } - - if (path.rfind("/.well-known/masque/", 0) != 0) { - // This request is not a MASQUE path. - return false; - } - masque_path = std::string(path.substr(sizeof("/.well-known/masque/") - 1)); - } else { - QUICHE_DCHECK_EQ(masque_mode_, MasqueMode::kOpen); - auto protocol_pair = request_headers.find(":protocol"); - if (method != "CONNECT" || protocol_pair == request_headers.end() || - protocol_pair->second != "connect-udp") { - // This is not a MASQUE request. - return false; - } + auto protocol_pair = request_headers.find(":protocol"); + if (method != "CONNECT" || protocol_pair == request_headers.end() || + protocol_pair->second != "connect-udp") { + // This is not a MASQUE request. + return false; } if (!server_authority_.empty()) { @@ -82,8 +58,7 @@ bool MasqueServerBackend::MaybeHandleMasqueRequest( BackendClient* backend_client = it->second.backend_client; std::unique_ptr<QuicBackendResponse> response = - backend_client->HandleMasqueRequest(masque_path, request_headers, - request_body, request_handler); + backend_client->HandleMasqueRequest(request_headers, request_handler); if (response == nullptr) { QUIC_LOG(ERROR) << "Backend client did not process request for " << masque_path << request_headers.DebugString(); @@ -103,8 +78,7 @@ void MasqueServerBackend::FetchResponseFromBackend( const spdy::Http2HeaderBlock& request_headers, const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) { - if (MaybeHandleMasqueRequest(request_headers, request_body, - request_handler)) { + if (MaybeHandleMasqueRequest(request_headers, request_handler)) { // Request was handled as a MASQUE request. return; } @@ -114,6 +88,19 @@ void MasqueServerBackend::FetchResponseFromBackend( request_headers, request_body, request_handler); } +void MasqueServerBackend::HandleConnectHeaders( + const spdy::Http2HeaderBlock& request_headers, + RequestHandler* request_handler) { + if (MaybeHandleMasqueRequest(request_headers, request_handler)) { + // Request was handled as a MASQUE request. + return; + } + QUIC_DLOG(INFO) << "Fetching non-MASQUE CONNECT response for " + << request_headers.DebugString(); + QuicMemoryCacheBackend::HandleConnectHeaders(request_headers, + request_handler); +} + void MasqueServerBackend::CloseBackendResponseStream( QuicSimpleServerBackend::RequestHandler* request_handler) { QUIC_DLOG(INFO) << "Closing response stream"; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.h b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.h index 7480a86e97b..a86209731a6 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.h @@ -21,9 +21,7 @@ class QUIC_NO_EXPORT MasqueServerBackend : public QuicMemoryCacheBackend { class QUIC_NO_EXPORT BackendClient { public: virtual std::unique_ptr<QuicBackendResponse> HandleMasqueRequest( - const std::string& masque_path, const spdy::Http2HeaderBlock& request_headers, - const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) = 0; virtual ~BackendClient() = default; }; @@ -41,6 +39,8 @@ class QUIC_NO_EXPORT MasqueServerBackend : public QuicMemoryCacheBackend { const spdy::Http2HeaderBlock& request_headers, const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) override; + void HandleConnectHeaders(const spdy::Http2HeaderBlock& request_headers, + RequestHandler* request_handler) override; void CloseBackendResponseStream( QuicSimpleServerBackend::RequestHandler* request_handler) override; @@ -56,7 +56,6 @@ class QUIC_NO_EXPORT MasqueServerBackend : public QuicMemoryCacheBackend { // Handle MASQUE request. bool MaybeHandleMasqueRequest( const spdy::Http2HeaderBlock& request_headers, - const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler); MasqueMode masque_mode_; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_bin.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_bin.cc index ac1c1898463..23d9d69c284 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_bin.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_bin.cc @@ -31,9 +31,9 @@ DEFINE_QUICHE_COMMAND_LINE_FLAG( "Specifies the authority over which the server will accept MASQUE " "requests. Defaults to empty which allows all authorities."); -DEFINE_QUICHE_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, currently only valid value is \"open\"."); int main(int argc, char* argv[]) { quiche::QuicheSystemEventLoop event_loop("masque_server"); @@ -46,23 +46,22 @@ int main(int argc, char* argv[]) { } quic::MasqueMode masque_mode = quic::MasqueMode::kOpen; - std::string mode_string = GetQuicFlag(FLAGS_masque_mode); - if (mode_string == "legacy") { - masque_mode = quic::MasqueMode::kLegacy; - } else if (!mode_string.empty() && mode_string != "open") { + std::string mode_string = quiche::GetQuicheCommandLineFlag(FLAGS_masque_mode); + if (!mode_string.empty() && mode_string != "open") { std::cerr << "Invalid masque_mode \"" << mode_string << "\"" << std::endl; return 1; } auto backend = std::make_unique<quic::MasqueServerBackend>( - masque_mode, GetQuicFlag(FLAGS_server_authority), - GetQuicFlag(FLAGS_cache_dir)); + masque_mode, quiche::GetQuicheCommandLineFlag(FLAGS_server_authority), + quiche::GetQuicheCommandLineFlag(FLAGS_cache_dir)); auto server = std::make_unique<quic::MasqueEpollServer>(masque_mode, backend.get()); if (!server->CreateUDPSocketAndListen(quic::QuicSocketAddress( - quic::QuicIpAddress::Any6(), GetQuicFlag(FLAGS_port)))) { + quic::QuicIpAddress::Any6(), + quiche::GetQuicheCommandLineFlag(FLAGS_port)))) { return 1; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.cc index f2210946077..742b0c654f9 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.cc @@ -78,7 +78,7 @@ std::unique_ptr<QuicBackendResponse> CreateBackendErrorResponse( MasqueServerSession::MasqueServerSession( MasqueMode masque_mode, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, - QuicConnection* connection, QuicSession::Visitor* visitor, Visitor* owner, + QuicConnection* connection, QuicSession::Visitor* visitor, QuicEpollServer* epoll_server, QuicCryptoServerStreamBase::Helper* helper, const QuicCryptoServerConfig* crypto_config, QuicCompressedCertsCache* compressed_certs_cache, @@ -87,9 +87,7 @@ MasqueServerSession::MasqueServerSession( helper, crypto_config, compressed_certs_cache, masque_server_backend), masque_server_backend_(masque_server_backend), - owner_(owner), epoll_server_(epoll_server), - compression_engine_(this), masque_mode_(masque_mode) { // Artificially increase the max packet length to 1350 to ensure we can fit // QUIC packets inside DATAGRAM frames. @@ -100,44 +98,6 @@ MasqueServerSession::MasqueServerSession( QUICHE_DCHECK_NE(epoll_server_, nullptr); } -void MasqueServerSession::OnMessageReceived(absl::string_view message) { - if (masque_mode_ == MasqueMode::kLegacy) { - QUIC_DVLOG(1) << "Received DATAGRAM frame of length " << message.length(); - QuicConnectionId client_connection_id, server_connection_id; - QuicSocketAddress target_server_address; - std::vector<char> packet; - bool version_present; - if (!compression_engine_.DecompressDatagram( - message, &client_connection_id, &server_connection_id, - &target_server_address, &packet, &version_present)) { - return; - } - - QUIC_DVLOG(1) << "Received packet of length " << packet.size() << " for " - << target_server_address << " client " - << client_connection_id; - - if (version_present) { - if (client_connection_id.length() != kQuicDefaultConnectionIdLength) { - QUIC_DLOG(ERROR) - << "Dropping long header with invalid client_connection_id " - << client_connection_id; - return; - } - owner_->RegisterClientConnectionId(client_connection_id, this); - } - - WriteResult write_result = connection()->writer()->WritePacket( - packet.data(), packet.size(), connection()->self_address().host(), - target_server_address, nullptr); - QUIC_DVLOG(1) << "Got " << write_result << " for " << packet.size() - << " bytes to " << target_server_address; - return; - } - QUICHE_DCHECK_EQ(masque_mode_, MasqueMode::kOpen); - QuicSpdySession::OnMessageReceived(message); -} - void MasqueServerSession::OnMessageAcked(QuicMessageId message_id, QuicTime /*receive_timestamp*/) { QUIC_DVLOG(1) << "Received ack for DATAGRAM frame " << message_id; @@ -166,211 +126,132 @@ void MasqueServerSession::OnStreamClosed(QuicStreamId stream_id) { } std::unique_ptr<QuicBackendResponse> MasqueServerSession::HandleMasqueRequest( - const std::string& masque_path, const spdy::Http2HeaderBlock& request_headers, - const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) { - if (masque_mode_ != MasqueMode::kLegacy) { - auto path_pair = request_headers.find(":path"); - auto scheme_pair = request_headers.find(":scheme"); - auto method_pair = request_headers.find(":method"); - auto protocol_pair = request_headers.find(":protocol"); - auto authority_pair = request_headers.find(":authority"); - if (path_pair == request_headers.end()) { - QUIC_DLOG(ERROR) << "MASQUE request is missing :path"; - return CreateBackendErrorResponse("400", "Missing :path"); - } - if (scheme_pair == request_headers.end()) { - QUIC_DLOG(ERROR) << "MASQUE request is missing :scheme"; - return CreateBackendErrorResponse("400", "Missing :scheme"); - } - if (method_pair == request_headers.end()) { - QUIC_DLOG(ERROR) << "MASQUE request is missing :method"; - return CreateBackendErrorResponse("400", "Missing :method"); - } - if (protocol_pair == request_headers.end()) { - QUIC_DLOG(ERROR) << "MASQUE request is missing :protocol"; - return CreateBackendErrorResponse("400", "Missing :protocol"); - } - if (authority_pair == request_headers.end()) { - QUIC_DLOG(ERROR) << "MASQUE request is missing :authority"; - return CreateBackendErrorResponse("400", "Missing :authority"); - } - absl::string_view path = path_pair->second; - absl::string_view scheme = scheme_pair->second; - absl::string_view method = method_pair->second; - absl::string_view protocol = protocol_pair->second; - absl::string_view authority = authority_pair->second; - if (path.empty()) { - QUIC_DLOG(ERROR) << "MASQUE request with empty path"; - return CreateBackendErrorResponse("400", "Empty path"); - } - if (scheme.empty()) { - return CreateBackendErrorResponse("400", "Empty scheme"); - } - if (method != "CONNECT") { - QUIC_DLOG(ERROR) << "MASQUE request with bad method \"" << method << "\""; - return CreateBackendErrorResponse("400", "Bad method"); - } - if (protocol != "connect-udp") { - QUIC_DLOG(ERROR) << "MASQUE request with bad protocol \"" << protocol - << "\""; - return CreateBackendErrorResponse("400", "Bad protocol"); - } - absl::optional<QuicDatagramStreamId> flow_id; - if (http_datagram_support() == HttpDatagramSupport::kDraft00) { - flow_id = SpdyUtils::ParseDatagramFlowIdHeader(request_headers); - if (!flow_id.has_value()) { - QUIC_DLOG(ERROR) - << "MASQUE request with bad or missing DatagramFlowId header"; - return CreateBackendErrorResponse( - "400", "Bad or missing DatagramFlowId header"); - } - } - // Extract target host and port from path using default template. - std::vector<absl::string_view> path_split = absl::StrSplit(path, '/'); - if (path_split.size() != 4 || !path_split[0].empty() || - path_split[1].empty() || path_split[2].empty() || - !path_split[3].empty()) { - QUIC_DLOG(ERROR) << "MASQUE request with bad path \"" << path << "\""; - return CreateBackendErrorResponse("400", "Bad path"); - } - absl::optional<std::string> host = quiche::AsciiUrlDecode(path_split[1]); - if (!host.has_value()) { - QUIC_DLOG(ERROR) << "Failed to decode host \"" << path_split[1] << "\""; - return CreateBackendErrorResponse("500", "Failed to decode host"); - } - absl::optional<std::string> port = quiche::AsciiUrlDecode(path_split[2]); - if (!port.has_value()) { - QUIC_DLOG(ERROR) << "Failed to decode port \"" << path_split[2] << "\""; - return CreateBackendErrorResponse("500", "Failed to decode port"); - } - - // Perform DNS resolution. - addrinfo hint = {}; - hint.ai_protocol = IPPROTO_UDP; - - addrinfo* info_list = nullptr; - int result = getaddrinfo(host.value().c_str(), port.value().c_str(), &hint, - &info_list); - if (result != 0) { - QUIC_DLOG(ERROR) << "Failed to resolve " << authority << ": " - << gai_strerror(result); - return CreateBackendErrorResponse("500", "DNS resolution failed"); - } - - QUICHE_CHECK_NE(info_list, nullptr); - std::unique_ptr<addrinfo, void (*)(addrinfo*)> info_list_owned( - info_list, freeaddrinfo); - QuicSocketAddress target_server_address(info_list->ai_addr, - info_list->ai_addrlen); - QUIC_DLOG(INFO) << "Got CONNECT_UDP request on stream ID " - << request_handler->stream_id() << " flow_id=" - << (flow_id.has_value() ? absl::StrCat(*flow_id) : "none") - << " target_server_address=\"" << target_server_address - << "\""; - - FdWrapper fd_wrapper(target_server_address.host().AddressFamilyToInt()); - if (fd_wrapper.fd() == kQuicInvalidSocketFd) { - QUIC_DLOG(ERROR) << "Socket creation failed"; - return CreateBackendErrorResponse("500", "Socket creation failed"); - } - QuicSocketAddress empty_address(QuicIpAddress::Any6(), 0); - if (target_server_address.host().IsIPv4()) { - empty_address = QuicSocketAddress(QuicIpAddress::Any4(), 0); - } - QuicUdpSocketApi socket_api; - if (!socket_api.Bind(fd_wrapper.fd(), empty_address)) { - QUIC_DLOG(ERROR) << "Socket bind failed"; - return CreateBackendErrorResponse("500", "Socket bind failed"); - } - epoll_server_->RegisterFDForRead(fd_wrapper.fd(), this); - - absl::optional<QuicDatagramContextId> context_id; - QuicSpdyStream* stream = static_cast<QuicSpdyStream*>( - GetActiveStream(request_handler->stream_id())); - if (stream == nullptr) { - QUIC_BUG(bad masque server stream type) - << "Unexpected stream type for stream ID " - << request_handler->stream_id(); - return CreateBackendErrorResponse("500", "Bad stream type"); - } - if (flow_id.has_value()) { - stream->RegisterHttp3DatagramFlowId(*flow_id); - } - connect_udp_server_states_.push_back( - ConnectUdpServerState(stream, context_id, target_server_address, - fd_wrapper.extract_fd(), this)); - - if (http_datagram_support() == HttpDatagramSupport::kDraft00) { - // TODO(b/181256914) remove this when we drop support for - // draft-ietf-masque-h3-datagram-00 in favor of later drafts. - stream->RegisterHttp3DatagramContextId( - context_id, DatagramFormatType::UDP_PAYLOAD, - /*format_additional_data=*/absl::string_view(), - &connect_udp_server_states_.back()); - } - - spdy::Http2HeaderBlock response_headers; - response_headers[":status"] = "200"; - if (flow_id.has_value()) { - SpdyUtils::AddDatagramFlowIdHeader(&response_headers, *flow_id); - } - auto response = std::make_unique<QuicBackendResponse>(); - response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE); - response->set_headers(std::move(response_headers)); - response->set_body(""); - - return response; + auto path_pair = request_headers.find(":path"); + auto scheme_pair = request_headers.find(":scheme"); + auto method_pair = request_headers.find(":method"); + auto protocol_pair = request_headers.find(":protocol"); + auto authority_pair = request_headers.find(":authority"); + if (path_pair == request_headers.end()) { + QUIC_DLOG(ERROR) << "MASQUE request is missing :path"; + return CreateBackendErrorResponse("400", "Missing :path"); + } + if (scheme_pair == request_headers.end()) { + QUIC_DLOG(ERROR) << "MASQUE request is missing :scheme"; + return CreateBackendErrorResponse("400", "Missing :scheme"); + } + if (method_pair == request_headers.end()) { + QUIC_DLOG(ERROR) << "MASQUE request is missing :method"; + return CreateBackendErrorResponse("400", "Missing :method"); + } + if (protocol_pair == request_headers.end()) { + QUIC_DLOG(ERROR) << "MASQUE request is missing :protocol"; + return CreateBackendErrorResponse("400", "Missing :protocol"); + } + if (authority_pair == request_headers.end()) { + QUIC_DLOG(ERROR) << "MASQUE request is missing :authority"; + return CreateBackendErrorResponse("400", "Missing :authority"); + } + absl::string_view path = path_pair->second; + absl::string_view scheme = scheme_pair->second; + absl::string_view method = method_pair->second; + absl::string_view protocol = protocol_pair->second; + absl::string_view authority = authority_pair->second; + if (path.empty()) { + QUIC_DLOG(ERROR) << "MASQUE request with empty path"; + return CreateBackendErrorResponse("400", "Empty path"); + } + if (scheme.empty()) { + return CreateBackendErrorResponse("400", "Empty scheme"); + } + if (method != "CONNECT") { + QUIC_DLOG(ERROR) << "MASQUE request with bad method \"" << method << "\""; + return CreateBackendErrorResponse("400", "Bad method"); + } + if (protocol != "connect-udp") { + QUIC_DLOG(ERROR) << "MASQUE request with bad protocol \"" << protocol + << "\""; + return CreateBackendErrorResponse("400", "Bad protocol"); + } + // Extract target host and port from path using default template. + std::vector<absl::string_view> path_split = absl::StrSplit(path, '/'); + if (path_split.size() != 7 || !path_split[0].empty() || + path_split[1] != ".well-known" || path_split[2] != "masque" || + path_split[3] != "udp" || path_split[4].empty() || + path_split[5].empty() || !path_split[6].empty()) { + QUIC_DLOG(ERROR) << "MASQUE request with bad path \"" << path << "\""; + return CreateBackendErrorResponse("400", "Bad path"); + } + absl::optional<std::string> host = quiche::AsciiUrlDecode(path_split[4]); + if (!host.has_value()) { + QUIC_DLOG(ERROR) << "Failed to decode host \"" << path_split[4] << "\""; + return CreateBackendErrorResponse("500", "Failed to decode host"); + } + absl::optional<std::string> port = quiche::AsciiUrlDecode(path_split[5]); + if (!port.has_value()) { + QUIC_DLOG(ERROR) << "Failed to decode port \"" << path_split[5] << "\""; + return CreateBackendErrorResponse("500", "Failed to decode port"); } - QUIC_DLOG(INFO) << "MasqueServerSession handling MASQUE request"; + // Perform DNS resolution. + addrinfo hint = {}; + hint.ai_protocol = IPPROTO_UDP; + + addrinfo* info_list = nullptr; + int result = getaddrinfo(host.value().c_str(), port.value().c_str(), &hint, + &info_list); + if (result != 0 || info_list == nullptr) { + QUIC_DLOG(ERROR) << "Failed to resolve " << authority << ": " + << gai_strerror(result); + return CreateBackendErrorResponse("500", "DNS resolution failed"); + } - if (masque_path == "init") { - if (masque_initialized_) { - QUIC_DLOG(ERROR) << "Got second MASQUE init request"; - return nullptr; - } - masque_initialized_ = true; - } else if (masque_path == "unregister") { - QuicConnectionId connection_id(request_body.data(), request_body.length()); - QUIC_DLOG(INFO) << "Received MASQUE request to unregister " - << connection_id; - owner_->UnregisterClientConnectionId(connection_id); - compression_engine_.UnregisterClientConnectionId(connection_id); - } else { - if (!masque_initialized_) { - QUIC_DLOG(ERROR) << "Got MASQUE request before init"; - return nullptr; - } + std::unique_ptr<addrinfo, void (*)(addrinfo*)> info_list_owned(info_list, + freeaddrinfo); + QuicSocketAddress target_server_address(info_list->ai_addr, + info_list->ai_addrlen); + QUIC_DLOG(INFO) << "Got CONNECT_UDP request on stream ID " + << request_handler->stream_id() << " target_server_address=\"" + << target_server_address << "\""; + + FdWrapper fd_wrapper(target_server_address.host().AddressFamilyToInt()); + if (fd_wrapper.fd() == kQuicInvalidSocketFd) { + QUIC_DLOG(ERROR) << "Socket creation failed"; + return CreateBackendErrorResponse("500", "Socket creation failed"); + } + QuicSocketAddress empty_address(QuicIpAddress::Any6(), 0); + if (target_server_address.host().IsIPv4()) { + empty_address = QuicSocketAddress(QuicIpAddress::Any4(), 0); + } + QuicUdpSocketApi socket_api; + if (!socket_api.Bind(fd_wrapper.fd(), empty_address)) { + QUIC_DLOG(ERROR) << "Socket bind failed"; + return CreateBackendErrorResponse("500", "Socket bind failed"); + } + epoll_server_->RegisterFDForRead(fd_wrapper.fd(), this); + + QuicSpdyStream* stream = + static_cast<QuicSpdyStream*>(GetActiveStream(request_handler->stream_id())); + if (stream == nullptr) { + QUIC_BUG(bad masque server stream type) + << "Unexpected stream type for stream ID " + << request_handler->stream_id(); + return CreateBackendErrorResponse("500", "Bad stream type"); } + connect_udp_server_states_.push_back(ConnectUdpServerState( + stream, target_server_address, fd_wrapper.extract_fd(), this)); - // TODO(dschinazi) implement binary protocol sent in response body. - const std::string response_body = ""; spdy::Http2HeaderBlock response_headers; response_headers[":status"] = "200"; auto response = std::make_unique<QuicBackendResponse>(); - response->set_response_type(QuicBackendResponse::REGULAR_RESPONSE); + response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE); response->set_headers(std::move(response_headers)); - response->set_body(response_body); + response->set_body(""); return response; } -void MasqueServerSession::HandlePacketFromServer( - const ReceivedPacketInfo& packet_info) { - QUIC_DVLOG(1) << "MasqueServerSession received " << packet_info; - if (masque_mode_ == MasqueMode::kLegacy) { - compression_engine_.CompressAndSendPacket( - packet_info.packet.AsStringPiece(), - packet_info.destination_connection_id, packet_info.source_connection_id, - packet_info.peer_address); - return; - } - QUIC_LOG(ERROR) << "Ignoring packet from server in " << masque_mode_ - << " mode"; -} - void MasqueServerSession::OnRegistration(QuicEpollServer* /*eps*/, QuicUdpSocketFd fd, int event_mask) { QUIC_DVLOG(1) << "OnRegistration " << fd << " event_mask " << event_mask; @@ -403,11 +284,12 @@ void MasqueServerSession::OnEvent(QuicUdpSocketFd fd, QuicEpollEvent* event) { << " server " << expected_target_server_address; QuicUdpSocketApi socket_api; BitMask64 packet_info_interested(QuicUdpPacketInfoBit::PEER_ADDRESS); - char packet_buffer[kMaxIncomingPacketSize]; + char packet_buffer[1 + kMaxIncomingPacketSize]; + packet_buffer[0] = 0; // context ID. char control_buffer[kDefaultUdpPacketControlBufferSize]; while (true) { QuicUdpSocketApi::ReadPacketResult read_result; - read_result.packet_buffer = {packet_buffer, sizeof(packet_buffer)}; + read_result.packet_buffer = {packet_buffer + 1, sizeof(packet_buffer) - 1}; read_result.control_buffer = {control_buffer, sizeof(control_buffer)}; socket_api.ReadPacket(fd, packet_info_interested, &read_result); if (!read_result.ok) { @@ -436,10 +318,9 @@ void MasqueServerSession::OnEvent(QuicUdpSocketFd fd, QuicEpollEvent* event) { return; } // The packet is valid, send it to the client in a DATAGRAM frame. - MessageStatus message_status = it->stream()->SendHttp3Datagram( - it->context_id(), - absl::string_view(read_result.packet_buffer.buffer, - read_result.packet_buffer.buffer_len)); + MessageStatus message_status = + it->stream()->SendHttp3Datagram(absl::string_view( + packet_buffer, read_result.packet_buffer.buffer_len + 1)); QUIC_DVLOG(1) << "Sent UDP packet from " << expected_target_server_address << " of length " << read_result.packet_buffer.buffer_len << " with stream ID " << it->stream()->id() @@ -476,25 +357,20 @@ bool MasqueServerSession::OnSettingsFrame(const SettingsFrame& frame) { } MasqueServerSession::ConnectUdpServerState::ConnectUdpServerState( - QuicSpdyStream* stream, absl::optional<QuicDatagramContextId> context_id, - const QuicSocketAddress& target_server_address, QuicUdpSocketFd fd, - MasqueServerSession* masque_session) + QuicSpdyStream* stream, const QuicSocketAddress& target_server_address, + QuicUdpSocketFd fd, MasqueServerSession* masque_session) : stream_(stream), - context_id_(context_id), target_server_address_(target_server_address), fd_(fd), masque_session_(masque_session) { QUICHE_DCHECK_NE(fd_, kQuicInvalidSocketFd); QUICHE_DCHECK_NE(masque_session_, nullptr); - this->stream()->RegisterHttp3DatagramRegistrationVisitor(this); + this->stream()->RegisterHttp3DatagramVisitor(this); } MasqueServerSession::ConnectUdpServerState::~ConnectUdpServerState() { if (stream() != nullptr) { - if (context_registered_) { - stream()->UnregisterHttp3DatagramContextId(context_id()); - } - stream()->UnregisterHttp3DatagramRegistrationVisitor(); + stream()->UnregisterHttp3DatagramVisitor(); } if (fd_ == kQuicInvalidSocketFd) { return; @@ -522,107 +398,38 @@ MasqueServerSession::ConnectUdpServerState::operator=( } stream_ = other.stream_; other.stream_ = nullptr; - context_id_ = other.context_id_; target_server_address_ = other.target_server_address_; fd_ = other.fd_; masque_session_ = other.masque_session_; other.fd_ = kQuicInvalidSocketFd; - context_registered_ = other.context_registered_; - other.context_registered_ = false; if (stream() != nullptr) { - stream()->MoveHttp3DatagramRegistration(this); - if (context_registered_) { - stream()->MoveHttp3DatagramContextIdRegistration(context_id(), this); - } + stream()->ReplaceHttp3DatagramVisitor(this); } return *this; } void MasqueServerSession::ConnectUdpServerState::OnHttp3Datagram( - QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id, - absl::string_view payload) { + QuicStreamId stream_id, absl::string_view payload) { QUICHE_DCHECK_EQ(stream_id, stream()->id()); - QUICHE_DCHECK(context_id == context_id_); + QuicDataReader reader(payload); + uint64_t context_id; + if (!reader.ReadVarInt62(&context_id)) { + QUIC_DLOG(ERROR) << "Failed to read context ID"; + return; + } + if (context_id != 0) { + QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID " + << context_id; + return; + } + absl::string_view http_payload = reader.ReadRemainingPayload(); QuicUdpSocketApi socket_api; QuicUdpPacketInfo packet_info; packet_info.SetPeerAddress(target_server_address_); WriteResult write_result = socket_api.WritePacket( - fd_, payload.data(), payload.length(), packet_info); - QUIC_DVLOG(1) << "Wrote packet of length " << payload.length() << " to " + fd_, http_payload.data(), http_payload.length(), packet_info); + QUIC_DVLOG(1) << "Wrote packet of length " << http_payload.length() << " to " << target_server_address_ << " with result " << write_result; } -void MasqueServerSession::ConnectUdpServerState::OnContextReceived( - QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id, - DatagramFormatType format_type, absl::string_view format_additional_data) { - if (stream_id != stream()->id()) { - QUIC_BUG(MASQUE server bad datagram context registration) - << "Registered stream ID " << stream_id << ", expected " - << stream()->id(); - return; - } - if (format_type != DatagramFormatType::UDP_PAYLOAD) { - QUIC_DLOG(INFO) << "Ignoring unexpected datagram format type " - << DatagramFormatTypeToString(format_type); - return; - } - if (!format_additional_data.empty()) { - QUIC_DLOG(ERROR) - << "Received non-empty format additional data for context ID " - << (context_id_.has_value() ? context_id_.value() : 0) - << " on stream ID " << stream()->id(); - masque_session_->ResetStream(stream()->id(), QUIC_STREAM_CANCELLED); - return; - } - if (!context_received_) { - context_received_ = true; - context_id_ = context_id; - } - if (context_id != context_id_) { - QUIC_DLOG(INFO) - << "Ignoring unexpected context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) : "none") - << " instead of " - << (context_id_.has_value() ? absl::StrCat(context_id_.value()) - : "none") - << " on stream ID " << stream()->id(); - return; - } - if (context_registered_) { - QUIC_BUG(MASQUE server double datagram context registration) - << "Try to re-register stream ID " << stream_id << " context ID " - << (context_id_.has_value() ? absl::StrCat(context_id_.value()) - : "none"); - return; - } - context_registered_ = true; - stream()->RegisterHttp3DatagramContextId(context_id_, format_type, - format_additional_data, this); -} - -void MasqueServerSession::ConnectUdpServerState::OnContextClosed( - QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id, - ContextCloseCode close_code, absl::string_view close_details) { - if (stream_id != stream()->id()) { - QUIC_BUG(MASQUE server bad datagram context registration) - << "Closed context on stream ID " << stream_id << ", expected " - << stream()->id(); - return; - } - if (context_id != context_id_) { - QUIC_DLOG(INFO) - << "Ignoring unexpected close of context ID " - << (context_id.has_value() ? absl::StrCat(context_id.value()) : "none") - << " instead of " - << (context_id_.has_value() ? absl::StrCat(context_id_.value()) - : "none") - << " on stream ID " << stream()->id(); - return; - } - QUIC_DLOG(INFO) << "Received datagram context close with close code " - << close_code << " close details \"" << close_details - << "\" on stream ID " << stream()->id() << ", closing stream"; - masque_session_->ResetStream(stream()->id(), QUIC_STREAM_CANCELLED); -} - } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.h b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.h index 746779e423a..59b33c29b72 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.h @@ -7,7 +7,6 @@ #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_udp_socket.h" -#include "quiche/quic/masque/masque_compression_engine.h" #include "quiche/quic/masque/masque_server_backend.h" #include "quiche/quic/masque/masque_utils.h" #include "quiche/quic/platform/api/quic_epoll.h" @@ -22,25 +21,10 @@ class QUIC_NO_EXPORT MasqueServerSession public MasqueServerBackend::BackendClient, public QuicEpollCallbackInterface { public: - // Interface meant to be implemented by owner of this MasqueServerSession - // instance. - class QUIC_NO_EXPORT Visitor { - public: - virtual ~Visitor() {} - // Register a client connection ID as being handled by this session. - virtual void RegisterClientConnectionId( - QuicConnectionId client_connection_id, - MasqueServerSession* masque_server_session) = 0; - - // Unregister a client connection ID. - virtual void UnregisterClientConnectionId( - QuicConnectionId client_connection_id) = 0; - }; - explicit MasqueServerSession( MasqueMode masque_mode, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, - QuicConnection* connection, QuicSession::Visitor* visitor, Visitor* owner, + QuicConnection* connection, QuicSession::Visitor* visitor, QuicEpollServer* epoll_server, QuicCryptoServerStreamBase::Helper* helper, const QuicCryptoServerConfig* crypto_config, QuicCompressedCertsCache* compressed_certs_cache, @@ -51,7 +35,6 @@ class QUIC_NO_EXPORT MasqueServerSession MasqueServerSession& operator=(const MasqueServerSession&) = delete; // From QuicSession. - void OnMessageReceived(absl::string_view message) override; void OnMessageAcked(QuicMessageId message_id, QuicTime receive_timestamp) override; void OnMessageLost(QuicMessageId message_id) override; @@ -61,9 +44,7 @@ class QUIC_NO_EXPORT MasqueServerSession // From MasqueServerBackend::BackendClient. std::unique_ptr<QuicBackendResponse> HandleMasqueRequest( - const std::string& masque_path, const spdy::Http2HeaderBlock& request_headers, - const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) override; // From QuicEpollCallbackInterface. @@ -75,24 +56,18 @@ class QUIC_NO_EXPORT MasqueServerSession void OnShutdown(QuicEpollServer* eps, QuicUdpSocketFd fd) override; std::string Name() const override; - // Handle packet for client, meant to be called by MasqueDispatcher. - void HandlePacketFromServer(const ReceivedPacketInfo& packet_info); - QuicEpollServer* epoll_server() const { return epoll_server_; } private: // State that the MasqueServerSession keeps for each CONNECT-UDP request. class QUIC_NO_EXPORT ConnectUdpServerState - : public QuicSpdyStream::Http3DatagramRegistrationVisitor, - public QuicSpdyStream::Http3DatagramVisitor { + : public QuicSpdyStream::Http3DatagramVisitor { public: // ConnectUdpServerState takes ownership of |fd|. It will unregister it // from |epoll_server| and close the file descriptor when destructed. explicit ConnectUdpServerState( - QuicSpdyStream* stream, - absl::optional<QuicDatagramContextId> context_id, - const QuicSocketAddress& target_server_address, QuicUdpSocketFd fd, - MasqueServerSession* masque_session); + QuicSpdyStream* stream, const QuicSocketAddress& target_server_address, + QuicUdpSocketFd fd, MasqueServerSession* masque_session); ~ConnectUdpServerState(); @@ -103,9 +78,6 @@ class QUIC_NO_EXPORT MasqueServerSession ConnectUdpServerState& operator=(ConnectUdpServerState&&); QuicSpdyStream* stream() const { return stream_; } - absl::optional<QuicDatagramContextId> context_id() const { - return context_id_; - } const QuicSocketAddress& target_server_address() const { return target_server_address_; } @@ -113,39 +85,23 @@ class QUIC_NO_EXPORT MasqueServerSession // From QuicSpdyStream::Http3DatagramVisitor. void OnHttp3Datagram(QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, absl::string_view payload) override; - // From QuicSpdyStream::Http3DatagramRegistrationVisitor. - void OnContextReceived(QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - DatagramFormatType format_type, - absl::string_view format_additional_data) override; - void OnContextClosed(QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - ContextCloseCode close_code, - absl::string_view close_details) override; - private: QuicSpdyStream* stream_; - absl::optional<QuicDatagramContextId> context_id_; QuicSocketAddress target_server_address_; QuicUdpSocketFd fd_; // Owned. MasqueServerSession* masque_session_; // Unowned. - bool context_received_ = false; - bool context_registered_ = false; }; // From QuicSpdySession. bool OnSettingsFrame(const SettingsFrame& frame) override; HttpDatagramSupport LocalHttpDatagramSupport() override { - return HttpDatagramSupport::kDraft00And04; + return HttpDatagramSupport::kDraft09; } MasqueServerBackend* masque_server_backend_; // Unowned. - Visitor* owner_; // Unowned. QuicEpollServer* epoll_server_; // Unowned. - MasqueCompressionEngine compression_engine_; MasqueMode masque_mode_; std::list<ConnectUdpServerState> connect_udp_server_states_; bool masque_initialized_ = false; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_utils.cc b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_utils.cc index b440bd1e9de..d09fc497575 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_utils.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_utils.cc @@ -30,8 +30,6 @@ std::string MasqueModeToString(MasqueMode masque_mode) { switch (masque_mode) { case MasqueMode::kInvalid: return "Invalid"; - case MasqueMode::kLegacy: - return "Legacy"; case MasqueMode::kOpen: return "Open"; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_utils.h b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_utils.h index 652bf358764..12faae0087c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_utils.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/masque/masque_utils.h @@ -26,10 +26,6 @@ enum : QuicByteCount { // Mode that MASQUE is operating in. enum class MasqueMode : uint8_t { kInvalid = 0, // Should never be used. - kLegacy = 1, // Legacy mode uses the legacy MASQUE protocol as documented in - // <https://tools.ietf.org/html/draft-schinazi-masque-protocol>. That version - // of MASQUE uses a custom application-protocol over HTTP/3, and also allows - // unauthenticated clients. kOpen = 2, // Open mode uses the MASQUE HTTP CONNECT-UDP method as documented // in <https://tools.ietf.org/html/draft-ietf-masque-connect-udp>. This mode // allows unauthenticated clients (a more restricted mode will be added to diff --git a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_containers.h b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_containers.h deleted file mode 100644 index 9420393edf7..00000000000 --- a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_containers.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2017 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_PLATFORM_API_QUIC_CONTAINERS_H_ -#define QUICHE_QUIC_PLATFORM_API_QUIC_CONTAINERS_H_ - -#include "quiche/common/platform/api/quiche_containers.h" - -namespace quic { - -// An ordered container optimized for small sets. -// An implementation with O(n) mutations might be chosen -// in case it has better memory usage and/or faster access. -// -// DOES NOT GUARANTEE POINTER OR ITERATOR STABILITY! -template <typename Key, typename Compare = std::less<Key>> -using QuicSmallOrderedSet = ::quiche::QuicheSmallOrderedSet<Key, Compare>; - -} // namespace quic - -#endif // QUICHE_QUIC_PLATFORM_API_QUIC_CONTAINERS_H_ diff --git a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_export.h b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_export.h index b4f82aa15f4..5edb835799d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_export.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_export.h @@ -5,17 +5,17 @@ #ifndef QUICHE_QUIC_PLATFORM_API_QUIC_EXPORT_H_ #define QUICHE_QUIC_PLATFORM_API_QUIC_EXPORT_H_ -#include "quiche_platform_impl/quiche_export_impl.h" +#include "quiche/common/platform/api/quiche_export.h" // QUIC_EXPORT is not meant to be used. -#define QUIC_EXPORT QUICHE_EXPORT_IMPL +#define QUIC_EXPORT QUICHE_EXPORT // QUIC_EXPORT_PRIVATE is meant for QUIC functionality that is built in Chromium // as part of //net, and not fully contained in headers. -#define QUIC_EXPORT_PRIVATE QUICHE_EXPORT_PRIVATE_IMPL +#define QUIC_EXPORT_PRIVATE QUICHE_EXPORT_PRIVATE // QUIC_NO_EXPORT is meant for QUIC functionality that is either fully defined // in a header, or is built in Chromium as part of tests or tools. -#define QUIC_NO_EXPORT QUICHE_NO_EXPORT_IMPL +#define QUIC_NO_EXPORT QUICHE_NO_EXPORT #endif // QUICHE_QUIC_PLATFORM_API_QUIC_EXPORT_H_ diff --git a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h index c25f160b497..3b36c8fafb0 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h @@ -8,7 +8,6 @@ #include <string> #include <vector> -#include "quiche_platform_impl/quic_flags_impl.h" #include "quiche/common/platform/api/quiche_flags.h" #define GetQuicReloadableFlag(flag) GetQuicheReloadableFlag(quic, flag) diff --git a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_ip_address.cc b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_ip_address.cc index 2dc20717f46..d8412c5e3d6 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_ip_address.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_ip_address.cc @@ -91,17 +91,13 @@ bool operator==(QuicIpAddress lhs, QuicIpAddress rhs) { return false; } -bool operator!=(QuicIpAddress lhs, QuicIpAddress rhs) { - return !(lhs == rhs); -} +bool operator!=(QuicIpAddress lhs, QuicIpAddress rhs) { return !(lhs == rhs); } bool QuicIpAddress::IsInitialized() const { return family_ != IpAddressFamily::IP_UNSPEC; } -IpAddressFamily QuicIpAddress::address_family() const { - return family_; -} +IpAddressFamily QuicIpAddress::address_family() const { return family_; } int QuicIpAddress::AddressFamilyToInt() const { return ToPlatformAddressFamily(family_); @@ -193,13 +189,9 @@ bool QuicIpAddress::FromString(std::string str) { return false; } -bool QuicIpAddress::IsIPv4() const { - return family_ == IpAddressFamily::IP_V4; -} +bool QuicIpAddress::IsIPv4() const { return family_ == IpAddressFamily::IP_V4; } -bool QuicIpAddress::IsIPv6() const { - return family_ == IpAddressFamily::IP_V6; -} +bool QuicIpAddress::IsIPv6() const { return family_ == IpAddressFamily::IP_V6; } bool QuicIpAddress::InSameSubnet(const QuicIpAddress& other, int subnet_length) { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_logging.h b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_logging.h index 442e39c57a9..c44e53f54a4 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_logging.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_logging.h @@ -22,12 +22,6 @@ #define QUIC_LOG_EVERY_N_SEC QUICHE_LOG_EVERY_N_SEC #define QUIC_LOG_IF QUICHE_LOG_IF -#define QUIC_PREDICT_FALSE QUICHE_PREDICT_FALSE -#define QUIC_PREDICT_TRUE QUICHE_PREDICT_TRUE - -// This is a noop in release build. -#define QUIC_NOTREACHED QUICHE_NOTREACHED - #define QUIC_PLOG QUICHE_PLOG #define QUIC_DLOG_INFO_IS_ON QUICHE_DLOG_INFO_IS_ON diff --git a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_mock_log.h b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_mock_log.h deleted file mode 100644 index 0402f10213d..00000000000 --- a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_mock_log.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2017 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_PLATFORM_API_QUIC_MOCK_LOG_H_ -#define QUICHE_QUIC_PLATFORM_API_QUIC_MOCK_LOG_H_ - -#include "quiche/common/platform/api/quiche_mock_log.h" - -using QuicMockLog = QuicheMockLogImpl; - -#define CREATE_QUIC_MOCK_LOG(log) CREATE_QUICHE_MOCK_LOG(log) - -#define EXPECT_QUIC_LOG_CALL(log) EXPECT_QUICHE_LOG_CALL(log) - -#define EXPECT_QUIC_LOG_CALL_CONTAINS(log, level, content) \ - EXPECT_QUICHE_LOG_CALL_CONTAINS(log, level, content) - -#endif // QUICHE_QUIC_PLATFORM_API_QUIC_MOCK_LOG_H_ diff --git a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_socket_address.cc b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_socket_address.cc index 0a35e8661e0..f14faea0f5a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_socket_address.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_socket_address.cc @@ -81,9 +81,7 @@ bool operator!=(const QuicSocketAddress& lhs, const QuicSocketAddress& rhs) { return !(lhs == rhs); } -bool QuicSocketAddress::IsInitialized() const { - return host_.IsInitialized(); -} +bool QuicSocketAddress::IsInitialized() const { return host_.IsInitialized(); } std::string QuicSocketAddress::ToString() const { switch (host_.address_family()) { @@ -114,13 +112,9 @@ QuicSocketAddress QuicSocketAddress::Normalized() const { return QuicSocketAddress(host_.Normalized(), port_); } -QuicIpAddress QuicSocketAddress::host() const { - return host_; -} +QuicIpAddress QuicSocketAddress::host() const { return host_; } -uint16_t QuicSocketAddress::port() const { - return port_; -} +uint16_t QuicSocketAddress::port() const { return port_; } sockaddr_storage QuicSocketAddress::generic_address() const { union { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_stream_buffer_allocator.h b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_stream_buffer_allocator.h deleted file mode 100644 index 174e8783645..00000000000 --- a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_stream_buffer_allocator.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2019 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_PLATFORM_API_QUIC_STREAM_BUFFER_ALLOCATOR_H_ -#define QUICHE_QUIC_PLATFORM_API_QUIC_STREAM_BUFFER_ALLOCATOR_H_ - -#include "quiche/common/platform/api/quiche_stream_buffer_allocator.h" - -namespace quic { - -using QuicStreamBufferAllocator = quiche::QuicheStreamBufferAllocator; -} - -#endif // QUICHE_QUIC_PLATFORM_API_QUIC_STREAM_BUFFER_ALLOCATOR_H_ diff --git a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_test.h b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_test.h index 9e63acca3c6..0d1d2b0b166 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_test.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_test.h @@ -8,22 +8,19 @@ #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/common/platform/api/quiche_test.h" -using QuicFlagSaver = QuicheFlagSaver; +namespace quic::test { + +using QuicFlagSaver = quiche::test::QuicheFlagSaver; // Defines the base classes to be used in QUIC tests. -using QuicTest = QuicheTest; +using QuicTest = quiche::test::QuicheTest; template <class T> -using QuicTestWithParam = QuicheTestWithParam<T>; +using QuicTestWithParam = quiche::test::QuicheTestWithParam<T>; -// Class which needs to be instantiated in tests which use threads. -using ScopedEnvironmentForThreads = ScopedEnvironmentForThreadsImpl; +} // namespace quic::test #define QUIC_TEST_DISABLED_IN_CHROME(name) QUICHE_TEST_DISABLED_IN_CHROME(name) -inline std::string QuicGetTestMemoryCachePath() { - return QuicheGetTestMemoryCachePath(); -} - #define QUIC_SLOW_TEST(test) QUICHE_SLOW_TEST(test) #endif // QUICHE_QUIC_PLATFORM_API_QUIC_TEST_H_ diff --git a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_udp_socket_platform_api.h b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_udp_socket_platform_api.h index d6009d92530..16b1025e39d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_udp_socket_platform_api.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/platform/api/quic_udp_socket_platform_api.h @@ -13,9 +13,7 @@ const size_t kCmsgSpaceForGooglePacketHeader = quiche::kCmsgSpaceForGooglePacketHeader; inline bool GetGooglePacketHeadersFromControlMessage( - struct ::cmsghdr* cmsg, - char** packet_headers, - size_t* packet_headers_len) { + struct ::cmsghdr* cmsg, char** packet_headers, size_t* packet_headers_len) { return quiche::GetGooglePacketHeadersFromControlMessage(cmsg, packet_headers, packet_headers_len); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/icmp_reachable_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/icmp_reachable_test.cc index ffb1092ed30..7a0ebe644de 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/icmp_reachable_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/icmp_reachable_test.cc @@ -7,13 +7,12 @@ #include <netinet/ip6.h> #include "absl/container/node_hash_map.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_epoll.h" #include "quiche/quic/platform/api/quic_ip_address.h" #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/qbone/platform/mock_kernel.h" -namespace quic { +namespace quic::test { namespace { using ::testing::_; @@ -264,4 +263,4 @@ TEST_F(IcmpReachableTest, HandlesReadErrors) { } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/mock_qbone_tunnel.h b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/mock_qbone_tunnel.h index 207ae299fec..409bc476420 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/mock_qbone_tunnel.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/mock_qbone_tunnel.h @@ -36,6 +36,8 @@ class MockQboneTunnel : public QboneTunnelInterface { MOCK_METHOD(State, state, ()); MOCK_METHOD(std::string, HealthString, ()); + + MOCK_METHOD(std::string, ServerRegionString, ()); }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/qbone_tunnel_interface.h b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/qbone_tunnel_interface.h index deb3b37dfe9..c4bd7b4bfa4 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/qbone_tunnel_interface.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/qbone_tunnel_interface.h @@ -61,6 +61,8 @@ class QboneTunnelInterface : public quic::QboneClientControlStream::Handler { virtual State state() = 0; virtual std::string HealthString() = 0; + + virtual std::string ServerRegionString() = 0; }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_controller_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_controller_test.cc index 65daa157c84..62cb8630b59 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_controller_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_controller_test.cc @@ -14,7 +14,7 @@ ABSL_DECLARE_FLAG(bool, qbone_tun_device_replace_default_routing_rules); -namespace quic { +namespace quic::test { namespace { using ::testing::Eq; @@ -255,4 +255,4 @@ TEST_F(DisabledTunDeviceControllerTest, UpdateAddressIsNop) { } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc index f7bf062324a..a6d3a39bfcf 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc @@ -9,7 +9,7 @@ #include "quiche/quic/qbone/mock_qbone_client.h" #include "quiche/quic/qbone/platform/mock_kernel.h" -namespace quic { +namespace quic::test { namespace { const size_t kMtu = 1000; @@ -116,4 +116,4 @@ TEST_F(TunDevicePacketExchangerTest, } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_test.cc index 4af7b20c59a..cc82a2f5ba5 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_test.cc @@ -11,7 +11,7 @@ #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/qbone/platform/mock_kernel.h" -namespace quic { +namespace quic::test { namespace { using ::testing::_; @@ -208,4 +208,4 @@ TEST_F(TunDeviceTest, FailToUp) { } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/internet_checksum.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/internet_checksum.cc index e819f37ca9d..f9901e5c8ec 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/internet_checksum.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/internet_checksum.cc @@ -4,15 +4,20 @@ #include "quiche/quic/qbone/platform/internet_checksum.h" +#include <stdint.h> +#include <string.h> + namespace quic { void InternetChecksum::Update(const char* data, size_t size) { const char* current; for (current = data; current + 1 < data + size; current += 2) { - accumulator_ += *reinterpret_cast<const uint16_t*>(current); + uint16_t v; + memcpy(&v, current, sizeof(v)); + accumulator_ += v; } if (current < data + size) { - accumulator_ += *reinterpret_cast<const uint8_t*>(current); + accumulator_ += *reinterpret_cast<const unsigned char*>(current); } } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink_test.cc index a858eaf4979..9bd91b07d13 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink_test.cc @@ -8,12 +8,11 @@ #include "absl/container/node_hash_set.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/qbone/platform/mock_kernel.h" #include "quiche/quic/qbone/qbone_constants.h" -namespace quic { +namespace quic::test { namespace { using ::testing::_; @@ -762,4 +761,4 @@ TEST_F(NetlinkTest, ChangeRouteReplace) { } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/tcp_packet.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/tcp_packet.cc index 8bc8cb7f4a6..e73e284a010 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/tcp_packet.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/platform/tcp_packet.cc @@ -6,6 +6,7 @@ #include <netinet/ip6.h> +#include "absl/base/optimization.h" #include "absl/strings/string_view.h" #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/qbone/platform/internet_checksum.h" @@ -35,17 +36,17 @@ void CreateTcpResetPacket(absl::string_view original_packet, // By the time this method is called, original_packet should be fairly // strongly validated. However, it's better to be more paranoid than not, so // here are a bunch of very obvious checks. - if (QUIC_PREDICT_FALSE(original_packet.size() < sizeof(ip6_hdr))) { + if (ABSL_PREDICT_FALSE(original_packet.size() < sizeof(ip6_hdr))) { return; } auto* ip6_header = reinterpret_cast<const ip6_hdr*>(original_packet.data()); - if (QUIC_PREDICT_FALSE(ip6_header->ip6_vfc >> 4 != 6)) { + if (ABSL_PREDICT_FALSE(ip6_header->ip6_vfc >> 4 != 6)) { return; } - if (QUIC_PREDICT_FALSE(ip6_header->ip6_nxt != IPPROTO_TCP)) { + if (ABSL_PREDICT_FALSE(ip6_header->ip6_nxt != IPPROTO_TCP)) { return; } - if (QUIC_PREDICT_FALSE(quiche::QuicheEndian::NetToHost16( + if (ABSL_PREDICT_FALSE(quiche::QuicheEndian::NetToHost16( ip6_header->ip6_plen) < sizeof(tcphdr))) { return; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_client_session.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_client_session.cc index 4c22d235b6a..cfc6001abd4 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_client_session.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_client_session.cc @@ -58,7 +58,8 @@ void QboneClientSession::Initialize() { QboneSessionBase::Initialize(); static_cast<QuicCryptoClientStreamBase*>(GetMutableCryptoStream()) ->CryptoConnect(); - if (!GetQuicFlag(FLAGS_qbone_client_defer_control_stream_creation)) { + if (!quiche::GetQuicheCommandLineFlag( + FLAGS_qbone_client_defer_control_stream_creation)) { CreateControlStream(); } } @@ -66,7 +67,8 @@ void QboneClientSession::Initialize() { void QboneClientSession::SetDefaultEncryptionLevel( quic::EncryptionLevel level) { QboneSessionBase::SetDefaultEncryptionLevel(level); - if (GetQuicFlag(FLAGS_qbone_client_defer_control_stream_creation) && + if (quiche::GetQuicheCommandLineFlag( + FLAGS_qbone_client_defer_control_stream_creation) && level == quic::ENCRYPTION_FORWARD_SECURE) { CreateControlStream(); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_client_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_client_test.cc index f796c461405..5fd7229ba91 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_client_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_client_test.cc @@ -32,6 +32,8 @@ namespace quic { namespace test { namespace { +using ::testing::ElementsAre; + ParsedQuicVersionVector GetTestParams() { ParsedQuicVersionVector test_versions; @@ -206,9 +208,11 @@ INSTANTIATE_TEST_SUITE_P(Tests, QboneClientTest, ::testing::PrintToStringParamName()); TEST_P(QboneClientTest, SendDataFromClient) { - auto server = new QboneTestServer(crypto_test_utils::ProofSourceForTesting()); + auto server = std::make_unique<QboneTestServer>( + crypto_test_utils::ProofSourceForTesting()); + QboneTestServer* server_ptr = server.get(); QuicSocketAddress server_address(TestLoopback(), 0); - ServerThread server_thread(server, server_address); + ServerThread server_thread(std::move(server), server_address); server_thread.Initialize(); server_address = QuicSocketAddress(server_address.host(), server_thread.GetPort()); @@ -229,29 +233,27 @@ TEST_P(QboneClientTest, SendDataFromClient) { // Wait until the server has received at least two packets, timeout after 5s. ASSERT_TRUE( - server_thread.WaitUntil([&] { return server->data().size() >= 2; }, + server_thread.WaitUntil([&] { return server_ptr->data().size() >= 2; }, QuicTime::Delta::FromSeconds(5))); - std::string long_data( - QboneConstants::kMaxQbonePacketBytes - sizeof(ip6_hdr) - 1, 'A'); - // Pretend the server gets data. - server_thread.Schedule([&server, &long_data]() { - EXPECT_THAT(server->data()[0], testing::Eq(TestPacketOut("hello"))); - EXPECT_THAT(server->data()[1], testing::Eq(TestPacketOut("world"))); + std::string long_data(1000, 'A'); + server_thread.Schedule([server_ptr, &long_data]() { + EXPECT_THAT(server_ptr->data(), + ElementsAre(TestPacketOut("hello"), TestPacketOut("world"))); auto server_session = static_cast<QboneServerSession*>( QuicDispatcherPeer::GetFirstSessionIfAny( - QuicServerPeer::GetDispatcher(server))); + QuicServerPeer::GetDispatcher(server_ptr))); server_session->ProcessPacketFromNetwork( TestPacketIn("Somethingsomething")); server_session->ProcessPacketFromNetwork(TestPacketIn(long_data)); server_session->ProcessPacketFromNetwork(TestPacketIn(long_data)); }); - ASSERT_TRUE(client.WaitForDataSize(3, QuicTime::Delta::FromSeconds(5))); - EXPECT_THAT(client.data()[0], - testing::Eq(TestPacketOut("Somethingsomething"))); - EXPECT_THAT(client.data()[1], testing::Eq(TestPacketOut(long_data))); - EXPECT_THAT(client.data()[2], testing::Eq(TestPacketOut(long_data))); + + EXPECT_TRUE(client.WaitForDataSize(3, QuicTime::Delta::FromSeconds(5))); + EXPECT_THAT(client.data(), + ElementsAre(TestPacketOut("Somethingsomething"), + TestPacketOut(long_data), TestPacketOut(long_data))); client.Disconnect(); server_thread.Quit(); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_processor.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_processor.cc index cad6cff1b37..abf77d5a663 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_processor.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_processor.cc @@ -6,6 +6,7 @@ #include <cstring> +#include "absl/base/optimization.h" #include "absl/strings/string_view.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/quic/platform/api/quic_ip_address_family.h" @@ -62,7 +63,7 @@ QbonePacketProcessor::Filter::FilterPacket(Direction direction, void QbonePacketProcessor::ProcessPacket(std::string* packet, Direction direction) { - if (QUIC_PREDICT_FALSE(!IsValid())) { + if (ABSL_PREDICT_FALSE(!IsValid())) { QUIC_BUG(quic_bug_11024_1) << "QuicPacketProcessor is invoked in an invalid state."; stats_->OnPacketDroppedSilently(direction); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_processor_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_processor_test.cc index ed3b45c61a7..e11fd5cea58 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_processor_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_processor_test.cc @@ -10,7 +10,7 @@ #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/qbone/qbone_packet_processor_test_tools.h" -namespace quic { +namespace quic::test { namespace { using Direction = QbonePacketProcessor::Direction; @@ -277,4 +277,4 @@ TEST_F(QbonePacketProcessorTest, FilterHelperFunctions) { } } // namespace -} // namespace quic +} // namespace quic::test diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_server_session.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_server_session.cc index 6f189e723bb..c6d622f2ee5 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_server_session.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_server_session.cc @@ -79,7 +79,8 @@ QuicStream* QboneServerSession::CreateControlStreamFromPendingStream( void QboneServerSession::Initialize() { QboneSessionBase::Initialize(); - if (!GetQuicFlag(FLAGS_qbone_server_defer_control_stream_creation)) { + if (!quiche::GetQuicheCommandLineFlag( + FLAGS_qbone_server_defer_control_stream_creation)) { CreateControlStream(); } } @@ -87,7 +88,8 @@ void QboneServerSession::Initialize() { void QboneServerSession::SetDefaultEncryptionLevel( quic::EncryptionLevel level) { QboneSessionBase::SetDefaultEncryptionLevel(level); - if (GetQuicFlag(FLAGS_qbone_server_defer_control_stream_creation) && + if (quiche::GetQuicheCommandLineFlag( + FLAGS_qbone_server_defer_control_stream_creation) && level == quic::ENCRYPTION_FORWARD_SECURE) { CreateControlStream(); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_session_base.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_session_base.cc index 95bd7c7da61..36517b75f5c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_session_base.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_session_base.cc @@ -18,6 +18,7 @@ #include "quiche/quic/qbone/platform/icmp_packet.h" #include "quiche/quic/qbone/qbone_constants.h" #include "quiche/common/platform/api/quiche_command_line_flags.h" +#include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/platform/api/quiche_mem_slice.h" #include "quiche/common/quiche_buffer_allocator.h" @@ -74,7 +75,7 @@ void QboneSessionBase::OnStreamFrame(const QuicStreamFrame& frame) { flow_controller()->AddBytesConsumed(frame.data_length); // TODO(b/147817422): Add a counter for how many streams were actually // closed here. - if (GetQuicFlag(FLAGS_qbone_close_ephemeral_frames)) { + if (quiche::GetQuicheCommandLineFlag(FLAGS_qbone_close_ephemeral_frames)) { ResetStream(frame.stream_id, QUIC_STREAM_CANCELLED); } return; @@ -92,7 +93,7 @@ QuicStream* QboneSessionBase::CreateIncomingStream(QuicStreamId id) { } QuicStream* QboneSessionBase::CreateIncomingStream(PendingStream* /*pending*/) { - QUIC_NOTREACHED(); + QUICHE_NOTREACHED(); return nullptr; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_session_base.h b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_session_base.h index b1278bd39a9..e643f0d942b 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_session_base.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_session_base.h @@ -10,7 +10,6 @@ #include "quiche/quic/core/quic_crypto_stream.h" #include "quiche/quic/core/quic_error_codes.h" #include "quiche/quic/core/quic_session.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/qbone/qbone_packet_writer.h" #include "quiche/quic/qbone/qbone_stream.h" @@ -89,10 +88,9 @@ class QUIC_EXPORT_PRIVATE QboneSessionBase : public QuicSession { QbonePacketWriter* writer_; - // If true, MESSAGE frames are used for short datagrams. If false, ephemeral - // streams are used instead. Note that receiving MESSAGE frames is always - // supported. - bool send_packets_as_messages_ = false; + // If true, send QUIC DATAGRAM (aka MESSAGE) frames instead of ephemeral + // streams. Note that receiving DATAGRAM frames is always supported. + bool send_packets_as_messages_ = true; private: // Used for the crypto handshake. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_stream.cc b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_stream.cc index 3ee8634908b..6465d5953ce 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_stream.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/qbone/qbone_stream.cc @@ -22,8 +22,8 @@ QboneWriteOnlyStream::QboneWriteOnlyStream(QuicStreamId id, : QuicStream(id, session, /*is_static=*/false, WRITE_UNIDIRECTIONAL) { // QBONE uses a LIFO queue to try to always make progress. An individual // packet may persist for upto to qbone_stream_ttl_secs seconds in memory. - MaybeSetTtl( - QuicTime::Delta::FromSeconds(GetQuicFlag(FLAGS_qbone_stream_ttl_secs))); + MaybeSetTtl(QuicTime::Delta::FromSeconds( + quiche::GetQuicheCommandLineFlag(FLAGS_qbone_stream_ttl_secs))); } void QboneWriteOnlyStream::WritePacketToQuicStream(absl::string_view packet) { @@ -39,8 +39,8 @@ QboneReadOnlyStream::QboneReadOnlyStream(QuicStreamId id, session_(session) { // QBONE uses a LIFO queue to try to always make progress. An individual // packet may persist for upto to qbone_stream_ttl_secs seconds in memory. - MaybeSetTtl( - QuicTime::Delta::FromSeconds(GetQuicFlag(FLAGS_qbone_stream_ttl_secs))); + MaybeSetTtl(QuicTime::Delta::FromSeconds( + quiche::GetQuicheCommandLineFlag(FLAGS_qbone_stream_ttl_secs))); } void QboneReadOnlyStream::OnDataAvailable() { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.cc index e2f5c8c432f..4df4f8f3cb2 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.cc @@ -10,14 +10,19 @@ #include <utility> #include "absl/strings/escaping.h" +#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" +#include "absl/types/optional.h" #include "openssl/bn.h" #include "openssl/ec.h" #include "openssl/ecdsa.h" #include "openssl/nid.h" #include "openssl/sha.h" +#include "quiche/quic/core/crypto/certificate_view.h" #include "quiche/quic/core/crypto/channel_id.h" #include "quiche/quic/core/crypto/crypto_handshake.h" +#include "quiche/quic/core/crypto/crypto_utils.h" +#include "quiche/quic/core/crypto/proof_source_x509.h" #include "quiche/quic/core/crypto/quic_crypto_server_config.h" #include "quiche/quic/core/crypto/quic_decrypter.h" #include "quiche/quic/core/crypto/quic_encrypter.h" @@ -28,9 +33,11 @@ #include "quiche/quic/core/quic_crypto_server_stream_base.h" #include "quiche/quic/core/quic_crypto_stream.h" #include "quiche/quic/core/quic_server_id.h" +#include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_utils.h" #include "quiche/quic/core/quic_versions.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" +#include "quiche/quic/platform/api/quic_hostname_utils.h" #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/platform/api/quic_socket_address.h" #include "quiche/quic/platform/api/quic_test.h" @@ -39,6 +46,7 @@ #include "quiche/quic/test_tools/quic_stream_peer.h" #include "quiche/quic/test_tools/quic_test_utils.h" #include "quiche/quic/test_tools/simple_quic_framer.h" +#include "quiche/quic/test_tools/test_certificates.h" #include "quiche/common/test_tools/quiche_test_utils.h" namespace quic { @@ -376,7 +384,7 @@ void CommunicateHandshakeMessages(PacketSavingConnection* client_conn, << client_conn->encrypted_packets_.size() - client_i << " packets client->server"; MovePackets(client_conn, &client_i, server, server_conn, - Perspective::IS_SERVER); + Perspective::IS_SERVER, /*process_stream_data=*/false); if (client->one_rtt_keys_available() && server->one_rtt_keys_available() && server_conn->encrypted_packets_.size() == server_i) { @@ -387,7 +395,7 @@ void CommunicateHandshakeMessages(PacketSavingConnection* client_conn, << server_conn->encrypted_packets_.size() - server_i << " packets server->client"; MovePackets(server_conn, &server_i, client, client_conn, - Perspective::IS_CLIENT); + Perspective::IS_CLIENT, /*process_stream_data=*/false); } } @@ -396,7 +404,8 @@ bool CommunicateHandshakeMessagesUntil(PacketSavingConnection* client_conn, std::function<bool()> client_condition, PacketSavingConnection* server_conn, QuicCryptoStream* server, - std::function<bool()> server_condition) { + std::function<bool()> server_condition, + bool process_stream_data) { size_t client_next_packet_to_deliver = client_conn->number_of_packets_delivered_; size_t server_next_packet_to_deliver = @@ -413,7 +422,7 @@ bool CommunicateHandshakeMessagesUntil(PacketSavingConnection* client_conn, client_next_packet_to_deliver << " packets client->server"; MovePackets(client_conn, &client_next_packet_to_deliver, server, - server_conn, Perspective::IS_SERVER); + server_conn, Perspective::IS_SERVER, process_stream_data); } if (!client_condition()) { QUIC_LOG(INFO) << "Processing " @@ -421,7 +430,7 @@ bool CommunicateHandshakeMessagesUntil(PacketSavingConnection* client_conn, server_next_packet_to_deliver << " packets server->client"; MovePackets(server_conn, &server_next_packet_to_deliver, client, - client_conn, Perspective::IS_CLIENT); + client_conn, Perspective::IS_CLIENT, process_stream_data); } } client_conn->number_of_packets_delivered_ = client_next_packet_to_deliver; @@ -449,7 +458,7 @@ std::pair<size_t, size_t> AdvanceHandshake(PacketSavingConnection* client_conn, << client_conn->encrypted_packets_.size() - client_i << " packets client->server"; MovePackets(client_conn, &client_i, server, server_conn, - Perspective::IS_SERVER); + Perspective::IS_SERVER, /*process_stream_data=*/false); } if (server_conn->encrypted_packets_.size() != server_i) { @@ -457,7 +466,7 @@ std::pair<size_t, size_t> AdvanceHandshake(PacketSavingConnection* client_conn, << server_conn->encrypted_packets_.size() - server_i << " packets server->client"; MovePackets(server_conn, &server_i, client, client_conn, - Perspective::IS_CLIENT); + Perspective::IS_CLIENT, /*process_stream_data=*/false); } return std::make_pair(client_i, server_i); @@ -701,7 +710,7 @@ CryptoHandshakeMessage CreateCHLO( void MovePackets(PacketSavingConnection* source_conn, size_t* inout_packet_index, QuicCryptoStream* dest_stream, PacketSavingConnection* dest_conn, - Perspective dest_perspective) { + Perspective dest_perspective, bool process_stream_data) { SimpleQuicFramer framer(source_conn->supported_versions(), dest_perspective); QuicFramerPeer::SetLastSerializedServerConnectionId(framer.framer(), TestConnectionId()); @@ -771,10 +780,17 @@ void MovePackets(PacketSavingConnection* source_conn, QuicConnectionPeer::SetCurrentPacket( dest_conn, source_conn->encrypted_packets_[index]->AsStringPiece()); for (const auto& stream_frame : framer.stream_frames()) { - // Ignore stream frames that are sent on other streams in the crypto - // event. - if (stream_frame->stream_id == dest_stream->id()) { - dest_stream->OnStreamFrame(*stream_frame); + if (process_stream_data && + dest_stream->handshake_protocol() == PROTOCOL_TLS1_3) { + // Deliver STREAM_FRAME such that application state is available and can + // be stored along with resumption ticket in session cache, + dest_conn->OnStreamFrame(*stream_frame); + } else { + // Ignore stream frames that are sent on other streams in the crypto + // event. + if (stream_frame->stream_id == dest_stream->id()) { + dest_stream->OnStreamFrame(*stream_frame); + } } } for (const auto& crypto_frame : framer.crypto_frames()) { @@ -852,6 +868,112 @@ void GenerateFullCHLO( signed_config, generator.GetValidateClientHelloCallback()); } +namespace { + +constexpr char kTestProofHostname[] = "test.example.com"; + +class TestProofSource : public ProofSourceX509 { + public: + TestProofSource() + : ProofSourceX509( + quiche::QuicheReferenceCountedPointer<ProofSource::Chain>( + new ProofSource::Chain( + std::vector<std::string>{std::string(kTestCertificate)})), + std::move(*CertificatePrivateKey::LoadFromDer( + kTestCertificatePrivateKey))) { + QUICHE_DCHECK(valid()); + } + + protected: + void MaybeAddSctsForHostname(absl::string_view /*hostname*/, + std::string& leaf_cert_scts) override { + leaf_cert_scts = "Certificate Transparency is really nice"; + } +}; + +class TestProofVerifier : public ProofVerifier { + public: + TestProofVerifier() + : certificate_(std::move( + *CertificateView::ParseSingleCertificate(kTestCertificate))) {} + + class Details : public ProofVerifyDetails { + public: + ProofVerifyDetails* Clone() const override { return new Details(*this); } + }; + + QuicAsyncStatus VerifyProof( + const std::string& hostname, const uint16_t port, + const std::string& server_config, + QuicTransportVersion /*transport_version*/, absl::string_view chlo_hash, + const std::vector<std::string>& certs, const std::string& cert_sct, + const std::string& signature, const ProofVerifyContext* context, + std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, + std::unique_ptr<ProofVerifierCallback> callback) override { + absl::optional<std::string> payload = + CryptoUtils::GenerateProofPayloadToBeSigned(chlo_hash, server_config); + if (!payload.has_value()) { + *error_details = "Failed to serialize signed payload"; + return QUIC_FAILURE; + } + if (!certificate_.VerifySignature(*payload, signature, + SSL_SIGN_RSA_PSS_RSAE_SHA256)) { + *error_details = "Invalid signature"; + return QUIC_FAILURE; + } + + uint8_t out_alert; + return VerifyCertChain(hostname, port, certs, /*ocsp_response=*/"", + cert_sct, context, error_details, details, + &out_alert, std::move(callback)); + } + + QuicAsyncStatus VerifyCertChain( + const std::string& hostname, const uint16_t /*port*/, + const std::vector<std::string>& certs, + const std::string& /*ocsp_response*/, const std::string& /*cert_sct*/, + const ProofVerifyContext* /*context*/, std::string* error_details, + std::unique_ptr<ProofVerifyDetails>* details, uint8_t* /*out_alert*/, + std::unique_ptr<ProofVerifierCallback> /*callback*/) override { + std::string normalized_hostname = + QuicHostnameUtils::NormalizeHostname(hostname); + if (normalized_hostname != kTestProofHostname) { + *error_details = absl::StrCat("Invalid hostname, expected ", + kTestProofHostname, " got ", hostname); + return QUIC_FAILURE; + } + if (certs.empty() || certs.front() != kTestCertificate) { + *error_details = "Received certificate different from the expected"; + return QUIC_FAILURE; + } + *details = std::make_unique<Details>(); + return QUIC_SUCCESS; + } + + std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override { + return nullptr; + } + + private: + CertificateView certificate_; +}; + +} // namespace + +std::unique_ptr<ProofSource> ProofSourceForTesting() { + return std::make_unique<TestProofSource>(); +} + +std::unique_ptr<ProofVerifier> ProofVerifierForTesting() { + return std::make_unique<TestProofVerifier>(); +} + +std::string CertificateHostnameForTesting() { return kTestProofHostname; } + +std::unique_ptr<ProofVerifyContext> ProofVerifyContextForTesting() { + return nullptr; +} + } // namespace crypto_test_utils } // namespace test } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h index a1cd35e244d..d21e8978b4b 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h @@ -109,15 +109,18 @@ void CommunicateHandshakeMessages(PacketSavingConnection* client_conn, // 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 +// 3) For IETF QUIC, if `process_stream_data` is true, STREAM_FRAME within the +// packet containing crypto messages is also processed. +// 4) Returns true if both conditions are met. +// 5) 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); + std::function<bool()> server_condition, + bool process_stream_data); // AdvanceHandshake attempts to moves messages from |client| to |server| and // |server| to |client|. Returns the number of messages moved. @@ -137,6 +140,9 @@ std::unique_ptr<ProofSource> ProofSourceForTesting(); // Returns a new |ProofVerifier| that uses the QUIC testing root CA. std::unique_ptr<ProofVerifier> ProofVerifierForTesting(); +// Returns the hostname used by the proof source and the proof verifier above. +std::string CertificateHostnameForTesting(); + // Returns a hash of the leaf test certificate. uint64_t LeafCertHashForTesting(); @@ -173,11 +179,13 @@ CryptoHandshakeMessage CreateCHLO( // MovePackets parses crypto handshake messages from packet number // |*inout_packet_index| through to the last packet (or until a packet fails // to decrypt) and has |dest_stream| process them. |*inout_packet_index| is -// updated with an index one greater than the last packet processed. +// updated with an index one greater than the last packet processed. For IETF +// QUIC, if `process_stream_data` is true, STREAM_FRAME within the packet +// containing crypto messages is also processed. void MovePackets(PacketSavingConnection* source_conn, size_t* inout_packet_index, QuicCryptoStream* dest_stream, PacketSavingConnection* dest_conn, - Perspective dest_perspective); + Perspective dest_perspective, bool process_stream_data); // Return an inchoate CHLO with some basic tag value pairs. CryptoHandshakeMessage GenerateDefaultInchoateCHLO( diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/packet_dropping_test_writer.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/packet_dropping_test_writer.cc index 03b65005d71..69aae1456f2 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/packet_dropping_test_writer.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/packet_dropping_test_writer.cc @@ -4,7 +4,6 @@ #include "quiche/quic/test_tools/packet_dropping_test_writer.h" -#include "quiche/quic/core/quic_epoll_connection_helper.h" #include "quiche/quic/platform/api/quic_logging.h" namespace quic { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/packet_dropping_test_writer.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/packet_dropping_test_writer.h index 0cc684e7f6b..a7e91d3465c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/packet_dropping_test_writer.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/packet_dropping_test_writer.h @@ -11,9 +11,11 @@ #include "absl/base/attributes.h" #include "quiche/quic/core/quic_alarm.h" +#include "quiche/quic/core/quic_alarm_factory.h" #include "quiche/quic/core/quic_clock.h" +#include "quiche/quic/core/quic_connection.h" #include "quiche/quic/core/quic_packet_writer_wrapper.h" -#include "quiche/quic/test_tools/quic_test_client.h" +#include "quiche/quic/platform/api/quic_mutex.h" #include "quiche/quic/test_tools/quic_test_utils.h" namespace quic { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.cc index e124580ebd2..e38bfc3980f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.cc @@ -60,10 +60,28 @@ QuicTime::Delta QuicConnectionPeer::GetHandshakeTimeout( } // static +QuicTime::Delta QuicConnectionPeer::GetBandwidthUpdateTimeout( + QuicConnection* connection) { + return connection->idle_network_detector_.bandwidth_update_timeout_; +} + +// static +void QuicConnectionPeer::DisableBandwidthUpdate(QuicConnection* connection) { + if (connection->idle_network_detector_.bandwidth_update_timeout_ + .IsInfinite()) { + return; + } + connection->idle_network_detector_.bandwidth_update_timeout_ = + QuicTime::Delta::Infinite(); + connection->idle_network_detector_.SetAlarm(); +} + +// static void QuicConnectionPeer::SetPerspective(QuicConnection* connection, Perspective perspective) { connection->perspective_ = perspective; QuicFramerPeer::SetPerspective(&connection->framer_, perspective); + connection->ping_manager_.perspective_ = perspective; } // static @@ -101,7 +119,7 @@ void QuicConnectionPeer::SwapCrypters(QuicConnection* connection, void QuicConnectionPeer::SetCurrentPacket(QuicConnection* connection, absl::string_view current_packet) { connection->current_packet_data_ = current_packet.data(); - connection->last_size_ = current_packet.size(); + connection->last_received_packet_info_.length = current_packet.size(); } // static @@ -128,6 +146,9 @@ QuicAlarm* QuicConnectionPeer::GetAckAlarm(QuicConnection* connection) { // static QuicAlarm* QuicConnectionPeer::GetPingAlarm(QuicConnection* connection) { + if (GetQuicReloadableFlag(quic_use_ping_manager2)) { + return connection->ping_manager_.alarm_.get(); + } return connection->ping_alarm_.get(); } @@ -219,7 +240,7 @@ QuicEncryptedPacket* QuicConnectionPeer::GetConnectionClosePacket( // static QuicPacketHeader* QuicConnectionPeer::GetLastHeader( QuicConnection* connection) { - return &connection->last_header_; + return &connection->last_received_packet_info_.header; } // static @@ -303,12 +324,6 @@ QuicConnection::PacketContent QuicConnectionPeer::GetCurrentPacketContent( } // static -void QuicConnectionPeer::SetLastHeaderFormat(QuicConnection* connection, - PacketHeaderFormat format) { - connection->last_header_.form = format; -} - -// static void QuicConnectionPeer::AddBytesReceived(QuicConnection* connection, size_t length) { if (connection->EnforceAntiAmplificationLimit()) { @@ -519,7 +534,7 @@ QuicConnectionPeer::MakeSelfIssuedConnectionIdManager( // static void QuicConnectionPeer::SetLastDecryptedLevel(QuicConnection* connection, EncryptionLevel level) { - connection->last_decrypted_packet_level_ = level; + connection->last_received_packet_info_.decrypted_level = level; } // static diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h index ffe3b3cbb16..d1a41f99006 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h @@ -53,6 +53,10 @@ class QuicConnectionPeer { static QuicTime::Delta GetHandshakeTimeout(QuicConnection* connection); + static QuicTime::Delta GetBandwidthUpdateTimeout(QuicConnection* connection); + + static void DisableBandwidthUpdate(QuicConnection* connection); + static void SetPerspective(QuicConnection* connection, Perspective perspective); @@ -128,8 +132,6 @@ class QuicConnectionPeer { static bool SupportsReleaseTime(QuicConnection* connection); static QuicConnection::PacketContent GetCurrentPacketContent( QuicConnection* connection); - static void SetLastHeaderFormat(QuicConnection* connection, - PacketHeaderFormat format); static void AddBytesReceived(QuicConnection* connection, size_t length); static void SetAddressValidated(QuicConnection* connection); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_http_response_cache_data/test.example.com/index.html b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_http_response_cache_data/test.example.com/index.html new file mode 100644 index 00000000000..5edaf9af7b5 --- /dev/null +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_http_response_cache_data/test.example.com/index.html @@ -0,0 +1,63 @@ +HTTP/1.1 200 OK +Date: Tue, 28 Aug 2012 15:08:56 GMT +Server: Apache/2.2.3 (CentOS) +X-Powered-By: PHP/5.1.6 +Set-Cookie: bblastvisit=1346166536; expires=Wed, 28-Aug-2013 15:08:56 GMT; path=/; domain=.nasioc.com +Set-Cookie: bblastactivity=0; expires=Wed, 28-Aug-2013 15:08:56 GMT; path=/; domain=.nasioc.com +Expires: 0 +Cache-Control: private, post-check=0, pre-check=0, max-age=0 +Pragma: no-cache +X-UA-Compatible: IE=7 +Connection: close +Content-Type: text/html; charset=ISO-8859-1 + +<!doctype html> +<html> +<head> + <title>Example Domain</title> + + <meta charset="utf-8" /> + <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <style type="text/css"> + body { + background-color: #f0f0f2; + margin: 0; + padding: 0; + font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + + } + div { + width: 600px; + margin: 5em auto; + padding: 50px; + background-color: #fff; + border-radius: 1em; + } + a:link, a:visited { + color: #38488f; + text-decoration: none; + } + @media (max-width: 700px) { + body { + background-color: #fff; + } + div { + width: auto; + margin: 0 auto; + border-radius: 0; + padding: 1em; + } + } + </style> +</head> + +<body> +<div> + <h1>Example Domain</h1> + <p>This domain is established to be used for illustrative examples in documents. You may use this + domain in examples without prior coordination or asking for permission.</p> + <p><a href="http://www.iana.org/domains/example">More information...</a></p> +</div> +</body> +</html> diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_http_response_cache_data/test.example.com/map.html b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_http_response_cache_data/test.example.com/map.html new file mode 100644 index 00000000000..b34c3b085f0 --- /dev/null +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_http_response_cache_data/test.example.com/map.html @@ -0,0 +1,65 @@ +HTTP/1.1 200 OK +Date: Tue, 28 Aug 2012 15:08:56 GMT +Server: Apache/2.2.3 (CentOS) +X-Powered-By: PHP/5.1.6 +Set-Cookie: bblastvisit=1346166536; expires=Wed, 28-Aug-2013 15:08:56 GMT; path=/; domain=.nasioc.com +Set-Cookie: bblastactivity=0; expires=Wed, 28-Aug-2013 15:08:56 GMT; path=/; domain=.nasioc.com +Expires: 0 +Cache-Control: private, post-check=0, pre-check=0, max-age=0 +Pragma: no-cache +X-UA-Compatible: IE=7 +Connection: close +Content-Type: text/html; charset=ISO-8859-1 +X-Original-Url: http://test.example.com/site_map.html + + +<!doctype html> +<html> +<head> + <title>Example Domain</title> + + <meta charset="utf-8" /> + <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <style type="text/css"> + body { + background-color: #f0f0f2; + margin: 0; + padding: 0; + font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + + } + div { + width: 600px; + margin: 5em auto; + padding: 50px; + background-color: #fff; + border-radius: 1em; + } + a:link, a:visited { + color: #38488f; + text-decoration: none; + } + @media (max-width: 700px) { + body { + background-color: #fff; + } + div { + width: auto; + margin: 0 auto; + border-radius: 0; + padding: 1em; + } + } + </style> +</head> + +<body> +<div> + <h1>Example Domain</h1> + <p>This domain is established to be used for illustrative examples in documents. You may use this + domain in examples without prior coordination or asking for permission.</p> + <p><a href="http://www.iana.org/domains/example">More information...</a></p> +</div> +</body> +</html> diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_sent_packet_manager_peer.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_sent_packet_manager_peer.cc index dc410411754..2f3cb6375c1 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_sent_packet_manager_peer.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_sent_packet_manager_peer.cc @@ -13,23 +13,6 @@ namespace quic { namespace test { -// static -size_t QuicSentPacketManagerPeer::GetMaxTailLossProbes( - QuicSentPacketManager* sent_packet_manager) { - return sent_packet_manager->max_tail_loss_probes_; -} - -// static -void QuicSentPacketManagerPeer::SetMaxTailLossProbes( - QuicSentPacketManager* sent_packet_manager, size_t max_tail_loss_probes) { - sent_packet_manager->max_tail_loss_probes_ = max_tail_loss_probes; -} - -// static -bool QuicSentPacketManagerPeer::GetUseNewRto( - QuicSentPacketManager* sent_packet_manager) { - return sent_packet_manager->use_new_rto_; -} // static void QuicSentPacketManagerPeer::SetPerspective( @@ -91,18 +74,6 @@ void QuicSentPacketManagerPeer::MarkForRetransmission( } // static -QuicTime::Delta QuicSentPacketManagerPeer::GetRetransmissionDelay( - const QuicSentPacketManager* sent_packet_manager) { - return sent_packet_manager->GetRetransmissionDelay(); -} - -// static -QuicTime::Delta QuicSentPacketManagerPeer::GetTailLossProbeDelay( - const QuicSentPacketManager* sent_packet_manager) { - return sent_packet_manager->GetTailLossProbeDelay(); -} - -// static size_t QuicSentPacketManagerPeer::GetNumRetransmittablePackets( const QuicSentPacketManager* sent_packet_manager) { size_t num_unacked_packets = 0; @@ -116,15 +87,9 @@ size_t QuicSentPacketManagerPeer::GetNumRetransmittablePackets( } // static -void QuicSentPacketManagerPeer::SetConsecutiveRtoCount( - QuicSentPacketManager* sent_packet_manager, size_t count) { - sent_packet_manager->consecutive_rto_count_ = count; -} - -// static -void QuicSentPacketManagerPeer::SetConsecutiveTlpCount( +void QuicSentPacketManagerPeer::SetConsecutivePtoCount( QuicSentPacketManager* sent_packet_manager, size_t count) { - sent_packet_manager->consecutive_tlp_count_ = count; + sent_packet_manager->consecutive_pto_count_ = count; } // static diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_sent_packet_manager_peer.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_sent_packet_manager_peer.h index be2a7bd7b80..aef38d30252 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_sent_packet_manager_peer.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_sent_packet_manager_peer.h @@ -18,13 +18,6 @@ class QuicSentPacketManagerPeer { public: QuicSentPacketManagerPeer() = delete; - static size_t GetMaxTailLossProbes( - QuicSentPacketManager* sent_packet_manager); - - static void SetMaxTailLossProbes(QuicSentPacketManager* sent_packet_manager, - size_t max_tail_loss_probes); - - static bool GetUseNewRto(QuicSentPacketManager* sent_packet_manager); static void SetPerspective(QuicSentPacketManager* sent_packet_manager, Perspective perspective); @@ -51,18 +44,10 @@ class QuicSentPacketManagerPeer { uint64_t packet_number, TransmissionType transmission_type); - static QuicTime::Delta GetRetransmissionDelay( - const QuicSentPacketManager* sent_packet_manager); - static QuicTime::Delta GetTailLossProbeDelay( - const QuicSentPacketManager* sent_packet_manager); - static size_t GetNumRetransmittablePackets( const QuicSentPacketManager* sent_packet_manager); - static void SetConsecutiveRtoCount(QuicSentPacketManager* sent_packet_manager, - size_t count); - - static void SetConsecutiveTlpCount(QuicSentPacketManager* sent_packet_manager, + static void SetConsecutivePtoCount(QuicSentPacketManager* sent_packet_manager, size_t count); static QuicSustainedBandwidthRecorder& GetBandwidthRecorder( diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_session_peer.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_session_peer.h index b01c925d202..041d9214616 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_session_peer.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_session_peer.h @@ -13,7 +13,6 @@ #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_session.h" #include "quiche/quic/core/quic_write_blocked_list.h" -#include "quiche/quic/platform/api/quic_containers.h" namespace quic { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_stream_peer.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_stream_peer.cc index d2ec5fd13a9..15806b372ab 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_stream_peer.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_stream_peer.cc @@ -25,11 +25,6 @@ QuicSpdyStreamPeer::unacked_frame_headers_offsets(QuicSpdyStream* stream) { } // static -bool QuicSpdyStreamPeer::use_datagram_contexts(QuicSpdyStream* stream) { - return stream->use_datagram_contexts_; -} - -// static bool QuicSpdyStreamPeer::OnHeadersFrameEnd(QuicSpdyStream* stream) { return stream->OnHeadersFrameEnd(); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_stream_peer.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_stream_peer.h index e92f89eca50..8b5083d2620 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_stream_peer.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_stream_peer.h @@ -7,7 +7,6 @@ #include "quiche/quic/core/quic_ack_listener_interface.h" #include "quiche/quic/core/quic_interval_set.h" -#include "quiche/quic/platform/api/quic_containers.h" namespace quic { @@ -24,7 +23,6 @@ class QuicSpdyStreamPeer { ack_listener); static const QuicIntervalSet<QuicStreamOffset>& unacked_frame_headers_offsets( QuicSpdyStream* stream); - static bool use_datagram_contexts(QuicSpdyStream* stream); static bool OnHeadersFrameEnd(QuicSpdyStream* stream); }; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.h index 8fef41a2336..33549cce8f9 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.h @@ -26,12 +26,6 @@ class QuicTestBackend : public QuicMemoryCacheBackend { enable_webtransport_ = enable_webtransport; } - bool UsesDatagramContexts() override { return use_datagram_contexts_; } - - void set_use_datagram_contexts(bool use_datagram_contexts) { - use_datagram_contexts_ = use_datagram_contexts; - } - bool SupportsExtendedConnect() override { return enable_extended_connect_; } void set_enable_extended_connect(bool enable_extended_connect) { @@ -40,7 +34,6 @@ class QuicTestBackend : public QuicMemoryCacheBackend { private: bool enable_webtransport_ = false; - bool use_datagram_contexts_ = false; bool enable_extended_connect_ = true; }; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.cc index b182dc5f713..6582ee715f8 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.cc @@ -657,9 +657,10 @@ MockQuicSpdySession::MockQuicSpdySession(QuicConnection* connection, return QuicSpdySession::SendWindowUpdate(id, byte_offset); }); - ON_CALL(*this, SendBlocked(_)).WillByDefault([this](QuicStreamId id) { - return QuicSpdySession::SendBlocked(id); - }); + ON_CALL(*this, SendBlocked(_, _)) + .WillByDefault([this](QuicStreamId id, QuicStreamOffset byte_offset) { + return QuicSpdySession::SendBlocked(id, byte_offset); + }); ON_CALL(*this, OnCongestionWindowChange(_)).WillByDefault(testing::Return()); } @@ -1335,9 +1336,10 @@ WriteResult TestPacketWriter::WritePacket(const char* buffer, size_t buf_len, ENCRYPTION_FORWARD_SECURE, std::make_unique<NullDecrypter>(framer_.framer()->perspective())); } - EXPECT_TRUE(framer_.ProcessPacket(packet)) + EXPECT_EQ(next_packet_processable_, framer_.ProcessPacket(packet)) << framer_.framer()->detailed_error() << " perspective " << framer_.framer()->perspective(); + next_packet_processable_ = true; if (block_on_next_write_) { write_blocked_ = true; block_on_next_write_ = false; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h index a26349bd7f6..0e2c20c509e 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h @@ -453,7 +453,6 @@ class MockQuicConnectionVisitor : public QuicConnectionVisitorInterface { (override)); MOCK_METHOD(void, OnWriteBlocked, (), (override)); MOCK_METHOD(void, OnCanWrite, (), (override)); - MOCK_METHOD(bool, SendProbingData, (), (override)); MOCK_METHOD(void, OnCongestionWindowChange, (QuicTime now), (override)); MOCK_METHOD(void, OnConnectionMigration, (AddressChangeType type), (override)); @@ -504,6 +503,8 @@ class MockQuicConnectionVisitor : public QuicConnectionVisitorInterface { const QuicSocketAddress& /*address*/) const override { return false; } + + void OnBandwidthUpdateTimeout() override {} }; class MockQuicConnectionHelper : public QuicConnectionHelperInterface { @@ -777,6 +778,8 @@ class MockQuicSession : public QuicSession { (override)); MOCK_METHOD(void, MaybeSendStopSendingFrame, (QuicStreamId stream_id, QuicResetStreamError error), (override)); + MOCK_METHOD(void, SendBlocked, + (QuicStreamId stream_id, QuicStreamOffset offset), (override)); MOCK_METHOD(bool, ShouldKeepConnectionAlive, (), (const, override)); MOCK_METHOD(std::vector<std::string>, GetAlpnsToOffer, (), (const, override)); @@ -853,6 +856,24 @@ class MockQuicCryptoStream : public QuicCryptoStream { return false; } SSL* GetSsl() const override { return nullptr; } + bool IsCryptoFrameExpectedForEncryptionLevel( + quic::EncryptionLevel level) const override { + return level != ENCRYPTION_ZERO_RTT; + } + EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace( + PacketNumberSpace space) const override { + switch (space) { + case INITIAL_DATA: + return ENCRYPTION_INITIAL; + case HANDSHAKE_DATA: + return ENCRYPTION_HANDSHAKE; + case APPLICATION_DATA: + return ENCRYPTION_FORWARD_SECURE; + default: + QUICHE_DCHECK(false); + return NUM_ENCRYPTION_LEVELS; + } + } private: quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_; @@ -908,7 +929,8 @@ class MockQuicSpdySession : public QuicSpdySession { (QuicStreamId stream_id, QuicResetStreamError error), (override)); MOCK_METHOD(void, SendWindowUpdate, (QuicStreamId id, QuicStreamOffset byte_offset), (override)); - MOCK_METHOD(void, SendBlocked, (QuicStreamId id), (override)); + MOCK_METHOD(void, SendBlocked, + (QuicStreamId id, QuicStreamOffset byte_offset), (override)); MOCK_METHOD(void, OnStreamHeadersPriority, (QuicStreamId stream_id, const spdy::SpdyStreamPrecedence& precedence), @@ -959,8 +981,6 @@ class MockHttp3DebugVisitor : public Http3DebugVisitor { MOCK_METHOD(void, OnSettingsFrameReceived, (const SettingsFrame&), (override)); MOCK_METHOD(void, OnGoAwayFrameReceived, (const GoAwayFrame&), (override)); - MOCK_METHOD(void, OnMaxPushIdFrameReceived, (const MaxPushIdFrame&), - (override)); MOCK_METHOD(void, OnPriorityUpdateFrameReceived, (const PriorityUpdateFrame&), (override)); MOCK_METHOD(void, OnAcceptChFrameReceived, (const AcceptChFrame&), @@ -1033,11 +1053,7 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase { void set_early_data_enabled(bool enabled) { early_data_enabled_ = enabled; } - void set_client_cert_mode(ClientCertMode mode) { - if (support_client_cert()) { - client_cert_mode_ = mode; - } - } + void set_client_cert_mode(ClientCertMode mode) { client_cert_mode_ = mode; } private: MockQuicSessionVisitor visitor_; @@ -1192,7 +1208,6 @@ class MockSendAlgorithm : public SendAlgorithmInterface { MOCK_METHOD(std::string, GetDebugState, (), (const, override)); MOCK_METHOD(bool, InSlowStart, (), (const, override)); MOCK_METHOD(bool, InRecovery, (), (const, override)); - MOCK_METHOD(bool, ShouldSendProbingPacket, (), (const, override)); MOCK_METHOD(QuicByteCount, GetSlowStartThreshold, (), (const, override)); MOCK_METHOD(CongestionControlType, GetCongestionControlType, (), (const, override)); @@ -1777,6 +1792,8 @@ class TestPacketWriter : public QuicPacketWriter { void SimulateNextPacketTooLarge() { next_packet_too_large_ = true; } + void ExpectNextPacketUnprocessable() { next_packet_processable_ = false; } + void AlwaysGetPacketTooLarge() { always_get_packet_too_large_ = true; } // Sets the amount of time that the writer should before the actual write. @@ -1923,6 +1940,7 @@ class TestPacketWriter : public QuicPacketWriter { bool block_on_next_flush_ = false; bool block_on_next_write_ = false; bool next_packet_too_large_ = false; + bool next_packet_processable_ = true; bool always_get_packet_too_large_ = false; bool is_write_blocked_data_buffered_ = false; bool is_batch_mode_ = false; @@ -1987,11 +2005,9 @@ class SavingHttp3DatagramVisitor : public QuicSpdyStream::Http3DatagramVisitor { public: struct SavedHttp3Datagram { QuicStreamId stream_id; - absl::optional<QuicDatagramContextId> context_id; std::string payload; bool operator==(const SavedHttp3Datagram& o) const { - return stream_id == o.stream_id && context_id == o.context_id && - payload == o.payload; + return stream_id == o.stream_id && payload == o.payload; } }; const std::vector<SavedHttp3Datagram>& received_h3_datagrams() const { @@ -2000,33 +2016,15 @@ class SavingHttp3DatagramVisitor : public QuicSpdyStream::Http3DatagramVisitor { // Override from QuicSpdyStream::Http3DatagramVisitor. void OnHttp3Datagram(QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, absl::string_view payload) override { received_h3_datagrams_.push_back( - SavedHttp3Datagram{stream_id, context_id, std::string(payload)}); + SavedHttp3Datagram{stream_id, std::string(payload)}); } private: std::vector<SavedHttp3Datagram> received_h3_datagrams_; }; -class MockHttp3DatagramRegistrationVisitor - : public QuicSpdyStream::Http3DatagramRegistrationVisitor { - public: - MOCK_METHOD(void, OnContextReceived, - (QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - DatagramFormatType format_type, - absl::string_view format_additional_data), - (override)); - - MOCK_METHOD(void, OnContextClosed, - (QuicStreamId stream_id, - absl::optional<QuicDatagramContextId> context_id, - ContextCloseCode close_code, absl::string_view close_details), - (override)); -}; - } // namespace test } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/server_thread.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/server_thread.cc index 12d2fc2c7c2..7e8ab1ef873 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/server_thread.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/server_thread.cc @@ -5,7 +5,6 @@ #include "quiche/quic/test_tools/server_thread.h" #include "quiche/quic/core/quic_dispatcher.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/test_tools/crypto_test_utils.h" #include "quiche/quic/test_tools/quic_dispatcher_peer.h" #include "quiche/quic/test_tools/quic_server_peer.h" @@ -13,10 +12,11 @@ namespace quic { namespace test { -ServerThread::ServerThread(QuicServer* server, const QuicSocketAddress& address) +ServerThread::ServerThread(std::unique_ptr<QuicServer> server, + const QuicSocketAddress& address) : QuicThread("server_thread"), - server_(server), - clock_(server->epoll_server()), + server_(std::move(server)), + clock_(server_->epoll_server()), address_(address), port_(0), initialized_(false) {} diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/server_thread.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/server_thread.h index 7f5d45a8851..fc534679ae6 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/server_thread.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/server_thread.h @@ -9,7 +9,6 @@ #include "quiche/quic/core/quic_config.h" #include "quiche/quic/core/quic_epoll_clock.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_mutex.h" #include "quiche/quic/platform/api/quic_socket_address.h" #include "quiche/quic/platform/api/quic_thread.h" @@ -21,7 +20,8 @@ namespace test { // Simple wrapper class to run QuicServer in a dedicated thread. class ServerThread : public QuicThread { public: - ServerThread(QuicServer* server, const QuicSocketAddress& address); + ServerThread(std::unique_ptr<QuicServer> server, + const QuicSocketAddress& address); ServerThread(const ServerThread&) = delete; ServerThread& operator=(const ServerThread&) = delete; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simple_data_producer.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simple_data_producer.h index dd312d91c71..96952d744a8 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simple_data_producer.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simple_data_producer.h @@ -9,7 +9,6 @@ #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_stream_frame_data_producer.h" #include "quiche/quic/core/quic_stream_send_buffer.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/common/simple_buffer_allocator.h" namespace quic { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simple_session_notifier_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simple_session_notifier_test.cc index 2aa35e51213..513394ccbfe 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simple_session_notifier_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simple_session_notifier_test.cc @@ -358,7 +358,7 @@ TEST_F(SimpleSessionNotifierTest, RetransmitFrames) { // stream 3 data [0, 3) is retransmitted and connection is blocked. EXPECT_CALL(connection_, SendStreamData(3, 3, 0, NO_FIN)) .WillOnce(Return(QuicConsumedData(2, false))); - notifier_.RetransmitFrames(frames, RTO_RETRANSMISSION); + notifier_.RetransmitFrames(frames, PTO_RETRANSMISSION); EXPECT_FALSE(notifier_.WillingToWrite()); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint.cc index 72f62ade3f7..64005ece38f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint.cc @@ -151,14 +151,6 @@ void QuicEndpoint::OnCanWrite() { WriteStreamData(); } -bool QuicEndpoint::SendProbingData() { - if (connection()->sent_packet_manager().MaybeRetransmitOldestPacket( - PROBING_RETRANSMISSION)) { - return true; - } - return false; -} - bool QuicEndpoint::WillingAndAbleToWrite() const { if (notifier_ != nullptr) { return notifier_->WillingToWrite(); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint.h index e1a8c3e5b63..d3741c50615 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint.h @@ -13,7 +13,6 @@ #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_stream_frame_data_producer.h" #include "quiche/quic/core/quic_trace_visitor.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/test_tools/simple_session_notifier.h" #include "quiche/quic/test_tools/simulator/link.h" #include "quiche/quic/test_tools/simulator/queue.h" @@ -47,7 +46,6 @@ class QuicEndpoint : public QuicEndpointBase, void OnStreamFrame(const QuicStreamFrame& frame) override; void OnCryptoFrame(const QuicCryptoFrame& frame) override; void OnCanWrite() override; - bool SendProbingData() override; bool WillingAndAbleToWrite() const override; bool ShouldKeepConnectionAlive() const override; @@ -108,6 +106,7 @@ class QuicEndpoint : public QuicEndpointBase, const QuicSocketAddress& /*address*/) const override { return false; } + void OnBandwidthUpdateTimeout() override {} // End QuicConnectionVisitorInterface implementation. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.h index 26bb0144e29..8eece0bc06a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.h @@ -15,7 +15,6 @@ #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_stream_frame_data_producer.h" #include "quiche/quic/core/quic_trace_visitor.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/test_tools/simple_session_notifier.h" #include "quiche/quic/test_tools/simulator/link.h" #include "quiche/quic/test_tools/simulator/queue.h" diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_test.cc index 823c190fe34..5850a8bdef5 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_test.cc @@ -28,7 +28,7 @@ const QuicByteCount kDefaultBdp = kDefaultBandwidth * kDefaultPropagationDelay; // A simple test harness where all hosts are connected to a switch with // identical links. -class QuicEndpointTest : public QuicTest { +class QuicEndpointTest : public quic::test::QuicTest { public: QuicEndpointTest() : simulator_(), switch_(&simulator_, "Switch", 8, kDefaultBdp * 2) {} diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/simulator.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/simulator.h index 0dabe4adc48..805d7c2dc88 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/simulator.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/simulator.h @@ -11,7 +11,6 @@ #include "absl/container/flat_hash_set.h" #include "quiche/quic/core/quic_connection.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/test_tools/simulator/actor.h" #include "quiche/quic/test_tools/simulator/alarm_factory.h" #include "quiche/common/simple_buffer_allocator.h" diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/simulator_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/simulator_test.cc index e43c79cd1b6..4ae04a7803e 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/simulator_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/simulator_test.cc @@ -7,7 +7,6 @@ #include <utility> #include "absl/container/node_hash_map.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/test_tools/quic_test_utils.h" @@ -48,7 +47,7 @@ class Counter : public Actor { QuicTime::Delta period_; }; -class SimulatorTest : public QuicTest {}; +class SimulatorTest : public quic::test::QuicTest {}; // Test that the basic event handling works, and that Actors can be created and // destroyed mid-simulation. diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/switch.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/switch.h index b73541c7b84..1bafed41493 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/switch.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/simulator/switch.h @@ -8,7 +8,6 @@ #include <deque> #include "absl/container/flat_hash_map.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/test_tools/simulator/queue.h" namespace quic { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/test_ticket_crypter.cc b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/test_ticket_crypter.cc index b886dde967a..dbdb2a9d35f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/test_ticket_crypter.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/test_ticket_crypter.cc @@ -55,7 +55,7 @@ std::vector<uint8_t> TestTicketCrypter::Decrypt(absl::string_view in) { void TestTicketCrypter::Decrypt( absl::string_view in, - std::unique_ptr<ProofSource::DecryptCallback> callback) { + std::shared_ptr<ProofSource::DecryptCallback> callback) { auto decrypted_ticket = Decrypt(in); if (run_async_) { pending_callbacks_.push_back({std::move(callback), decrypted_ticket}); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/test_ticket_crypter.h b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/test_ticket_crypter.h index 84430994582..888bdef932d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/test_tools/test_ticket_crypter.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/test_tools/test_ticket_crypter.h @@ -22,7 +22,7 @@ class TestTicketCrypter : public ProofSource::TicketCrypter { std::vector<uint8_t> Encrypt(absl::string_view in, absl::string_view encryption_key) override; void Decrypt(absl::string_view in, - std::unique_ptr<ProofSource::DecryptCallback> callback) override; + std::shared_ptr<ProofSource::DecryptCallback> callback) override; void SetRunCallbacksAsync(bool run_async); size_t NumPendingCallbacks(); @@ -36,7 +36,7 @@ class TestTicketCrypter : public ProofSource::TicketCrypter { std::vector<uint8_t> Decrypt(absl::string_view in); struct PendingCallback { - std::unique_ptr<ProofSource::DecryptCallback> callback; + std::shared_ptr<ProofSource::DecryptCallback> callback; std::vector<uint8_t> decrypted_ticket; }; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_message_printer_bin.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/crypto_message_printer_bin.cc index eb7393d549e..eb7393d549e 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_message_printer_bin.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/crypto_message_printer_bin.cc diff --git a/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_offline_decoder_bin.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/qpack_offline_decoder_bin.cc index a5cbc856dd4..a5cbc856dd4 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_offline_decoder_bin.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/qpack_offline_decoder_bin.cc diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client.cc index b024ac61fc1..b3e4705e102 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client.cc @@ -130,8 +130,7 @@ std::unique_ptr<QuicSession> QuicClient::CreateQuicClientSession( QuicConnection* connection) { return std::make_unique<QuicSimpleClientSession>( *config(), supported_versions, connection, server_id(), crypto_config(), - push_promise_index(), drop_response_body(), enable_web_transport(), - use_datagram_contexts()); + push_promise_index(), drop_response_body(), enable_web_transport()); } QuicClientEpollNetworkHelper* QuicClient::epoll_network_helper() { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client.h b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client.h index ebf8cb921d4..e0106c79465 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client.h @@ -16,7 +16,6 @@ #include "quiche/quic/core/http/quic_spdy_client_session.h" #include "quiche/quic/core/quic_config.h" #include "quiche/quic/core/quic_packet_reader.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_epoll.h" #include "quiche/quic/tools/quic_client_epoll_network_helper.h" #include "quiche/quic/tools/quic_spdy_client_base.h" diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client_interop_test_bin.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client_interop_test_bin.cc index 549be2ebfd5..9a29afeec25 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client_interop_test_bin.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_client_interop_test_bin.cc @@ -395,9 +395,9 @@ int main(int argc, char* argv[]) { quiche::QuichePrintCommandLineFlagHelp(usage); exit(1); } - std::string dns_host = GetQuicFlag(FLAGS_host); + std::string dns_host = quiche::GetQuicheCommandLineFlag(FLAGS_host); std::string url_host = ""; - int port = GetQuicFlag(FLAGS_port); + int port = quiche::GetQuicheCommandLineFlag(FLAGS_port); if (!args.empty()) { quic::QuicUrl url(args[0], "https"); @@ -423,7 +423,8 @@ int main(int argc, char* argv[]) { // Pick QUIC version to use. quic::QuicVersionInitializeSupportForIetfDraft(); quic::ParsedQuicVersion version = quic::UnsupportedQuicVersion(); - std::string quic_version_string = GetQuicFlag(FLAGS_quic_version); + std::string quic_version_string = + quiche::GetQuicheCommandLineFlag(FLAGS_quic_version); if (!quic_version_string.empty()) { version = quic::ParseQuicVersionString(quic_version_string); } else { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h index e272351a648..1738e3c8acf 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h @@ -13,7 +13,6 @@ #include "absl/container/flat_hash_map.h" #include "absl/strings/string_view.h" #include "quiche/quic/core/http/spdy_utils.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_mutex.h" #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/quic/tools/quic_simple_server_backend.h" diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend_test.cc index bb5e67520c7..a75b46ec58c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend_test.cc @@ -11,6 +11,7 @@ #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/common/platform/api/quiche_file_utils.h" +#include "quiche/common/platform/api/quiche_test.h" namespace quic { namespace test { @@ -30,7 +31,9 @@ class QuicMemoryCacheBackendTest : public QuicTest { (*headers)[":scheme"] = "https"; } - std::string CacheDirectory() { return QuicGetTestMemoryCachePath(); } + std::string CacheDirectory() { + return quiche::test::QuicheGetTestMemoryCachePath(); + } QuicMemoryCacheBackend cache_; }; @@ -97,36 +100,6 @@ TEST_F(QuicMemoryCacheBackendTest, MAYBE_ReadsCacheDir) { // TODO(crbug.com/1249712) This test is failing on iOS. #if defined(OS_IOS) -#define MAYBE_ReadsCacheDirWithServerPushResource \ - DISABLED_ReadsCacheDirWithServerPushResource -#else -#define MAYBE_ReadsCacheDirWithServerPushResource \ - ReadsCacheDirWithServerPushResource -#endif -TEST_F(QuicMemoryCacheBackendTest, MAYBE_ReadsCacheDirWithServerPushResource) { - cache_.InitializeBackend(CacheDirectory() + "_with_push"); - std::list<ServerPushInfo> resources = - cache_.GetServerPushResources("test.example.com/"); - ASSERT_EQ(1UL, resources.size()); -} - -// TODO(crbug.com/1249712) This test is failing on iOS. -#if defined(OS_IOS) -#define MAYBE_ReadsCacheDirWithServerPushResources \ - DISABLED_ReadsCacheDirWithServerPushResources -#else -#define MAYBE_ReadsCacheDirWithServerPushResources \ - ReadsCacheDirWithServerPushResources -#endif -TEST_F(QuicMemoryCacheBackendTest, MAYBE_ReadsCacheDirWithServerPushResources) { - cache_.InitializeBackend(CacheDirectory() + "_with_push"); - std::list<ServerPushInfo> resources = - cache_.GetServerPushResources("test.example.com/index2.html"); - ASSERT_EQ(2UL, resources.size()); -} - -// TODO(crbug.com/1249712) This test is failing on iOS. -#if defined(OS_IOS) #define MAYBE_UsesOriginalUrl DISABLED_UsesOriginalUrl #else #define MAYBE_UsesOriginalUrl UsesOriginalUrl diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_packet_printer_bin.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_packet_printer_bin.cc index 8867e44df9f..740971c078c 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_packet_printer_bin.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_packet_printer_bin.cc @@ -271,8 +271,8 @@ int main(int argc, char* argv[]) { quic::QuicTime start(quic::QuicTime::Zero()); quic::QuicFramer framer(versions, start, perspective, quic::kQuicDefaultConnectionIdLength); - const quic::ParsedQuicVersion& version = - quic::ParseQuicVersionString(GetQuicFlag(FLAGS_quic_version)); + const quic::ParsedQuicVersion& version = quic::ParseQuicVersionString( + quiche::GetQuicheCommandLineFlag(FLAGS_quic_version)); if (version != quic::ParsedQuicVersion::Unsupported()) { framer.set_version(version); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.cc index fa211aca59e..1a001fb414a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.cc @@ -16,20 +16,18 @@ QuicSimpleClientSession::QuicSimpleClientSession( : QuicSimpleClientSession(config, supported_versions, connection, server_id, crypto_config, push_promise_index, drop_response_body, - /*enable_web_transport=*/false, - /*use_datagram_contexts=*/false) {} + /*enable_web_transport=*/false) {} QuicSimpleClientSession::QuicSimpleClientSession( const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, QuicConnection* connection, const QuicServerId& server_id, QuicCryptoClientConfig* crypto_config, QuicClientPushPromiseIndex* push_promise_index, bool drop_response_body, - bool enable_web_transport, bool use_datagram_contexts) + bool enable_web_transport) : QuicSpdyClientSession(config, supported_versions, connection, server_id, crypto_config, push_promise_index), drop_response_body_(drop_response_body), - enable_web_transport_(enable_web_transport), - use_datagram_contexts_(use_datagram_contexts) {} + enable_web_transport_(enable_web_transport) {} std::unique_ptr<QuicSpdyClientStream> QuicSimpleClientSession::CreateClientStream() { @@ -42,10 +40,6 @@ bool QuicSimpleClientSession::ShouldNegotiateWebTransport() { return enable_web_transport_; } -bool QuicSimpleClientSession::ShouldNegotiateDatagramContexts() { - return use_datagram_contexts_; -} - HttpDatagramSupport QuicSimpleClientSession::LocalHttpDatagramSupport() { return enable_web_transport_ ? HttpDatagramSupport::kDraft04 : HttpDatagramSupport::kNone; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.h b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.h index 75ed195c249..6b6f4a7437d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.h @@ -25,18 +25,15 @@ class QuicSimpleClientSession : public QuicSpdyClientSession { const QuicServerId& server_id, QuicCryptoClientConfig* crypto_config, QuicClientPushPromiseIndex* push_promise_index, - bool drop_response_body, bool enable_web_transport, - bool use_datagram_contexts); + bool drop_response_body, bool enable_web_transport); std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override; bool ShouldNegotiateWebTransport() override; - bool ShouldNegotiateDatagramContexts() override; HttpDatagramSupport LocalHttpDatagramSupport() override; private: const bool drop_response_body_; const bool enable_web_transport_; - const bool use_datagram_contexts_; }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_backend.h b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_backend.h index f976e72bc11..c603468b134 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_backend.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_backend.h @@ -5,10 +5,14 @@ #ifndef QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_BACKEND_H_ #define QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_BACKEND_H_ +#include <cstdint> #include <memory> +#include "absl/strings/string_view.h" +#include "quiche/quic/core/quic_error_codes.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/web_transport_interface.h" +#include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/spdy/core/spdy_header_block.h" @@ -33,6 +37,14 @@ class QuicSimpleServerBackend { // the QUIC client. virtual void OnResponseBackendComplete( const QuicBackendResponse* response) = 0; + // Sends additional non-full-response data (without headers) to the request + // stream, e.g. for CONNECT data. May only be called after sending an + // incomplete response (using `QuicBackendResponse::INCOMPLETE_RESPONSE`). + // Sends the data with the FIN bit to close the stream if `close_stream` is + // true. + virtual void SendStreamData(absl::string_view data, bool close_stream) = 0; + // Abruptly terminates (resets) the request stream with `error`. + virtual void TerminateStreamWithError(QuicResetStreamError error) = 0; }; struct WebTransportResponse { @@ -49,12 +61,43 @@ class QuicSimpleServerBackend { virtual bool IsBackendInitialized() const = 0; // Triggers a HTTP request to be sent to the backend server or cache // If response is immediately available, the function synchronously calls - // the |request_handler| with the HTTP response. + // the `request_handler` with the HTTP response. // If the response has to be fetched over the network, the function - // asynchronously calls |request_handler| with the HTTP response. + // asynchronously calls `request_handler` with the HTTP response. + // + // Not called for requests using the CONNECT method. virtual void FetchResponseFromBackend( const spdy::Http2HeaderBlock& request_headers, const std::string& request_body, RequestHandler* request_handler) = 0; + + // Handles headers for requests using the CONNECT method. Called immediately + // on receiving the headers, potentially before the request is complete or + // data is received. Any response (complete or incomplete) should be sent, + // potentially asynchronously, using `request_handler`. + // + // If not overridden by backend, sends an error appropriate for a server that + // does not handle CONNECT requests. + virtual void HandleConnectHeaders( + const spdy::Http2HeaderBlock& /*request_headers*/, + RequestHandler* request_handler) { + spdy::Http2HeaderBlock headers; + headers[":status"] = "405"; + QuicBackendResponse response; + response.set_headers(std::move(headers)); + request_handler->OnResponseBackendComplete(&response); + } + // Handles data for requests using the CONNECT method. Called repeatedly + // whenever new data is available. If `data_complete` is true, data was + // received with the FIN bit, and this is the last call to this method. + // + // If not overridden by backend, abruptly terminates the stream. + virtual void HandleConnectData(absl::string_view /*data*/, + bool /*data_complete*/, + RequestHandler* request_handler) { + request_handler->TerminateStreamWithError( + QuicResetStreamError::FromInternal(QUIC_STREAM_CONNECT_ERROR)); + } + // Clears the state of the backend instance virtual void CloseBackendResponseStream(RequestHandler* request_handler) = 0; @@ -66,7 +109,6 @@ class QuicSimpleServerBackend { return response; } virtual bool SupportsWebTransport() { return false; } - virtual bool UsesDatagramContexts() { return false; } virtual bool SupportsExtendedConnect() { return true; } }; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.h b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.h index 872a4577bcd..0530ce26a3a 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.h @@ -20,7 +20,6 @@ #include "quiche/quic/core/http/quic_spdy_session.h" #include "quiche/quic/core/quic_crypto_server_stream_base.h" #include "quiche/quic/core/quic_packets.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/quic/tools/quic_simple_server_backend.h" #include "quiche/quic/tools/quic_simple_server_stream.h" @@ -70,10 +69,6 @@ class QuicSimpleServerSession : public QuicServerSessionBase { void OnCanCreateNewOutgoingStream(bool unidirectional) override; - bool ShouldNegotiateDatagramContexts() override { - return quic_simple_server_backend_->UsesDatagramContexts(); - } - protected: // QuicSession methods: QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override; @@ -102,7 +97,7 @@ class QuicSimpleServerSession : public QuicServerSessionBase { } HttpDatagramSupport LocalHttpDatagramSupport() override { if (ShouldNegotiateWebTransport()) { - return HttpDatagramSupport::kDraft00And04; + return HttpDatagramSupport::kDraft04; } return QuicServerSessionBase::LocalHttpDatagramSupport(); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session_test.cc index a5124ea41ab..d1db8c9aa9d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session_test.cc @@ -19,7 +19,6 @@ #include "quiche/quic/core/quic_utils.h" #include "quiche/quic/core/quic_versions.h" #include "quiche/quic/core/tls_server_handshaker.h" -#include "quiche/quic/platform/api/quic_containers.h" #include "quiche/quic/platform/api/quic_expect_bug.h" #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_socket_address.h" @@ -180,7 +179,7 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession { const spdy::Http2HeaderBlock& headers), ()); - MOCK_METHOD(void, SendBlocked, (QuicStreamId), (override)); + MOCK_METHOD(void, SendBlocked, (QuicStreamId, QuicStreamOffset), (override)); MOCK_METHOD(bool, WriteControlFrame, (const QuicFrame& frame, TransmissionType type), (override)); }; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.cc index 91f91d31875..608d7b58289 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.cc @@ -4,16 +4,18 @@ #include "quiche/quic/tools/quic_simple_server_stream.h" +#include <cstdint> #include <list> #include <utility> -#include "absl/strings/match.h" #include "absl/strings/numbers.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" +#include "absl/types/optional.h" #include "quiche/quic/core/http/quic_spdy_stream.h" #include "quiche/quic/core/http/spdy_utils.h" #include "quiche/quic/core/http/web_transport_http3.h" +#include "quiche/quic/core/quic_error_codes.h" #include "quiche/quic/core/quic_utils.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/quic/platform/api/quic_flags.h" @@ -61,15 +63,36 @@ void QuicSimpleServerStream::OnInitialHeadersComplete( SendErrorResponse(); } ConsumeHeaderList(); - if (!fin && !response_sent_) { - // CONNECT and other CONNECT-like methods (such as CONNECT-UDP) require - // sending the response right after parsing the headers even though the FIN - // bit has not been received on the request stream. - auto it = request_headers_.find(":method"); - if (it != request_headers_.end() && - absl::StartsWith(it->second, "CONNECT")) { - SendResponse(); + + // CONNECT requests do not carry any message content but carry data after the + // headers, so they require sending the response right after parsing the + // headers even though the FIN bit has not been received on the request + // stream. + if (!fin && !response_sent_ && IsConnectRequest()) { + if (quic_simple_server_backend_ == nullptr) { + QUIC_DVLOG(1) << "Backend is missing on CONNECT headers."; + SendErrorResponse(); + return; + } + + if (web_transport() != nullptr) { + QuicSimpleServerBackend::WebTransportResponse response = + quic_simple_server_backend_->ProcessWebTransportRequest( + request_headers_, web_transport()); + if (response.response_headers[":status"] == "200") { + WriteHeaders(std::move(response.response_headers), false, nullptr); + if (response.visitor != nullptr) { + web_transport()->SetVisitor(std::move(response.visitor)); + } + web_transport()->HeadersReceived(request_headers_); + } else { + WriteHeaders(std::move(response.response_headers), true, nullptr); + } + return; } + + quic_simple_server_backend_->HandleConnectHeaders(request_headers_, + /*request_handler=*/this); } } @@ -99,7 +122,11 @@ void QuicSimpleServerStream::OnBodyAvailable() { } MarkConsumed(iov.iov_len); } + if (!sequencer()->IsClosed()) { + if (IsConnectRequest()) { + HandleRequestConnectData(/*fin_received=*/false); + } sequencer()->SetUnblocked(); return; } @@ -112,7 +139,11 @@ void QuicSimpleServerStream::OnBodyAvailable() { return; } - SendResponse(); + if (IsConnectRequest()) { + HandleRequestConnectData(/*fin_received=*/true); + } else { + SendResponse(); + } } void QuicSimpleServerStream::PushResponse( @@ -134,7 +165,28 @@ void QuicSimpleServerStream::PushResponse( SendResponse(); } +void QuicSimpleServerStream::HandleRequestConnectData(bool fin_received) { + QUICHE_DCHECK(IsConnectRequest()); + + if (quic_simple_server_backend_ == nullptr) { + QUIC_DVLOG(1) << "Backend is missing on CONNECT data."; + ResetWriteSide( + QuicResetStreamError::FromInternal(QUIC_STREAM_CONNECT_ERROR)); + return; + } + + // Clear `body_`, so only new data is sent to the backend next time. + std::string data = std::move(body_); + body_.clear(); + + quic_simple_server_backend_->HandleConnectData(data, + /*data_complete=*/fin_received, + this); +} + void QuicSimpleServerStream::SendResponse() { + QUICHE_DCHECK(!IsConnectRequest()); + if (request_headers_.empty()) { QUIC_DVLOG(1) << "Request headers empty."; SendErrorResponse(); @@ -156,19 +208,13 @@ void QuicSimpleServerStream::SendResponse() { } if (!request_headers_.contains(":path")) { - // CONNECT and other CONNECT-like methods (such as CONNECT-UDP) do not all - // require :path to be present. - auto it = request_headers_.find(":method"); - if (it == request_headers_.end() || - !absl::StartsWith(it->second, "CONNECT")) { - QUIC_DVLOG(1) << "Request headers do not contain :path."; - SendErrorResponse(); - return; - } + QUIC_DVLOG(1) << "Request headers do not contain :path."; + SendErrorResponse(); + return; } if (quic_simple_server_backend_ == nullptr) { - QUIC_DVLOG(1) << "Backend is missing."; + QUIC_DVLOG(1) << "Backend is missing in SendResponse()."; SendErrorResponse(); return; } @@ -309,6 +355,27 @@ void QuicSimpleServerStream::OnResponseBackendComplete( response->trailers().Clone()); } +void QuicSimpleServerStream::SendStreamData(absl::string_view data, + bool close_stream) { + // Doesn't make sense to call this without data or `close_stream`. + QUICHE_DCHECK(!data.empty() || close_stream); + + if (close_stream) { + SendHeadersAndBodyAndTrailers( + /*response_headers=*/absl::nullopt, data, + /*response_trailers=*/spdy::Http2HeaderBlock()); + } else { + SendIncompleteResponse(/*response_headers=*/absl::nullopt, data); + } +} + +void QuicSimpleServerStream::TerminateStreamWithError( + QuicResetStreamError error) { + QUIC_DVLOG(1) << "Stream " << id() << " abruptly terminating with error " + << error.internal_code(); + ResetWriteSide(error); +} + void QuicSimpleServerStream::OnCanWrite() { QuicSpdyStream::OnCanWrite(); WriteGeneratedBytes(); @@ -351,12 +418,16 @@ void QuicSimpleServerStream::SendErrorResponse(int resp_code) { } void QuicSimpleServerStream::SendIncompleteResponse( - Http2HeaderBlock response_headers, absl::string_view body) { - QUIC_DLOG(INFO) << "Stream " << id() << " writing headers (fin = false) : " - << response_headers.DebugString(); - WriteHeaders(std::move(response_headers), /*fin=*/false, nullptr); - QUICHE_DCHECK(!response_sent_); - response_sent_ = true; + absl::optional<Http2HeaderBlock> response_headers, absl::string_view body) { + // Headers should be sent iff not sent in a previous response. + QUICHE_DCHECK_NE(response_headers.has_value(), response_sent_); + + if (response_headers.has_value()) { + QUIC_DLOG(INFO) << "Stream " << id() << " writing headers (fin = false) : " + << response_headers.value().DebugString(); + WriteHeaders(std::move(response_headers).value(), /*fin=*/false, nullptr); + response_sent_ = true; + } QUIC_DLOG(INFO) << "Stream " << id() << " writing body (fin = false) with size: " << body.size(); @@ -372,22 +443,27 @@ void QuicSimpleServerStream::SendHeadersAndBody( } void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers( - Http2HeaderBlock response_headers, absl::string_view body, + absl::optional<Http2HeaderBlock> response_headers, absl::string_view body, Http2HeaderBlock response_trailers) { - // Send the headers, with a FIN if there's nothing else to send. - bool send_fin = (body.empty() && response_trailers.empty()); - QUIC_DLOG(INFO) << "Stream " << id() << " writing headers (fin = " << send_fin - << ") : " << response_headers.DebugString(); - WriteHeaders(std::move(response_headers), send_fin, nullptr); - QUICHE_DCHECK(!response_sent_); - response_sent_ = true; - if (send_fin) { - // Nothing else to send. - return; + // Headers should be sent iff not sent in a previous response. + QUICHE_DCHECK_NE(response_headers.has_value(), response_sent_); + + if (response_headers.has_value()) { + // Send the headers, with a FIN if there's nothing else to send. + bool send_fin = (body.empty() && response_trailers.empty()); + QUIC_DLOG(INFO) << "Stream " << id() + << " writing headers (fin = " << send_fin + << ") : " << response_headers.value().DebugString(); + WriteHeaders(std::move(response_headers).value(), send_fin, nullptr); + response_sent_ = true; + if (send_fin) { + // Nothing else to send. + return; + } } // Send the body, with a FIN if there's no trailers to send. - send_fin = response_trailers.empty(); + bool send_fin = response_trailers.empty(); QUIC_DLOG(INFO) << "Stream " << id() << " writing body (fin = " << send_fin << ") with size: " << body.size(); if (!body.empty() || send_fin) { @@ -404,6 +480,11 @@ void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers( WriteTrailers(std::move(response_trailers), nullptr); } +bool QuicSimpleServerStream::IsConnectRequest() const { + auto method_it = request_headers_.find(":method"); + return method_it != request_headers_.end() && method_it->second == "CONNECT"; +} + void QuicSimpleServerStream::OnInvalidHeaders() { QUIC_DVLOG(1) << "Invalid headers"; SendErrorResponse(400); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.h b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.h index f3221c88b50..7b7859a8f5f 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.h @@ -5,8 +5,12 @@ #ifndef QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_STREAM_H_ #define QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_STREAM_H_ +#include <cstdint> + #include "absl/strings/string_view.h" +#include "absl/types/optional.h" #include "quiche/quic/core/http/quic_spdy_server_stream_base.h" +#include "quiche/quic/core/quic_error_codes.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/quic/tools/quic_simple_server_backend.h" @@ -55,10 +59,15 @@ class QuicSimpleServerStream : public QuicSpdyServerStreamBase, QuicStreamId stream_id() const override; std::string peer_host() const override; void OnResponseBackendComplete(const QuicBackendResponse* response) override; + void SendStreamData(absl::string_view data, bool close_stream) override; + void TerminateStreamWithError(QuicResetStreamError error) override; protected: - // Sends a basic 200 response using SendHeaders for the headers and WriteData - // for the body. + // Handles fresh body data whenever received when method is CONNECT. + void HandleRequestConnectData(bool fin_received); + + // Sends a response using SendHeaders for the headers and WriteData for the + // body. virtual void SendResponse(); // Sends a basic 500 response using SendHeaders for the headers and WriteData @@ -70,23 +79,34 @@ class QuicSimpleServerStream : public QuicSpdyServerStreamBase, // for the body. void SendNotFoundResponse(); - // Sends the response header and body, but not the fin. - void SendIncompleteResponse(spdy::Http2HeaderBlock response_headers, - absl::string_view body); + // Sends the response header (if not `absl::nullopt`) and body, but not the + // fin. + void SendIncompleteResponse( + absl::optional<spdy::Http2HeaderBlock> response_headers, + absl::string_view body); void SendHeadersAndBody(spdy::Http2HeaderBlock response_headers, absl::string_view body); - void SendHeadersAndBodyAndTrailers(spdy::Http2HeaderBlock response_headers, - absl::string_view body, - spdy::Http2HeaderBlock response_trailers); + void SendHeadersAndBodyAndTrailers( + absl::optional<spdy::Http2HeaderBlock> response_headers, + absl::string_view body, spdy::Http2HeaderBlock response_trailers); spdy::Http2HeaderBlock* request_headers() { return &request_headers_; } + // Returns true iff the request (per saved `request_headers_`) is a CONNECT or + // Extended CONNECT request. + bool IsConnectRequest() const; + const std::string& body() { return body_; } // Writes the body bytes for the GENERATE_BYTES response type. void WriteGeneratedBytes(); + void set_quic_simple_server_backend_for_test( + QuicSimpleServerBackend* backend) { + quic_simple_server_backend_ = backend; + } + // The parsed headers received from the client. spdy::Http2HeaderBlock request_headers_; int64_t content_length_; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream_test.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream_test.cc index c2aa58efd79..5d9ff15e3b2 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream_test.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream_test.cc @@ -30,8 +30,10 @@ #include "quiche/quic/test_tools/quic_test_utils.h" #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/quic/tools/quic_memory_cache_backend.h" +#include "quiche/quic/tools/quic_simple_server_backend.h" #include "quiche/quic/tools/quic_simple_server_session.h" #include "quiche/common/simple_buffer_allocator.h" +#include "quiche/spdy/core/spdy_header_block.h" using testing::_; using testing::AnyNumber; @@ -51,12 +53,20 @@ class TestStream : public QuicSimpleServerStream { TestStream(QuicStreamId stream_id, QuicSpdySession* session, StreamType type, QuicSimpleServerBackend* quic_simple_server_backend) : QuicSimpleServerStream(stream_id, session, type, - quic_simple_server_backend) {} + quic_simple_server_backend) { + EXPECT_CALL(*this, WriteOrBufferBody(_, _)) + .Times(AnyNumber()) + .WillRepeatedly([this](absl::string_view data, bool fin) { + this->QuicSimpleServerStream::WriteOrBufferBody(data, fin); + }); + } ~TestStream() override = default; MOCK_METHOD(void, WriteHeadersMock, (bool fin), ()); MOCK_METHOD(void, WriteEarlyHintsHeadersMock, (bool fin), ()); + MOCK_METHOD(void, WriteOrBufferBody, (absl::string_view data, bool fin), + (override)); size_t WriteHeaders( spdy::Http2HeaderBlock header_block, bool fin, @@ -89,6 +99,10 @@ class TestStream : public QuicSimpleServerStream { return it->second; } + void ReplaceBackend(QuicSimpleServerBackend* backend) { + set_quic_simple_server_backend_for_test(backend); + } + protected: void SendResponse() override { send_response_was_called_ = true; @@ -256,6 +270,11 @@ class QuicSimpleServerStreamTest : public QuicTestWithParam<ParsedQuicVersion> { return VersionUsesHttp3(connection_->transport_version()); } + void ReplaceBackend(std::unique_ptr<QuicSimpleServerBackend> backend) { + replacement_backend_ = std::move(backend); + stream_->ReplaceBackend(replacement_backend_.get()); + } + spdy::Http2HeaderBlock response_headers_; MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; @@ -265,6 +284,7 @@ class QuicSimpleServerStreamTest : public QuicTestWithParam<ParsedQuicVersion> { std::unique_ptr<QuicCryptoServerConfig> crypto_config_; QuicCompressedCertsCache compressed_certs_cache_; QuicMemoryCacheBackend memory_cache_backend_; + std::unique_ptr<QuicSimpleServerBackend> replacement_backend_; StrictMock<MockQuicSimpleServerSession> session_; StrictMock<TestStream>* stream_; // Owned by session_. std::unique_ptr<QuicBackendResponse> quic_response_; @@ -732,26 +752,115 @@ TEST_P(QuicSimpleServerStreamTest, InvalidHeadersWithFin) { stream_->OnStreamFrame(frame); } -TEST_P(QuicSimpleServerStreamTest, ConnectSendsResponseBeforeFinReceived) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) - .WillRepeatedly( - Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData)); +// Basic QuicSimpleServerBackend that implements its behavior through mocking. +class TestQuicSimpleServerBackend : public QuicSimpleServerBackend { + public: + TestQuicSimpleServerBackend() = default; + ~TestQuicSimpleServerBackend() override = default; + + // QuicSimpleServerBackend: + bool InitializeBackend(const std::string& /*backend_url*/) override { + return true; + } + bool IsBackendInitialized() const override { return true; } + MOCK_METHOD(void, FetchResponseFromBackend, + (const spdy::Http2HeaderBlock&, const std::string&, + RequestHandler*), + (override)); + MOCK_METHOD(void, HandleConnectHeaders, + (const spdy::Http2HeaderBlock&, RequestHandler*), (override)); + MOCK_METHOD(void, HandleConnectData, + (absl::string_view, bool, RequestHandler*), (override)); + void CloseBackendResponseStream( + RequestHandler* /*request_handler*/) override {} +}; + +ACTION_P(SendHeadersResponse, response_ptr) { + arg1->OnResponseBackendComplete(response_ptr); +} + +ACTION_P(SendStreamData, data, close_stream) { + arg2->SendStreamData(data, close_stream); +} + +ACTION_P(TerminateStream, error) { arg1->TerminateStreamWithError(error); } + +TEST_P(QuicSimpleServerStreamTest, ConnectSendsIntermediateResponses) { + auto test_backend = std::make_unique<TestQuicSimpleServerBackend>(); + TestQuicSimpleServerBackend* test_backend_ptr = test_backend.get(); + ReplaceBackend(std::move(test_backend)); + + constexpr absl::string_view kRequestBody = "\x11\x11"; + spdy::Http2HeaderBlock response_headers; + response_headers[":status"] = "200"; + QuicBackendResponse headers_response; + headers_response.set_headers(response_headers.Clone()); + headers_response.set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE); + constexpr absl::string_view kBody1 = "\x22\x22"; + constexpr absl::string_view kBody2 = "\x33\x33"; + + // Expect an initial headers-only request to result in a headers-only + // incomplete response. Then a data frame without fin, resulting in stream + // data. Then a data frame with fin, resulting in stream data with fin. + InSequence s; + EXPECT_CALL(*test_backend_ptr, HandleConnectHeaders(_, _)) + .WillOnce(SendHeadersResponse(&headers_response)); + EXPECT_CALL(*stream_, WriteHeadersMock(false)); + EXPECT_CALL(*test_backend_ptr, HandleConnectData(kRequestBody, false, _)) + .WillOnce(SendStreamData(kBody1, + /*close_stream=*/false)); + EXPECT_CALL(*stream_, WriteOrBufferBody(kBody1, false)); + EXPECT_CALL(*test_backend_ptr, HandleConnectData(kRequestBody, true, _)) + .WillOnce(SendStreamData(kBody2, + /*close_stream=*/true)); + EXPECT_CALL(*stream_, WriteOrBufferBody(kBody2, true)); + QuicHeaderList header_list; header_list.OnHeaderBlockStart(); header_list.OnHeader(":authority", "www.google.com:4433"); header_list.OnHeader(":method", "CONNECT"); header_list.OnHeaderBlockEnd(128, 128); - EXPECT_CALL(*stream_, WriteHeadersMock(/*fin=*/false)); + stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list); quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader( - body_.length(), quiche::SimpleBufferAllocator::Get()); - std::string data = - UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_; + kRequestBody.length(), quiche::SimpleBufferAllocator::Get()); + std::string data = UsesHttp3() + ? absl::StrCat(header.AsStringView(), kRequestBody) + : std::string(kRequestBody); stream_->OnStreamFrame( QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data)); - EXPECT_EQ("CONNECT", StreamHeadersValue(":method")); - EXPECT_EQ(body_, StreamBody()); - EXPECT_TRUE(stream_->send_response_was_called()); + stream_->OnStreamFrame( + QuicStreamFrame(stream_->id(), /*fin=*/true, data.length(), data)); + + // Expect to not go through SendResponse(). + EXPECT_FALSE(stream_->send_response_was_called()); + EXPECT_FALSE(stream_->send_error_response_was_called()); +} + +TEST_P(QuicSimpleServerStreamTest, ErrorOnUnhandledConnect) { + // Expect single set of failure response headers with FIN in response to the + // headers. Then, expect abrupt stream termination in response to the body. + EXPECT_CALL(*stream_, WriteHeadersMock(true)); + EXPECT_CALL(session_, MaybeSendRstStreamFrame(stream_->id(), _, _)); + + QuicHeaderList header_list; + header_list.OnHeaderBlockStart(); + header_list.OnHeader(":authority", "www.google.com:4433"); + header_list.OnHeader(":method", "CONNECT"); + header_list.OnHeaderBlockEnd(128, 128); + constexpr absl::string_view kRequestBody = "\x11\x11"; + + stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list); + quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader( + kRequestBody.length(), quiche::SimpleBufferAllocator::Get()); + std::string data = UsesHttp3() + ? absl::StrCat(header.AsStringView(), kRequestBody) + : std::string(kRequestBody); + stream_->OnStreamFrame( + QuicStreamFrame(stream_->id(), /*fin=*/true, /*offset=*/0, data)); + + // Expect failure to not go through SendResponse(). + EXPECT_FALSE(stream_->send_response_was_called()); EXPECT_FALSE(stream_->send_error_response_was_called()); } @@ -785,6 +894,30 @@ TEST_P(QuicSimpleServerStreamTest, ConnectWithInvalidHeader) { EXPECT_TRUE(stream_->send_error_response_was_called()); } +TEST_P(QuicSimpleServerStreamTest, BackendCanTerminateStream) { + auto test_backend = std::make_unique<TestQuicSimpleServerBackend>(); + TestQuicSimpleServerBackend* test_backend_ptr = test_backend.get(); + ReplaceBackend(std::move(test_backend)); + + EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + .WillRepeatedly( + Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData)); + + QuicResetStreamError expected_error = + QuicResetStreamError::FromInternal(QUIC_STREAM_CONNECT_ERROR); + EXPECT_CALL(*test_backend_ptr, HandleConnectHeaders(_, _)) + .WillOnce(TerminateStream(expected_error)); + EXPECT_CALL(session_, + MaybeSendRstStreamFrame(stream_->id(), expected_error, _)); + + QuicHeaderList header_list; + header_list.OnHeaderBlockStart(); + header_list.OnHeader(":authority", "www.google.com:4433"); + header_list.OnHeader(":method", "CONNECT"); + header_list.OnHeaderBlockEnd(128, 128); + stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list); +} + } // namespace } // namespace test } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_tcp_like_trace_converter.h b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_tcp_like_trace_converter.h index aa0c0f2e53f..3aeaa0fd5aa 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_tcp_like_trace_converter.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_tcp_like_trace_converter.h @@ -12,7 +12,6 @@ #include "quiche/quic/core/quic_interval.h" #include "quiche/quic/core/quic_interval_set.h" #include "quiche/quic/core/quic_types.h" -#include "quiche/quic/platform/api/quic_containers.h" namespace quic { diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_toy_client.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_toy_client.cc index 9baccbf7b3d..790e26361ae 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_toy_client.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_toy_client.cc @@ -230,18 +230,18 @@ QuicToyClient::QuicToyClient(ClientFactory* client_factory) int QuicToyClient::SendRequestsAndPrintResponses( std::vector<std::string> urls) { QuicUrl url(urls[0], "https"); - std::string host = GetQuicFlag(FLAGS_host); + std::string host = quiche::GetQuicheCommandLineFlag(FLAGS_host); if (host.empty()) { host = url.host(); } - int port = GetQuicFlag(FLAGS_port); + int port = quiche::GetQuicheCommandLineFlag(FLAGS_port); if (port == 0) { port = url.port(); } quic::ParsedQuicVersionVector versions = quic::CurrentSupportedVersions(); - if (GetQuicFlag(FLAGS_quic_ietf_draft)) { + if (quiche::GetQuicheCommandLineFlag(FLAGS_quic_ietf_draft)) { quic::QuicVersionInitializeSupportForIetfDraft(); versions = {}; for (const ParsedQuicVersion& version : AllSupportedVersions()) { @@ -252,7 +252,8 @@ int QuicToyClient::SendRequestsAndPrintResponses( } } - std::string quic_version_string = GetQuicFlag(FLAGS_quic_version); + std::string quic_version_string = + quiche::GetQuicheCommandLineFlag(FLAGS_quic_version); if (!quic_version_string.empty()) { versions = quic::ParseQuicVersionVectorString(quic_version_string); } @@ -266,36 +267,40 @@ int QuicToyClient::SendRequestsAndPrintResponses( quic::QuicEnableVersion(version); } - if (GetQuicFlag(FLAGS_force_version_negotiation)) { + if (quiche::GetQuicheCommandLineFlag(FLAGS_force_version_negotiation)) { versions.insert(versions.begin(), quic::QuicVersionReservedForNegotiation()); } - const int32_t num_requests(GetQuicFlag(FLAGS_num_requests)); + const int32_t num_requests( + quiche::GetQuicheCommandLineFlag(FLAGS_num_requests)); std::unique_ptr<quic::ProofVerifier> proof_verifier; - if (GetQuicFlag(FLAGS_disable_certificate_verification)) { + if (quiche::GetQuicheCommandLineFlag( + FLAGS_disable_certificate_verification)) { proof_verifier = std::make_unique<FakeProofVerifier>(); } else { proof_verifier = quic::CreateDefaultProofVerifier(url.host()); } std::unique_ptr<quic::SessionCache> session_cache; - if (num_requests > 1 && GetQuicFlag(FLAGS_one_connection_per_request)) { + if (num_requests > 1 && + quiche::GetQuicheCommandLineFlag(FLAGS_one_connection_per_request)) { session_cache = std::make_unique<QuicClientSessionCache>(); } QuicConfig config; - std::string connection_options_string = GetQuicFlag(FLAGS_connection_options); + std::string connection_options_string = + quiche::GetQuicheCommandLineFlag(FLAGS_connection_options); if (!connection_options_string.empty()) { config.SetConnectionOptionsToSend( ParseQuicTagVector(connection_options_string)); } std::string client_connection_options_string = - GetQuicFlag(FLAGS_client_connection_options); + quiche::GetQuicheCommandLineFlag(FLAGS_client_connection_options); if (!client_connection_options_string.empty()) { config.SetClientConnectionOptions( ParseQuicTagVector(client_connection_options_string)); } - if (GetQuicFlag(FLAGS_multi_packet_chlo)) { + if (quiche::GetQuicheCommandLineFlag(FLAGS_multi_packet_chlo)) { // Make the ClientHello span multiple packets by adding a custom transport // parameter. constexpr auto kCustomParameter = @@ -304,13 +309,16 @@ int QuicToyClient::SendRequestsAndPrintResponses( config.custom_transport_parameters_to_send()[kCustomParameter] = custom_value; } - config.set_max_time_before_crypto_handshake(QuicTime::Delta::FromMilliseconds( - GetQuicFlag(FLAGS_max_time_before_crypto_handshake_ms))); + config.set_max_time_before_crypto_handshake( + QuicTime::Delta::FromMilliseconds(quiche::GetQuicheCommandLineFlag( + FLAGS_max_time_before_crypto_handshake_ms))); int address_family_for_lookup = AF_UNSPEC; - if (GetQuicFlag(FLAGS_ip_version_for_host_lookup) == "4") { + if (quiche::GetQuicheCommandLineFlag(FLAGS_ip_version_for_host_lookup) == + "4") { address_family_for_lookup = AF_INET; - } else if (GetQuicFlag(FLAGS_ip_version_for_host_lookup) == "6") { + } else if (quiche::GetQuicheCommandLineFlag( + FLAGS_ip_version_for_host_lookup) == "6") { address_family_for_lookup = AF_INET6; } @@ -324,11 +332,13 @@ int QuicToyClient::SendRequestsAndPrintResponses( return 1; } - if (!GetQuicFlag(FLAGS_default_client_cert).empty() && - !GetQuicFlag(FLAGS_default_client_cert_key).empty()) { + if (!quiche::GetQuicheCommandLineFlag(FLAGS_default_client_cert).empty() && + !quiche::GetQuicheCommandLineFlag(FLAGS_default_client_cert_key) + .empty()) { std::unique_ptr<ClientProofSource> proof_source = - CreateTestClientProofSource(GetQuicFlag(FLAGS_default_client_cert), - GetQuicFlag(FLAGS_default_client_cert_key)); + CreateTestClientProofSource( + quiche::GetQuicheCommandLineFlag(FLAGS_default_client_cert), + quiche::GetQuicheCommandLineFlag(FLAGS_default_client_cert_key)); if (proof_source == nullptr) { std::cerr << "Failed to create client proof source." << std::endl; return 1; @@ -336,22 +346,23 @@ int QuicToyClient::SendRequestsAndPrintResponses( client->crypto_config()->set_proof_source(std::move(proof_source)); } - int32_t initial_mtu = GetQuicFlag(FLAGS_initial_mtu); + int32_t initial_mtu = quiche::GetQuicheCommandLineFlag(FLAGS_initial_mtu); client->set_initial_max_packet_length( initial_mtu != 0 ? initial_mtu : quic::kDefaultMaxPacketSize); - client->set_drop_response_body(GetQuicFlag(FLAGS_drop_response_body)); + client->set_drop_response_body( + quiche::GetQuicheCommandLineFlag(FLAGS_drop_response_body)); const int32_t server_connection_id_length = - GetQuicFlag(FLAGS_server_connection_id_length); + quiche::GetQuicheCommandLineFlag(FLAGS_server_connection_id_length); if (server_connection_id_length >= 0) { client->set_server_connection_id_length(server_connection_id_length); } const int32_t client_connection_id_length = - GetQuicFlag(FLAGS_client_connection_id_length); + quiche::GetQuicheCommandLineFlag(FLAGS_client_connection_id_length); if (client_connection_id_length >= 0) { client->set_client_connection_id_length(client_connection_id_length); } const size_t max_inbound_header_list_size = - GetQuicFlag(FLAGS_max_inbound_header_list_size); + quiche::GetQuicheCommandLineFlag(FLAGS_max_inbound_header_list_size); if (max_inbound_header_list_size > 0) { client->set_max_inbound_header_list_size(max_inbound_header_list_size); } @@ -366,7 +377,8 @@ int QuicToyClient::SendRequestsAndPrintResponses( << ". " << client->session()->error_details() << std::endl; // 0: No error. // 20: Failed to connect due to QUIC_INVALID_VERSION. - return GetQuicFlag(FLAGS_version_mismatch_ok) ? 0 : 20; + return quiche::GetQuicheCommandLineFlag(FLAGS_version_mismatch_ok) ? 0 + : 20; } std::cerr << "Failed to connect to " << host << ":" << port << ". " << quic::QuicErrorCodeToString(error) << " " @@ -376,11 +388,12 @@ int QuicToyClient::SendRequestsAndPrintResponses( std::cerr << "Connected to " << host << ":" << port << std::endl; // Construct the string body from flags, if provided. - std::string body = GetQuicFlag(FLAGS_body); - if (!GetQuicFlag(FLAGS_body_hex).empty()) { - QUICHE_DCHECK(GetQuicFlag(FLAGS_body).empty()) + std::string body = quiche::GetQuicheCommandLineFlag(FLAGS_body); + if (!quiche::GetQuicheCommandLineFlag(FLAGS_body_hex).empty()) { + QUICHE_DCHECK(quiche::GetQuicheCommandLineFlag(FLAGS_body).empty()) << "Only set one of --body and --body_hex."; - body = absl::HexStringToBytes(GetQuicFlag(FLAGS_body_hex)); + body = absl::HexStringToBytes( + quiche::GetQuicheCommandLineFlag(FLAGS_body_hex)); } // Construct a GET or POST request for supplied URL. @@ -391,7 +404,7 @@ int QuicToyClient::SendRequestsAndPrintResponses( header_block[":path"] = url.PathParamsQuery(); // Append any additional headers supplied on the command line. - const std::string headers = GetQuicFlag(FLAGS_headers); + const std::string headers = quiche::GetQuicheCommandLineFlag(FLAGS_headers); for (absl::string_view sp : absl::StrSplit(headers, ';')) { QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&sp); if (sp.empty()) { @@ -412,14 +425,14 @@ int QuicToyClient::SendRequestsAndPrintResponses( client->SendRequestAndWaitForResponse(header_block, body, /*fin=*/true); // Print request and response details. - if (!GetQuicFlag(FLAGS_quiet)) { + if (!quiche::GetQuicheCommandLineFlag(FLAGS_quiet)) { std::cout << "Request:" << std::endl; std::cout << "headers:" << header_block.DebugString(); - if (!GetQuicFlag(FLAGS_body_hex).empty()) { + if (!quiche::GetQuicheCommandLineFlag(FLAGS_body_hex).empty()) { // Print the user provided hex, rather than binary body. std::cout << "body:\n" - << QuicheTextUtils::HexDump( - absl::HexStringToBytes(GetQuicFlag(FLAGS_body_hex))) + << QuicheTextUtils::HexDump(absl::HexStringToBytes( + quiche::GetQuicheCommandLineFlag(FLAGS_body_hex))) << std::endl; } else { std::cout << "body: " << body << std::endl; @@ -436,7 +449,7 @@ int QuicToyClient::SendRequestsAndPrintResponses( std::cout << "headers: " << client->latest_response_headers() << std::endl; std::string response_body = client->latest_response_body(); - if (!GetQuicFlag(FLAGS_body_hex).empty()) { + if (!quiche::GetQuicheCommandLineFlag(FLAGS_body_hex).empty()) { // Assume response is binary data. std::cout << "body:\n" << QuicheTextUtils::HexDump(response_body) << std::endl; @@ -458,7 +471,7 @@ int QuicToyClient::SendRequestsAndPrintResponses( if (response_code >= 200 && response_code < 300) { std::cout << "Request succeeded (" << response_code << ")." << std::endl; } else if (response_code >= 300 && response_code < 400) { - if (GetQuicFlag(FLAGS_redirect_is_success)) { + if (quiche::GetQuicheCommandLineFlag(FLAGS_redirect_is_success)) { std::cout << "Request succeeded (redirect " << response_code << ")." << std::endl; } else { @@ -472,7 +485,7 @@ int QuicToyClient::SendRequestsAndPrintResponses( } if (i + 1 < num_requests) { // There are more requests to perform. - if (GetQuicFlag(FLAGS_one_connection_per_request)) { + if (quiche::GetQuicheCommandLineFlag(FLAGS_one_connection_per_request)) { std::cout << "Disconnecting client between requests." << std::endl; client->Disconnect(); if (!client->Initialize()) { @@ -485,7 +498,8 @@ int QuicToyClient::SendRequestsAndPrintResponses( << std::endl; return 1; } - } else if (!GetQuicFlag(FLAGS_disable_port_changes)) { + } else if (!quiche::GetQuicheCommandLineFlag( + FLAGS_disable_port_changes)) { // Change the ephemeral port. if (!client->ChangeEphemeralPort()) { std::cerr << "Failed to change ephemeral port." << std::endl; diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_toy_server.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_toy_server.cc index 03f910c90fd..1e31b2e0124 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_toy_server.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_toy_server.cc @@ -45,14 +45,15 @@ namespace quic { std::unique_ptr<quic::QuicSimpleServerBackend> QuicToyServer::MemoryCacheBackendFactory::CreateBackend() { auto memory_cache_backend = std::make_unique<QuicMemoryCacheBackend>(); - if (GetQuicFlag(FLAGS_generate_dynamic_responses)) { + if (quiche::GetQuicheCommandLineFlag(FLAGS_generate_dynamic_responses)) { memory_cache_backend->GenerateDynamicResponses(); } - if (!GetQuicFlag(FLAGS_quic_response_cache_dir).empty()) { + if (!quiche::GetQuicheCommandLineFlag(FLAGS_quic_response_cache_dir) + .empty()) { memory_cache_backend->InitializeBackend( - GetQuicFlag(FLAGS_quic_response_cache_dir)); + quiche::GetQuicheCommandLineFlag(FLAGS_quic_response_cache_dir)); } - if (GetQuicFlag(FLAGS_enable_webtransport)) { + if (quiche::GetQuicheCommandLineFlag(FLAGS_enable_webtransport)) { memory_cache_backend->EnableWebTransport(); } return memory_cache_backend; @@ -64,7 +65,7 @@ QuicToyServer::QuicToyServer(BackendFactory* backend_factory, int QuicToyServer::Start() { ParsedQuicVersionVector supported_versions; - if (GetQuicFlag(FLAGS_quic_ietf_draft)) { + if (quiche::GetQuicheCommandLineFlag(FLAGS_quic_ietf_draft)) { QuicVersionInitializeSupportForIetfDraft(); for (const ParsedQuicVersion& version : AllSupportedVersions()) { // Add all versions that supports IETF QUIC. @@ -76,7 +77,8 @@ int QuicToyServer::Start() { } else { supported_versions = AllSupportedVersions(); } - std::string versions_string = GetQuicFlag(FLAGS_quic_versions); + std::string versions_string = + quiche::GetQuicheCommandLineFlag(FLAGS_quic_versions); if (!versions_string.empty()) { supported_versions = ParseQuicVersionVectorString(versions_string); } @@ -92,7 +94,8 @@ int QuicToyServer::Start() { backend.get(), std::move(proof_source), supported_versions); if (!server->CreateUDPSocketAndListen(quic::QuicSocketAddress( - quic::QuicIpAddress::Any6(), GetQuicFlag(FLAGS_port)))) { + quic::QuicIpAddress::Any6(), + quiche::GetQuicheCommandLineFlag(FLAGS_port)))) { return 1; } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_dispatcher.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_dispatcher.cc deleted file mode 100644 index 7fdcfe96b2c..00000000000 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_dispatcher.cc +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2019 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 "quiche/quic/tools/quic_transport_simple_server_dispatcher.h" - -#include <memory> - -#include "absl/strings/string_view.h" -#include "quiche/quic/core/quic_connection.h" -#include "quiche/quic/core/quic_dispatcher.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/tools/quic_transport_simple_server_session.h" - -namespace quic { - -QuicTransportSimpleServerDispatcher::QuicTransportSimpleServerDispatcher( - const QuicConfig* config, const QuicCryptoServerConfig* crypto_config, - QuicVersionManager* version_manager, - std::unique_ptr<QuicConnectionHelperInterface> helper, - std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper, - std::unique_ptr<QuicAlarmFactory> alarm_factory, - uint8_t expected_server_connection_id_length, - std::vector<url::Origin> accepted_origins) - : QuicDispatcher(config, crypto_config, version_manager, std::move(helper), - std::move(session_helper), std::move(alarm_factory), - expected_server_connection_id_length), - accepted_origins_(accepted_origins) {} - -std::unique_ptr<QuicSession> -QuicTransportSimpleServerDispatcher::CreateQuicSession( - QuicConnectionId server_connection_id, - const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, absl::string_view /*alpn*/, - const ParsedQuicVersion& version, - const ParsedClientHello& /*parsed_chlo*/) { - auto connection = std::make_unique<QuicConnection>( - server_connection_id, self_address, peer_address, helper(), - alarm_factory(), writer(), - /*owns_writer=*/false, Perspective::IS_SERVER, - ParsedQuicVersionVector{version}); - auto session = std::make_unique<QuicTransportSimpleServerSession>( - connection.release(), /*owns_connection=*/true, this, config(), - GetSupportedVersions(), crypto_config(), compressed_certs_cache(), - accepted_origins_); - session->Initialize(); - return session; -} - -} // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_dispatcher.h b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_dispatcher.h deleted file mode 100644 index 98562a08f41..00000000000 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_dispatcher.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_DISPATCHER_H_ -#define QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_DISPATCHER_H_ - -#include "absl/strings/string_view.h" -#include "url/origin.h" -#include "quiche/quic/core/quic_dispatcher.h" -#include "quiche/quic/tools/quic_transport_simple_server_session.h" - -namespace quic { - -// Dispatcher that creates a QuicTransportSimpleServerSession for every incoming -// connection. -class QuicTransportSimpleServerDispatcher : public QuicDispatcher { - public: - QuicTransportSimpleServerDispatcher( - const QuicConfig* config, const QuicCryptoServerConfig* crypto_config, - QuicVersionManager* version_manager, - std::unique_ptr<QuicConnectionHelperInterface> helper, - std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper, - std::unique_ptr<QuicAlarmFactory> alarm_factory, - uint8_t expected_server_connection_id_length, - std::vector<url::Origin> accepted_origins); - - protected: - std::unique_ptr<QuicSession> CreateQuicSession( - QuicConnectionId server_connection_id, - const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, absl::string_view alpn, - const ParsedQuicVersion& version, - const ParsedClientHello& parsed_chlo) override; - - std::vector<url::Origin> accepted_origins_; -}; - -} // namespace quic - -#endif // QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_DISPATCHER_H_ diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_session.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_session.cc deleted file mode 100644 index fcd70ce541a..00000000000 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_session.cc +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2019 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 "quiche/quic/tools/quic_transport_simple_server_session.h" - -#include <memory> - -#include "url/gurl.h" -#include "url/origin.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_flags.h" -#include "quiche/quic/platform/api/quic_logging.h" -#include "quiche/quic/quic_transport/quic_transport_protocol.h" -#include "quiche/quic/quic_transport/quic_transport_stream.h" -#include "quiche/quic/tools/web_transport_test_visitors.h" -#include "quiche/common/platform/api/quiche_mem_slice.h" -#include "quiche/common/quiche_buffer_allocator.h" - -namespace quic { - -QuicTransportSimpleServerSession::QuicTransportSimpleServerSession( - QuicConnection* connection, bool owns_connection, Visitor* owner, - const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - std::vector<url::Origin> accepted_origins) - : QuicTransportServerSession(connection, owner, config, supported_versions, - crypto_config, compressed_certs_cache, this), - owns_connection_(owns_connection), - mode_(DISCARD), - accepted_origins_(accepted_origins) {} - -QuicTransportSimpleServerSession::~QuicTransportSimpleServerSession() { - if (owns_connection_) { - DeleteConnection(); - } -} - -void QuicTransportSimpleServerSession::OnIncomingDataStream( - QuicTransportStream* stream) { - switch (mode_) { - case DISCARD: - stream->SetVisitor(std::make_unique<WebTransportDiscardVisitor>(stream)); - break; - - case ECHO: - switch (stream->type()) { - case BIDIRECTIONAL: - QUIC_DVLOG(1) << "Opening bidirectional echo stream " << stream->id(); - stream->SetVisitor( - std::make_unique<WebTransportBidirectionalEchoVisitor>(stream)); - break; - case READ_UNIDIRECTIONAL: - QUIC_DVLOG(1) - << "Started receiving data on unidirectional echo stream " - << stream->id(); - stream->SetVisitor( - std::make_unique<WebTransportUnidirectionalEchoReadVisitor>( - stream, - [this](const std::string& s) { this->EchoStreamBack(s); })); - break; - default: - QUIC_NOTREACHED(); - break; - } - break; - - case OUTGOING_BIDIRECTIONAL: - stream->SetVisitor(std::make_unique<WebTransportDiscardVisitor>(stream)); - ++pending_outgoing_bidirectional_streams_; - MaybeCreateOutgoingBidirectionalStream(); - break; - } -} - -void QuicTransportSimpleServerSession::OnCanCreateNewOutgoingStream( - bool unidirectional) { - if (mode_ == ECHO && unidirectional) { - MaybeEchoStreamsBack(); - } else if (mode_ == OUTGOING_BIDIRECTIONAL && !unidirectional) { - MaybeCreateOutgoingBidirectionalStream(); - } -} - -bool QuicTransportSimpleServerSession::CheckOrigin(url::Origin origin) { - if (accepted_origins_.empty()) { - return true; - } - - for (const url::Origin& accepted_origin : accepted_origins_) { - if (origin.IsSameOriginWith(accepted_origin)) { - return true; - } - } - return false; -} - -bool QuicTransportSimpleServerSession::ProcessPath(const GURL& url) { - if (url.path() == "/discard") { - mode_ = DISCARD; - return true; - } - if (url.path() == "/echo") { - mode_ = ECHO; - return true; - } - if (url.path() == "/receive-bidirectional") { - mode_ = OUTGOING_BIDIRECTIONAL; - return true; - } - - QUIC_DLOG(WARNING) << "Unknown path requested: " << url.path(); - return false; -} - -void QuicTransportSimpleServerSession::OnMessageReceived( - absl::string_view message) { - if (mode_ != ECHO) { - return; - } - datagram_queue()->SendOrQueueDatagram( - quiche::QuicheMemSlice(quiche::QuicheBuffer::Copy( - connection()->helper()->GetStreamSendBufferAllocator(), message))); -} - -void QuicTransportSimpleServerSession::MaybeEchoStreamsBack() { - while (!streams_to_echo_back_.empty() && - CanOpenNextOutgoingUnidirectionalStream()) { - // Remove the stream from the queue first, in order to avoid accidentally - // entering an infinite loop in case any of the following code calls - // OnCanCreateNewOutgoingStream(). - std::string data = std::move(streams_to_echo_back_.front()); - streams_to_echo_back_.pop_front(); - - auto stream_owned = std::make_unique<QuicTransportStream>( - GetNextOutgoingUnidirectionalStreamId(), this, this); - QuicTransportStream* stream = stream_owned.get(); - ActivateStream(std::move(stream_owned)); - QUIC_DVLOG(1) << "Opened echo response stream " << stream->id(); - - stream->SetVisitor( - std::make_unique<WebTransportUnidirectionalEchoWriteVisitor>(stream, - data)); - stream->visitor()->OnCanWrite(); - } -} - -void QuicTransportSimpleServerSession:: - MaybeCreateOutgoingBidirectionalStream() { - while (pending_outgoing_bidirectional_streams_ > 0 && - CanOpenNextOutgoingBidirectionalStream()) { - auto stream_owned = std::make_unique<QuicTransportStream>( - GetNextOutgoingBidirectionalStreamId(), this, this); - QuicTransportStream* stream = stream_owned.get(); - ActivateStream(std::move(stream_owned)); - QUIC_DVLOG(1) << "Opened outgoing bidirectional stream " << stream->id(); - stream->SetVisitor( - std::make_unique<WebTransportBidirectionalEchoVisitor>(stream)); - if (!stream->Write("hello")) { - QUIC_DVLOG(1) << "Write failed."; - } - --pending_outgoing_bidirectional_streams_; - } -} - -} // namespace quic diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_session.h b/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_session.h deleted file mode 100644 index 4d59f90a667..00000000000 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/quic_transport_simple_server_session.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_SESSION_H_ -#define QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_SESSION_H_ - -#include <memory> -#include <vector> - -#include "url/origin.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_containers.h" -#include "quiche/quic/platform/api/quic_flags.h" -#include "quiche/quic/quic_transport/quic_transport_server_session.h" -#include "quiche/quic/quic_transport/quic_transport_stream.h" - -namespace quic { - -// QuicTransport simple server is a non-production server that can be used for -// testing QuicTransport. It has two modes that can be changed using the -// command line flags, "echo" and "discard". -class QuicTransportSimpleServerSession - : public QuicTransportServerSession, - QuicTransportServerSession::ServerVisitor { - public: - enum Mode { - // In DISCARD mode, any data on incoming streams is discarded and no - // outgoing streams are initiated. - DISCARD, - // In ECHO mode, any data sent on a bidirectional stream is echoed back. - // Any data sent on a unidirectional stream is buffered, and echoed back on - // a server-initiated unidirectional stream that is sent as soon as a FIN is - // received on the incoming stream. - ECHO, - // In OUTGOING_BIDIRECTIONAL mode, a server-originated bidirectional stream - // is created on receipt of a unidirectional stream. The contents of the - // unidirectional stream are disregarded. The bidirectional stream initially - // sends "hello", then any received data is echoed back. - // TODO(ricea): Maybe this should be replaced by a more general mechanism - // where commands on the unidirectional stream trigger different behaviour? - OUTGOING_BIDIRECTIONAL, - }; - - QuicTransportSimpleServerSession( - QuicConnection* connection, bool owns_connection, Visitor* owner, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - std::vector<url::Origin> accepted_origins); - ~QuicTransportSimpleServerSession(); - - void OnIncomingDataStream(QuicTransportStream* stream) override; - void OnCanCreateNewOutgoingStream(bool unidirectional) override; - bool CheckOrigin(url::Origin origin) override; - bool ProcessPath(const GURL& url) override; - void OnMessageReceived(absl::string_view message) override; - - void EchoStreamBack(const std::string& data) { - streams_to_echo_back_.push_back(data); - MaybeEchoStreamsBack(); - } - - private: - void MaybeEchoStreamsBack(); - void MaybeCreateOutgoingBidirectionalStream(); - - const bool owns_connection_; - size_t pending_outgoing_bidirectional_streams_ = 0u; - Mode mode_; - std::vector<url::Origin> accepted_origins_; - quiche::QuicheCircularDeque<std::string> streams_to_echo_back_; -}; - -} // namespace quic - -#endif // QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_SESSION_H_ diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/simple_ticket_crypter.cc b/chromium/net/third_party/quiche/src/quiche/quic/tools/simple_ticket_crypter.cc index aa1e65e8838..ad9fea1a098 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/simple_ticket_crypter.cc +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/simple_ticket_crypter.cc @@ -87,7 +87,7 @@ std::vector<uint8_t> SimpleTicketCrypter::Decrypt(absl::string_view in) { void SimpleTicketCrypter::Decrypt( absl::string_view in, - std::unique_ptr<quic::ProofSource::DecryptCallback> callback) { + std::shared_ptr<quic::ProofSource::DecryptCallback> callback) { callback->Run(Decrypt(in)); } diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/simple_ticket_crypter.h b/chromium/net/third_party/quiche/src/quiche/quic/tools/simple_ticket_crypter.h index f0395f0d1e8..b5ad16d6f96 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/simple_ticket_crypter.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/simple_ticket_crypter.h @@ -28,7 +28,7 @@ class QUIC_NO_EXPORT SimpleTicketCrypter absl::string_view encryption_key) override; void Decrypt( absl::string_view in, - std::unique_ptr<quic::ProofSource::DecryptCallback> callback) override; + std::shared_ptr<quic::ProofSource::DecryptCallback> callback) override; private: std::vector<uint8_t> Decrypt(absl::string_view in); diff --git a/chromium/net/third_party/quiche/src/quiche/quic/tools/web_transport_test_visitors.h b/chromium/net/third_party/quiche/src/quiche/quic/tools/web_transport_test_visitors.h index 07d3161bbcc..e5b7fefda9d 100644 --- a/chromium/net/third_party/quiche/src/quiche/quic/tools/web_transport_test_visitors.h +++ b/chromium/net/third_party/quiche/src/quiche/quic/tools/web_transport_test_visitors.h @@ -9,6 +9,7 @@ #include "quiche/quic/core/web_transport_interface.h" #include "quiche/quic/platform/api/quic_logging.h" +#include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/platform/api/quiche_mem_slice.h" #include "quiche/common/quiche_circular_deque.h" #include "quiche/common/simple_buffer_allocator.h" @@ -123,7 +124,7 @@ class WebTransportUnidirectionalEchoReadVisitor } } - void OnCanWrite() override { QUIC_NOTREACHED(); } + void OnCanWrite() override { QUICHE_NOTREACHED(); } void OnResetStreamReceived(WebTransportStreamError /*error*/) override {} void OnStopSendingReceived(WebTransportStreamError /*error*/) override {} @@ -143,7 +144,7 @@ class WebTransportUnidirectionalEchoWriteVisitor const std::string& data) : stream_(stream), data_(data) {} - void OnCanRead() override { QUIC_NOTREACHED(); } + void OnCanRead() override { QUICHE_NOTREACHED(); } void OnCanWrite() override { if (data_.empty()) { return; |