diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-17 13:57:45 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-19 13:44:40 +0000 |
commit | 6ec7b8da05d21a3878bd21c691b41e675d74bb1c (patch) | |
tree | b87f250bc19413750b9bb9cdbf2da20ef5014820 /chromium/net/quic/core | |
parent | ec02ee4181c49b61fce1c8fb99292dbb8139cc90 (diff) | |
download | qtwebengine-chromium-6ec7b8da05d21a3878bd21c691b41e675d74bb1c.tar.gz |
BASELINE: Update Chromium to 60.0.3112.70
Change-Id: I9911c2280a014d4632f254857876a395d4baed2d
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/net/quic/core')
163 files changed, 6371 insertions, 2685 deletions
diff --git a/chromium/net/quic/core/congestion_control/bandwidth_sampler.cc b/chromium/net/quic/core/congestion_control/bandwidth_sampler.cc index 6f150044dec..f95fdd71816 100644 --- a/chromium/net/quic/core/congestion_control/bandwidth_sampler.cc +++ b/chromium/net/quic/core/congestion_control/bandwidth_sampler.cc @@ -7,6 +7,8 @@ #include <algorithm> #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" namespace net { BandwidthSampler::BandwidthSampler() @@ -18,7 +20,10 @@ BandwidthSampler::BandwidthSampler() last_sent_packet_(0), is_app_limited_(false), end_of_app_limited_phase_(0), - connection_state_map_() {} + connection_state_map_(), + connection_state_map_new_(), + use_new_connection_state_map_( + FLAGS_quic_reloadable_flag_quic_faster_bandwidth_sampler) {} BandwidthSampler::~BandwidthSampler() {} @@ -51,6 +56,23 @@ void BandwidthSampler::OnPacketSent( last_acked_packet_sent_time_ = sent_time; } + if (use_new_connection_state_map_) { + if (!connection_state_map_new_.IsEmpty() && + packet_number > + connection_state_map_new_.last_packet() + kMaxTrackedPackets) { + QUIC_BUG << "BandwidthSampler in-flight packet map has exceeded maximum " + "number " + "of tracked packets."; + } + + bool success = connection_state_map_new_.Emplace(packet_number, sent_time, + bytes, *this); + QUIC_BUG_IF(!success) << "BandwidthSampler failed to insert the packet " + "into the map, most likely because it's already " + "in it."; + return; + } + DCHECK(connection_state_map_.find(packet_number) == connection_state_map_.end()); connection_state_map_.emplace( @@ -64,6 +86,20 @@ void BandwidthSampler::OnPacketSent( BandwidthSample BandwidthSampler::OnPacketAcknowledged( QuicTime ack_time, QuicPacketNumber packet_number) { + if (use_new_connection_state_map_) { + ConnectionStateOnSentPacket* sent_packet_pointer = + connection_state_map_new_.GetEntry(packet_number); + if (sent_packet_pointer == nullptr) { + // See the TODO below. + return BandwidthSample(); + } + BandwidthSample sample = OnPacketAcknowledgedInner(ack_time, packet_number, + *sent_packet_pointer); + connection_state_map_new_.Remove(packet_number); + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_faster_bandwidth_sampler, 1, 2); + return sample; + } + auto it = connection_state_map_.find(packet_number); if (it == connection_state_map_.end()) { // TODO(vasilvv): currently, this can happen because the congestion @@ -72,15 +108,21 @@ BandwidthSample BandwidthSampler::OnPacketAcknowledged( // this should be a QUIC_BUG equivalent. return BandwidthSample(); } - const ConnectionStateOnSentPacket sent_packet = it->second; + BandwidthSample sample = + OnPacketAcknowledgedInner(ack_time, packet_number, it->second); + connection_state_map_.erase(it); + return sample; +} +BandwidthSample BandwidthSampler::OnPacketAcknowledgedInner( + QuicTime ack_time, + QuicPacketNumber packet_number, + const ConnectionStateOnSentPacket& sent_packet) { total_bytes_acked_ += sent_packet.size; total_bytes_sent_at_last_acked_packet_ = sent_packet.total_bytes_sent; last_acked_packet_sent_time_ = sent_packet.sent_time; last_acked_packet_ack_time_ = ack_time; - connection_state_map_.erase(it); - // Exit app-limited phase once a packet that was sent while the connection is // not app-limited is acknowledged. if (is_app_limited_ && packet_number > end_of_app_limited_phase_) { @@ -130,6 +172,15 @@ BandwidthSample BandwidthSampler::OnPacketAcknowledged( } void BandwidthSampler::OnPacketLost(QuicPacketNumber packet_number) { + if (use_new_connection_state_map_) { + // TODO(vasilvv): see the comment for the case of missing packets in + // BandwidthSampler::OnPacketAcknowledged on why this does not raise a + // QUIC_BUG when removal fails. + connection_state_map_new_.Remove(packet_number); + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_faster_bandwidth_sampler, 2, 2); + return; + } + auto it = connection_state_map_.find(packet_number); if (it == connection_state_map_.end()) { // TODO(vasilvv): see the comment for the same case in @@ -146,6 +197,14 @@ void BandwidthSampler::OnAppLimited() { } void BandwidthSampler::RemoveObsoletePackets(QuicPacketNumber least_unacked) { + if (use_new_connection_state_map_) { + while (!connection_state_map_new_.IsEmpty() && + connection_state_map_new_.first_packet() < least_unacked) { + connection_state_map_new_.Remove( + connection_state_map_new_.first_packet()); + } + return; + } while (!connection_state_map_.empty() && connection_state_map_.begin()->first < least_unacked) { connection_state_map_.pop_front(); diff --git a/chromium/net/quic/core/congestion_control/bandwidth_sampler.h b/chromium/net/quic/core/congestion_control/bandwidth_sampler.h index 0bedd6cae72..75845404186 100644 --- a/chromium/net/quic/core/congestion_control/bandwidth_sampler.h +++ b/chromium/net/quic/core/congestion_control/bandwidth_sampler.h @@ -5,6 +5,7 @@ #ifndef NET_QUIC_CORE_CONGESTION_CONTROL_BANDWIDTH_SAMPLER_H_ #define NET_QUIC_CORE_CONGESTION_CONTROL_BANDWIDTH_SAMPLER_H_ +#include "net/quic/core/packet_number_indexed_queue.h" #include "net/quic/core/quic_bandwidth.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_time.h" @@ -206,6 +207,13 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler { total_bytes_acked_at_the_last_acked_packet( sampler.total_bytes_acked_), is_app_limited(sampler.is_app_limited_) {} + + // Default constructor. Required to put this structure into + // PacketNumberIndexedQueue. + ConnectionStateOnSentPacket() + : sent_time(QuicTime::Zero()), + last_acked_packet_sent_time(QuicTime::Zero()), + last_acked_packet_ack_time(QuicTime::Zero()) {} }; typedef QuicLinkedHashMap<QuicPacketNumber, ConnectionStateOnSentPacket> @@ -242,6 +250,16 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler { // Record of the connection state at the point where each packet in flight was // sent, indexed by the packet number. ConnectionStateMap connection_state_map_; + PacketNumberIndexedQueue<ConnectionStateOnSentPacket> + connection_state_map_new_; + const bool use_new_connection_state_map_; + + // Handles the actual bandwidth calculations, whereas the outer method handles + // retrieving and removing |sent_packet|. + BandwidthSample OnPacketAcknowledgedInner( + QuicTime ack_time, + QuicPacketNumber packet_number, + const ConnectionStateOnSentPacket& sent_packet); }; } // namespace net diff --git a/chromium/net/quic/core/congestion_control/bandwidth_sampler_test.cc b/chromium/net/quic/core/congestion_control/bandwidth_sampler_test.cc index bf6f7e6c5d9..517ab552cb8 100644 --- a/chromium/net/quic/core/congestion_control/bandwidth_sampler_test.cc +++ b/chromium/net/quic/core/congestion_control/bandwidth_sampler_test.cc @@ -4,9 +4,9 @@ #include "net/quic/core/congestion_control/bandwidth_sampler.h" +#include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { namespace test { @@ -14,11 +14,17 @@ namespace test { class BandwidthSamplerPeer { public: static size_t GetNumberOfTrackedPackets(const BandwidthSampler& sampler) { + if (FLAGS_quic_reloadable_flag_quic_faster_bandwidth_sampler) { + return sampler.connection_state_map_new_.number_of_present_entries(); + } return sampler.connection_state_map_.size(); } static QuicByteCount GetPacketSize(const BandwidthSampler& sampler, QuicPacketNumber packet_number) { + if (FLAGS_quic_reloadable_flag_quic_faster_bandwidth_sampler) { + return sampler.connection_state_map_new_.GetEntry(packet_number)->size; + } auto iterator = sampler.connection_state_map_.find(packet_number); return iterator->second.size; } @@ -30,7 +36,7 @@ static_assert((kRegularPacketSize & 31) == 0, "kRegularPacketSize has to be five times divisible by 2"); // A test fixture with utility methods for BandwidthSampler tests. -class BandwidthSamplerTest : public ::testing::Test { +class BandwidthSamplerTest : public QuicTest { protected: BandwidthSamplerTest() : bytes_in_flight_(0) { // Ensure that the clock does not start at zero. @@ -198,9 +204,9 @@ TEST_F(BandwidthSamplerTest, NotCongestionControlled) { // Send 20 packets, each 1 ms apart. Every even packet is not congestion // controlled. for (QuicPacketNumber i = 1; i <= 20; i++) { - SendPacketInner(i, kRegularPacketSize, i % 2 == 0 - ? HAS_RETRANSMITTABLE_DATA - : NO_RETRANSMITTABLE_DATA); + SendPacketInner( + i, kRegularPacketSize, + i % 2 == 0 ? HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA); clock_.AdvanceTime(time_between_packets); } @@ -213,9 +219,9 @@ TEST_F(BandwidthSamplerTest, NotCongestionControlled) { if (i % 2 == 0) { AckPacket(i); } - SendPacketInner(i + 20, kRegularPacketSize, i % 2 == 0 - ? HAS_RETRANSMITTABLE_DATA - : NO_RETRANSMITTABLE_DATA); + SendPacketInner( + i + 20, kRegularPacketSize, + i % 2 == 0 ? HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA); clock_.AdvanceTime(time_between_packets); } diff --git a/chromium/net/quic/core/congestion_control/bbr_sender.cc b/chromium/net/quic/core/congestion_control/bbr_sender.cc index ead7e0de80f..0d40c3fd76a 100644 --- a/chromium/net/quic/core/congestion_control/bbr_sender.cc +++ b/chromium/net/quic/core/congestion_control/bbr_sender.cc @@ -10,9 +10,9 @@ #include "net/quic/core/congestion_control/rtt_stats.h" #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/proto/cached_network_parameters.pb.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net { @@ -46,6 +46,12 @@ const QuicTime::Delta kProbeRttTime = QuicTime::Delta::FromMilliseconds(200); // will exit the STARTUP mode. const float kStartupGrowthTarget = 1.25; const QuicRoundTripCount kRoundTripsWithoutGrowthBeforeExitingStartup = 3; + +// Maintain ack history for this fraction of the smoothed RTT. +const float kRecentlyAckedRttFraction = 0.5f; +// Minimum period over which ack history will be maintained. +const QuicTime::Delta kMinAckHistory = QuicTime::Delta::FromMilliseconds(5); + } // namespace BbrSender::DebugState::DebugState(const BbrSender& sender) @@ -80,9 +86,6 @@ BbrSender::BbrSender(const RttStats* rtt_stats, last_sent_packet_(0), current_round_trip_end_(0), max_bandwidth_(kBandwidthWindowSize, QuicBandwidth::Zero(), 0), - max_ack_spacing_(kBandwidthWindowSize, QuicTime::Delta::Zero(), 0), - largest_acked_time_(QuicTime::Zero()), - largest_acked_sent_time_(QuicTime::Zero()), max_ack_height_(kBandwidthWindowSize, 0, 0), aggregation_epoch_start_time_(QuicTime::Zero()), aggregation_epoch_bytes_(0), @@ -96,10 +99,14 @@ BbrSender::BbrSender(const RttStats* rtt_stats, pacing_gain_(1), congestion_window_gain_(1), congestion_window_gain_constant_( - static_cast<float>(base::GetFlag(FLAGS_quic_bbr_cwnd_gain))), - rtt_variance_weight_(static_cast<float>( - base::GetFlag(FLAGS_quic_bbr_rtt_variation_weight))), + static_cast<float>(FLAGS_quic_bbr_cwnd_gain)), + rtt_variance_weight_( + static_cast<float>(FLAGS_quic_bbr_rtt_variation_weight)), num_startup_rtts_(kRoundTripsWithoutGrowthBeforeExitingStartup), + congestion_window_gain_for_slow_delivery_( + static_cast<float>(FLAGS_quic_bbr_slow_delivery_cwnd_gain)), + threshold_multiplier_for_slow_delivery_(static_cast<float>( + FLAGS_quic_bbr_slow_delivery_threshold_multiplier)), cycle_current_offset_(0), last_cycle_start_(QuicTime::Zero()), is_at_full_bandwidth_(false), @@ -111,7 +118,8 @@ BbrSender::BbrSender(const RttStats* rtt_stats, last_sample_is_app_limited_(false), recovery_state_(NOT_IN_RECOVERY), end_recovery_at_(0), - recovery_window_(max_congestion_window_) { + recovery_window_(max_congestion_window_), + bytes_recently_acked_(0) { EnterStartupMode(); } @@ -137,15 +145,49 @@ bool BbrSender::OnPacketSent(QuicTime sent_time, return is_retransmittable == HAS_RETRANSMITTABLE_DATA; } -QuicTime::Delta BbrSender::TimeUntilSend(QuicTime /* now */, - QuicByteCount bytes_in_flight) const { +bool BbrSender::SlowDeliveryAllowsSending(QuicTime now, + QuicByteCount bytes_in_flight) { + if (mode_ != BbrSender::PROBE_BW) { + return false; + } + UpdateRecentlyAcked(now, 0u); + // Set a (large) limit to how much we send into a blackhole. + if (bytes_in_flight >= + congestion_window_gain_for_slow_delivery_ * GetCongestionWindow()) { + return false; + } + // If no acks were recorded in the recent past, continue sending. + if (recently_acked_.empty()) { + return true; + } + // Compute the time period over which acks should have been recorded. + QuicTime::Delta ack_period = + std::max(now - recently_acked_.front().ack_time, + std::max(kMinAckHistory, kRecentlyAckedRttFraction * + rtt_stats_->smoothed_rtt())); + // If delivery rate is less than BW by a factor of threshold_multiplier_, + // ack rate has suddenly decreased substantially. Continue sending. + if (BandwidthEstimate() * ack_period > + threshold_multiplier_for_slow_delivery_ * bytes_recently_acked_) { + return true; + } + return false; +} + +QuicTime::Delta BbrSender::TimeUntilSend(QuicTime now, + QuicByteCount bytes_in_flight) { if (bytes_in_flight < GetCongestionWindow()) { return QuicTime::Delta::Zero(); } + if (FLAGS_quic_reloadable_flag_quic_bbr_slow_recent_delivery && + SlowDeliveryAllowsSending(now, bytes_in_flight)) { + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_slow_recent_delivery, 2, 2); + return QuicTime::Delta::Zero(); + } return QuicTime::Delta::Infinite(); } -QuicBandwidth BbrSender::PacingRate(QuicByteCount /*bytes_in_flight*/) const { +QuicBandwidth BbrSender::PacingRate(QuicByteCount bytes_in_flight) const { if (pacing_rate_.IsZero()) { return kHighGain * QuicBandwidth::FromBytesAndTimeDelta( initial_congestion_window_, GetMinRtt()); @@ -179,14 +221,11 @@ bool BbrSender::InRecovery() const { void BbrSender::SetFromConfig(const QuicConfig& config, Perspective perspective) { - if (FLAGS_quic_reloadable_flag_quic_allow_2_rtt_bbr_startup) { - QUIC_FLAG_COUNT(quic_reloadable_flag_quic_allow_2_rtt_bbr_startup); - if (config.HasClientRequestedIndependentOption(k1RTT, perspective)) { - num_startup_rtts_ = 1; - } - if (config.HasClientRequestedIndependentOption(k2RTT, perspective)) { - num_startup_rtts_ = 2; - } + if (config.HasClientRequestedIndependentOption(k1RTT, perspective)) { + num_startup_rtts_ = 1; + } + if (config.HasClientRequestedIndependentOption(k2RTT, perspective)) { + num_startup_rtts_ = 2; } } @@ -197,6 +236,8 @@ void BbrSender::ResumeConnectionState( return; } + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_bbr_bandwidth_resumption); + QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond( max_bandwidth_resumption ? cached_network_params.max_bandwidth_estimate_bytes_per_second() @@ -229,10 +270,14 @@ void BbrSender::OnCongestionEvent(bool /*rtt_updated*/, min_rtt_expired = UpdateBandwidthAndMinRtt(event_time, acked_packets); UpdateRecoveryState(last_acked_packet, !lost_packets.empty(), is_round_start); - if (FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_spacing2, 1, 2); - UpdateAckSpacing(event_time, last_acked_packet, acked_packets); + + if (FLAGS_quic_reloadable_flag_quic_bbr_slow_recent_delivery) { + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_slow_recent_delivery, 1, + 2); + UpdateRecentlyAcked( + event_time, sampler_.total_bytes_acked() - total_bytes_acked_before); } + if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes) { QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 1, 2); @@ -255,13 +300,19 @@ void BbrSender::OnCongestionEvent(bool /*rtt_updated*/, // Handle logic specific to PROBE_RTT. MaybeEnterOrExitProbeRtt(event_time, is_round_start, min_rtt_expired); - // After the model is updated, recalculate the pacing rate and congestion - // window. + // Calculate number of packets acked and lost. QuicByteCount bytes_acked = sampler_.total_bytes_acked() - total_bytes_acked_before; + QuicByteCount bytes_lost = 0; + for (const auto& packet : lost_packets) { + bytes_lost += packet.second; + } + + // After the model is updated, recalculate the pacing rate and congestion + // window. CalculatePacingRate(); CalculateCongestionWindow(bytes_acked); - CalculateRecoveryWindow(bytes_acked); + CalculateRecoveryWindow(bytes_acked, bytes_lost); // Cleanup internal state. sampler_.RemoveObsoletePackets(unacked_packets_->GetLeastUnacked()); @@ -302,8 +353,7 @@ void BbrSender::EnterProbeBandwidthMode(QuicTime now) { // Pick a random offset for the gain cycle out of {0, 2..7} range. 1 is // excluded because in that case increased gain and decreased gain would not // follow each other. - cycle_current_offset_ = - random_->RandUint64() % (sizeof(kGainCycleLength) - 1); + cycle_current_offset_ = random_->RandUint64() % (kGainCycleLength - 1); if (cycle_current_offset_ >= 1) { cycle_current_offset_ += 1; } @@ -483,6 +533,13 @@ void BbrSender::UpdateRecoveryState(QuicPacketNumber last_acked_packet, // Enter conservation on the first loss. if (has_losses) { recovery_state_ = CONSERVATION; + if (FLAGS_quic_reloadable_flag_quic_bbr_fix_conservation2) { + // This will cause the |recovery_window_| to be set to the correct + // value in CalculateRecoveryWindow(). + recovery_window_ = 0; + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_fix_conservation2, 1, + 3); + } // Since the conservation phase is meant to be lasting for a whole // round, extend the current round as if it were started right now. current_round_trip_end_ = last_sent_packet_; @@ -498,44 +555,48 @@ void BbrSender::UpdateRecoveryState(QuicPacketNumber last_acked_packet, // Exit recovery if appropriate. if (!has_losses && last_acked_packet > end_recovery_at_) { recovery_state_ = NOT_IN_RECOVERY; + return; + } + + if (!FLAGS_quic_reloadable_flag_quic_bbr_extra_conservation) { + return; + } + + // Use "single round in conservation" approach outside of PROBE_BW. + if (mode_ != PROBE_BW) { + return; + } + + // Switch between conservation and growth depending on position in the + // gain cycle. + if (cycle_current_offset_ == 0 || + cycle_current_offset_ == kGainCycleLength - 1) { + recovery_state_ = GROWTH; + } else { + recovery_state_ = CONSERVATION; } break; } } -// TODO(ianswett): Move this logic into BandwidthSampler. -void BbrSender::UpdateAckSpacing(QuicTime ack_time, - QuicPacketNumber largest_newly_acked, - const CongestionVector& acked_packets) { - // Ignore acks of reordered packets. - if (largest_newly_acked < unacked_packets_->largest_observed()) { - return; - } - // Ignore acks of only one packet to filter out delayed acks. - if (acked_packets.size() == 1) { - return; - } - QuicTime largest_newly_acked_sent_time = - unacked_packets_->GetTransmissionInfo(largest_newly_acked).sent_time; - // Initialize on the first ack. - if (!largest_acked_time_.IsInitialized()) { - largest_acked_time_ = ack_time; - largest_acked_sent_time_ = largest_newly_acked_sent_time; - return; +void BbrSender::UpdateRecentlyAcked(QuicTime new_ack_time, + QuicByteCount newly_acked_bytes) { + // Discard information stored for acks received too far in the past. + QuicTime::Delta recent_period = std::max( + kMinAckHistory, kRecentlyAckedRttFraction * rtt_stats_->smoothed_rtt()); + while (!recently_acked_.empty() && + (recently_acked_.front().ack_time + recent_period < new_ack_time)) { + DCHECK_GE(bytes_recently_acked_, recently_acked_.front().acked_bytes); + bytes_recently_acked_ -= recently_acked_.front().acked_bytes; + recently_acked_.pop_front(); } - QuicTime::Delta ack_delta = ack_time - largest_acked_time_; - QuicTime::Delta send_delta = - largest_newly_acked_sent_time - largest_acked_sent_time_; - largest_acked_time_ = ack_time; - largest_acked_sent_time_ = largest_newly_acked_sent_time; - if (ack_delta <= send_delta) { + // Nothing to add to recently_acked_ if no new ack. + if (newly_acked_bytes == 0) return; - } - - // Limit the ack spacing to SRTT to filter outliers. - QuicTime::Delta ack_spacing = - std::min(ack_delta - send_delta, rtt_stats_->smoothed_rtt()); - max_ack_spacing_.Update(ack_spacing, round_trip_count_); + // Add information for new ack + DataDelivered new_ack = {new_ack_time, newly_acked_bytes}; + recently_acked_.push_back(new_ack); + bytes_recently_acked_ += newly_acked_bytes; } // TODO(ianswett): Move this logic into BandwidthSampler. @@ -595,11 +656,6 @@ void BbrSender::CalculateCongestionWindow(QuicByteCount bytes_acked) { if (rtt_variance_weight_ > 0.f && !BandwidthEstimate().IsZero()) { target_window += rtt_variance_weight_ * rtt_stats_->mean_deviation() * BandwidthEstimate(); - } else if (FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2 && - is_at_full_bandwidth_) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_spacing2, 2, 2); - // Add CWND for inter-ack spacing once STARTUP has been exited. - target_window += max_ack_spacing_.GetBest() * BandwidthEstimate(); } else if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes && is_at_full_bandwidth_) { QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 2, @@ -640,7 +696,43 @@ void BbrSender::CalculateCongestionWindow(QuicByteCount bytes_acked) { congestion_window_ = std::min(congestion_window_, max_congestion_window_); } -void BbrSender::CalculateRecoveryWindow(QuicByteCount bytes_acked) { +void BbrSender::CalculateRecoveryWindow(QuicByteCount bytes_acked, + QuicByteCount bytes_lost) { + if (FLAGS_quic_reloadable_flag_quic_bbr_fix_conservation2) { + if (recovery_state_ == NOT_IN_RECOVERY) { + return; + } + + // Set up the initial recovery window. + if (recovery_window_ == 0) { + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_fix_conservation2, 2, 3); + recovery_window_ = unacked_packets_->bytes_in_flight() + bytes_acked; + recovery_window_ = std::max(kMinimumCongestionWindow, recovery_window_); + return; + } + + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_fix_conservation2, 3, 3); + + // Remove losses from the recovery window, while accounting for a potential + // integer underflow. + recovery_window_ = recovery_window_ >= bytes_lost + ? recovery_window_ - bytes_lost + : kMaxSegmentSize; + + // In CONSERVATION mode, just subtracting losses is sufficient. In GROWTH, + // release additional |bytes_acked| to achieve a slow-start-like behavior. + if (recovery_state_ == GROWTH) { + recovery_window_ += bytes_acked; + } + + // Sanity checks. Ensure that we always allow to send at least + // |bytes_acked| in response. + recovery_window_ = std::max( + recovery_window_, unacked_packets_->bytes_in_flight() + bytes_acked); + recovery_window_ = std::max(kMinimumCongestionWindow, recovery_window_); + return; + } + switch (recovery_state_) { case CONSERVATION: recovery_window_ = unacked_packets_->bytes_in_flight() + bytes_acked; diff --git a/chromium/net/quic/core/congestion_control/bbr_sender.h b/chromium/net/quic/core/congestion_control/bbr_sender.h index 421f625f6f6..31102b7d91f 100644 --- a/chromium/net/quic/core/congestion_control/bbr_sender.h +++ b/chromium/net/quic/core/congestion_control/bbr_sender.h @@ -119,7 +119,7 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface { void OnRetransmissionTimeout(bool packets_retransmitted) override {} void OnConnectionMigration() override {} QuicTime::Delta TimeUntilSend(QuicTime now, - QuicByteCount bytes_in_flight) const override; + QuicByteCount bytes_in_flight) override; QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const override; QuicBandwidth BandwidthEstimate() const override; QuicByteCount GetCongestionWindow() const override; @@ -196,10 +196,15 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface { bool has_losses, bool is_round_start); - // Updates the ack spacing max filter if a larger value is observed. - void UpdateAckSpacing(QuicTime ack_time, - QuicPacketNumber largest_newly_acked, - const CongestionVector& acked_packets); + // Returns true if recent ack rate has decreased substantially and if sender + // is allowed to continue sending when congestion window limited. + bool SlowDeliveryAllowsSending(QuicTime now, QuicByteCount bytes_in_flight); + + // Updates history of recently received acks. Acks are considered recent + // if received within kRecentlyAckedRttFraction x smoothed RTT in the past. + // Adds new ack to recently_acked_ if |newly_acked_bytes| is non-zero. + void UpdateRecentlyAcked(QuicTime new_ack_time, + QuicByteCount newly_acked_bytes); // Updates the ack aggregation max filter in bytes. void UpdateAckAggregationBytes(QuicTime ack_time, @@ -211,7 +216,8 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface { void CalculateCongestionWindow(QuicByteCount bytes_acked); // Determines the approriate window that constrains the in-flight during // recovery. - void CalculateRecoveryWindow(QuicByteCount bytes_acked); + void CalculateRecoveryWindow(QuicByteCount bytes_acked, + QuicByteCount bytes_lost); const RttStats* rtt_stats_; const QuicUnackedPacketMap* unacked_packets_; @@ -236,13 +242,6 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface { // round-trips. MaxBandwidthFilter max_bandwidth_; - // Tracks the maximum spacing between two acks acknowledging in order packets. - MaxAckDelayFilter max_ack_spacing_; - - // The time the largest acked packet was acked and when it was sent. - QuicTime largest_acked_time_; - QuicTime largest_acked_sent_time_; - // Tracks the maximum number of bytes acked faster than the sending rate. MaxAckHeightFilter max_ack_height_; @@ -282,6 +281,13 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface { // The number of RTTs to stay in STARTUP mode. Defaults to 3. QuicRoundTripCount num_startup_rtts_; + // Gain to use when delivery rate is slow. + // TODO(jri): Make this a constant if we decide to use this code for BBR. + const float congestion_window_gain_for_slow_delivery_; + // Threshold multiplier below which delivery is considered slow. + // TODO(jri): Make this a constant if we decide to use this code for BBR. + const float threshold_multiplier_for_slow_delivery_; + // Number of round-trips in PROBE_BW mode, used for determining the current // pacing gain cycle. int cycle_current_offset_; @@ -317,6 +323,17 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface { // A window used to limit the number of bytes in flight during loss recovery. QuicByteCount recovery_window_; + // Records information about a received ack + struct DataDelivered { + QuicTime ack_time; + QuicByteCount acked_bytes; + }; + + // Data structure to record recently received acks. Used for determining + // recently seen ack rate over a short period in the past. + std::deque<DataDelivered> recently_acked_; + QuicByteCount bytes_recently_acked_; + DISALLOW_COPY_AND_ASSIGN(BbrSender); }; diff --git a/chromium/net/quic/core/congestion_control/bbr_sender_test.cc b/chromium/net/quic/core/congestion_control/bbr_sender_test.cc index 4480504211c..cad6186c0c5 100644 --- a/chromium/net/quic/core/congestion_control/bbr_sender_test.cc +++ b/chromium/net/quic/core/congestion_control/bbr_sender_test.cc @@ -12,6 +12,7 @@ #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_logging.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/quic_config_peer.h" #include "net/quic/test_tools/quic_connection_peer.h" @@ -20,7 +21,6 @@ #include "net/quic/test_tools/simulator/quic_endpoint.h" #include "net/quic/test_tools/simulator/simulator.h" #include "net/quic/test_tools/simulator/switch.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { namespace test { @@ -64,7 +64,7 @@ const QuicTime::Delta kTestRtt = (kTestPropagationDelay + kLocalPropagationDelay + kTestTransferTime) * 2; const QuicByteCount kTestBdp = kTestRtt * kTestLinkBandwidth; -class BbrSenderTest : public ::testing::Test { +class BbrSenderTest : public QuicTest { protected: BbrSenderTest() : simulator_(), @@ -82,14 +82,21 @@ class BbrSenderTest : public ::testing::Test { "Receiver", "BBR sender", Perspective::IS_SERVER, - /*connection_id=*/42), + /*connection_id=*/GetPeerInMemoryConnectionId(42)), competing_receiver_(&simulator_, "Competing receiver", "Competing sender", Perspective::IS_SERVER, - /*connection_id=*/43), + /*connection_id=*/GetPeerInMemoryConnectionId(43)), receiver_multiplexer_("Receiver multiplexer", {&receiver_, &competing_receiver_}) { + // These will be changed by the appropriate tests as necessary. + FLAGS_quic_reloadable_flag_quic_bbr_slow_recent_delivery = false; + FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd = false; + + FLAGS_quic_reloadable_flag_quic_bbr_extra_conservation = true; + FLAGS_quic_reloadable_flag_quic_bbr_fix_conservation2 = true; + rtt_stats_ = bbr_sender_.connection()->sent_packet_manager().GetRttStats(); sender_ = SetupBbrSender(&bbr_sender_); @@ -118,7 +125,6 @@ class BbrSenderTest : public ::testing::Test { const QuicClock* clock_; const RttStats* rtt_stats_; BbrSender* sender_; - QuicFlagSaver flags_; // Enables BBR on |endpoint| and returns the associated BBR congestion // controller. @@ -289,9 +295,8 @@ TEST_F(BbrSenderTest, SimpleTransferSmallBuffer) { } // Test a simple long data transfer with 2 rtts of aggregation. -TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregation) { - QuicFlagSaver flags; - FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2 = true; +TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes) { + FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes = true; FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd = false; CreateDefaultSetup(); // 2 RTTs of aggregation, with a max of 10kb. @@ -309,20 +314,29 @@ TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregation) { sender_->ExportDebugState().max_bandwidth); // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures // bandwidth higher than the link rate. + EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited); // The margin here is high, because the aggregation greatly increases // smoothed rtt. EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt()); - ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.1f); + ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.12f); } // Test a simple long data transfer with 2 rtts of aggregation. -TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes) { - FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2 = false; +TEST_F(BbrSenderTest, SimpleTransferAckDecimation) { FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes = true; - FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd = false; + // Decrease the CWND gain so extra CWND is required with stretch acks. + FLAGS_quic_bbr_cwnd_gain = 1.0; + sender_ = new BbrSender( + rtt_stats_, + QuicSentPacketManagerPeer::GetUnackedPacketMap( + QuicConnectionPeer::GetSentPacketManager(bbr_sender_.connection())), + kInitialCongestionWindowPackets, kDefaultMaxCongestionWindowPackets, + &random_); + QuicConnectionPeer::SetSendAlgorithm(bbr_sender_.connection(), sender_); + // Enable Ack Decimation on the receiver. + QuicConnectionPeer::SetAckMode(receiver_.connection(), + QuicConnection::AckMode::ACK_DECIMATION); CreateDefaultSetup(); - // 2 RTTs of aggregation, with a max of 10kb. - EnableAggregation(10 * 1024, 2 * kTestRtt); // Transfer 12MB. DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35)); @@ -339,27 +353,21 @@ TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes) { EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited); // The margin here is high, because the aggregation greatly increases // smoothed rtt. - EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt()); + EXPECT_GE(kTestRtt * 2, rtt_stats_->smoothed_rtt()); ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.1f); } // Test a simple long data transfer with 2 rtts of aggregation. -TEST_F(BbrSenderTest, SimpleTransferAckDecimation) { - FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2 = false; - FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes = true; - // Decrease the CWND gain so extra CWND is required with stretch acks. - base::SetFlag(&FLAGS_quic_bbr_cwnd_gain, 1.0); - sender_ = new BbrSender( - rtt_stats_, - QuicSentPacketManagerPeer::GetUnackedPacketMap( - QuicConnectionPeer::GetSentPacketManager(bbr_sender_.connection())), - kInitialCongestionWindowPackets, kDefaultMaxCongestionWindowPackets, - &random_); - QuicConnectionPeer::SetSendAlgorithm(bbr_sender_.connection(), sender_); - // Enable Ack Decimation on the receiver. - QuicConnectionPeer::SetAckMode(receiver_.connection(), - QuicConnection::AckMode::ACK_DECIMATION); +TEST_F(BbrSenderTest, + SimpleTransfer2RTTAggregationBytesWithIncreasedInflightLimit) { + FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes = false; + FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd = false; + FLAGS_quic_reloadable_flag_quic_bbr_slow_recent_delivery = true; + FLAGS_quic_bbr_slow_delivery_threshold_multiplier = 0.5; + FLAGS_quic_bbr_slow_delivery_cwnd_gain = 4.0; CreateDefaultSetup(); + // 2 RTTs of aggregation, with a max of 10kb. + EnableAggregation(10 * 1024, 2 * kTestRtt); // Transfer 12MB. DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35)); @@ -376,8 +384,8 @@ TEST_F(BbrSenderTest, SimpleTransferAckDecimation) { EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited); // The margin here is high, because the aggregation greatly increases // smoothed rtt. - EXPECT_GE(kTestRtt * 2, rtt_stats_->smoothed_rtt()); - ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.1f); + EXPECT_GE(kTestRtt * 5, rtt_stats_->smoothed_rtt()); + ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.25f); } // Test the number of losses incurred by the startup phase in a situation when @@ -389,12 +397,18 @@ TEST_F(BbrSenderTest, PacketLossOnSmallBufferStartup) { float loss_rate = static_cast<float>(bbr_sender_.connection()->GetStats().packets_lost) / bbr_sender_.connection()->GetStats().packets_sent; - EXPECT_LE(loss_rate, 0.27); + EXPECT_LE(loss_rate, 0.31); } // Ensures the code transitions loss recovery states correctly (NOT_IN_RECOVERY // -> CONSERVATION -> GROWTH -> NOT_IN_RECOVERY). TEST_F(BbrSenderTest, RecoveryStates) { + // Set seed to the position where the gain cycling causes the sender go + // into conservation upon entering PROBE_BW. + // + // TODO(vasilvv): there should be a better way to test this. + random_.set_seed(UINT64_C(14719894707049085006)); + const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10); bool simulator_result; CreateSmallBufferSetup(); @@ -427,9 +441,16 @@ TEST_F(BbrSenderTest, RecoveryStates) { return sender_->ExportDebugState().recovery_state != BbrSender::GROWTH; }, timeout); + + ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode); + if (FLAGS_quic_reloadable_flag_quic_bbr_extra_conservation) { + ASSERT_EQ(BbrSender::CONSERVATION, + sender_->ExportDebugState().recovery_state); + } else { + ASSERT_EQ(BbrSender::NOT_IN_RECOVERY, + sender_->ExportDebugState().recovery_state); + } ASSERT_TRUE(simulator_result); - ASSERT_EQ(BbrSender::NOT_IN_RECOVERY, - sender_->ExportDebugState().recovery_state); } // Verify the behavior of the algorithm in the case when the connection sends @@ -619,7 +640,6 @@ TEST_F(BbrSenderTest, NoBandwidthDropOnStartup) { // Test exiting STARTUP earlier due to the 1RTT connection option. TEST_F(BbrSenderTest, SimpleTransfer1RTTStartup) { - FLAGS_quic_reloadable_flag_quic_allow_2_rtt_bbr_startup = true; CreateDefaultSetup(); QuicConfig config; @@ -652,7 +672,6 @@ TEST_F(BbrSenderTest, SimpleTransfer1RTTStartup) { // Test exiting STARTUP earlier due to the 2RTT connection option. TEST_F(BbrSenderTest, SimpleTransfer2RTTStartup) { - FLAGS_quic_reloadable_flag_quic_allow_2_rtt_bbr_startup = true; // Adding TSO CWND causes packet loss before exiting startup. FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd = false; CreateDefaultSetup(); diff --git a/chromium/net/quic/core/congestion_control/cubic.cc b/chromium/net/quic/core/congestion_control/cubic.cc index 0fef6f8cccf..4849cf9790c 100644 --- a/chromium/net/quic/core/congestion_control/cubic.cc +++ b/chromium/net/quic/core/congestion_control/cubic.cc @@ -8,8 +8,8 @@ #include <cmath> #include <cstdint> -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net { diff --git a/chromium/net/quic/core/congestion_control/cubic_bytes.cc b/chromium/net/quic/core/congestion_control/cubic_bytes.cc index e490e06a972..4d9807f8250 100644 --- a/chromium/net/quic/core/congestion_control/cubic_bytes.cc +++ b/chromium/net/quic/core/congestion_control/cubic_bytes.cc @@ -8,8 +8,8 @@ #include <cmath> #include <cstdint> -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net { diff --git a/chromium/net/quic/core/congestion_control/cubic_bytes_test.cc b/chromium/net/quic/core/congestion_control/cubic_bytes_test.cc index 6cbe7ecf657..a0641ee5ce9 100644 --- a/chromium/net/quic/core/congestion_control/cubic_bytes_test.cc +++ b/chromium/net/quic/core/congestion_control/cubic_bytes_test.cc @@ -6,10 +6,10 @@ #include <cstdint> -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_str_cat.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; @@ -92,7 +92,7 @@ std::vector<TestParams> GetTestParams() { } // namespace -class CubicBytesTest : public ::testing::TestWithParam<TestParams> { +class CubicBytesTest : public QuicTestWithParam<TestParams> { protected: CubicBytesTest() : one_ms_(QuicTime::Delta::FromMilliseconds(1)), diff --git a/chromium/net/quic/core/congestion_control/cubic_test.cc b/chromium/net/quic/core/congestion_control/cubic_test.cc index 7233566cd80..c7e31266e6b 100644 --- a/chromium/net/quic/core/congestion_control/cubic_test.cc +++ b/chromium/net/quic/core/congestion_control/cubic_test.cc @@ -6,10 +6,10 @@ #include <cstdint> -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_str_cat.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; @@ -83,7 +83,7 @@ std::vector<TestParams> GetTestParams() { // TODO(jokulik): Once we've rolled out the cubic convex fix, we will // no longer need a parameterized test. -class CubicTest : public ::testing::TestWithParam<TestParams> { +class CubicTest : public QuicTestWithParam<TestParams> { protected: CubicTest() : one_ms_(QuicTime::Delta::FromMilliseconds(1)), diff --git a/chromium/net/quic/core/congestion_control/general_loss_algorithm.cc b/chromium/net/quic/core/congestion_control/general_loss_algorithm.cc index 722134c003a..f71f0ed542e 100644 --- a/chromium/net/quic/core/congestion_control/general_loss_algorithm.cc +++ b/chromium/net/quic/core/congestion_control/general_loss_algorithm.cc @@ -5,9 +5,10 @@ #include "net/quic/core/congestion_control/general_loss_algorithm.h" #include "net/quic/core/congestion_control/rtt_stats.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" namespace net { @@ -134,10 +135,6 @@ void GeneralLossAlgorithm::SpuriousRetransmitDetected( if (loss_type_ != kAdaptiveTime || reordering_shift_ == 0) { return; } - if (spurious_retransmission <= largest_sent_on_spurious_retransmit_) { - return; - } - largest_sent_on_spurious_retransmit_ = unacked_packets.largest_sent_packet(); // Calculate the extra time needed so this wouldn't have been declared lost. // Extra time needed is based on how long it's been since the spurious // retransmission was sent, because the SRTT and latest RTT may have changed. @@ -147,6 +144,19 @@ void GeneralLossAlgorithm::SpuriousRetransmitDetected( // Increase the reordering fraction until enough time would be allowed. QuicTime::Delta max_rtt = std::max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt()); + if (FLAGS_quic_reloadable_flag_quic_fix_adaptive_time_loss) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_fix_adaptive_time_loss); + while ((max_rtt >> reordering_shift_) <= extra_time_needed && + reordering_shift_ > 0) { + --reordering_shift_; + } + return; + } + + if (spurious_retransmission <= largest_sent_on_spurious_retransmit_) { + return; + } + largest_sent_on_spurious_retransmit_ = unacked_packets.largest_sent_packet(); QuicTime::Delta proposed_extra_time(QuicTime::Delta::Zero()); do { proposed_extra_time = max_rtt >> reordering_shift_; diff --git a/chromium/net/quic/core/congestion_control/general_loss_algorithm.h b/chromium/net/quic/core/congestion_control/general_loss_algorithm.h index d2557e56779..281a13950b7 100644 --- a/chromium/net/quic/core/congestion_control/general_loss_algorithm.h +++ b/chromium/net/quic/core/congestion_control/general_loss_algorithm.h @@ -59,6 +59,8 @@ class QUIC_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface { QuicTime loss_detection_timeout_; // Largest sent packet when a spurious retransmit is detected. // Prevents increasing the reordering threshold multiple times per epoch. + // TODO(ianswett): Deprecate when + // quic_reloadable_flag_quic_fix_adaptive_time_loss is deprecated. QuicPacketNumber largest_sent_on_spurious_retransmit_; LossDetectionType loss_type_; // Fraction of a max(SRTT, latest_rtt) to permit reordering before declaring diff --git a/chromium/net/quic/core/congestion_control/general_loss_algorithm_test.cc b/chromium/net/quic/core/congestion_control/general_loss_algorithm_test.cc index 6fa96d7b827..87168602b9c 100644 --- a/chromium/net/quic/core/congestion_control/general_loss_algorithm_test.cc +++ b/chromium/net/quic/core/congestion_control/general_loss_algorithm_test.cc @@ -9,11 +9,11 @@ #include "base/stl_util.h" #include "net/quic/core/congestion_control/rtt_stats.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_unacked_packet_map.h" +#include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { namespace test { @@ -22,7 +22,7 @@ namespace { // Default packet length. const uint32_t kDefaultLength = 1000; -class GeneralLossAlgorithmTest : public ::testing::Test { +class GeneralLossAlgorithmTest : public QuicTest { protected: GeneralLossAlgorithmTest() { rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(100), @@ -50,21 +50,19 @@ class GeneralLossAlgorithmTest : public ::testing::Test { } void VerifyLosses(QuicPacketNumber largest_newly_acked, - QuicPacketNumber* losses_expected, - size_t num_losses) { + const std::vector<QuicPacketNumber>& losses_expected) { if (largest_newly_acked > unacked_packets_.largest_observed()) { unacked_packets_.IncreaseLargestObserved(largest_newly_acked); } SendAlgorithmInterface::CongestionVector lost_packets; loss_algorithm_.DetectLosses(unacked_packets_, clock_.Now(), rtt_stats_, largest_newly_acked, &lost_packets); - EXPECT_EQ(num_losses, lost_packets.size()); - for (size_t i = 0; i < num_losses; ++i) { + ASSERT_EQ(losses_expected.size(), lost_packets.size()); + for (size_t i = 0; i < losses_expected.size(); ++i) { EXPECT_EQ(lost_packets[i].first, losses_expected[i]); } } - QuicFlagSaver flags_; // Save/restore all QUIC flag values. QuicUnackedPacketMap unacked_packets_; GeneralLossAlgorithm loss_algorithm_; RttStats rtt_stats_; @@ -79,14 +77,13 @@ TEST_F(GeneralLossAlgorithmTest, NackRetransmit1Packet) { } // No loss on one ack. unacked_packets_.RemoveFromInFlight(2); - VerifyLosses(2, nullptr, 0); + VerifyLosses(2, std::vector<QuicPacketNumber>{}); // No loss on two acks. unacked_packets_.RemoveFromInFlight(3); - VerifyLosses(3, nullptr, 0); + VerifyLosses(3, std::vector<QuicPacketNumber>{}); // Loss on three acks. unacked_packets_.RemoveFromInFlight(4); - QuicPacketNumber lost[] = {1}; - VerifyLosses(4, lost, arraysize(lost)); + VerifyLosses(4, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -103,8 +100,7 @@ TEST_F(GeneralLossAlgorithmTest, NackRetransmit1PacketWith1StretchAck) { unacked_packets_.RemoveFromInFlight(2); unacked_packets_.RemoveFromInFlight(3); unacked_packets_.RemoveFromInFlight(4); - QuicPacketNumber lost[] = {1}; - VerifyLosses(4, lost, arraysize(lost)); + VerifyLosses(4, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -118,8 +114,7 @@ TEST_F(GeneralLossAlgorithmTest, NackRetransmit1PacketSingleAck) { // Nack the first packet 3 times in an AckFrame with three missing packets. unacked_packets_.RemoveFromInFlight(4); - QuicPacketNumber lost[] = {1}; - VerifyLosses(4, lost, arraysize(lost)); + VerifyLosses(4, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -131,13 +126,12 @@ TEST_F(GeneralLossAlgorithmTest, EarlyRetransmit1Packet) { } // Early retransmit when the final packet gets acked and the first is nacked. unacked_packets_.RemoveFromInFlight(2); - VerifyLosses(2, nullptr, 0); + VerifyLosses(2, std::vector<QuicPacketNumber>{}); EXPECT_EQ(clock_.Now() + 1.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout()); clock_.AdvanceTime(1.25 * rtt_stats_.latest_rtt()); - QuicPacketNumber lost[] = {1}; - VerifyLosses(2, lost, arraysize(lost)); + VerifyLosses(2, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -155,21 +149,18 @@ TEST_F(GeneralLossAlgorithmTest, EarlyRetransmitAllPackets) { // elapsed since the packets were sent. unacked_packets_.RemoveFromInFlight(kNumSentPackets); // This simulates a single ack following multiple missing packets with FACK. - QuicPacketNumber lost[] = {1, 2}; - VerifyLosses(kNumSentPackets, lost, arraysize(lost)); + VerifyLosses(kNumSentPackets, {1, 2}); // The time has already advanced 1/4 an RTT, so ensure the timeout is set // 1.25 RTTs after the earliest pending packet(3), not the last(4). EXPECT_EQ(clock_.Now() + rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout()); clock_.AdvanceTime(rtt_stats_.smoothed_rtt()); - QuicPacketNumber lost2[] = {1, 2, 3}; - VerifyLosses(kNumSentPackets, lost2, arraysize(lost2)); + VerifyLosses(kNumSentPackets, {1, 2, 3}); EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout()); clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); - QuicPacketNumber lost3[] = {1, 2, 3, 4}; - VerifyLosses(kNumSentPackets, lost3, arraysize(lost3)); + VerifyLosses(kNumSentPackets, {1, 2, 3, 4}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -185,7 +176,7 @@ TEST_F(GeneralLossAlgorithmTest, DontEarlyRetransmitNeuteredPacket) { // Early retransmit when the final packet gets acked and the first is nacked. unacked_packets_.IncreaseLargestObserved(2); unacked_packets_.RemoveFromInFlight(2); - VerifyLosses(2, nullptr, 0); + VerifyLosses(2, std::vector<QuicPacketNumber>{}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -199,14 +190,13 @@ TEST_F(GeneralLossAlgorithmTest, EarlyRetransmitWithLargerUnackablePackets) { // Early retransmit when the final packet gets acked and the first is nacked. unacked_packets_.IncreaseLargestObserved(2); unacked_packets_.RemoveFromInFlight(2); - VerifyLosses(2, nullptr, 0); + VerifyLosses(2, std::vector<QuicPacketNumber>{}); EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout()); // The packet should be lost once the loss timeout is reached. clock_.AdvanceTime(0.25 * rtt_stats_.latest_rtt()); - QuicPacketNumber lost[] = {1}; - VerifyLosses(2, lost, arraysize(lost)); + VerifyLosses(2, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -224,8 +214,7 @@ TEST_F(GeneralLossAlgorithmTest, AlwaysLosePacketSent1RTTEarlier) { clock_.AdvanceTime(rtt_stats_.smoothed_rtt()); unacked_packets_.IncreaseLargestObserved(2); unacked_packets_.RemoveFromInFlight(2); - QuicPacketNumber lost[] = {1}; - VerifyLosses(2, lost, arraysize(lost)); + VerifyLosses(2, {1}); } // NoFack loss detection tests. @@ -238,14 +227,13 @@ TEST_F(GeneralLossAlgorithmTest, LazyFackNackRetransmit1Packet) { } // No loss on one ack. unacked_packets_.RemoveFromInFlight(2); - VerifyLosses(2, nullptr, 0); + VerifyLosses(2, std::vector<QuicPacketNumber>{}); // No loss on two acks. unacked_packets_.RemoveFromInFlight(3); - VerifyLosses(3, nullptr, 0); + VerifyLosses(3, std::vector<QuicPacketNumber>{}); // Loss on three acks. unacked_packets_.RemoveFromInFlight(4); - QuicPacketNumber lost[] = {1}; - VerifyLosses(4, lost, arraysize(lost)); + VerifyLosses(4, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -264,13 +252,12 @@ TEST_F(GeneralLossAlgorithmTest, unacked_packets_.RemoveFromInFlight(2); unacked_packets_.RemoveFromInFlight(3); unacked_packets_.RemoveFromInFlight(4); - VerifyLosses(4, nullptr, 0); + VerifyLosses(4, std::vector<QuicPacketNumber>{}); // The timer isn't set because we expect more acks. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // Process another ack and then packet 1 will be lost. unacked_packets_.RemoveFromInFlight(5); - QuicPacketNumber lost[] = {1}; - VerifyLosses(5, lost, arraysize(lost)); + VerifyLosses(5, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -285,13 +272,12 @@ TEST_F(GeneralLossAlgorithmTest, LazyFackNackRetransmit1PacketSingleAck) { // Nack the first packet 3 times in an AckFrame with three missing packets. unacked_packets_.RemoveFromInFlight(4); - VerifyLosses(4, nullptr, 0); + VerifyLosses(4, std::vector<QuicPacketNumber>{}); // The timer isn't set because we expect more acks. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // Process another ack and then packet 1 and 2 will be lost. unacked_packets_.RemoveFromInFlight(5); - QuicPacketNumber lost[] = {1, 2}; - VerifyLosses(5, lost, arraysize(lost)); + VerifyLosses(5, {1, 2}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -305,7 +291,7 @@ TEST_F(GeneralLossAlgorithmTest, NoLossFor500Nacks) { } unacked_packets_.RemoveFromInFlight(2); for (size_t i = 1; i < 500; ++i) { - VerifyLosses(2, nullptr, 0); + VerifyLosses(2, std::vector<QuicPacketNumber>{}); } EXPECT_EQ(1.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout() - clock_.Now()); @@ -323,14 +309,13 @@ TEST_F(GeneralLossAlgorithmTest, NoLossUntilTimeout) { EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // The packet should not be lost until 1.25 RTTs pass. unacked_packets_.RemoveFromInFlight(2); - VerifyLosses(2, nullptr, 0); + VerifyLosses(2, std::vector<QuicPacketNumber>{}); // Expect the timer to be set to 0.25 RTT's in the future. EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout() - clock_.Now()); - VerifyLosses(2, nullptr, 0); + VerifyLosses(2, std::vector<QuicPacketNumber>{}); clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); - QuicPacketNumber lost[] = {1}; - VerifyLosses(2, lost, arraysize(lost)); + VerifyLosses(2, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -346,13 +331,13 @@ TEST_F(GeneralLossAlgorithmTest, NoLossWithoutNack) { EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // The packet should not be lost without a nack. unacked_packets_.RemoveFromInFlight(1); - VerifyLosses(1, nullptr, 0); + VerifyLosses(1, std::vector<QuicPacketNumber>{}); // The timer should still not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); - VerifyLosses(1, nullptr, 0); + VerifyLosses(1, std::vector<QuicPacketNumber>{}); clock_.AdvanceTime(rtt_stats_.smoothed_rtt()); - VerifyLosses(1, nullptr, 0); + VerifyLosses(1, std::vector<QuicPacketNumber>{}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -369,13 +354,12 @@ TEST_F(GeneralLossAlgorithmTest, MultipleLossesAtOnce) { EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // The packet should not be lost until 1.25 RTTs pass. unacked_packets_.RemoveFromInFlight(10); - VerifyLosses(10, nullptr, 0); + VerifyLosses(10, std::vector<QuicPacketNumber>{}); // Expect the timer to be set to 0.25 RTT's in the future. EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout() - clock_.Now()); clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); - QuicPacketNumber lost[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; - VerifyLosses(10, lost, arraysize(lost)); + VerifyLosses(10, {1, 2, 3, 4, 5, 6, 7, 8, 9}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -392,7 +376,7 @@ TEST_F(GeneralLossAlgorithmTest, NoSpuriousLossesFromLargeReordering) { // The packet should not be lost until 1.25 RTTs pass. unacked_packets_.RemoveFromInFlight(10); - VerifyLosses(10, nullptr, 0); + VerifyLosses(10, std::vector<QuicPacketNumber>{}); // Expect the timer to be set to 0.25 RTT's in the future. EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout() - clock_.Now()); @@ -401,7 +385,7 @@ TEST_F(GeneralLossAlgorithmTest, NoSpuriousLossesFromLargeReordering) { // are lost. for (QuicPacketNumber i = 1; i <= 9; ++i) { unacked_packets_.RemoveFromInFlight(i); - VerifyLosses(i, nullptr, 0); + VerifyLosses(i, std::vector<QuicPacketNumber>{}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } } @@ -421,14 +405,13 @@ TEST_F(GeneralLossAlgorithmTest, IncreaseThresholdUponSpuriousLoss) { EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // Packet 1 should not be lost until 1/16 RTTs pass. unacked_packets_.RemoveFromInFlight(2); - VerifyLosses(2, nullptr, 0); + VerifyLosses(2, std::vector<QuicPacketNumber>{}); // Expect the timer to be set to 1/16 RTT's in the future. EXPECT_EQ(rtt_stats_.smoothed_rtt() * (1.0f / 16), loss_algorithm_.GetLossTimeout() - clock_.Now()); - VerifyLosses(2, nullptr, 0); + VerifyLosses(2, std::vector<QuicPacketNumber>{}); clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 16)); - QuicPacketNumber lost[] = {1}; - VerifyLosses(2, lost, arraysize(lost)); + VerifyLosses(2, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // Retransmit packet 1 as 11 and 2 as 12. SendDataPacket(11); @@ -437,6 +420,11 @@ TEST_F(GeneralLossAlgorithmTest, IncreaseThresholdUponSpuriousLoss) { // Advance the time 1/4 RTT and indicate the loss was spurious. // The new threshold should be 1/2 RTT. clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 4)); + if (FLAGS_quic_reloadable_flag_quic_fix_adaptive_time_loss) { + // The flag fixes an issue where adaptive time loss would increase the + // reordering threshold by an extra factor of two. + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); + } loss_algorithm_.SpuriousRetransmitDetected(unacked_packets_, clock_.Now(), rtt_stats_, 11); EXPECT_EQ(1, loss_algorithm_.reordering_shift()); diff --git a/chromium/net/quic/core/congestion_control/hybrid_slow_start_test.cc b/chromium/net/quic/core/congestion_control/hybrid_slow_start_test.cc index 24310569849..3ed84958a83 100644 --- a/chromium/net/quic/core/congestion_control/hybrid_slow_start_test.cc +++ b/chromium/net/quic/core/congestion_control/hybrid_slow_start_test.cc @@ -6,12 +6,12 @@ #include <memory> -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { -class HybridSlowStartTest : public ::testing::Test { +class HybridSlowStartTest : public QuicTest { protected: HybridSlowStartTest() : one_ms_(QuicTime::Delta::FromMilliseconds(1)), diff --git a/chromium/net/quic/core/congestion_control/pacing_sender.cc b/chromium/net/quic/core/congestion_control/pacing_sender.cc index 976c408134c..c645b8a8b41 100644 --- a/chromium/net/quic/core/congestion_control/pacing_sender.cc +++ b/chromium/net/quic/core/congestion_control/pacing_sender.cc @@ -109,9 +109,8 @@ bool PacingSender::OnPacketSent( return in_flight; } -QuicTime::Delta PacingSender::TimeUntilSend( - QuicTime now, - QuicByteCount bytes_in_flight) const { +QuicTime::Delta PacingSender::TimeUntilSend(QuicTime now, + QuicByteCount bytes_in_flight) { DCHECK(sender_ != nullptr); QuicTime::Delta time_until_send = sender_->TimeUntilSend(now, bytes_in_flight); diff --git a/chromium/net/quic/core/congestion_control/pacing_sender.h b/chromium/net/quic/core/congestion_control/pacing_sender.h index b297b8f8050..65047210b91 100644 --- a/chromium/net/quic/core/congestion_control/pacing_sender.h +++ b/chromium/net/quic/core/congestion_control/pacing_sender.h @@ -45,13 +45,15 @@ class QUIC_EXPORT_PRIVATE PacingSender { QuicTime event_time, const SendAlgorithmInterface::CongestionVector& acked_packets, const SendAlgorithmInterface::CongestionVector& lost_packets); + bool OnPacketSent(QuicTime sent_time, QuicByteCount bytes_in_flight, QuicPacketNumber packet_number, QuicByteCount bytes, HasRetransmittableData is_retransmittable); - QuicTime::Delta TimeUntilSend(QuicTime now, - QuicByteCount bytes_in_flight) const; + + QuicTime::Delta TimeUntilSend(QuicTime now, QuicByteCount bytes_in_flight); + QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const; private: @@ -65,7 +67,7 @@ class QUIC_EXPORT_PRIVATE PacingSender { // Send time of the last packet considered delayed. QuicTime last_delayed_packet_sent_time_; QuicTime ideal_next_packet_send_time_; // When can the next packet be sent. - mutable bool was_last_send_delayed_; // True when the last send was delayed. + bool was_last_send_delayed_; // True when the last send was delayed. DISALLOW_COPY_AND_ASSIGN(PacingSender); }; diff --git a/chromium/net/quic/core/congestion_control/pacing_sender_test.cc b/chromium/net/quic/core/congestion_control/pacing_sender_test.cc index 7fc3019d0fd..174d93da223 100644 --- a/chromium/net/quic/core/congestion_control/pacing_sender_test.cc +++ b/chromium/net/quic/core/congestion_control/pacing_sender_test.cc @@ -8,6 +8,7 @@ #include "net/quic/core/quic_packets.h" #include "net/quic/platform/api/quic_logging.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/quic_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" @@ -22,7 +23,7 @@ namespace test { const QuicByteCount kBytesInFlight = 1024; const int kInitialBurstPackets = 10; -class PacingSenderTest : public ::testing::Test { +class PacingSenderTest : public QuicTest { protected: PacingSenderTest() : zero_time_(QuicTime::Delta::Zero()), diff --git a/chromium/net/quic/core/congestion_control/prr_sender_test.cc b/chromium/net/quic/core/congestion_control/prr_sender_test.cc index aa54700add5..94e78738347 100644 --- a/chromium/net/quic/core/congestion_control/prr_sender_test.cc +++ b/chromium/net/quic/core/congestion_control/prr_sender_test.cc @@ -8,7 +8,7 @@ #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/quic_constants.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { @@ -18,7 +18,7 @@ namespace { const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS; } // namespace -class PrrSenderTest : public ::testing::Test {}; +class PrrSenderTest : public QuicTest {}; TEST_F(PrrSenderTest, SingleLossResultsInSendOnEveryOtherAck) { PrrSender prr; diff --git a/chromium/net/quic/core/congestion_control/rtt_stats_test.cc b/chromium/net/quic/core/congestion_control/rtt_stats_test.cc index b249a2b927a..905b714d83c 100644 --- a/chromium/net/quic/core/congestion_control/rtt_stats_test.cc +++ b/chromium/net/quic/core/congestion_control/rtt_stats_test.cc @@ -7,8 +7,8 @@ #include <cmath> #include "base/test/mock_log.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/rtt_stats_peer.h" -#include "testing/gtest/include/gtest/gtest.h" using logging::LOG_WARNING; using testing::HasSubstr; @@ -18,7 +18,7 @@ using testing::_; namespace net { namespace test { -class RttStatsTest : public ::testing::Test { +class RttStatsTest : public QuicTest { protected: RttStats rtt_stats_; }; diff --git a/chromium/net/quic/core/congestion_control/send_algorithm_interface.cc b/chromium/net/quic/core/congestion_control/send_algorithm_interface.cc index f754366944d..385d46eda13 100644 --- a/chromium/net/quic/core/congestion_control/send_algorithm_interface.cc +++ b/chromium/net/quic/core/congestion_control/send_algorithm_interface.cc @@ -7,9 +7,11 @@ #include "net/quic/core/congestion_control/bbr_sender.h" #include "net/quic/core/congestion_control/tcp_cubic_sender_bytes.h" #include "net/quic/core/congestion_control/tcp_cubic_sender_packets.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_pcc_sender.h" namespace net { @@ -32,8 +34,17 @@ SendAlgorithmInterface* SendAlgorithmInterface::Create( initial_congestion_window, max_congestion_window, random); } - // Fall back to CUBIC if BBR is disabled. + // FALLTHROUGH_INTENDED + case kPCC: + if (FLAGS_quic_reloadable_flag_quic_enable_pcc) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_pcc); + return CreatePccSender(clock, rtt_stats, unacked_packets, random, stats, + initial_congestion_window, + max_congestion_window); + } + // Fall back to CUBIC if PCC is disabled. + // FALLTHROUGH_INTENDED case kCubic: return new TcpCubicSenderPackets( clock, rtt_stats, false /* don't use Reno */, diff --git a/chromium/net/quic/core/congestion_control/send_algorithm_interface.h b/chromium/net/quic/core/congestion_control/send_algorithm_interface.h index dacccba33a7..5abb3e94761 100644 --- a/chromium/net/quic/core/congestion_control/send_algorithm_interface.h +++ b/chromium/net/quic/core/congestion_control/send_algorithm_interface.h @@ -82,9 +82,8 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface { virtual void OnConnectionMigration() = 0; // Calculate the time until we can send the next packet. - virtual QuicTime::Delta TimeUntilSend( - QuicTime now, - QuicByteCount bytes_in_flight) const = 0; + virtual QuicTime::Delta TimeUntilSend(QuicTime now, + QuicByteCount bytes_in_flight) = 0; // The pacing rate of the send algorithm. May be zero if the rate is unknown. virtual QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const = 0; diff --git a/chromium/net/quic/core/congestion_control/send_algorithm_test.cc b/chromium/net/quic/core/congestion_control/send_algorithm_test.cc index 4078944d4d3..c2d6632028c 100644 --- a/chromium/net/quic/core/congestion_control/send_algorithm_test.cc +++ b/chromium/net/quic/core/congestion_control/send_algorithm_test.cc @@ -12,6 +12,7 @@ #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_str_cat.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/quic_config_peer.h" #include "net/quic/test_tools/quic_connection_peer.h" @@ -20,7 +21,6 @@ #include "net/quic/test_tools/simulator/quic_endpoint.h" #include "net/quic/test_tools/simulator/simulator.h" #include "net/quic/test_tools/simulator/switch.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; @@ -114,6 +114,8 @@ const char* CongestionControlTypeToString(CongestionControlType cc_type) { return "RENO_BYTES"; case kBBR: return "BBR"; + case kPCC: + return "PCC"; default: QUIC_DLOG(FATAL) << "Unexpected CongestionControlType"; return nullptr; @@ -163,7 +165,7 @@ string TestParamToString(const testing::TestParamInfo<TestParams>& params) { std::vector<TestParams> GetTestParams() { std::vector<TestParams> params; for (const CongestionControlType congestion_control_type : - {kBBR, kCubic, kCubicBytes, kReno, kRenoBytes}) { + {kBBR, kCubic, kCubicBytes, kReno, kRenoBytes, kPCC}) { if (congestion_control_type != kCubic && congestion_control_type != kCubicBytes) { params.push_back( @@ -204,7 +206,7 @@ std::vector<TestParams> GetTestParams() { } // namespace -class SendAlgorithmTest : public ::testing::TestWithParam<TestParams> { +class SendAlgorithmTest : public QuicTestWithParam<TestParams> { protected: SendAlgorithmTest() : simulator_(), @@ -217,7 +219,7 @@ class SendAlgorithmTest : public ::testing::TestWithParam<TestParams> { "Receiver", "QUIC sender", Perspective::IS_SERVER, - 42) { + net::test::GetPeerInMemoryConnectionId(42)) { rtt_stats_ = quic_sender_.connection()->sent_packet_manager().GetRttStats(); sender_ = SendAlgorithmInterface::Create( simulator_.GetClock(), rtt_stats_, @@ -230,7 +232,13 @@ class SendAlgorithmTest : public ::testing::TestWithParam<TestParams> { SetExperimentalOptionsInServerConfig(); QuicConnectionPeer::SetSendAlgorithm(quic_sender_.connection(), sender_); - + // TODO(jokulik): Remove once b/38032710 is fixed. + // Disable pacing for PCC. + if (sender_->GetCongestionControlType() == kPCC) { + QuicSentPacketManagerPeer::SetUsingPacing( + QuicConnectionPeer::GetSentPacketManager(quic_sender_.connection()), + false); + } clock_ = simulator_.GetClock(); simulator_.set_random_generator(&random_); diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.cc index 151cc3ec6a3..d56fbf8394c 100644 --- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.cc +++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.cc @@ -188,7 +188,7 @@ bool TcpCubicSenderBase::OnPacketSent( QuicTime::Delta TcpCubicSenderBase::TimeUntilSend( QuicTime /* now */, - QuicByteCount bytes_in_flight) const { + QuicByteCount bytes_in_flight) { if (!no_prr_ && InRecovery()) { // PRR is used when in recovery. return prr_.TimeUntilSend(GetCongestionWindow(), bytes_in_flight, diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.h b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.h index a4ac1e57128..2488bf2536c 100644 --- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.h +++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_base.h @@ -62,7 +62,7 @@ class QUIC_EXPORT_PRIVATE TcpCubicSenderBase : public SendAlgorithmInterface { void OnRetransmissionTimeout(bool packets_retransmitted) override; void OnConnectionMigration() override; QuicTime::Delta TimeUntilSend(QuicTime now, - QuicByteCount bytes_in_flight) const override; + QuicByteCount bytes_in_flight) override; QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const override; QuicBandwidth BandwidthEstimate() const override; bool InSlowStart() const override; diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc index 0dbbb8dd76e..f22bdd02088 100644 --- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc +++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc @@ -10,8 +10,8 @@ #include "net/quic/core/congestion_control/prr_sender.h" #include "net/quic/core/congestion_control/rtt_stats.h" #include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net { diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc index 7c265e17324..b35cb2b7dbb 100644 --- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc +++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc @@ -15,9 +15,9 @@ #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_logging.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/quic_config_peer.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { namespace test { @@ -51,7 +51,7 @@ class TcpCubicSenderBytesPeer : public TcpCubicSenderBytes { QuicConnectionStats stats_; }; -class TcpCubicSenderBytesTest : public ::testing::Test { +class TcpCubicSenderBytesTest : public QuicTest { protected: TcpCubicSenderBytesTest() : one_ms_(QuicTime::Delta::FromMilliseconds(1)), diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc index 94154d864a8..74ebb2fc285 100644 --- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc +++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc @@ -9,8 +9,8 @@ #include "net/quic/core/congestion_control/prr_sender.h" #include "net/quic/core/congestion_control/rtt_stats.h" #include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net { diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc index 2b4cfa6577b..66afc3fd4ed 100644 --- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc +++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc @@ -14,9 +14,9 @@ #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_logging.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/quic_config_peer.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { namespace test { @@ -58,7 +58,7 @@ class TcpCubicSenderPacketsPeer : public TcpCubicSenderPackets { QuicConnectionStats stats_; }; -class TcpCubicSenderPacketsTest : public ::testing::Test { +class TcpCubicSenderPacketsTest : public QuicTest { protected: TcpCubicSenderPacketsTest() : one_ms_(QuicTime::Delta::FromMilliseconds(1)), diff --git a/chromium/net/quic/core/congestion_control/windowed_filter_test.cc b/chromium/net/quic/core/congestion_control/windowed_filter_test.cc index 38c0658a1bc..0f27441cb53 100644 --- a/chromium/net/quic/core/congestion_control/windowed_filter_test.cc +++ b/chromium/net/quic/core/congestion_control/windowed_filter_test.cc @@ -7,12 +7,12 @@ #include "net/quic/core/congestion_control/rtt_stats.h" #include "net/quic/core/quic_bandwidth.h" #include "net/quic/core/quic_packets.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { -class WindowedFilterTest : public ::testing::Test { +class WindowedFilterTest : public QuicTest { public: // Set the window to 99ms, so 25ms is more than a quarter rtt. WindowedFilterTest() diff --git a/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc b/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc index 2a14d177f02..3f439767bc5 100644 --- a/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc +++ b/chromium/net/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc @@ -7,6 +7,7 @@ #include <memory> #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/quic/test_tools/quic_test_utils.h" @@ -219,7 +220,9 @@ QuicData* DecryptWithNonce(Aes128Gcm12Decrypter* decrypter, return new QuicData(output.release(), output_length, true); } -TEST(Aes128Gcm12DecrypterTest, Decrypt) { +class Aes128Gcm12DecrypterTest : public QuicTest {}; + +TEST_F(Aes128Gcm12DecrypterTest, Decrypt) { for (size_t i = 0; i < arraysize(test_group_array); i++) { SCOPED_TRACE(i); const TestVector* test_vectors = test_group_array[i]; diff --git a/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc b/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc index 352c18c3cf6..bf98368484d 100644 --- a/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc +++ b/chromium/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc @@ -7,6 +7,7 @@ #include <memory> #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/quic/test_tools/quic_test_utils.h" @@ -171,7 +172,9 @@ QuicData* EncryptWithNonce(Aes128Gcm12Encrypter* encrypter, return new QuicData(ciphertext.release(), ciphertext_size, true); } -TEST(Aes128Gcm12EncrypterTest, Encrypt) { +class Aes128Gcm12EncrypterTest : public QuicTest {}; + +TEST_F(Aes128Gcm12EncrypterTest, Encrypt) { for (size_t i = 0; i < arraysize(test_group_array); i++) { SCOPED_TRACE(i); const TestVector* test_vectors = test_group_array[i]; @@ -220,14 +223,14 @@ TEST(Aes128Gcm12EncrypterTest, Encrypt) { } } -TEST(Aes128Gcm12EncrypterTest, GetMaxPlaintextSize) { +TEST_F(Aes128Gcm12EncrypterTest, GetMaxPlaintextSize) { Aes128Gcm12Encrypter encrypter; EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1012)); EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(112)); EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(22)); } -TEST(Aes128Gcm12EncrypterTest, GetCiphertextSize) { +TEST_F(Aes128Gcm12EncrypterTest, GetCiphertextSize) { Aes128Gcm12Encrypter encrypter; EXPECT_EQ(1012u, encrypter.GetCiphertextSize(1000)); EXPECT_EQ(112u, encrypter.GetCiphertextSize(100)); diff --git a/chromium/net/quic/core/crypto/cert_compressor_test.cc b/chromium/net/quic/core/crypto/cert_compressor_test.cc index af6f6174c60..a75cb590885 100644 --- a/chromium/net/quic/core/crypto/cert_compressor_test.cc +++ b/chromium/net/quic/core/crypto/cert_compressor_test.cc @@ -7,16 +7,18 @@ #include <memory> #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/quic/test_tools/crypto_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; namespace net { namespace test { -TEST(CertCompressor, EmptyChain) { +class CertCompressorTest : public QuicTest {}; + +TEST_F(CertCompressorTest, EmptyChain) { std::vector<string> chain; const string compressed = CertCompressor::CompressChain( chain, QuicStringPiece(), QuicStringPiece(), nullptr); @@ -28,7 +30,7 @@ TEST(CertCompressor, EmptyChain) { EXPECT_EQ(chain.size(), chain2.size()); } -TEST(CertCompressor, Compressed) { +TEST_F(CertCompressorTest, Compressed) { std::vector<string> chain; chain.push_back("testcert"); const string compressed = CertCompressor::CompressChain( @@ -43,7 +45,7 @@ TEST(CertCompressor, Compressed) { EXPECT_EQ(chain[0], chain2[0]); } -TEST(CertCompressor, Common) { +TEST_F(CertCompressorTest, Common) { std::vector<string> chain; chain.push_back("testcert"); static const uint64_t set_hash = 42; @@ -68,7 +70,7 @@ TEST(CertCompressor, Common) { EXPECT_EQ(chain[0], chain2[0]); } -TEST(CertCompressor, Cached) { +TEST_F(CertCompressorTest, Cached) { std::vector<string> chain; chain.push_back("testcert"); uint64_t hash = QuicUtils::FNV1a_64_Hash(chain[0]); @@ -88,7 +90,7 @@ TEST(CertCompressor, Cached) { EXPECT_EQ(chain[0], chain2[0]); } -TEST(CertCompressor, BadInputs) { +TEST_F(CertCompressorTest, BadInputs) { std::vector<string> cached_certs, chain; EXPECT_FALSE(CertCompressor::DecompressChain( diff --git a/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter_test.cc b/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter_test.cc index a24d5315187..c9307450890 100644 --- a/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter_test.cc +++ b/chromium/net/quic/core/crypto/chacha20_poly1305_decrypter_test.cc @@ -7,6 +7,7 @@ #include <memory> #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/quic/test_tools/quic_test_utils.h" @@ -133,7 +134,9 @@ QuicData* DecryptWithNonce(ChaCha20Poly1305Decrypter* decrypter, return new QuicData(output.release(), output_length, true); } -TEST(ChaCha20Poly1305DecrypterTest, Decrypt) { +class ChaCha20Poly1305DecrypterTest : public QuicTest {}; + +TEST_F(ChaCha20Poly1305DecrypterTest, Decrypt) { for (size_t i = 0; test_vectors[i].key != nullptr; i++) { // If not present then decryption is expected to fail. bool has_pt = test_vectors[i].pt; diff --git a/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter_test.cc b/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter_test.cc index f7c847a3bba..544ad0a6a22 100644 --- a/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter_test.cc +++ b/chromium/net/quic/core/crypto/chacha20_poly1305_encrypter_test.cc @@ -8,6 +8,7 @@ #include "net/quic/core/crypto/chacha20_poly1305_decrypter.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/quic/test_tools/quic_test_utils.h" @@ -83,7 +84,9 @@ QuicData* EncryptWithNonce(ChaCha20Poly1305Encrypter* encrypter, return new QuicData(ciphertext.release(), ciphertext_size, true); } -TEST(ChaCha20Poly1305EncrypterTest, EncryptThenDecrypt) { +class ChaCha20Poly1305EncrypterTest : public QuicTest {}; + +TEST_F(ChaCha20Poly1305EncrypterTest, EncryptThenDecrypt) { ChaCha20Poly1305Encrypter encrypter; ChaCha20Poly1305Decrypter decrypter; @@ -108,7 +111,7 @@ TEST(ChaCha20Poly1305EncrypterTest, EncryptThenDecrypt) { &len, arraysize(decrypted))); } -TEST(ChaCha20Poly1305EncrypterTest, Encrypt) { +TEST_F(ChaCha20Poly1305EncrypterTest, Encrypt) { for (size_t i = 0; test_vectors[i].key != nullptr; i++) { // Decode the test vector. string key = QuicTextUtils::HexDecode(test_vectors[i].key); @@ -136,14 +139,14 @@ TEST(ChaCha20Poly1305EncrypterTest, Encrypt) { } } -TEST(ChaCha20Poly1305EncrypterTest, GetMaxPlaintextSize) { +TEST_F(ChaCha20Poly1305EncrypterTest, GetMaxPlaintextSize) { ChaCha20Poly1305Encrypter encrypter; EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1012)); EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(112)); EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(22)); } -TEST(ChaCha20Poly1305EncrypterTest, GetCiphertextSize) { +TEST_F(ChaCha20Poly1305EncrypterTest, GetCiphertextSize) { ChaCha20Poly1305Encrypter encrypter; EXPECT_EQ(1012u, encrypter.GetCiphertextSize(1000)); EXPECT_EQ(112u, encrypter.GetCiphertextSize(100)); diff --git a/chromium/net/quic/core/crypto/channel_id_test.cc b/chromium/net/quic/core/crypto/channel_id_test.cc index 6fac40f0490..08875eb9544 100644 --- a/chromium/net/quic/core/crypto/channel_id_test.cc +++ b/chromium/net/quic/core/crypto/channel_id_test.cc @@ -6,8 +6,8 @@ #include <memory> +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/crypto_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; @@ -243,8 +243,10 @@ bool DecodeHexString(const char* in, } // namespace +class ChannelIDTest : public QuicTest {}; + // A known answer test for ChannelIDVerifier. -TEST(ChannelIDTest, VerifyKnownAnswerTest) { +TEST_F(ChannelIDTest, VerifyKnownAnswerTest) { char msg[1024]; size_t msg_len; char key[64]; @@ -281,7 +283,7 @@ TEST(ChannelIDTest, VerifyKnownAnswerTest) { } } -TEST(ChannelIDTest, SignAndVerify) { +TEST_F(ChannelIDTest, SignAndVerify) { std::unique_ptr<ChannelIDSource> source( crypto_test_utils::ChannelIDSourceForTesting()); diff --git a/chromium/net/quic/core/crypto/common_cert_set_test.cc b/chromium/net/quic/core/crypto/common_cert_set_test.cc index 85bc74b2341..316657d5029 100644 --- a/chromium/net/quic/core/crypto/common_cert_set_test.cc +++ b/chromium/net/quic/core/crypto/common_cert_set_test.cc @@ -6,7 +6,7 @@ #include <cstdint> -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { @@ -189,7 +189,9 @@ static const unsigned char kGIACertificate3[] = { 0xc1, 0x21, 0xc6, 0x16, }; -TEST(CommonCertSets, FindGIA_2) { +class CommonCertSetsTest : public QuicTest {}; + +TEST_F(CommonCertSetsTest, FindGIA_2) { QuicStringPiece gia(reinterpret_cast<const char*>(kGIACertificate2), sizeof(kGIACertificate2)); @@ -210,7 +212,7 @@ TEST(CommonCertSets, FindGIA_2) { EXPECT_EQ(0, memcmp(gia.data(), gia_copy.data(), gia.size())); } -TEST(CommonCertSets, FindGIA_3) { +TEST_F(CommonCertSetsTest, FindGIA_3) { QuicStringPiece gia(reinterpret_cast<const char*>(kGIACertificate3), sizeof(kGIACertificate3)); @@ -231,7 +233,7 @@ TEST(CommonCertSets, FindGIA_3) { EXPECT_EQ(0, memcmp(gia.data(), gia_copy.data(), gia.size())); } -TEST(CommonCertSets, NonMatch) { +TEST_F(CommonCertSetsTest, NonMatch) { const CommonCertSets* sets(CommonCertSets::GetInstanceQUIC()); QuicStringPiece not_a_cert("hello"); const uint64_t in_hash = UINT64_C(0xc9fef74053f99f39); diff --git a/chromium/net/quic/core/crypto/crypto_framer.cc b/chromium/net/quic/core/crypto/crypto_framer.cc index b978bf0b931..77d1bfa46bf 100644 --- a/chromium/net/quic/core/crypto/crypto_framer.cc +++ b/chromium/net/quic/core/crypto/crypto_framer.cc @@ -108,7 +108,7 @@ QuicData* CryptoFramer::ConstructHandshakeMessage( } std::unique_ptr<char[]> buffer(new char[len]); - QuicDataWriter writer(len, buffer.get(), perspective); + QuicDataWriter writer(len, buffer.get(), perspective, HOST_BYTE_ORDER); if (!writer.WriteTag(message.tag())) { DCHECK(false) << "Failed to write message tag."; return nullptr; @@ -197,7 +197,8 @@ QuicErrorCode CryptoFramer::Process(QuicStringPiece input, Perspective perspective) { // Add this data to the buffer. buffer_.append(input.data(), input.length()); - QuicDataReader reader(buffer_.data(), buffer_.length(), perspective); + QuicDataReader reader(buffer_.data(), buffer_.length(), perspective, + HOST_BYTE_ORDER); switch (state_) { case STATE_READING_TAG: diff --git a/chromium/net/quic/core/crypto/crypto_framer_test.cc b/chromium/net/quic/core/crypto/crypto_framer_test.cc index e8f37e946a1..846f91f4be1 100644 --- a/chromium/net/quic/core/crypto/crypto_framer_test.cc +++ b/chromium/net/quic/core/crypto/crypto_framer_test.cc @@ -12,6 +12,7 @@ #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/quic_packets.h" #include "net/quic/platform/api/quic_logging.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/quic_test_utils.h" @@ -25,7 +26,7 @@ char* AsChars(unsigned char* data) { return reinterpret_cast<char*>(data); } -class CryptoFramerTest : public ::testing::TestWithParam<Perspective> {}; +class CryptoFramerTest : public QuicTestWithParam<Perspective> {}; class TestCryptoVisitor : public CryptoFramerVisitorInterface { public: diff --git a/chromium/net/quic/core/crypto/crypto_handshake_message.cc b/chromium/net/quic/core/crypto/crypto_handshake_message.cc index 4e03d4ef7f1..220c46adfc0 100644 --- a/chromium/net/quic/core/crypto/crypto_handshake_message.cc +++ b/chromium/net/quic/core/crypto/crypto_handshake_message.cc @@ -11,6 +11,7 @@ #include "net/quic/core/crypto/crypto_utils.h" #include "net/quic/core/quic_socket_address_coder.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_endian.h" #include "net/quic/platform/api/quic_map_util.h" #include "net/quic/platform/api/quic_str_cat.h" #include "net/quic/platform/api/quic_text_utils.h" @@ -246,6 +247,9 @@ string CryptoHandshakeMessage::DebugStringInternal( if (it->second.size() == 8) { uint64_t value; memcpy(&value, it->second.data(), sizeof(value)); + if (QuicUtils::IsConnectionIdWireFormatBigEndian(perspective)) { + value = QuicEndian::NetToHost64(value); + } ret += QuicTextUtils::Uint64ToString(value); done = true; } diff --git a/chromium/net/quic/core/crypto/crypto_handshake_message_test.cc b/chromium/net/quic/core/crypto/crypto_handshake_message_test.cc index c12f4cd12f6..a44e64af5c0 100644 --- a/chromium/net/quic/core/crypto/crypto_handshake_message_test.cc +++ b/chromium/net/quic/core/crypto/crypto_handshake_message_test.cc @@ -6,14 +6,13 @@ #include "net/quic/core/crypto/crypto_handshake.h" #include "net/quic/core/crypto/crypto_protocol.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { namespace { -class CryptoHandshakeMessageTest - : public ::testing::TestWithParam<Perspective> {}; +class CryptoHandshakeMessageTest : public QuicTestWithParam<Perspective> {}; TEST_P(CryptoHandshakeMessageTest, DebugString) { const char* str = "SHLO<\n>"; diff --git a/chromium/net/quic/core/crypto/crypto_protocol.h b/chromium/net/quic/core/crypto/crypto_protocol.h index 6e9a355f697..d073226c728 100644 --- a/chromium/net/quic/core/crypto/crypto_protocol.h +++ b/chromium/net/quic/core/crypto/crypto_protocol.h @@ -82,6 +82,8 @@ const QuicTag kTBBR = TAG('T', 'B', 'B', 'R'); // Reduced Buffer Bloat TCP const QuicTag k1RTT = TAG('1', 'R', 'T', 'T'); // STARTUP in BBR for 1 RTT const QuicTag k2RTT = TAG('2', 'R', 'T', 'T'); // STARTUP in BBR for 2 RTTs const QuicTag kRENO = TAG('R', 'E', 'N', 'O'); // Reno Congestion Control +const QuicTag kTPCC = TAG('P', 'C', 'C', '\0'); // Performance-Oriented + // Congestion Control const QuicTag kBYTE = TAG('B', 'Y', 'T', 'E'); // TCP cubic or reno in bytes const QuicTag kRATE = TAG('R', 'A', 'T', 'E'); // TCP cubic rate based sending const QuicTag kIW03 = TAG('I', 'W', '0', '3'); // Force ICWND to 3 @@ -111,6 +113,7 @@ const QuicTag kAKD4 = TAG('A', 'K', 'D', '4'); // Ack decimation with 1/8 RTT const QuicTag kSSLR = TAG('S', 'S', 'L', 'R'); // Slow Start Large Reduction. const QuicTag kNPRR = TAG('N', 'P', 'R', 'R'); // Pace at unity instead of PRR const QuicTag k5RTO = TAG('5', 'R', 'T', 'O'); // Close connection on 5 RTOs +const QuicTag k3RTO = TAG('3', 'R', 'T', 'O'); // Close connection on 3 RTOs const QuicTag kCTIM = TAG('C', 'T', 'I', 'M'); // Client timestamp in seconds // since UNIX epoch. const QuicTag kDHDT = TAG('D', 'H', 'D', 'T'); // Disable HPACK dynamic table. diff --git a/chromium/net/quic/core/crypto/crypto_secret_boxer_test.cc b/chromium/net/quic/core/crypto/crypto_secret_boxer_test.cc index 12820179c16..18fea413bfd 100644 --- a/chromium/net/quic/core/crypto/crypto_secret_boxer_test.cc +++ b/chromium/net/quic/core/crypto/crypto_secret_boxer_test.cc @@ -5,14 +5,16 @@ #include "net/quic/core/crypto/crypto_secret_boxer.h" #include "net/quic/core/crypto/quic_random.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" using std::string; namespace net { namespace test { -TEST(CryptoSecretBoxerTest, BoxAndUnbox) { +class CryptoSecretBoxerTest : public QuicTest {}; + +TEST_F(CryptoSecretBoxerTest, BoxAndUnbox) { QuicStringPiece message("hello world"); CryptoSecretBoxer boxer; @@ -47,7 +49,7 @@ static bool CanDecode(const CryptoSecretBoxer& decoder, return ok; } -TEST(CryptoSecretBoxerTest, MultipleKeys) { +TEST_F(CryptoSecretBoxerTest, MultipleKeys) { string key_11(CryptoSecretBoxer::GetKeySize(), 0x11); string key_12(CryptoSecretBoxer::GetKeySize(), 0x12); diff --git a/chromium/net/quic/core/crypto/crypto_server_test.cc b/chromium/net/quic/core/crypto/crypto_server_test.cc index 85f07520f51..13a040e76b5 100644 --- a/chromium/net/quic/core/crypto/crypto_server_test.cc +++ b/chromium/net/quic/core/crypto/crypto_server_test.cc @@ -16,10 +16,12 @@ #include "net/quic/core/crypto/proof_source.h" #include "net/quic/core/crypto/quic_crypto_server_config.h" #include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_socket_address_coder.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_endian.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_string_piece.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/delayed_verify_strike_register_client.h" @@ -28,7 +30,6 @@ #include "net/quic/test_tools/mock_random.h" #include "net/quic/test_tools/quic_crypto_server_config_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" #include "third_party/boringssl/src/include/openssl/sha.h" using std::string; @@ -100,7 +101,7 @@ std::vector<TestParams> GetTestParams() { return params; } -class CryptoServerTest : public ::testing::TestWithParam<TestParams> { +class CryptoServerTest : public QuicTestWithParam<TestParams> { public: CryptoServerTest() : rand_(QuicRandom::GetInstance()), @@ -363,6 +364,11 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> { } else { ASSERT_EQ(QUIC_NO_ERROR, out_.GetUint64(kRCID, &server_designated_connection_id)); + if (QuicUtils::IsConnectionIdWireFormatBigEndian( + Perspective::IS_SERVER)) { + server_designated_connection_id = + QuicEndian::NetToHost64(server_designated_connection_id); + } EXPECT_EQ(rand_for_id_generation_.RandUint64(), server_designated_connection_id); } @@ -389,7 +395,6 @@ class CryptoServerTest : public ::testing::TestWithParam<TestParams> { } protected: - QuicFlagSaver flags_; // Save/restore all QUIC flag values. QuicRandom* const rand_; MockRandom rand_for_id_generation_; MockClock clock_; @@ -942,7 +947,9 @@ TEST_P(CryptoServerTest, ProofSourceFailure) { ShouldFailMentioning("", msg); } -TEST(CryptoServerConfigGenerationTest, Determinism) { +class CryptoServerConfigGenerationTest : public QuicTest {}; + +TEST_F(CryptoServerConfigGenerationTest, Determinism) { // Test that using a deterministic PRNG causes the server-config to be // deterministic. @@ -963,7 +970,7 @@ TEST(CryptoServerConfigGenerationTest, Determinism) { scfg_b->DebugString(Perspective::IS_SERVER)); } -TEST(CryptoServerConfigGenerationTest, SCIDVaries) { +TEST_F(CryptoServerConfigGenerationTest, SCIDVaries) { // This test ensures that the server config ID varies for different server // configs. @@ -988,7 +995,7 @@ TEST(CryptoServerConfigGenerationTest, SCIDVaries) { EXPECT_NE(scid_a, scid_b); } -TEST(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) { +TEST_F(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) { MockRandom rand_a; const QuicCryptoServerConfig::ConfigOptions options; MockClock clock; diff --git a/chromium/net/quic/core/crypto/crypto_utils.cc b/chromium/net/quic/core/crypto/crypto_utils.cc index b8a6120d5e4..0e005bff26b 100644 --- a/chromium/net/quic/core/crypto/crypto_utils.cc +++ b/chromium/net/quic/core/crypto/crypto_utils.cc @@ -137,7 +137,7 @@ bool CryptoUtils::DeriveKeys(QuicStringPiece premaster_secret, } if (subkey_secret != nullptr) { - hkdf.subkey_secret().CopyToString(subkey_secret); + *subkey_secret = string(hkdf.subkey_secret()); } return true; @@ -168,7 +168,7 @@ bool CryptoUtils::ExportKeyingMaterial(QuicStringPiece subkey_secret, crypto::HKDF hkdf(subkey_secret, QuicStringPiece() /* no salt */, info, result_len, 0 /* no fixed IV */, 0 /* no subkey secret */); - hkdf.client_write_key().CopyToString(result); + *result = string(hkdf.client_write_key()); return true; } diff --git a/chromium/net/quic/core/crypto/crypto_utils_test.cc b/chromium/net/quic/core/crypto/crypto_utils_test.cc index 641de83b061..ef00ced4653 100644 --- a/chromium/net/quic/core/crypto/crypto_utils_test.cc +++ b/chromium/net/quic/core/crypto/crypto_utils_test.cc @@ -5,9 +5,9 @@ #include "net/quic/core/crypto/crypto_utils.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; @@ -15,7 +15,9 @@ namespace net { namespace test { namespace { -TEST(CryptoUtilsTest, TestExportKeyingMaterial) { +class CryptoUtilsTest : public QuicTest {}; + +TEST_F(CryptoUtilsTest, TestExportKeyingMaterial) { const struct TestVector { // Input (strings of hexadecimal digits): const char* subkey_secret; @@ -72,7 +74,7 @@ TEST(CryptoUtilsTest, TestExportKeyingMaterial) { } } -TEST(CryptoUtilsTest, HandshakeFailureReasonToString) { +TEST_F(CryptoUtilsTest, HandshakeFailureReasonToString) { EXPECT_STREQ("HANDSHAKE_OK", CryptoUtils::HandshakeFailureReasonToString(HANDSHAKE_OK)); EXPECT_STREQ("CLIENT_NONCE_UNKNOWN_FAILURE", diff --git a/chromium/net/quic/core/crypto/curve25519_key_exchange_test.cc b/chromium/net/quic/core/crypto/curve25519_key_exchange_test.cc index 6ded8a76b8c..7496bca828e 100644 --- a/chromium/net/quic/core/crypto/curve25519_key_exchange_test.cc +++ b/chromium/net/quic/core/crypto/curve25519_key_exchange_test.cc @@ -7,16 +7,18 @@ #include <memory> #include "net/quic/core/crypto/quic_random.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" using std::string; namespace net { namespace test { +class Curve25519KeyExchangeTest : public QuicTest {}; + // SharedKey just tests that the basic key exchange identity holds: that both // parties end up with the same key. -TEST(Curve25519KeyExchange, SharedKey) { +TEST_F(Curve25519KeyExchangeTest, SharedKey) { QuicRandom* const rand = QuicRandom::GetInstance(); for (int i = 0; i < 5; i++) { diff --git a/chromium/net/quic/core/crypto/local_strike_register_client_test.cc b/chromium/net/quic/core/crypto/local_strike_register_client_test.cc index 4af0afc560b..79fa94f4394 100644 --- a/chromium/net/quic/core/crypto/local_strike_register_client_test.cc +++ b/chromium/net/quic/core/crypto/local_strike_register_client_test.cc @@ -11,7 +11,7 @@ #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/quic_time.h" #include "net/quic/platform/api/quic_str_cat.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" using std::string; @@ -54,7 +54,7 @@ const uint32_t kCurrentTimeExternalSecs = 12345678; size_t kMaxEntries = 100; uint32_t kWindowSecs = 60; -class LocalStrikeRegisterClientTest : public ::testing::Test { +class LocalStrikeRegisterClientTest : public QuicTest { protected: LocalStrikeRegisterClientTest() {} diff --git a/chromium/net/quic/core/crypto/null_decrypter.cc b/chromium/net/quic/core/crypto/null_decrypter.cc index 5e0ea06f69c..c42fd34e9cd 100644 --- a/chromium/net/quic/core/crypto/null_decrypter.cc +++ b/chromium/net/quic/core/crypto/null_decrypter.cc @@ -43,7 +43,8 @@ bool NullDecrypter::DecryptPacket(QuicVersion version, char* output, size_t* output_length, size_t max_output_length) { - QuicDataReader reader(ciphertext.data(), ciphertext.length(), perspective_); + QuicDataReader reader(ciphertext.data(), ciphertext.length(), perspective_, + HOST_BYTE_ORDER); uint128 hash; if (!ReadHash(&reader, &hash)) { diff --git a/chromium/net/quic/core/crypto/null_decrypter_test.cc b/chromium/net/quic/core/crypto/null_decrypter_test.cc index 10f4c31b208..a6750ab4630 100644 --- a/chromium/net/quic/core/crypto/null_decrypter_test.cc +++ b/chromium/net/quic/core/crypto/null_decrypter_test.cc @@ -3,12 +3,13 @@ // found in the LICENSE file. #include "net/quic/core/crypto/null_decrypter.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_test_utils.h" namespace net { namespace test { -class NullDecrypterTest : public ::testing::TestWithParam<bool> {}; +class NullDecrypterTest : public QuicTestWithParam<bool> {}; TEST_F(NullDecrypterTest, DecryptClient) { unsigned char expected[] = { diff --git a/chromium/net/quic/core/crypto/null_encrypter_test.cc b/chromium/net/quic/core/crypto/null_encrypter_test.cc index a40b35e8e3d..6992a27a845 100644 --- a/chromium/net/quic/core/crypto/null_encrypter_test.cc +++ b/chromium/net/quic/core/crypto/null_encrypter_test.cc @@ -3,12 +3,13 @@ // found in the LICENSE file. #include "net/quic/core/crypto/null_encrypter.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_test_utils.h" namespace net { namespace test { -class NullEncrypterTest : public ::testing::TestWithParam<bool> {}; +class NullEncrypterTest : public QuicTestWithParam<bool> {}; TEST_F(NullEncrypterTest, EncryptClient) { unsigned char expected[] = { diff --git a/chromium/net/quic/core/crypto/p256_key_exchange_test.cc b/chromium/net/quic/core/crypto/p256_key_exchange_test.cc index 7ff40220b97..1156df4f4a2 100644 --- a/chromium/net/quic/core/crypto/p256_key_exchange_test.cc +++ b/chromium/net/quic/core/crypto/p256_key_exchange_test.cc @@ -6,16 +6,18 @@ #include <memory> -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" using std::string; namespace net { namespace test { +class P256KeyExchangeTest : public QuicTest {}; + // SharedKey just tests that the basic key exchange identity holds: that both // parties end up with the same key. -TEST(P256KeyExchange, SharedKey) { +TEST_F(P256KeyExchangeTest, SharedKey) { for (int i = 0; i < 5; i++) { string alice_private(P256KeyExchange::NewPrivateKey()); string bob_private(P256KeyExchange::NewPrivateKey()); diff --git a/chromium/net/quic/core/crypto/quic_compressed_certs_cache.cc b/chromium/net/quic/core/crypto/quic_compressed_certs_cache.cc index c9ba5301beb..84a58faae8b 100644 --- a/chromium/net/quic/core/crypto/quic_compressed_certs_cache.cc +++ b/chromium/net/quic/core/crypto/quic_compressed_certs_cache.cc @@ -19,7 +19,9 @@ inline void hash_combine(uint64_t* seed, const uint64_t& val) { } // namespace QuicCompressedCertsCache::UncompressedCerts::UncompressedCerts() - : chain(nullptr) {} + : chain(nullptr), + client_common_set_hashes(nullptr), + client_cached_cert_hashes(nullptr) {} QuicCompressedCertsCache::UncompressedCerts::UncompressedCerts( const QuicReferenceCountedPointer<ProofSource::Chain>& chain, diff --git a/chromium/net/quic/core/crypto/quic_compressed_certs_cache_test.cc b/chromium/net/quic/core/crypto/quic_compressed_certs_cache_test.cc index 4abfca0a0c4..c5cad2f2327 100644 --- a/chromium/net/quic/core/crypto/quic_compressed_certs_cache_test.cc +++ b/chromium/net/quic/core/crypto/quic_compressed_certs_cache_test.cc @@ -6,9 +6,9 @@ #include "base/macros.h" #include "net/quic/core/crypto/cert_compressor.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/quic/test_tools/crypto_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" using base::IntToString; using std::string; diff --git a/chromium/net/quic/core/crypto/quic_crypto_client_config.cc b/chromium/net/quic/core/crypto/quic_crypto_client_config.cc index 35b44e97ffe..2a80d68bd30 100644 --- a/chromium/net/quic/core/crypto/quic_crypto_client_config.cc +++ b/chromium/net/quic/core/crypto/quic_crypto_client_config.cc @@ -22,6 +22,7 @@ #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_endian.h" #include "net/quic/platform/api/quic_hostname_utils.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_map_util.h" @@ -192,6 +193,7 @@ void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() { scfg_.reset(); SetProofInvalid(); std::queue<QuicConnectionId> empty_queue; + using std::swap; swap(server_designated_connection_ids_, empty_queue); } @@ -236,6 +238,7 @@ void QuicCryptoClientConfig::CachedState::Clear() { scfg_.reset(); ++generation_counter_; std::queue<QuicConnectionId> empty_queue; + using std::swap; swap(server_designated_connection_ids_, empty_queue); } @@ -281,9 +284,10 @@ bool QuicCryptoClientConfig::CachedState::Initialize( return false; } - chlo_hash.CopyToString(&chlo_hash_); - signature.CopyToString(&server_config_sig_); - source_address_token.CopyToString(&source_address_token_); + chlo_hash_.assign(chlo_hash.data(), chlo_hash.size()); + server_config_sig_.assign(signature.data(), signature.size()); + source_address_token_.assign(source_address_token.data(), + source_address_token.size()); certs_ = certs; cert_sct_ = cert_sct; return true; @@ -499,6 +503,9 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello( CryptoHandshakeMessage* out, string* error_details) const { DCHECK(error_details != nullptr); + if (QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective::IS_CLIENT)) { + connection_id = QuicEndian::HostToNet64(connection_id); + } FillInchoateClientHello(server_id, preferred_version, cached, rand, /* demand_x509_proof= */ true, out_params, out); @@ -819,6 +826,9 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection( *error_details = "Missing kRCID"; return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; } + if (QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective::IS_CLIENT)) { + connection_id = QuicEndian::NetToHost64(connection_id); + } cached->add_server_designated_connection_id(connection_id); if (!nonce.empty()) { cached->add_server_nonce(nonce.as_string()); diff --git a/chromium/net/quic/core/crypto/quic_crypto_client_config_test.cc b/chromium/net/quic/core/crypto/quic_crypto_client_config_test.cc index 694767f177a..54bc6e18893 100644 --- a/chromium/net/quic/core/crypto/quic_crypto_client_config_test.cc +++ b/chromium/net/quic/core/crypto/quic_crypto_client_config_test.cc @@ -6,10 +6,12 @@ #include "net/quic/core/crypto/proof_verifier.h" #include "net/quic/core/quic_server_id.h" +#include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_endian.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/mock_random.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; @@ -45,24 +47,26 @@ class AllServerIdsFilter : public QuicCryptoClientConfig::ServerIdFilter { } // namespace -TEST(QuicCryptoClientConfigTest, CachedState_IsEmpty) { +class QuicCryptoClientConfigTest : public QuicTest {}; + +TEST_F(QuicCryptoClientConfigTest, CachedState_IsEmpty) { QuicCryptoClientConfig::CachedState state; EXPECT_TRUE(state.IsEmpty()); } -TEST(QuicCryptoClientConfigTest, CachedState_IsComplete) { +TEST_F(QuicCryptoClientConfigTest, CachedState_IsComplete) { QuicCryptoClientConfig::CachedState state; EXPECT_FALSE(state.IsComplete(QuicWallTime::FromUNIXSeconds(0))); } -TEST(QuicCryptoClientConfigTest, CachedState_GenerationCounter) { +TEST_F(QuicCryptoClientConfigTest, CachedState_GenerationCounter) { QuicCryptoClientConfig::CachedState state; EXPECT_EQ(0u, state.generation_counter()); state.SetProofInvalid(); EXPECT_EQ(1u, state.generation_counter()); } -TEST(QuicCryptoClientConfigTest, CachedState_SetProofVerifyDetails) { +TEST_F(QuicCryptoClientConfigTest, CachedState_SetProofVerifyDetails) { QuicCryptoClientConfig::CachedState state; EXPECT_TRUE(state.proof_verify_details() == nullptr); ProofVerifyDetails* details = new TestProofVerifyDetails; @@ -70,7 +74,7 @@ TEST(QuicCryptoClientConfigTest, CachedState_SetProofVerifyDetails) { EXPECT_EQ(details, state.proof_verify_details()); } -TEST(QuicCryptoClientConfigTest, CachedState_ServerDesignatedConnectionId) { +TEST_F(QuicCryptoClientConfigTest, CachedState_ServerDesignatedConnectionId) { QuicCryptoClientConfig::CachedState state; EXPECT_FALSE(state.has_server_designated_connection_id()); @@ -101,7 +105,7 @@ TEST(QuicCryptoClientConfigTest, CachedState_ServerDesignatedConnectionId) { EXPECT_EQ(second_cid, state.GetNextServerDesignatedConnectionId()); } -TEST(QuicCryptoClientConfigTest, CachedState_ServerIdConsumedBeforeSet) { +TEST_F(QuicCryptoClientConfigTest, CachedState_ServerIdConsumedBeforeSet) { QuicCryptoClientConfig::CachedState state; EXPECT_FALSE(state.has_server_designated_connection_id()); #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) @@ -111,7 +115,7 @@ TEST(QuicCryptoClientConfigTest, CachedState_ServerIdConsumedBeforeSet) { #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) } -TEST(QuicCryptoClientConfigTest, CachedState_ServerNonce) { +TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonce) { QuicCryptoClientConfig::CachedState state; EXPECT_FALSE(state.has_server_nonce()); @@ -142,7 +146,7 @@ TEST(QuicCryptoClientConfigTest, CachedState_ServerNonce) { EXPECT_EQ(second_nonce, state.GetNextServerNonce()); } -TEST(QuicCryptoClientConfigTest, CachedState_ServerNonceConsumedBeforeSet) { +TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonceConsumedBeforeSet) { QuicCryptoClientConfig::CachedState state; EXPECT_FALSE(state.has_server_nonce()); #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) @@ -152,7 +156,7 @@ TEST(QuicCryptoClientConfigTest, CachedState_ServerNonceConsumedBeforeSet) { #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) } -TEST(QuicCryptoClientConfigTest, CachedState_InitializeFrom) { +TEST_F(QuicCryptoClientConfigTest, CachedState_InitializeFrom) { QuicCryptoClientConfig::CachedState state; QuicCryptoClientConfig::CachedState other; state.set_source_address_token("TOKEN"); @@ -166,7 +170,7 @@ TEST(QuicCryptoClientConfigTest, CachedState_InitializeFrom) { EXPECT_FALSE(state.has_server_nonce()); } -TEST(QuicCryptoClientConfigTest, InchoateChlo) { +TEST_F(QuicCryptoClientConfigTest, InchoateChlo) { QuicCryptoClientConfig::CachedState state; QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params( @@ -185,7 +189,7 @@ TEST(QuicCryptoClientConfigTest, InchoateChlo) { EXPECT_EQ(string(32, 'r'), proof_nonce); } -TEST(QuicCryptoClientConfigTest, PreferAesGcm) { +TEST_F(QuicCryptoClientConfigTest, PreferAesGcm) { QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); if (config.aead.size() > 1) EXPECT_NE(kAESG, config.aead[0]); @@ -193,7 +197,7 @@ TEST(QuicCryptoClientConfigTest, PreferAesGcm) { EXPECT_EQ(kAESG, config.aead[0]); } -TEST(QuicCryptoClientConfigTest, InchoateChloSecure) { +TEST_F(QuicCryptoClientConfigTest, InchoateChloSecure) { QuicCryptoClientConfig::CachedState state; QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params( @@ -211,7 +215,7 @@ TEST(QuicCryptoClientConfigTest, InchoateChloSecure) { EXPECT_FALSE(msg.GetStringPiece(kSCID, &scid)); } -TEST(QuicCryptoClientConfigTest, InchoateChloSecureWithSCIDNoEXPY) { +TEST_F(QuicCryptoClientConfigTest, InchoateChloSecureWithSCIDNoEXPY) { // Test that a config with no EXPY is still valid when a non-zero // expiry time is passed in. QuicCryptoClientConfig::CachedState state; @@ -239,7 +243,7 @@ TEST(QuicCryptoClientConfigTest, InchoateChloSecureWithSCIDNoEXPY) { EXPECT_EQ("12345678", scid); } -TEST(QuicCryptoClientConfigTest, InchoateChloSecureWithSCID) { +TEST_F(QuicCryptoClientConfigTest, InchoateChloSecureWithSCID) { QuicCryptoClientConfig::CachedState state; CryptoHandshakeMessage scfg; scfg.set_tag(kSCFG); @@ -266,7 +270,7 @@ TEST(QuicCryptoClientConfigTest, InchoateChloSecureWithSCID) { EXPECT_EQ("12345678", scid); } -TEST(QuicCryptoClientConfigTest, FillClientHello) { +TEST_F(QuicCryptoClientConfigTest, FillClientHello) { QuicCryptoClientConfig::CachedState state; QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params( @@ -287,7 +291,7 @@ TEST(QuicCryptoClientConfigTest, FillClientHello) { EXPECT_EQ(QuicVersionToQuicTag(QuicVersionMax()), cver); } -TEST(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) { +TEST_F(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) { QuicVersionVector supported_versions = AllSupportedVersions(); if (supported_versions.size() == 1) { // No downgrade attack is possible if the client only supports one version. @@ -314,7 +318,7 @@ TEST(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) { EXPECT_EQ("Downgrade attack detected", error); } -TEST(QuicCryptoClientConfigTest, InitializeFrom) { +TEST_F(QuicCryptoClientConfigTest, InitializeFrom) { QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); QuicServerId canonical_server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); @@ -335,7 +339,7 @@ TEST(QuicCryptoClientConfigTest, InitializeFrom) { EXPECT_EQ(1u, other->generation_counter()); } -TEST(QuicCryptoClientConfigTest, Canonical) { +TEST_F(QuicCryptoClientConfigTest, Canonical) { QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); config.AddCanonicalSuffix(".google.com"); QuicServerId canonical_id1("www.google.com", 443, PRIVACY_MODE_DISABLED); @@ -359,7 +363,7 @@ TEST(QuicCryptoClientConfigTest, Canonical) { EXPECT_TRUE(config.LookupOrCreate(different_id)->IsEmpty()); } -TEST(QuicCryptoClientConfigTest, CanonicalNotUsedIfNotValid) { +TEST_F(QuicCryptoClientConfigTest, CanonicalNotUsedIfNotValid) { QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); config.AddCanonicalSuffix(".google.com"); QuicServerId canonical_id1("www.google.com", 443, PRIVACY_MODE_DISABLED); @@ -374,7 +378,7 @@ TEST(QuicCryptoClientConfigTest, CanonicalNotUsedIfNotValid) { EXPECT_TRUE(config.LookupOrCreate(canonical_id2)->IsEmpty()); } -TEST(QuicCryptoClientConfigTest, ClearCachedStates) { +TEST_F(QuicCryptoClientConfigTest, ClearCachedStates) { QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting()); // Create two states on different origins. @@ -462,7 +466,7 @@ TEST(QuicCryptoClientConfigTest, ClearCachedStates) { EXPECT_EQ(3u, cleared_cache->generation_counter()); } -TEST(QuicCryptoClientConfigTest, ProcessReject) { +TEST_F(QuicCryptoClientConfigTest, ProcessReject) { CryptoHandshakeMessage rej; crypto_test_utils::FillInDummyReject(&rej, /* stateless */ false); @@ -480,7 +484,7 @@ TEST(QuicCryptoClientConfigTest, ProcessReject) { EXPECT_FALSE(cached.has_server_nonce()); } -TEST(QuicCryptoClientConfigTest, ProcessRejectWithLongTTL) { +TEST_F(QuicCryptoClientConfigTest, ProcessRejectWithLongTTL) { CryptoHandshakeMessage rej; crypto_test_utils::FillInDummyReject(&rej, /* stateless */ false); QuicTime::Delta one_week = QuicTime::Delta::FromSeconds(kNumSecondsPerWeek); @@ -505,7 +509,7 @@ TEST(QuicCryptoClientConfigTest, ProcessRejectWithLongTTL) { QuicWallTime::FromUNIXSeconds(one_week.ToSeconds() - 1))); } -TEST(QuicCryptoClientConfigTest, ProcessStatelessReject) { +TEST_F(QuicCryptoClientConfigTest, ProcessStatelessReject) { // Create a dummy reject message and mark it as stateless. CryptoHandshakeMessage rej; crypto_test_utils::FillInDummyReject(&rej, /* stateless */ true); @@ -525,11 +529,14 @@ TEST(QuicCryptoClientConfigTest, ProcessStatelessReject) { AllSupportedVersions().front(), "", &cached, out_params, &error)); EXPECT_TRUE(cached.has_server_designated_connection_id()); - EXPECT_EQ(kConnectionId, cached.GetNextServerDesignatedConnectionId()); + EXPECT_EQ(QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective::IS_CLIENT) + ? QuicEndian::NetToHost64(kConnectionId) + : kConnectionId, + cached.GetNextServerDesignatedConnectionId()); EXPECT_EQ(server_nonce, cached.GetNextServerNonce()); } -TEST(QuicCryptoClientConfigTest, BadlyFormattedStatelessReject) { +TEST_F(QuicCryptoClientConfigTest, BadlyFormattedStatelessReject) { // Create a dummy reject message and mark it as stateless. Do not // add an server-designated connection-id. CryptoHandshakeMessage rej; @@ -549,7 +556,7 @@ TEST(QuicCryptoClientConfigTest, BadlyFormattedStatelessReject) { EXPECT_EQ("Missing kRCID", error); } -TEST(QuicCryptoClientConfigTest, ServerNonceinSHLO) { +TEST_F(QuicCryptoClientConfigTest, ServerNonceinSHLO) { // Test that the server must include a nonce in the SHLO. CryptoHandshakeMessage msg; msg.set_tag(kSHLO); diff --git a/chromium/net/quic/core/crypto/quic_crypto_server_config.cc b/chromium/net/quic/core/crypto/quic_crypto_server_config.cc index b7a44bdeac7..f0f40a0789b 100644 --- a/chromium/net/quic/core/crypto/quic_crypto_server_config.cc +++ b/chromium/net/quic/core/crypto/quic_crypto_server_config.cc @@ -29,12 +29,13 @@ #include "net/quic/core/crypto/quic_encrypter.h" #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/proto/source_address_token.pb.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_socket_address_coder.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_clock.h" +#include "net/quic/platform/api/quic_endian.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_hostname_utils.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_reference_counted.h" @@ -745,6 +746,10 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof( const QuicReferenceCountedPointer<Config>& requested_config, const QuicReferenceCountedPointer<Config>& primary_config, std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const { + if (QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective::IS_SERVER)) { + connection_id = QuicEndian::HostToNet64(connection_id); + } + ProcessClientHelloHelper helper(&done_cb); if (found_error) { @@ -1479,6 +1484,10 @@ void QuicCryptoServerConfig::BuildRejection( << "with server-designated connection ID " << server_designated_connection_id; out->set_tag(kSREJ); + if (QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective::IS_SERVER)) { + server_designated_connection_id = + QuicEndian::HostToNet64(server_designated_connection_id); + } out->SetValue(kRCID, server_designated_connection_id); } else { out->set_tag(kREJ); @@ -1742,8 +1751,8 @@ QuicCryptoServerConfig::ParseConfigProtobuf( } void QuicCryptoServerConfig::SetEphemeralKeySource( - EphemeralKeySource* ephemeral_key_source) { - ephemeral_key_source_.reset(ephemeral_key_source); + std::unique_ptr<EphemeralKeySource> ephemeral_key_source) { + ephemeral_key_source_ = std::move(ephemeral_key_source); } void QuicCryptoServerConfig::set_replay_protection(bool on) { diff --git a/chromium/net/quic/core/crypto/quic_crypto_server_config.h b/chromium/net/quic/core/crypto/quic_crypto_server_config.h index 9c30c01bd06..4094855afda 100644 --- a/chromium/net/quic/core/crypto/quic_crypto_server_config.h +++ b/chromium/net/quic/core/crypto/quic_crypto_server_config.h @@ -349,10 +349,10 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig { std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; // SetEphemeralKeySource installs an object that can cache ephemeral keys for - // a short period of time. This object takes ownership of - // |ephemeral_key_source|. If not set then ephemeral keys will be generated + // a short period of time. If not set, ephemeral keys will be generated // per-connection. - void SetEphemeralKeySource(EphemeralKeySource* ephemeral_key_source); + void SetEphemeralKeySource( + std::unique_ptr<EphemeralKeySource> ephemeral_key_source); // set_replay_protection controls whether replay protection is enabled. If // replay protection is disabled then no strike registers are needed and diff --git a/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc b/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc index d67030e4246..6c1407661cd 100644 --- a/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc +++ b/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc @@ -16,17 +16,19 @@ #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/quic_time.h" #include "net/quic/platform/api/quic_socket_address.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/quic_crypto_server_config_peer.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; namespace net { namespace test { -TEST(QuicCryptoServerConfigTest, ServerConfig) { +class QuicCryptoServerConfigTest : public QuicTest {}; + +TEST_F(QuicCryptoServerConfigTest, ServerConfig) { QuicRandom* rand = QuicRandom::GetInstance(); QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand, crypto_test_utils::ProofSourceForTesting()); @@ -45,7 +47,7 @@ TEST(QuicCryptoServerConfigTest, ServerConfig) { EXPECT_LE(1u, aead.size()); } -TEST(QuicCryptoServerConfigTest, CompressCerts) { +TEST_F(QuicCryptoServerConfigTest, CompressCerts) { QuicCompressedCertsCache compressed_certs_cache( QuicCompressedCertsCache::kQuicCompressedCertsCacheSize); @@ -64,7 +66,7 @@ TEST(QuicCryptoServerConfigTest, CompressCerts) { EXPECT_EQ(compressed_certs_cache.Size(), 1u); } -TEST(QuicCryptoServerConfigTest, CompressSameCertsTwice) { +TEST_F(QuicCryptoServerConfigTest, CompressSameCertsTwice) { QuicCompressedCertsCache compressed_certs_cache( QuicCompressedCertsCache::kQuicCompressedCertsCacheSize); @@ -91,7 +93,7 @@ TEST(QuicCryptoServerConfigTest, CompressSameCertsTwice) { EXPECT_EQ(compressed_certs_cache.Size(), 1u); } -TEST(QuicCryptoServerConfigTest, CompressDifferentCerts) { +TEST_F(QuicCryptoServerConfigTest, CompressDifferentCerts) { // This test compresses a set of similar but not identical certs. Cache if // used should return cache miss and add all the compressed certs. QuicCompressedCertsCache compressed_certs_cache( @@ -132,7 +134,7 @@ TEST(QuicCryptoServerConfigTest, CompressDifferentCerts) { EXPECT_EQ(compressed_certs_cache.Size(), 3u); } -class SourceAddressTokenTest : public ::testing::Test { +class SourceAddressTokenTest : public QuicTest { public: SourceAddressTokenTest() : ip4_(QuicIpAddress::Loopback4()), @@ -274,7 +276,7 @@ TEST_F(SourceAddressTokenTest, SourceAddressTokenMultipleAddresses) { ValidateSourceAddressTokens(kPrimary, token4or6, ip6_)); } -class CryptoServerConfigsTest : public ::testing::Test { +class CryptoServerConfigsTest : public QuicTest { public: CryptoServerConfigsTest() : rand_(QuicRandom::GetInstance()), diff --git a/chromium/net/quic/core/crypto/quic_random_test.cc b/chromium/net/quic/core/crypto/quic_random_test.cc index d4f8a7bbd9b..5d6f437d6e7 100644 --- a/chromium/net/quic/core/crypto/quic_random_test.cc +++ b/chromium/net/quic/core/crypto/quic_random_test.cc @@ -4,12 +4,14 @@ #include "net/quic/core/crypto/quic_random.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { -TEST(QuicRandomTest, RandBytes) { +class QuicRandomTest : public QuicTest {}; + +TEST_F(QuicRandomTest, RandBytes) { unsigned char buf1[16]; unsigned char buf2[16]; memset(buf1, 0xaf, sizeof(buf1)); @@ -21,14 +23,14 @@ TEST(QuicRandomTest, RandBytes) { EXPECT_NE(0, memcmp(buf1, buf2, sizeof(buf1))); } -TEST(QuicRandomTest, RandUint64) { +TEST_F(QuicRandomTest, RandUint64) { QuicRandom* rng = QuicRandom::GetInstance(); uint64_t value1 = rng->RandUint64(); uint64_t value2 = rng->RandUint64(); EXPECT_NE(value1, value2); } -TEST(QuicRandomTest, Reseed) { +TEST_F(QuicRandomTest, Reseed) { char buf[1024]; memset(buf, 0xaf, sizeof(buf)); diff --git a/chromium/net/quic/core/crypto/scoped_evp_aead_ctx.cc b/chromium/net/quic/core/crypto/scoped_evp_aead_ctx.cc index 447235833e4..ab9e54adf02 100644 --- a/chromium/net/quic/core/crypto/scoped_evp_aead_ctx.cc +++ b/chromium/net/quic/core/crypto/scoped_evp_aead_ctx.cc @@ -8,6 +8,7 @@ namespace net { ScopedEVPAEADCtx::ScopedEVPAEADCtx() { ctx_.aead = nullptr; + ctx_.aead_state = nullptr; } ScopedEVPAEADCtx::~ScopedEVPAEADCtx() { diff --git a/chromium/net/quic/core/crypto/strike_register_test.cc b/chromium/net/quic/core/crypto/strike_register_test.cc index b056a9e0de7..bcf2ec27a00 100644 --- a/chromium/net/quic/core/crypto/strike_register_test.cc +++ b/chromium/net/quic/core/crypto/strike_register_test.cc @@ -10,6 +10,7 @@ #include <string> #include "base/rand_util.h" +#include "net/quic/platform/api/quic_test.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -31,7 +32,9 @@ void SetNonce(uint8_t nonce[32], unsigned time, const uint8_t orbit[8]) { memset(nonce + 12, 0, 20); } -TEST(StrikeRegisterTest, SimpleHorizon) { +class StrikeRegisterTest : public QuicTest {}; + +TEST_F(StrikeRegisterTest, SimpleHorizon) { // The set must reject values created on or before its own creation time. StrikeRegister set(10 /* max size */, 1000 /* current time */, 100 /* window secs */, kOrbit, @@ -50,7 +53,7 @@ TEST(StrikeRegisterTest, SimpleHorizon) { EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1300 /* current time */)); } -TEST(StrikeRegisterTest, NoStartupMode) { +TEST_F(StrikeRegisterTest, NoStartupMode) { // Check that a strike register works immediately if NO_STARTUP_PERIOD_NEEDED // is specified. StrikeRegister set(10 /* max size */, 1000 /* current time */, @@ -68,7 +71,7 @@ TEST(StrikeRegisterTest, NoStartupMode) { EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1300 /* current time */)); } -TEST(StrikeRegisterTest, WindowFuture) { +TEST_F(StrikeRegisterTest, WindowFuture) { // The set must reject values outside the window. StrikeRegister set(10 /* max size */, 1000 /* current time */, 100 /* window secs */, kOrbit, @@ -80,7 +83,7 @@ TEST(StrikeRegisterTest, WindowFuture) { EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1100)); } -TEST(StrikeRegisterTest, BadOrbit) { +TEST_F(StrikeRegisterTest, BadOrbit) { // The set must reject values with the wrong orbit StrikeRegister set(10 /* max size */, 1000 /* current time */, 100 /* window secs */, kOrbit, @@ -91,7 +94,7 @@ TEST(StrikeRegisterTest, BadOrbit) { EXPECT_EQ(NONCE_INVALID_ORBIT_FAILURE, set.Insert(nonce, 1100)); } -TEST(StrikeRegisterTest, OneValue) { +TEST_F(StrikeRegisterTest, OneValue) { StrikeRegister set(10 /* max size */, 1000 /* current time */, 100 /* window secs */, kOrbit, StrikeRegister::DENY_REQUESTS_AT_STARTUP); @@ -100,7 +103,7 @@ TEST(StrikeRegisterTest, OneValue) { EXPECT_EQ(NONCE_OK, set.Insert(nonce, 1101)); } -TEST(StrikeRegisterTest, RejectDuplicate) { +TEST_F(StrikeRegisterTest, RejectDuplicate) { // The set must reject values with the wrong orbit StrikeRegister set(10 /* max size */, 1000 /* current time */, 100 /* window secs */, kOrbit, @@ -111,7 +114,7 @@ TEST(StrikeRegisterTest, RejectDuplicate) { EXPECT_EQ(NONCE_NOT_UNIQUE_FAILURE, set.Insert(nonce, 1101)); } -TEST(StrikeRegisterTest, HorizonUpdating) { +TEST_F(StrikeRegisterTest, HorizonUpdating) { StrikeRegister::StartupType startup_types[] = { StrikeRegister::DENY_REQUESTS_AT_STARTUP, StrikeRegister::NO_STARTUP_PERIOD_NEEDED}; @@ -163,7 +166,7 @@ TEST(StrikeRegisterTest, HorizonUpdating) { } } -TEST(StrikeRegisterTest, InsertMany) { +TEST_F(StrikeRegisterTest, InsertMany) { StrikeRegister set(5000 /* max size */, 1000 /* current time */, 500 /* window secs */, kOrbit, StrikeRegister::DENY_REQUESTS_AT_STARTUP); @@ -283,7 +286,7 @@ class SlowStrikeRegister { std::set<std::pair<uint32_t, string>> nonces_; }; -class StrikeRegisterStressTest : public ::testing::Test {}; +class StrikeRegisterStressTest : public QuicTest {}; TEST_F(StrikeRegisterStressTest, InOrderInsertion) { // Fixed seed gives reproducibility for this test. diff --git a/chromium/net/quic/core/frames/quic_frames_test.cc b/chromium/net/quic/core/frames/quic_frames_test.cc index dbc0d0cc8de..67ff6f8f0f3 100644 --- a/chromium/net/quic/core/frames/quic_frames_test.cc +++ b/chromium/net/quic/core/frames/quic_frames_test.cc @@ -14,8 +14,7 @@ #include "net/quic/core/frames/quic_stop_waiting_frame.h" #include "net/quic/core/frames/quic_stream_frame.h" #include "net/quic/core/frames/quic_window_update_frame.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { @@ -23,7 +22,9 @@ namespace { using testing::_; -TEST(QuicFramesTest, AckFrameToString) { +class QuicFramesTest : public QuicTest {}; + +TEST_F(QuicFramesTest, AckFrameToString) { QuicAckFrame frame; frame.largest_observed = 2; frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3); @@ -39,7 +40,7 @@ TEST(QuicFramesTest, AckFrameToString) { stream.str()); } -TEST(QuicFramesTest, PaddingFrameToString) { +TEST_F(QuicFramesTest, PaddingFrameToString) { QuicPaddingFrame frame; frame.num_padding_bytes = 1; std::ostringstream stream; @@ -47,7 +48,7 @@ TEST(QuicFramesTest, PaddingFrameToString) { EXPECT_EQ("{ num_padding_bytes: 1 }\n", stream.str()); } -TEST(QuicFramesTest, RstStreamFrameToString) { +TEST_F(QuicFramesTest, RstStreamFrameToString) { QuicRstStreamFrame frame; frame.stream_id = 1; frame.error_code = QUIC_STREAM_CANCELLED; @@ -56,7 +57,7 @@ TEST(QuicFramesTest, RstStreamFrameToString) { EXPECT_EQ("{ stream_id: 1, error_code: 6 }\n", stream.str()); } -TEST(QuicFramesTest, ConnectionCloseFrameToString) { +TEST_F(QuicFramesTest, ConnectionCloseFrameToString) { QuicConnectionCloseFrame frame; frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT; frame.error_details = "No recent network activity."; @@ -67,7 +68,7 @@ TEST(QuicFramesTest, ConnectionCloseFrameToString) { stream.str()); } -TEST(QuicFramesTest, GoAwayFrameToString) { +TEST_F(QuicFramesTest, GoAwayFrameToString) { QuicGoAwayFrame frame; frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT; frame.last_good_stream_id = 2; @@ -79,7 +80,7 @@ TEST(QuicFramesTest, GoAwayFrameToString) { stream.str()); } -TEST(QuicFramesTest, WindowUpdateFrameToString) { +TEST_F(QuicFramesTest, WindowUpdateFrameToString) { QuicWindowUpdateFrame frame; std::ostringstream stream; frame.stream_id = 1; @@ -88,7 +89,7 @@ TEST(QuicFramesTest, WindowUpdateFrameToString) { EXPECT_EQ("{ stream_id: 1, byte_offset: 2 }\n", stream.str()); } -TEST(QuicFramesTest, BlockedFrameToString) { +TEST_F(QuicFramesTest, BlockedFrameToString) { QuicBlockedFrame frame; frame.stream_id = 1; std::ostringstream stream; @@ -96,7 +97,7 @@ TEST(QuicFramesTest, BlockedFrameToString) { EXPECT_EQ("{ stream_id: 1 }\n", stream.str()); } -TEST(QuicFramesTest, StreamFrameToString) { +TEST_F(QuicFramesTest, StreamFrameToString) { QuicStreamFrame frame; frame.stream_id = 1; frame.fin = false; @@ -107,7 +108,7 @@ TEST(QuicFramesTest, StreamFrameToString) { EXPECT_EQ("{ stream_id: 1, fin: 0, offset: 2, length: 3 }\n", stream.str()); } -TEST(QuicFramesTest, StopWaitingFrameToString) { +TEST_F(QuicFramesTest, StopWaitingFrameToString) { QuicStopWaitingFrame frame; frame.least_unacked = 2; std::ostringstream stream; @@ -115,7 +116,7 @@ TEST(QuicFramesTest, StopWaitingFrameToString) { EXPECT_EQ("{ least_unacked: 2 }\n", stream.str()); } -TEST(QuicFramesTest, IsAwaitingPacket) { +TEST_F(QuicFramesTest, IsAwaitingPacket) { QuicAckFrame ack_frame1; ack_frame1.largest_observed = 10u; ack_frame1.packets.Add(1, 11); @@ -136,7 +137,7 @@ TEST(QuicFramesTest, IsAwaitingPacket) { EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 50u, 20u)); } -TEST(QuicFramesTest, RemoveSmallestInterval) { +TEST_F(QuicFramesTest, RemoveSmallestInterval) { QuicAckFrame ack_frame1; ack_frame1.largest_observed = 100u; ack_frame1.packets.Add(51, 60); @@ -153,8 +154,10 @@ TEST(QuicFramesTest, RemoveSmallestInterval) { EXPECT_EQ(99u, ack_frame1.packets.Max()); } +class PacketNumberQueueTest : public QuicTest {}; + // Tests that a queue contains the expected data after calls to Add(). -TEST(PacketNumberQueueTest, AddRange) { +TEST_F(PacketNumberQueueTest, AddRange) { PacketNumberQueue queue; queue.Add(1, 51); queue.Add(53); @@ -176,7 +179,7 @@ TEST(PacketNumberQueueTest, AddRange) { } // Tests that a queue contains the expected data after calls to Remove(). -TEST(PacketNumberQueueTest, Removal) { +TEST_F(PacketNumberQueueTest, Removal) { PacketNumberQueue queue; queue.Add(0, 100); @@ -203,7 +206,7 @@ TEST(PacketNumberQueueTest, Removal) { } // Tests that a queue is empty when all of its elements are removed. -TEST(PacketNumberQueueTest, Empty) { +TEST_F(PacketNumberQueueTest, Empty) { PacketNumberQueue queue; EXPECT_TRUE(queue.Empty()); EXPECT_EQ(0u, queue.NumPacketsSlow()); @@ -215,7 +218,7 @@ TEST(PacketNumberQueueTest, Empty) { } // Tests that logging the state of a PacketNumberQueue does not crash. -TEST(PacketNumberQueueTest, LogDoesNotCrash) { +TEST_F(PacketNumberQueueTest, LogDoesNotCrash) { std::ostringstream oss; PacketNumberQueue queue; oss << queue; @@ -226,7 +229,7 @@ TEST(PacketNumberQueueTest, LogDoesNotCrash) { } // Tests that the iterators returned from a packet queue iterate over the queue. -TEST(PacketNumberQueueTest, Iterators) { +TEST_F(PacketNumberQueueTest, Iterators) { PacketNumberQueue queue; queue.Add(1, 100); @@ -239,7 +242,7 @@ TEST(PacketNumberQueueTest, Iterators) { EXPECT_EQ(expected_intervals, actual_intervals); } -TEST(PacketNumberQueueTest, LowerBoundEquals) { +TEST_F(PacketNumberQueueTest, LowerBoundEquals) { PacketNumberQueue queue; queue.Add(1, 100); @@ -251,7 +254,7 @@ TEST(PacketNumberQueueTest, LowerBoundEquals) { EXPECT_TRUE(queue.end() == it); } -TEST(PacketNumberQueueTest, LowerBoundGreater) { +TEST_F(PacketNumberQueueTest, LowerBoundGreater) { PacketNumberQueue queue; queue.Add(15, 25); queue.Add(50, 100); @@ -262,7 +265,7 @@ TEST(PacketNumberQueueTest, LowerBoundGreater) { EXPECT_EQ(25u, it->max()); } -TEST(PacketNumberQueueTest, IntervalLengthAndRemoveInterval) { +TEST_F(PacketNumberQueueTest, IntervalLengthAndRemoveInterval) { PacketNumberQueue queue; queue.Add(1, 10); queue.Add(20, 30); @@ -275,7 +278,7 @@ TEST(PacketNumberQueueTest, IntervalLengthAndRemoveInterval) { EXPECT_FALSE(queue.Contains(20)); } -TEST(PacketNumberQueueTest, Complement) { +TEST_F(PacketNumberQueueTest, Complement) { PacketNumberQueue queue; queue.Add(1, 10); queue.Add(12, 20); diff --git a/chromium/net/quic/core/frames/quic_window_update_frame.h b/chromium/net/quic/core/frames/quic_window_update_frame.h index 0edf79ab0ff..55e6f040ed2 100644 --- a/chromium/net/quic/core/frames/quic_window_update_frame.h +++ b/chromium/net/quic/core/frames/quic_window_update_frame.h @@ -12,7 +12,7 @@ namespace net { -// Flow control updates per-stream and at the connection levoel. +// Flow control updates per-stream and at the connection level. // Based on SPDY's WINDOW_UPDATE frame, but uses an absolute byte offset rather // than a window delta. // TODO(rjshade): A possible future optimization is to make stream_id and diff --git a/chromium/net/quic/core/packet_number_indexed_queue.h b/chromium/net/quic/core/packet_number_indexed_queue.h new file mode 100644 index 00000000000..84388c2cbba --- /dev/null +++ b/chromium/net/quic/core/packet_number_indexed_queue.h @@ -0,0 +1,207 @@ +// 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 NET_QUIC_CORE_PACKET_NUMBER_INDEXED_QUEUE_H_ +#define NET_QUIC_CORE_PACKET_NUMBER_INDEXED_QUEUE_H_ + +#include <deque> + +#include "base/logging.h" +#include "net/quic/core/quic_types.h" + +namespace net { + +// PacketNumberIndexedQueue is a queue of mostly continuous numbered entries +// which supports the following operations: +// - adding elements to the end of the queue, or at some point past the end +// - removing elements in any order +// - retrieving elements +// If all elements are inserted in order, all of the operations above are +// amortized O(1) time. +// +// Internally, the data structure is a deque where each element is marked as +// present or not. The deque starts at the lowest present index. Whenever an +// element is removed, it's marked as not present, and the front of the deque is +// cleared of elements that are not present. +// +// The tail of the queue is not cleared due to the assumption of entries being +// inserted in order, though removing all elements of the queue will return it +// to its initial state. +// +// Note that this data structure is inherently hazardous, since an addition of +// just two entries will cause it to consume all of the memory available. +// Because of that, it is not a general-purpose container and should not be used +// as one. +template <typename T> +class PacketNumberIndexedQueue { + public: + PacketNumberIndexedQueue() + : number_of_present_entries_(0), first_packet_(0) {} + + // Retrieve the entry associated with the packet number. Returns the pointer + // to the entry in case of success, or nullptr if the entry does not exist. + T* GetEntry(QuicPacketNumber packet_number); + const T* GetEntry(QuicPacketNumber packet_number) const; + + // Inserts data associated |packet_number| into (or past) the end of the + // queue, filling up the missing intermediate entries as necessary. Returns + // true if the element has been inserted successfully, false if it was already + // in the queue or inserted out of order. + template <typename... Args> + bool Emplace(QuicPacketNumber packet_number, Args&&... args); + + // Removes data associated with |packet_number| and frees the slots in the + // queue as necessary. + bool Remove(QuicPacketNumber packet_number); + + bool IsEmpty() const { return number_of_present_entries_ == 0; } + + // Returns the number of entries in the queue. + size_t number_of_present_entries() const { + return number_of_present_entries_; + } + + // Returns the number of entries allocated in the underlying deque. This is + // proportional to the memory usage of the queue. + size_t entry_slots_used() const { return entries_.size(); } + + // Packet number of the first entry in the queue. Zero if the queue is empty. + size_t first_packet() const { return first_packet_; } + + // Packet number of the last entry ever inserted in the queue. Note that the + // entry in question may have already been removed. Zero if the queue is + // empty. + size_t last_packet() const { + if (IsEmpty()) { + return 0; + } + return first_packet_ + entries_.size() - 1; + } + + private: + // Wrapper around T used to mark whether the entry is actually in the map. + struct EntryWrapper { + T data; + bool present; + + EntryWrapper() : data(), present(false) {} + + template <typename... Args> + explicit EntryWrapper(Args&&... args) + : data(std::forward<Args>(args)...), present(true) {} + }; + + // Cleans up unused slots in the front after removing an element. + void Cleanup(); + + const EntryWrapper* GetEntryWrapper(QuicPacketNumber offset) const; + EntryWrapper* GetEntryWrapper(QuicPacketNumber offset) { + const auto* const_this = this; + return const_cast<EntryWrapper*>(const_this->GetEntryWrapper(offset)); + } + + std::deque<EntryWrapper> entries_; + size_t number_of_present_entries_; + QuicPacketNumber first_packet_; +}; + +template <typename T> +T* PacketNumberIndexedQueue<T>::GetEntry(QuicPacketNumber packet_number) { + EntryWrapper* entry = GetEntryWrapper(packet_number); + if (entry == nullptr) { + return nullptr; + } + return &entry->data; +} + +template <typename T> +const T* PacketNumberIndexedQueue<T>::GetEntry( + QuicPacketNumber packet_number) const { + const EntryWrapper* entry = GetEntryWrapper(packet_number); + if (entry == nullptr) { + return nullptr; + } + return &entry->data; +} + +template <typename T> +template <typename... Args> +bool PacketNumberIndexedQueue<T>::Emplace(QuicPacketNumber packet_number, + Args&&... args) { + if (IsEmpty()) { + DCHECK(entries_.empty()); + DCHECK_EQ(0u, first_packet_); + + entries_.emplace_back(std::forward<Args>(args)...); + number_of_present_entries_ = 1; + first_packet_ = packet_number; + return true; + } + + // Do not allow insertion out-of-order. + if (packet_number <= last_packet()) { + return false; + } + + // Handle potentially missing elements. + size_t offset = packet_number - first_packet_; + if (offset > entries_.size()) { + entries_.resize(offset); + } + + number_of_present_entries_++; + entries_.emplace_back(std::forward<Args>(args)...); + DCHECK_EQ(packet_number, last_packet()); + return true; +} + +template <typename T> +bool PacketNumberIndexedQueue<T>::Remove(QuicPacketNumber packet_number) { + EntryWrapper* entry = GetEntryWrapper(packet_number); + if (entry == nullptr) { + return false; + } + entry->present = false; + number_of_present_entries_--; + + if (packet_number == first_packet()) { + Cleanup(); + } + return true; +} + +template <typename T> +void PacketNumberIndexedQueue<T>::Cleanup() { + while (!entries_.empty() && !entries_.front().present) { + entries_.pop_front(); + first_packet_++; + } + if (entries_.empty()) { + first_packet_ = 0; + } +} + +template <typename T> +auto PacketNumberIndexedQueue<T>::GetEntryWrapper(QuicPacketNumber offset) const + -> const EntryWrapper* { + if (offset < first_packet_) { + return nullptr; + } + + offset -= first_packet_; + if (offset >= entries_.size()) { + return nullptr; + } + + const EntryWrapper* entry = &entries_[offset]; + if (!entry->present) { + return nullptr; + } + + return entry; +} + +} // namespace net + +#endif // NET_QUIC_CORE_PACKET_NUMBER_INDEXED_QUEUE_H_ diff --git a/chromium/net/quic/core/packet_number_indexed_queue_test.cc b/chromium/net/quic/core/packet_number_indexed_queue_test.cc new file mode 100644 index 00000000000..3d8c6cc1ece --- /dev/null +++ b/chromium/net/quic/core/packet_number_indexed_queue_test.cc @@ -0,0 +1,181 @@ +// 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. + +#include "net/quic/core/packet_number_indexed_queue.h" + +#include <limits> +#include <map> +#include <string> + +#include "testing/gtest/include/gtest/gtest.h" + +using std::string; + +namespace net { +namespace { + +class PacketNumberIndexedQueueTest : public ::testing::Test { + public: + PacketNumberIndexedQueueTest() {} + + protected: + PacketNumberIndexedQueue<string> queue_; +}; + +TEST_F(PacketNumberIndexedQueueTest, InitialState) { + EXPECT_TRUE(queue_.IsEmpty()); + EXPECT_EQ(0u, queue_.first_packet()); + EXPECT_EQ(0u, queue_.last_packet()); + EXPECT_EQ(0u, queue_.number_of_present_entries()); + EXPECT_EQ(0u, queue_.entry_slots_used()); +} + +TEST_F(PacketNumberIndexedQueueTest, InsertingContinuousElements) { + ASSERT_TRUE(queue_.Emplace(1001, "one")); + EXPECT_EQ("one", *queue_.GetEntry(1001)); + + ASSERT_TRUE(queue_.Emplace(1002, "two")); + EXPECT_EQ("two", *queue_.GetEntry(1002)); + + EXPECT_FALSE(queue_.IsEmpty()); + EXPECT_EQ(1001u, queue_.first_packet()); + EXPECT_EQ(1002u, queue_.last_packet()); + EXPECT_EQ(2u, queue_.number_of_present_entries()); + EXPECT_EQ(2u, queue_.entry_slots_used()); +} + +TEST_F(PacketNumberIndexedQueueTest, InsertingOutOfOrder) { + queue_.Emplace(1001, "one"); + + ASSERT_TRUE(queue_.Emplace(1003, "three")); + EXPECT_EQ(nullptr, queue_.GetEntry(1002)); + EXPECT_EQ("three", *queue_.GetEntry(1003)); + + EXPECT_EQ(1001u, queue_.first_packet()); + EXPECT_EQ(1003u, queue_.last_packet()); + EXPECT_EQ(2u, queue_.number_of_present_entries()); + EXPECT_EQ(3u, queue_.entry_slots_used()); + + ASSERT_FALSE(queue_.Emplace(1002, "two")); +} + +TEST_F(PacketNumberIndexedQueueTest, InsertingIntoPast) { + queue_.Emplace(1001, "one"); + EXPECT_FALSE(queue_.Emplace(1000, "zero")); +} + +TEST_F(PacketNumberIndexedQueueTest, InsertingDuplicate) { + queue_.Emplace(1001, "one"); + EXPECT_FALSE(queue_.Emplace(1001, "one")); +} + +TEST_F(PacketNumberIndexedQueueTest, RemoveInTheMiddle) { + queue_.Emplace(1001, "one"); + queue_.Emplace(1002, "two"); + queue_.Emplace(1003, "three"); + + ASSERT_TRUE(queue_.Remove(1002)); + EXPECT_EQ(nullptr, queue_.GetEntry(1002)); + + EXPECT_EQ(1001u, queue_.first_packet()); + EXPECT_EQ(1003u, queue_.last_packet()); + EXPECT_EQ(2u, queue_.number_of_present_entries()); + EXPECT_EQ(3u, queue_.entry_slots_used()); + + EXPECT_FALSE(queue_.Emplace(1002, "two")); + EXPECT_TRUE(queue_.Emplace(1004, "four")); +} + +TEST_F(PacketNumberIndexedQueueTest, RemoveAtImmediateEdges) { + queue_.Emplace(1001, "one"); + queue_.Emplace(1002, "two"); + queue_.Emplace(1003, "three"); + ASSERT_TRUE(queue_.Remove(1001)); + EXPECT_EQ(nullptr, queue_.GetEntry(1001)); + ASSERT_TRUE(queue_.Remove(1003)); + EXPECT_EQ(nullptr, queue_.GetEntry(1003)); + + EXPECT_EQ(1002u, queue_.first_packet()); + EXPECT_EQ(1003u, queue_.last_packet()); + EXPECT_EQ(1u, queue_.number_of_present_entries()); + EXPECT_EQ(2u, queue_.entry_slots_used()); + + EXPECT_TRUE(queue_.Emplace(1004, "four")); +} + +TEST_F(PacketNumberIndexedQueueTest, RemoveAtDistantFront) { + queue_.Emplace(1001, "one"); + queue_.Emplace(1002, "one (kinda)"); + queue_.Emplace(2001, "two"); + + EXPECT_EQ(1001u, queue_.first_packet()); + EXPECT_EQ(2001u, queue_.last_packet()); + EXPECT_EQ(3u, queue_.number_of_present_entries()); + EXPECT_EQ(1001u, queue_.entry_slots_used()); + + ASSERT_TRUE(queue_.Remove(1002)); + EXPECT_EQ(1001u, queue_.first_packet()); + EXPECT_EQ(2001u, queue_.last_packet()); + EXPECT_EQ(2u, queue_.number_of_present_entries()); + EXPECT_EQ(1001u, queue_.entry_slots_used()); + + ASSERT_TRUE(queue_.Remove(1001)); + EXPECT_EQ(2001u, queue_.first_packet()); + EXPECT_EQ(2001u, queue_.last_packet()); + EXPECT_EQ(1u, queue_.number_of_present_entries()); + EXPECT_EQ(1u, queue_.entry_slots_used()); +} + +TEST_F(PacketNumberIndexedQueueTest, RemoveAtDistantBack) { + queue_.Emplace(1001, "one"); + queue_.Emplace(2001, "two"); + + EXPECT_EQ(1001u, queue_.first_packet()); + EXPECT_EQ(2001u, queue_.last_packet()); + + ASSERT_TRUE(queue_.Remove(2001)); + EXPECT_EQ(1001u, queue_.first_packet()); + EXPECT_EQ(2001u, queue_.last_packet()); +} + +TEST_F(PacketNumberIndexedQueueTest, ClearAndRepopulate) { + queue_.Emplace(1001, "one"); + queue_.Emplace(2001, "two"); + + ASSERT_TRUE(queue_.Remove(1001)); + ASSERT_TRUE(queue_.Remove(2001)); + EXPECT_TRUE(queue_.IsEmpty()); + EXPECT_EQ(0u, queue_.first_packet()); + EXPECT_EQ(0u, queue_.last_packet()); + + EXPECT_TRUE(queue_.Emplace(101, "one")); + EXPECT_TRUE(queue_.Emplace(201, "two")); + EXPECT_EQ(101u, queue_.first_packet()); + EXPECT_EQ(201u, queue_.last_packet()); +} + +TEST_F(PacketNumberIndexedQueueTest, FailToRemoveElementsThatNeverExisted) { + ASSERT_FALSE(queue_.Remove(1000)); + queue_.Emplace(1001, "one"); + ASSERT_FALSE(queue_.Remove(1000)); + ASSERT_FALSE(queue_.Remove(1002)); +} + +TEST_F(PacketNumberIndexedQueueTest, FailToRemoveElementsTwice) { + queue_.Emplace(1001, "one"); + ASSERT_TRUE(queue_.Remove(1001)); + ASSERT_FALSE(queue_.Remove(1001)); + ASSERT_FALSE(queue_.Remove(1001)); +} + +TEST_F(PacketNumberIndexedQueueTest, ConstGetter) { + queue_.Emplace(1001, "one"); + const auto& const_queue = queue_; + + EXPECT_EQ("one", *const_queue.GetEntry(1001)); + EXPECT_EQ(nullptr, const_queue.GetEntry(1002)); +} + +} // namespace +} // namespace net diff --git a/chromium/net/quic/core/quic_alarm_test.cc b/chromium/net/quic/core/quic_alarm_test.cc index cb6aeac464c..ce4d4b504fb 100644 --- a/chromium/net/quic/core/quic_alarm_test.cc +++ b/chromium/net/quic/core/quic_alarm_test.cc @@ -4,8 +4,7 @@ #include "net/quic/core/quic_alarm.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" using testing::Return; using testing::Invoke; @@ -74,7 +73,7 @@ class DestructiveAlarm : public QuicAlarm { void CancelImpl() override {} }; -class QuicAlarmTest : public ::testing::Test { +class QuicAlarmTest : public QuicTest { public: QuicAlarmTest() : delegate_(new MockDelegate()), diff --git a/chromium/net/quic/core/quic_arena_scoped_ptr_test.cc b/chromium/net/quic/core/quic_arena_scoped_ptr_test.cc index 7c59e479489..a404b4584dc 100644 --- a/chromium/net/quic/core/quic_arena_scoped_ptr_test.cc +++ b/chromium/net/quic/core/quic_arena_scoped_ptr_test.cc @@ -5,8 +5,7 @@ #include "net/quic/core/quic_arena_scoped_ptr.h" #include "net/quic/core/quic_one_block_arena.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace { @@ -22,7 +21,7 @@ struct TestObject { std::vector<char> buffer; }; -class QuicArenaScopedPtrParamTest : public ::testing::TestWithParam<TestParam> { +class QuicArenaScopedPtrParamTest : public QuicTestWithParam<TestParam> { protected: QuicArenaScopedPtr<TestObject> CreateObject(uintptr_t value) { QuicArenaScopedPtr<TestObject> ptr; @@ -48,7 +47,7 @@ INSTANTIATE_TEST_CASE_P(QuicArenaScopedPtrParamTest, testing::Values(TestParam::kFromHeap, TestParam::kFromArena)); -TEST(QuicArenaScopedPtrTest, NullObjects) { +TEST_P(QuicArenaScopedPtrParamTest, NullObjects) { QuicArenaScopedPtr<TestObject> def; QuicArenaScopedPtr<TestObject> null(nullptr); EXPECT_EQ(def, null); @@ -56,7 +55,7 @@ TEST(QuicArenaScopedPtrTest, NullObjects) { EXPECT_EQ(null, nullptr); } -TEST(QuicArenaScopedPtrTest, FromArena) { +TEST_P(QuicArenaScopedPtrParamTest, FromArena) { QuicOneBlockArena<1024> arena_; EXPECT_TRUE(arena_.New<TestObject>(0).is_from_arena()); EXPECT_FALSE( diff --git a/chromium/net/quic/core/quic_bandwidth_test.cc b/chromium/net/quic/core/quic_bandwidth_test.cc index 17b46e24fcd..406b62d2de2 100644 --- a/chromium/net/quic/core/quic_bandwidth_test.cc +++ b/chromium/net/quic/core/quic_bandwidth_test.cc @@ -4,12 +4,12 @@ #include "net/quic/core/quic_bandwidth.h" #include "net/quic/core/quic_time.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { -class QuicBandwidthTest : public ::testing::Test {}; +class QuicBandwidthTest : public QuicTest {}; TEST_F(QuicBandwidthTest, FromTo) { EXPECT_EQ(QuicBandwidth::FromKBitsPerSecond(1), diff --git a/chromium/net/quic/core/quic_buffered_packet_store.cc b/chromium/net/quic/core/quic_buffered_packet_store.cc index 8c4ac46add6..c2b4a4e6456 100644 --- a/chromium/net/quic/core/quic_buffered_packet_store.cc +++ b/chromium/net/quic/core/quic_buffered_packet_store.cc @@ -4,8 +4,8 @@ #include "net/quic/core/quic_buffered_packet_store.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_map_util.h" namespace net { diff --git a/chromium/net/quic/core/quic_buffered_packet_store_test.cc b/chromium/net/quic/core/quic_buffered_packet_store_test.cc index 698316339c8..6ab09c57be0 100644 --- a/chromium/net/quic/core/quic_buffered_packet_store_test.cc +++ b/chromium/net/quic/core/quic_buffered_packet_store_test.cc @@ -7,12 +7,11 @@ #include <list> #include <string> -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/quic_buffered_packet_store_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; @@ -47,7 +46,7 @@ class QuicBufferedPacketStoreVisitor BufferedPacketList last_expired_packet_queue_; }; -class QuicBufferedPacketStoreTest : public ::testing::Test { +class QuicBufferedPacketStoreTest : public QuicTest { public: QuicBufferedPacketStoreTest() : store_(&visitor_, &clock_, &alarm_factory_), @@ -58,7 +57,6 @@ class QuicBufferedPacketStoreTest : public ::testing::Test { packet_(packet_content_.data(), packet_content_.size(), packet_time_) {} protected: - QuicFlagSaver flags_; // Save/restore all QUIC flag values. QuicBufferedPacketStoreVisitor visitor_; MockClock clock_; MockAlarmFactory alarm_factory_; diff --git a/chromium/net/quic/core/quic_client_promised_info.h b/chromium/net/quic/core/quic_client_promised_info.h index 0f4bd8dcdf6..1f755fe45c1 100644 --- a/chromium/net/quic/core/quic_client_promised_info.h +++ b/chromium/net/quic/core/quic_client_promised_info.h @@ -14,7 +14,7 @@ #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_spdy_stream.h" #include "net/quic/platform/api/quic_export.h" -#include "net/spdy/spdy_framer.h" +#include "net/spdy/core/spdy_framer.h" namespace net { diff --git a/chromium/net/quic/core/quic_client_promised_info_test.cc b/chromium/net/quic/core/quic_client_promised_info_test.cc index f9503909dde..954f21b4425 100644 --- a/chromium/net/quic/core/quic_client_promised_info_test.cc +++ b/chromium/net/quic/core/quic_client_promised_info_test.cc @@ -10,8 +10,10 @@ #include "net/quic/core/spdy_utils.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_socket_address.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/quic_client_promised_info_peer.h" +#include "net/quic/test_tools/quic_spdy_session_peer.h" #include "net/test/gtest_util.h" #include "net/tools/quic/quic_client_session.h" @@ -50,7 +52,7 @@ class MockQuicClientSession : public QuicClientSession { DISALLOW_COPY_AND_ASSIGN(MockQuicClientSession); }; -class QuicClientPromisedInfoTest : public ::testing::Test { +class QuicClientPromisedInfoTest : public QuicTest { public: class StreamVisitor; @@ -60,13 +62,15 @@ class QuicClientPromisedInfoTest : public ::testing::Test { Perspective::IS_CLIENT)), session_(connection_, &push_promise_index_), body_("hello world"), - promise_id_(kServerDataStreamId1) { + promise_id_(kInvalidStreamId) { session_.Initialize(); headers_[":status"] = "200"; headers_["content-length"] = "11"; - stream_.reset(new QuicSpdyClientStream(kClientDataStreamId1, &session_)); + stream_.reset(new QuicSpdyClientStream( + QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0), + &session_)); stream_visitor_.reset(new StreamVisitor()); stream_->set_visitor(stream_visitor_.get()); @@ -79,6 +83,8 @@ class QuicClientPromisedInfoTest : public ::testing::Test { promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_); client_request_ = push_promise_.Clone(); + promise_id_ = + QuicSpdySessionPeer::GetNthServerInitiatedStreamId(session_, 0); } class StreamVisitor : public QuicSpdyClientStream::Visitor { diff --git a/chromium/net/quic/core/quic_client_push_promise_index_test.cc b/chromium/net/quic/core/quic_client_push_promise_index_test.cc index cdc09028612..0a93cf177e2 100644 --- a/chromium/net/quic/core/quic_client_push_promise_index_test.cc +++ b/chromium/net/quic/core/quic_client_push_promise_index_test.cc @@ -7,8 +7,10 @@ #include <string> #include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/mock_quic_client_promised_info.h" +#include "net/quic/test_tools/quic_spdy_session_peer.h" #include "net/quic/test_tools/quic_test_utils.h" #include "net/tools/quic/quic_client_session.h" @@ -42,14 +44,17 @@ class MockQuicClientSession : public QuicClientSession { DISALLOW_COPY_AND_ASSIGN(MockQuicClientSession); }; -class QuicClientPushPromiseIndexTest : public ::testing::Test { +class QuicClientPushPromiseIndexTest : public QuicTest { public: QuicClientPushPromiseIndexTest() : connection_(new StrictMock<MockQuicConnection>(&helper_, &alarm_factory_, Perspective::IS_CLIENT)), session_(connection_, &index_), - promised_(&session_, kServerDataStreamId1, url_) { + promised_( + &session_, + QuicSpdySessionPeer::GetNthServerInitiatedStreamId(session_, 0), + url_) { request_[":path"] = "/bar"; request_[":authority"] = "www.google.com"; request_[":version"] = "HTTP/1.1"; diff --git a/chromium/net/quic/core/quic_client_session_base.cc b/chromium/net/quic/core/quic_client_session_base.cc index 1c7e1016579..b13496d73d7 100644 --- a/chromium/net/quic/core/quic_client_session_base.cc +++ b/chromium/net/quic/core/quic_client_session_base.cc @@ -5,8 +5,8 @@ #include "net/quic/core/quic_client_session_base.h" #include "net/quic/core/quic_client_promised_info.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" using std::string; diff --git a/chromium/net/quic/core/quic_config.cc b/chromium/net/quic/core/quic_config.cc index 9a29d94b1df..745370895e4 100644 --- a/chromium/net/quic/core/quic_config.cc +++ b/chromium/net/quic/core/quic_config.cc @@ -8,11 +8,11 @@ #include "net/quic/core/crypto/crypto_handshake_message.h" #include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_socket_address_coder.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_string_piece.h" @@ -341,9 +341,7 @@ QuicConfig::QuicConfig() connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL), alternate_server_address_(kASAD, PRESENCE_OPTIONAL), force_hol_blocking_(kFHL2, PRESENCE_OPTIONAL), - support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL), - latched_no_socket_receive_buffer_( - FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { + support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL) { SetDefaults(); } @@ -544,22 +542,6 @@ uint32_t QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const { return initial_session_flow_control_window_bytes_.GetReceivedValue(); } -void QuicConfig::SetSocketReceiveBufferToSend(uint32_t tcp_receive_window) { - if (latched_no_socket_receive_buffer_) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_no_socket_receive_buffer, 1, 3); - } else { - socket_receive_buffer_.SetSendValue(tcp_receive_window); - } -} - -bool QuicConfig::HasReceivedSocketReceiveBuffer() const { - return socket_receive_buffer_.HasReceivedValue(); -} - -uint32_t QuicConfig::ReceivedSocketReceiveBuffer() const { - return socket_receive_buffer_.GetReceivedValue(); -} - void QuicConfig::SetDisableConnectionMigration() { connection_migration_disabled_.SetSendValue(1); } @@ -638,11 +620,6 @@ void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const { initial_round_trip_time_us_.ToHandshakeMessage(out); initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out); initial_session_flow_control_window_bytes_.ToHandshakeMessage(out); - if (latched_no_socket_receive_buffer_) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_no_socket_receive_buffer, 2, 3); - } else { - socket_receive_buffer_.ToHandshakeMessage(out); - } connection_migration_disabled_.ToHandshakeMessage(out); connection_options_.ToHandshakeMessage(out); alternate_server_address_.ToHandshakeMessage(out); @@ -689,12 +666,6 @@ QuicErrorCode QuicConfig::ProcessPeerHello( error = initial_session_flow_control_window_bytes_.ProcessPeerHello( peer_hello, hello_type, error_details); } - if (latched_no_socket_receive_buffer_) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_no_socket_receive_buffer, 3, 3); - } else if (error == QUIC_NO_ERROR) { - error = socket_receive_buffer_.ProcessPeerHello(peer_hello, hello_type, - error_details); - } if (error == QUIC_NO_ERROR) { error = connection_migration_disabled_.ProcessPeerHello( peer_hello, hello_type, error_details); diff --git a/chromium/net/quic/core/quic_config.h b/chromium/net/quic/core/quic_config.h index c1d7a89c4a5..7737689d1de 100644 --- a/chromium/net/quic/core/quic_config.h +++ b/chromium/net/quic/core/quic_config.h @@ -344,13 +344,6 @@ class QUIC_EXPORT_PRIVATE QuicConfig { uint32_t ReceivedInitialSessionFlowControlWindowBytes() const; - // Sets socket receive buffer to transmit to the peer. - void SetSocketReceiveBufferToSend(uint32_t window_bytes); - - bool HasReceivedSocketReceiveBuffer() const; - - uint32_t ReceivedSocketReceiveBuffer() const; - void SetDisableConnectionMigration(); bool DisableConnectionMigration() const; @@ -435,9 +428,6 @@ class QUIC_EXPORT_PRIVATE QuicConfig { // Whether support HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame. QuicFixedUint32 support_max_header_list_size_; - - // Latched copy of FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer - bool latched_no_socket_receive_buffer_; }; } // namespace net diff --git a/chromium/net/quic/core/quic_config_test.cc b/chromium/net/quic/core/quic_config_test.cc index 06e789d67e3..32df9eaa376 100644 --- a/chromium/net/quic/core/quic_config_test.cc +++ b/chromium/net/quic/core/quic_config_test.cc @@ -9,10 +9,10 @@ #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_time.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_config_peer.h" #include "net/quic/test_tools/quic_test_utils.h" #include "net/test/gtest_util.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; @@ -20,7 +20,7 @@ namespace net { namespace test { namespace { -class QuicConfigTest : public ::testing::Test { +class QuicConfigTest : public QuicTest { protected: QuicConfig config_; }; @@ -33,9 +33,6 @@ TEST_F(QuicConfigTest, ToHandshakeMessage) { config_.SetIdleNetworkTimeout(QuicTime::Delta::FromSeconds(5), QuicTime::Delta::FromSeconds(2)); config_.SetMaxStreamsPerConnection(4, 2); - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - config_.SetSocketReceiveBufferToSend(kDefaultSocketReceiveBuffer); - } CryptoHandshakeMessage msg; config_.ToHandshakeMessage(&msg); @@ -55,12 +52,6 @@ TEST_F(QuicConfigTest, ToHandshakeMessage) { error = msg.GetUint32(kCFCW, &value); EXPECT_EQ(QUIC_NO_ERROR, error); EXPECT_EQ(kInitialSessionFlowControlWindowForTest, value); - - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - error = msg.GetUint32(kSRBF, &value); - EXPECT_EQ(QUIC_NO_ERROR, error); - EXPECT_EQ(kDefaultSocketReceiveBuffer, value); - } } TEST_F(QuicConfigTest, ProcessClientHello) { @@ -77,9 +68,6 @@ TEST_F(QuicConfigTest, ProcessClientHello) { 2 * kInitialStreamFlowControlWindowForTest); client_config.SetInitialSessionFlowControlWindowToSend( 2 * kInitialSessionFlowControlWindowForTest); - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - client_config.SetSocketReceiveBufferToSend(kDefaultSocketReceiveBuffer); - } client_config.SetForceHolBlocking(); QuicTagVector copt; copt.push_back(kTBBR); @@ -115,10 +103,6 @@ TEST_F(QuicConfigTest, ProcessClientHello) { 2 * kInitialStreamFlowControlWindowForTest); EXPECT_EQ(config_.ReceivedInitialSessionFlowControlWindowBytes(), 2 * kInitialSessionFlowControlWindowForTest); - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - EXPECT_EQ(config_.ReceivedSocketReceiveBuffer(), - kDefaultSocketReceiveBuffer); - } } TEST_F(QuicConfigTest, ProcessServerHello) { @@ -138,9 +122,6 @@ TEST_F(QuicConfigTest, ProcessServerHello) { 2 * kInitialStreamFlowControlWindowForTest); server_config.SetInitialSessionFlowControlWindowToSend( 2 * kInitialSessionFlowControlWindowForTest); - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - server_config.SetSocketReceiveBufferToSend(kDefaultSocketReceiveBuffer); - } server_config.SetAlternateServerAddressToSend(kTestServerAddress); CryptoHandshakeMessage msg; server_config.ToHandshakeMessage(&msg); @@ -158,10 +139,6 @@ TEST_F(QuicConfigTest, ProcessServerHello) { 2 * kInitialStreamFlowControlWindowForTest); EXPECT_EQ(config_.ReceivedInitialSessionFlowControlWindowBytes(), 2 * kInitialSessionFlowControlWindowForTest); - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - EXPECT_EQ(config_.ReceivedSocketReceiveBuffer(), - kDefaultSocketReceiveBuffer); - } EXPECT_TRUE(config_.HasReceivedAlternateServerAddress()); EXPECT_EQ(kTestServerAddress, config_.ReceivedAlternateServerAddress()); } diff --git a/chromium/net/quic/core/quic_connection.cc b/chromium/net/quic/core/quic_connection.cc index 99daacf033e..6ca59553cbb 100644 --- a/chromium/net/quic/core/quic_connection.cc +++ b/chromium/net/quic/core/quic_connection.cc @@ -24,12 +24,12 @@ #include "net/quic/core/proto/cached_network_parameters.pb.h" #include "net/quic/core/quic_bandwidth.h" #include "net/quic/core/quic_config.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packet_generator.h" #include "net/quic/core/quic_pending_retransmission.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_map_util.h" #include "net/quic/platform/api/quic_str_cat.h" @@ -49,8 +49,12 @@ namespace { const QuicPacketNumber kMaxPacketGap = 5000; // Maximum number of acks received before sending an ack in response. +// TODO(fayang): Remove this constant when deprecating QUIC_VERSION_38. const QuicPacketCount kMaxPacketsReceivedBeforeAckSend = 20; +// Maximum number of consecutive sent nonretransmittable packets. +const QuicPacketCount kMaxConsecutiveNonRetransmittablePackets = 19; + // Maximum number of retransmittable packets received before sending an ack. const QuicPacketCount kDefaultRetransmittablePacketsBeforeAck = 2; // Minimum number of packets received before ack decimation is enabled. @@ -203,6 +207,7 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id, idle_timeout_connection_close_behavior_( ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET), close_connection_after_five_rtos_(false), + close_connection_after_three_rtos_(false), received_packet_manager_(&stats_), ack_queued_(false), num_retransmittable_packets_received_since_last_ack_sent_(0), @@ -240,6 +245,7 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id, debug_visitor_(nullptr), packet_generator_(connection_id_, &framer_, + random_generator_, helper->GetBufferAllocator(), this), idle_network_timeout_(QuicTime::Delta::Infinite()), @@ -260,7 +266,8 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id, goaway_sent_(false), goaway_received_(false), write_error_occured_(false), - no_stop_waiting_frames_(false) { + no_stop_waiting_frames_(false), + consecutive_num_packets_with_no_retransmittable_frames_(0) { QUIC_DLOG(INFO) << ENDPOINT << "Created connection with connection_id: " << connection_id; framer_.set_visitor(this); @@ -345,7 +352,13 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) { if (config.HasClientSentConnectionOption(k5RTO, perspective_)) { close_connection_after_five_rtos_ = true; } + if (FLAGS_quic_reloadable_flag_quic_enable_3rtos && + config.HasClientSentConnectionOption(k3RTO, perspective_)) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_3rtos); + close_connection_after_three_rtos_ = true; + } if (packet_generator_.latched_flag_no_stop_waiting_frames() && + version() > QUIC_VERSION_37 && config.HasClientSentConnectionOption(kNSTP, perspective_)) { QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_no_stop_waiting_frames, 2, 2); no_stop_waiting_frames_ = true; @@ -931,8 +944,9 @@ void QuicConnection::MaybeQueueAck(bool was_missing) { ++num_packets_received_since_last_ack_sent_; // Always send an ack every 20 packets in order to allow the peer to discard // information from the SentPacketManager and provide an RTT measurement. - if (num_packets_received_since_last_ack_sent_ >= - kMaxPacketsReceivedBeforeAckSend) { + if (version() <= QUIC_VERSION_38 && + num_packets_received_since_last_ack_sent_ >= + kMaxPacketsReceivedBeforeAckSend) { ack_queued_ = true; } @@ -1056,9 +1070,9 @@ QuicConsumedData QuicConnection::SendStreamData( QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { - if (!fin && iov.total_length == 0) { + if (state == NO_FIN && iov.total_length == 0) { QUIC_BUG << "Attempt to send empty stream frame"; return QuicConsumedData(0, false); } @@ -1073,12 +1087,12 @@ QuicConsumedData QuicConnection::SendStreamData( // The optimized path may be used for data only packets which fit into a // standard buffer and don't need padding. if (id != kCryptoStreamId && !packet_generator_.HasQueuedFrames() && - iov.total_length > kMaxPacketSize) { + iov.total_length > kMaxPacketSize && state != FIN_AND_PADDING) { // Use the fast path to send full data packets. - return packet_generator_.ConsumeDataFastPath(id, iov, offset, fin, - std::move(ack_listener)); + return packet_generator_.ConsumeDataFastPath( + id, iov, offset, state != NO_FIN, std::move(ack_listener)); } - return packet_generator_.ConsumeData(id, iov, offset, fin, + return packet_generator_.ConsumeData(id, iov, offset, state, std::move(ack_listener)); } @@ -1115,6 +1129,8 @@ void QuicConnection::SendRstStream(QuicStreamId id, ClearSerializedPacket(&(*packet_iterator)); packet_iterator = queued_packets_.erase(packet_iterator); } + // TODO(ianswett): Consider checking for 3 RTOs when the last stream is + // cancelled as well. } void QuicConnection::SendWindowUpdate(QuicStreamId id, @@ -1297,17 +1313,6 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) { return false; } - // Multipath is not enabled, but a packet with multipath flag on is - // received. - if (header.public_header.multipath_flag) { - const string error_details = - "Received a packet with multipath flag but multipath is not enabled."; - QUIC_BUG << error_details; - CloseConnection(QUIC_BAD_MULTIPATH_FLAG, error_details, - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return false; - } - if (version_negotiation_state_ != NEGOTIATED_VERSION) { if (perspective_ == Perspective::IS_SERVER) { if (!header.public_header.version_flag) { @@ -1658,6 +1663,17 @@ void QuicConnection::OnSerializedPacket(SerializedPacket* serialized_packet) { ConnectionCloseSource::FROM_SELF); return; } + + if (version() > QUIC_VERSION_38) { + if (serialized_packet->retransmittable_frames.empty() && + serialized_packet->original_packet_number == 0) { + // Increment consecutive_num_packets_with_no_retransmittable_frames_ if + // this packet is a new transmission with no retransmittable frames. + ++consecutive_num_packets_with_no_retransmittable_frames_; + } else { + consecutive_num_packets_with_no_retransmittable_frames_ = 0; + } + } SendOrQueuePacket(serialized_packet); } @@ -1747,11 +1763,34 @@ void QuicConnection::SendAck() { num_packets_received_since_last_ack_sent_ = 0; packet_generator_.SetShouldSendAck(!no_stop_waiting_frames_); + if (consecutive_num_packets_with_no_retransmittable_frames_ < + kMaxConsecutiveNonRetransmittablePackets) { + return; + } + consecutive_num_packets_with_no_retransmittable_frames_ = 0; + if (packet_generator_.HasRetransmittableFrames()) { + // There is pending retransmittable frames. + return; + } + + visitor_->OnAckNeedsRetransmittableFrame(); + if (!packet_generator_.HasRetransmittableFrames()) { + // Visitor did not add a retransmittable frame, add a ping frame. + packet_generator_.AddControlFrame(QuicFrame(QuicPingFrame())); + } } void QuicConnection::OnRetransmissionTimeout() { DCHECK(sent_packet_manager_.HasUnackedPackets()); + if (close_connection_after_three_rtos_ && + sent_packet_manager_.GetConsecutiveRtoCount() >= 2 && + !visitor_->HasOpenDynamicStreams()) { + // Close on the 3rd consecutive RTO, so after 2 previous RTOs have occurred. + CloseConnection(QUIC_TOO_MANY_RTOS, "3 consecutive retransmission timeouts", + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + return; + } if (close_connection_after_five_rtos_ && sent_packet_manager_.GetConsecutiveRtoCount() >= 4) { // Close on the 5th consecutive RTO, so after 4 previous RTOs have occurred. diff --git a/chromium/net/quic/core/quic_connection.h b/chromium/net/quic/core/quic_connection.h index e5bf4ca9168..fd78c93dd79 100644 --- a/chromium/net/quic/core/quic_connection.h +++ b/chromium/net/quic/core/quic_connection.h @@ -141,6 +141,12 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface { // been done. virtual void PostProcessAfterData() = 0; + // Called when the connection sends ack after + // kMaxConsecutiveNonRetransmittablePackets consecutive not retransmittable + // packets sent. To instigate an ack from peer, a retransmittable frame needs + // to be added. + virtual void OnAckNeedsRetransmittableFrame() = 0; + // Called to ask if the visitor wants to schedule write resumption as it both // has pending data to write, and is able to write (e.g. based on flow control // limits). @@ -345,7 +351,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); // Send a RST_STREAM frame to the peer. @@ -924,6 +930,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection // When true, close the QUIC connection after 5 RTOs. Due to the min rto of // 200ms, this is over 5 seconds. bool close_connection_after_five_rtos_; + // When true, close the QUIC connection when there are no open streams after + // 3 consecutive RTOs. + bool close_connection_after_three_rtos_; QuicReceivedPacketManager received_packet_manager_; @@ -1082,6 +1091,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection // Indicates not to send or process stop waiting frames. bool no_stop_waiting_frames_; + // Consecutive number of sent packets which have no retransmittable frames. + size_t consecutive_num_packets_with_no_retransmittable_frames_; + DISALLOW_COPY_AND_ASSIGN(QuicConnection); }; diff --git a/chromium/net/quic/core/quic_connection_test.cc b/chromium/net/quic/core/quic_connection_test.cc index 92b57be616c..6f95275b0ee 100644 --- a/chromium/net/quic/core/quic_connection_test.cc +++ b/chromium/net/quic/core/quic_connection_test.cc @@ -17,13 +17,15 @@ #include "net/quic/core/crypto/null_encrypter.h" #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_simple_buffer_allocator.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_reference_counted.h" #include "net/quic/platform/api/quic_str_cat.h" +#include "net/quic/platform/api/quic_string_piece.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/mock_random.h" #include "net/quic/test_tools/quic_config_peer.h" @@ -35,14 +37,14 @@ #include "net/quic/test_tools/quic_test_utils.h" #include "net/quic/test_tools/simple_quic_framer.h" #include "net/test/gtest_util.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gmock_mutant.h" using std::string; using testing::AnyNumber; using testing::AtLeast; using testing::DoAll; using testing::InSequence; +using testing::Invoke; using testing::InvokeWithoutArgs; using testing::NiceMock; using testing::Ref; @@ -56,10 +58,12 @@ namespace net { namespace test { namespace { +const QuicStreamId kClientDataStreamId1 = kHeadersStreamId + 2; +const QuicStreamId kClientDataStreamId2 = kClientDataStreamId1 + 2; + const char data1[] = "foo"; const char data2[] = "bar"; -const bool kFin = true; const bool kHasStopWaiting = true; const int kDefaultRetransmissionTimeMs = 500; @@ -390,6 +394,14 @@ class TestPacketWriter : public QuicPacketWriter { return framer_.ping_frames(); } + const std::vector<QuicWindowUpdateFrame>& window_update_frames() const { + return framer_.window_update_frames(); + } + + const std::vector<QuicPaddingFrame>& padding_frames() const { + return framer_.padding_frames(); + } + size_t last_packet_size() { return last_packet_size_; } const QuicVersionNegotiationPacket* version_negotiation_packet() { @@ -511,24 +523,24 @@ class TestConnection : public QuicConnection { QuicStreamId id, QuicStringPiece data, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { if (id != kCryptoStreamId && this->encryption_level() == ENCRYPTION_NONE) { this->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); } struct iovec iov; QuicIOVector data_iov(MakeIOVector(data, &iov)); - return QuicConnection::SendStreamData(id, data_iov, offset, fin, + return QuicConnection::SendStreamData(id, data_iov, offset, state, std::move(ack_listener)); } QuicConsumedData SendStreamData3() { - return SendStreamDataWithString(kClientDataStreamId1, "food", 0, !kFin, + return SendStreamDataWithString(kClientDataStreamId1, "food", 0, NO_FIN, nullptr); } QuicConsumedData SendStreamData5() { - return SendStreamDataWithString(kClientDataStreamId2, "food2", 0, !kFin, + return SendStreamDataWithString(kClientDataStreamId2, "food2", 0, NO_FIN, nullptr); } @@ -544,7 +556,8 @@ class TestConnection : public QuicConnection { // split needlessly across packet boundaries). As a result, we have separate // tests for some cases for this stream. QuicConsumedData SendCryptoStreamData() { - return SendStreamDataWithString(kCryptoStreamId, "chlo", 0, !kFin, nullptr); + return SendStreamDataWithString(kCryptoStreamId, "chlo", 0, NO_FIN, + nullptr); } void set_version(QuicVersion version) { @@ -570,6 +583,7 @@ class TestConnection : public QuicConnection { QuicTagVector connection_options; connection_options.push_back(kMTUH); config.SetConnectionOptionsToSend(connection_options); + EXPECT_CALL(*send_algorithm, GetCongestionControlType()); EXPECT_CALL(*send_algorithm, SetFromConfig(_, _)); SetFromConfig(config); @@ -676,7 +690,7 @@ std::vector<TestParams> GetTestParams() { return params; } -class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { +class QuicConnectionTest : public QuicTestWithParam<TestParams> { protected: QuicConnectionTest() : connection_id_(42), @@ -690,7 +704,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { peer_framer_(SupportedVersions(version()), QuicTime::Zero(), Perspective::IS_SERVER), - peer_creator_(connection_id_, + peer_creator_(GetPeerInMemoryConnectionId(connection_id_), &peer_framer_, &buffer_allocator_, /*delegate=*/nullptr), @@ -832,10 +846,10 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { QuicFrame frame, EncryptionLevel level) { QuicPacketHeader header; - header.public_header.connection_id = connection_id_; + header.public_header.connection_id = + GetPeerInMemoryConnectionId(connection_id_); header.public_header.packet_number_length = packet_number_length_; header.public_header.connection_id_length = connection_id_length_; - header.public_header.multipath_flag = false; header.packet_number = number; QuicFrames frames; frames.push_back(frame); @@ -884,12 +898,12 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { QuicByteCount SendStreamDataToPeer(QuicStreamId id, QuicStringPiece data, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicPacketNumber* last_packet) { QuicByteCount packet_size; EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&packet_size), Return(true))); - connection_.SendStreamDataWithString(id, data, offset, fin, nullptr); + connection_.SendStreamDataWithString(id, data, offset, state, nullptr); if (last_packet != nullptr) { *last_packet = creator_->packet_number(); } @@ -942,10 +956,12 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { QuicPacket* ConstructDataPacket(QuicPacketNumber number, bool has_stop_waiting) { QuicPacketHeader header; - header.public_header.connection_id = connection_id_; + // Set connection_id to peer's in memory representation as this data packet + // is created by peer_framer. + header.public_header.connection_id = + GetPeerInMemoryConnectionId(connection_id_); header.public_header.packet_number_length = packet_number_length_; header.public_header.connection_id_length = connection_id_length_; - header.public_header.multipath_flag = false; header.packet_number = number; QuicFrames frames; @@ -958,7 +974,10 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { QuicPacket* ConstructClosePacket(QuicPacketNumber number) { QuicPacketHeader header; - header.public_header.connection_id = connection_id_; + // Set connection_id to peer's in memory representation as this connection + // close packet is created by peer_framer. + header.public_header.connection_id = + GetPeerInMemoryConnectionId(connection_id_); header.packet_number = number; QuicConnectionCloseFrame qccf; @@ -1044,8 +1063,6 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { InvertPerspective(perspective)); } - QuicFlagSaver flags_; // Save/restore all QUIC flag values. - QuicConnectionId connection_id_; QuicFramer framer_; @@ -1199,7 +1216,8 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) { connection_.SetMaxPacketLength(1000); QuicPacketHeader header; - header.public_header.connection_id = connection_id_; + header.public_header.connection_id = + GetPeerInMemoryConnectionId(connection_id_); header.public_header.version_flag = true; header.packet_number = 1; @@ -1232,7 +1250,8 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSizeWhileWriterLimited) { EXPECT_EQ(1000u, connection_.max_packet_length()); QuicPacketHeader header; - header.public_header.connection_id = connection_id_; + header.public_header.connection_id = + GetPeerInMemoryConnectionId(connection_id_); header.public_header.version_flag = true; header.packet_number = 1; @@ -1409,8 +1428,8 @@ TEST_P(QuicConnectionTest, OutOfOrderReceiptCausesAckSend) { TEST_P(QuicConnectionTest, OutOfOrderAckReceiptCausesNoAck) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); - SendStreamDataToPeer(1, "bar", 3, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); + SendStreamDataToPeer(1, "bar", 3, NO_FIN, nullptr); EXPECT_EQ(2u, writer_->packets_write_attempts()); QuicAckFrame ack1 = InitAckFrame(1); @@ -1432,7 +1451,7 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce( DoAll(SaveArg<2>(&original), SaveArg<3>(&packet_size), Return(true))); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); QuicAckFrame frame = InitAckFrame(original); NackPacket(original, &frame); // First nack triggers early retransmit. @@ -1459,7 +1478,7 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) { // indicate the high water mark needs to be raised. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)); - connection_.SendStreamDataWithString(3, "foo", 3, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 3, NO_FIN, nullptr); // No ack sent. EXPECT_EQ(1u, writer_->frame_count()); EXPECT_EQ(1u, writer_->stream_frames().size()); @@ -1469,7 +1488,7 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) { ProcessAckPacket(&frame2); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)); - connection_.SendStreamDataWithString(3, "foo", 3, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 3, NO_FIN, nullptr); // Ack bundled. if (GetParam().no_stop_waiting) { EXPECT_EQ(2u, writer_->frame_count()); @@ -1486,9 +1505,12 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) { } TEST_P(QuicConnectionTest, 20AcksCausesAckSend) { + if (connection_.version() > QUIC_VERSION_38) { + return; + } EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); QuicAlarm* ack_alarm = QuicConnectionPeer::GetAckAlarm(&connection_); // But an ack with no missing packets will not send an ack. @@ -1504,12 +1526,60 @@ TEST_P(QuicConnectionTest, 20AcksCausesAckSend) { EXPECT_EQ(2u, writer_->packets_write_attempts()); } +TEST_P(QuicConnectionTest, AckNeedsRetransmittableFrames) { + if (connection_.version() <= QUIC_VERSION_38) { + return; + } + + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(99); + + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(19); + // Receives packets 1 - 39. + for (size_t i = 1; i <= 39; ++i) { + ProcessDataPacket(i); + } + // Receiving Packet 40 causes 20th ack to send. Session is informed and adds + // WINDOW_UPDATE. + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()) + .WillOnce( + Invoke(testing::CreateFunctor(&QuicConnection::SendWindowUpdate, + base::Unretained(&connection_), 0, 0))); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); + EXPECT_EQ(0u, writer_->window_update_frames().size()); + ProcessDataPacket(40); + EXPECT_EQ(1u, writer_->window_update_frames().size()); + + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(9); + // Receives packets 41 - 59. + for (size_t i = 41; i <= 59; ++i) { + ProcessDataPacket(i); + } + // Send a packet containing stream frame. + SendStreamDataToPeer(1, "bar", 3, NO_FIN, nullptr); + + // Session will not be informed until receiving another 20 packets. + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(19); + for (size_t i = 60; i <= 98; ++i) { + ProcessDataPacket(i); + EXPECT_EQ(0u, writer_->window_update_frames().size()); + } + // Session does not add a retransmittable frame. + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(1); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); + EXPECT_EQ(0u, writer_->ping_frames().size()); + ProcessDataPacket(99); + EXPECT_EQ(0u, writer_->window_update_frames().size()); + // A ping frame will be added. + EXPECT_EQ(1u, writer_->ping_frames().size()); +} + TEST_P(QuicConnectionTest, LeastUnackedLower) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); - SendStreamDataToPeer(1, "bar", 3, !kFin, nullptr); - SendStreamDataToPeer(1, "eep", 6, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); + SendStreamDataToPeer(1, "bar", 3, NO_FIN, nullptr); + SendStreamDataToPeer(1, "eep", 6, NO_FIN, nullptr); // Start out saying the least unacked is 2. QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5); @@ -1544,7 +1614,7 @@ TEST_P(QuicConnectionTest, TooManySentPackets) { const int num_packets = kMaxTrackedPackets + 100; for (int i = 0; i < num_packets; ++i) { - SendStreamDataToPeer(1, "foo", 3 * i, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 3 * i, NO_FIN, nullptr); } // Ack packet 1, which leaves more than the limit outstanding. @@ -1558,6 +1628,7 @@ TEST_P(QuicConnectionTest, TooManySentPackets) { TEST_P(QuicConnectionTest, TooManyReceivedPackets) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); // Miss 99 of every 100 packets for 5500 packets. for (QuicPacketNumber i = 1; i < kMaxTrackedPackets + 500; i += 100) { ProcessPacket(i); @@ -1570,9 +1641,9 @@ TEST_P(QuicConnectionTest, TooManyReceivedPackets) { TEST_P(QuicConnectionTest, LargestObservedLower) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); - SendStreamDataToPeer(1, "bar", 3, !kFin, nullptr); - SendStreamDataToPeer(1, "eep", 6, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); + SendStreamDataToPeer(1, "bar", 3, NO_FIN, nullptr); + SendStreamDataToPeer(1, "eep", 6, NO_FIN, nullptr); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); // Start out saying the largest observed is 2. @@ -1610,7 +1681,7 @@ TEST_P(QuicConnectionTest, AckAll) { TEST_P(QuicConnectionTest, BasicSending) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); QuicPacketNumber last_packet; - SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1 + SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1 EXPECT_EQ(1u, last_packet); SendAckPacketToPeer(); // Packet 2 @@ -1629,7 +1700,7 @@ TEST_P(QuicConnectionTest, BasicSending) { EXPECT_EQ(1u, least_unacked()); } - SendStreamDataToPeer(1, "bar", 3, !kFin, &last_packet); // Packet 4 + SendStreamDataToPeer(1, "bar", 3, NO_FIN, &last_packet); // Packet 4 EXPECT_EQ(4u, last_packet); SendAckPacketToPeer(); // Packet 5 if (GetParam().no_stop_waiting) { @@ -1682,7 +1753,7 @@ TEST_P(QuicConnectionTest, BasicSending) { } // But if we send more data it should. - SendStreamDataToPeer(1, "eep", 6, !kFin, &last_packet); // Packet 8 + SendStreamDataToPeer(1, "eep", 6, NO_FIN, &last_packet); // Packet 8 EXPECT_EQ(8u, last_packet); SendAckPacketToPeer(); // Packet 9 if (GetParam().no_stop_waiting) { @@ -1706,7 +1777,7 @@ TEST_P(QuicConnectionTest, RecordSentTimeBeforePacketSent) { // First send without any pause and check the result. QuicTime expected_recorded_send_time = clock_.Now(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time) << "Expected time = " << expected_recorded_send_time.ToDebuggingValue() << ". Actual time = " << actual_recorded_send_time.ToDebuggingValue(); @@ -1720,7 +1791,7 @@ TEST_P(QuicConnectionTest, RecordSentTimeBeforePacketSent) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<0>(&actual_recorded_send_time), Return(true))); - connection_.SendStreamDataWithString(2, "baz", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(2, "baz", 0, NO_FIN, nullptr); EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time) << "Expected time = " << expected_recorded_send_time.ToDebuggingValue() << ". Actual time = " << actual_recorded_send_time.ToDebuggingValue(); @@ -1767,8 +1838,9 @@ TEST_P(QuicConnectionTest, FramePackingNonCryptoThenCrypto) { EXPECT_FALSE(connection_.HasQueuedData()); // Parse the last packet and ensure it's the crypto stream frame. - EXPECT_EQ(1u, writer_->frame_count()); + EXPECT_EQ(2u, writer_->frame_count()); ASSERT_EQ(1u, writer_->stream_frames().size()); + ASSERT_EQ(1u, writer_->padding_frames().size()); EXPECT_EQ(kCryptoStreamId, writer_->stream_frames()[0]->stream_id); } @@ -1838,15 +1910,16 @@ TEST_P(QuicConnectionTest, FramePackingSendv) { iov[0].iov_len = 2; iov[1].iov_base = data + 2; iov[1].iov_len = 2; - connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, !kFin, nullptr); + connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, NO_FIN, nullptr); EXPECT_EQ(0u, connection_.NumQueuedPackets()); EXPECT_FALSE(connection_.HasQueuedData()); // Parse the last packet and ensure multiple iovector blocks have // been packed into a single stream frame from one stream. - EXPECT_EQ(1u, writer_->frame_count()); + EXPECT_EQ(2u, writer_->frame_count()); EXPECT_EQ(1u, writer_->stream_frames().size()); + EXPECT_EQ(1u, writer_->padding_frames().size()); QuicStreamFrame* frame = writer_->stream_frames()[0].get(); EXPECT_EQ(1u, frame->stream_id); EXPECT_EQ("ABCD", QuicStringPiece(frame->data_buffer, frame->data_length)); @@ -1863,7 +1936,7 @@ TEST_P(QuicConnectionTest, FramePackingSendvQueued) { iov[0].iov_len = 2; iov[1].iov_base = data + 2; iov[1].iov_len = 2; - connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, !kFin, nullptr); + connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, NO_FIN, nullptr); EXPECT_EQ(1u, connection_.NumQueuedPackets()); EXPECT_TRUE(connection_.HasQueuedData()); @@ -1874,8 +1947,9 @@ TEST_P(QuicConnectionTest, FramePackingSendvQueued) { EXPECT_EQ(0u, connection_.NumQueuedPackets()); // Parse the last packet and ensure it's one stream frame from one stream. - EXPECT_EQ(1u, writer_->frame_count()); + EXPECT_EQ(2u, writer_->frame_count()); EXPECT_EQ(1u, writer_->stream_frames().size()); + EXPECT_EQ(1u, writer_->padding_frames().size()); EXPECT_EQ(1u, writer_->stream_frames()[0]->stream_id); } @@ -1884,7 +1958,7 @@ TEST_P(QuicConnectionTest, SendingZeroBytes) { // Send a zero byte write with a fin using writev. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); QuicIOVector empty_iov(nullptr, 0, 0); - connection_.SendStreamData(kHeadersStreamId, empty_iov, 0, kFin, nullptr); + connection_.SendStreamData(kHeadersStreamId, empty_iov, 0, FIN, nullptr); EXPECT_EQ(0u, connection_.NumQueuedPackets()); EXPECT_FALSE(connection_.HasQueuedData()); @@ -1917,7 +1991,7 @@ TEST_P(QuicConnectionTest, LargeSendWithPendingAck) { iov.iov_len = len; QuicIOVector iovector(&iov, 1, len); QuicConsumedData consumed = - connection_.SendStreamData(kHeadersStreamId, iovector, 0, true, nullptr); + connection_.SendStreamData(kHeadersStreamId, iovector, 0, FIN, nullptr); EXPECT_EQ(len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_EQ(0u, connection_.NumQueuedPackets()); @@ -1962,10 +2036,10 @@ TEST_P(QuicConnectionTest, OnCanWrite) { TEST_P(QuicConnectionTest, RetransmitOnNack) { QuicPacketNumber last_packet; QuicByteCount second_packet_size; - SendStreamDataToPeer(3, "foo", 0, !kFin, &last_packet); // Packet 1 + SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet); // Packet 1 second_packet_size = - SendStreamDataToPeer(3, "foos", 3, !kFin, &last_packet); // Packet 2 - SendStreamDataToPeer(3, "fooos", 7, !kFin, &last_packet); // Packet 3 + SendStreamDataToPeer(3, "foos", 3, NO_FIN, &last_packet); // Packet 2 + SendStreamDataToPeer(3, "fooos", 7, NO_FIN, &last_packet); // Packet 3 EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); @@ -1993,7 +2067,7 @@ TEST_P(QuicConnectionTest, DoNotSendQueuedPacketForResetStream) { BlockOnNextWrite(); QuicStreamId stream_id = 2; - connection_.SendStreamDataWithString(stream_id, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(stream_id, "foo", 0, NO_FIN, nullptr); // Now that there is a queued packet, reset the stream. connection_.SendRstStream(stream_id, QUIC_ERROR_PROCESSING_STREAM, 14); @@ -2011,7 +2085,7 @@ TEST_P(QuicConnectionTest, SendQueuedPacketForQuicRstStreamNoError) { BlockOnNextWrite(); QuicStreamId stream_id = 2; - connection_.SendStreamDataWithString(stream_id, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(stream_id, "foo", 0, NO_FIN, nullptr); // Now that there is a queued packet, reset the stream. connection_.SendRstStream(stream_id, QUIC_STREAM_NO_ERROR, 14); @@ -2028,9 +2102,9 @@ TEST_P(QuicConnectionTest, SendQueuedPacketForQuicRstStreamNoError) { TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnNack) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "foos", 3, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "fooos", 7, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "foos", 3, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "fooos", 7, NO_FIN, &last_packet); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.SendRstStream(stream_id, QUIC_ERROR_PROCESSING_STREAM, 14); @@ -2048,9 +2122,9 @@ TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnNack) { TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnNack) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "foos", 3, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "fooos", 7, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "foos", 3, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "fooos", 7, NO_FIN, &last_packet); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.SendRstStream(stream_id, QUIC_STREAM_NO_ERROR, 14); @@ -2071,7 +2145,7 @@ TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnNack) { TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnRTO) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.SendRstStream(stream_id, QUIC_ERROR_PROCESSING_STREAM, 14); @@ -2090,7 +2164,7 @@ TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnRTO) { TEST_P(QuicConnectionTest, CancelRetransmissionAlarmAfterResetStream) { QuicStreamId stream_id = 2; QuicPacketNumber last_data_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_data_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_data_packet); // Cancel the stream. const QuicPacketNumber rst_packet = last_data_packet + 1; @@ -2117,7 +2191,7 @@ TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnRTO) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.SendRstStream(stream_id, QUIC_STREAM_NO_ERROR, 14); @@ -2135,10 +2209,10 @@ TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnRTO) { TEST_P(QuicConnectionTest, DoNotSendPendingRetransmissionForResetStream) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "foos", 3, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "foos", 3, NO_FIN, &last_packet); BlockOnNextWrite(); - connection_.SendStreamDataWithString(stream_id, "fooos", 7, !kFin, nullptr); + connection_.SendStreamDataWithString(stream_id, "fooos", 7, NO_FIN, nullptr); // Lose a packet which will trigger a pending retransmission. QuicAckFrame ack = InitAckFrame(last_packet); @@ -2164,10 +2238,10 @@ TEST_P(QuicConnectionTest, DoNotSendPendingRetransmissionForResetStream) { TEST_P(QuicConnectionTest, SendPendingRetransmissionForQuicRstStreamNoError) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "foos", 3, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "foos", 3, NO_FIN, &last_packet); BlockOnNextWrite(); - connection_.SendStreamDataWithString(stream_id, "fooos", 7, !kFin, nullptr); + connection_.SendStreamDataWithString(stream_id, "fooos", 7, NO_FIN, nullptr); // Lose a packet which will trigger a pending retransmission. QuicAckFrame ack = InitAckFrame(last_packet); @@ -2194,9 +2268,9 @@ TEST_P(QuicConnectionTest, SendPendingRetransmissionForQuicRstStreamNoError) { TEST_P(QuicConnectionTest, RetransmitAckedPacket) { QuicPacketNumber last_packet; - SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1 - SendStreamDataToPeer(1, "foos", 3, !kFin, &last_packet); // Packet 2 - SendStreamDataToPeer(1, "fooos", 7, !kFin, &last_packet); // Packet 3 + SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1 + SendStreamDataToPeer(1, "foos", 3, NO_FIN, &last_packet); // Packet 2 + SendStreamDataToPeer(1, "fooos", 7, NO_FIN, &last_packet); // Packet 3 EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); @@ -2239,7 +2313,7 @@ TEST_P(QuicConnectionTest, RetransmitNackedLargestObserved) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<2>(&largest_observed), SaveArg<3>(&packet_size), Return(true))); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); QuicAckFrame frame = InitAckFrame(1); NackPacket(largest_observed, &frame); @@ -2259,7 +2333,7 @@ TEST_P(QuicConnectionTest, QueueAfterTwoRTOs) { for (int i = 0; i < 10; ++i) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - connection_.SendStreamDataWithString(3, "foo", i * 3, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", i * 3, NO_FIN, nullptr); } // Block the writer and ensure they're queued. @@ -2284,7 +2358,7 @@ TEST_P(QuicConnectionTest, WriteBlockedBufferedThenSent) { BlockOnNextWrite(); writer_->set_is_write_blocked_data_buffered(true); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); writer_->SetWritable(); @@ -2295,14 +2369,14 @@ TEST_P(QuicConnectionTest, WriteBlockedBufferedThenSent) { TEST_P(QuicConnectionTest, WriteBlockedThenSent) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0); BlockOnNextWrite(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); EXPECT_EQ(1u, connection_.NumQueuedPackets()); // The second packet should also be queued, in order to ensure packets are // never sent out of order. writer_->SetWritable(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(2u, connection_.NumQueuedPackets()); // Now both are sent in order when we unblock. @@ -2313,7 +2387,7 @@ TEST_P(QuicConnectionTest, WriteBlockedThenSent) { TEST_P(QuicConnectionTest, RetransmitWriteBlockedAckedOriginalThenSent) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); BlockOnNextWrite(); @@ -2338,7 +2412,7 @@ TEST_P(QuicConnectionTest, RetransmitWriteBlockedAckedOriginalThenSent) { TEST_P(QuicConnectionTest, AlarmsWhenWriteBlocked) { // Block the connection. BlockOnNextWrite(); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, writer_->packets_write_attempts()); EXPECT_TRUE(writer_->IsWriteBlocked()); @@ -2357,7 +2431,7 @@ TEST_P(QuicConnectionTest, NoLimitPacketsPerNack) { int offset = 0; // Send packets 1 to 15. for (int i = 0; i < 15; ++i) { - SendStreamDataToPeer(1, "foo", offset, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", offset, NO_FIN, nullptr); offset += 3; } @@ -2383,16 +2457,16 @@ TEST_P(QuicConnectionTest, NoLimitPacketsPerNack) { // Test sending multiple acks from the connection to the session. TEST_P(QuicConnectionTest, MultipleAcks) { QuicPacketNumber last_packet; - SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1 + SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1 EXPECT_EQ(1u, last_packet); - SendStreamDataToPeer(3, "foo", 0, !kFin, &last_packet); // Packet 2 + SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet); // Packet 2 EXPECT_EQ(2u, last_packet); SendAckPacketToPeer(); // Packet 3 - SendStreamDataToPeer(5, "foo", 0, !kFin, &last_packet); // Packet 4 + SendStreamDataToPeer(5, "foo", 0, NO_FIN, &last_packet); // Packet 4 EXPECT_EQ(4u, last_packet); - SendStreamDataToPeer(1, "foo", 3, !kFin, &last_packet); // Packet 5 + SendStreamDataToPeer(1, "foo", 3, NO_FIN, &last_packet); // Packet 5 EXPECT_EQ(5u, last_packet); - SendStreamDataToPeer(3, "foo", 3, !kFin, &last_packet); // Packet 6 + SendStreamDataToPeer(3, "foo", 3, NO_FIN, &last_packet); // Packet 6 EXPECT_EQ(6u, last_packet); // Client will ack packets 1, 2, [!3], 4, 5. @@ -2409,7 +2483,7 @@ TEST_P(QuicConnectionTest, MultipleAcks) { } TEST_P(QuicConnectionTest, DontLatchUnackedPacket) { - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); // Packet 1; + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); // Packet 1; // From now on, we send acks, so the send algorithm won't mark them pending. ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillByDefault(Return(false)); @@ -2451,7 +2525,7 @@ TEST_P(QuicConnectionTest, DontLatchUnackedPacket) { ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillByDefault(Return(true)); - SendStreamDataToPeer(1, "bar", 3, false, nullptr); // Packet 4 + SendStreamDataToPeer(1, "bar", 3, NO_FIN, nullptr); // Packet 4 EXPECT_EQ(4u, stop_waiting()->least_unacked); ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillByDefault(Return(false)); @@ -2467,8 +2541,8 @@ TEST_P(QuicConnectionTest, DontLatchUnackedPacket) { // the least unacked is raised above the ack packets. ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillByDefault(Return(true)); - SendStreamDataToPeer(1, "bar", 6, false, nullptr); // Packet 6 - SendStreamDataToPeer(1, "bar", 9, false, nullptr); // Packet 7 + SendStreamDataToPeer(1, "bar", 6, NO_FIN, nullptr); // Packet 6 + SendStreamDataToPeer(1, "bar", 9, NO_FIN, nullptr); // Packet 7 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); frame = InitAckFrame(7); @@ -2482,7 +2556,7 @@ TEST_P(QuicConnectionTest, DontLatchUnackedPacket) { TEST_P(QuicConnectionTest, TLP) { connection_.SetMaxTailLossProbes(1); - SendStreamDataToPeer(3, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, stop_waiting()->least_unacked); QuicTime retransmission_time = connection_.GetRetransmissionAlarm()->deadline(); @@ -2504,7 +2578,7 @@ TEST_P(QuicConnectionTest, RTO) { QuicTime default_retransmission_time = clock_.ApproximateNow() + DefaultRetransmissionTime(); - SendStreamDataToPeer(3, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, stop_waiting()->least_unacked); EXPECT_EQ(1u, writer_->header().packet_number); @@ -2525,12 +2599,12 @@ TEST_P(QuicConnectionTest, RetransmitWithSameEncryptionLevel) { // A TaggingEncrypter puts kTagSize copies of the given byte (0x01 here) at // the end of the packet. We can test this to check which encrypter was used. connection_.SetEncrypter(ENCRYPTION_NONE, new TaggingEncrypter(0x01)); - SendStreamDataToPeer(kCryptoStreamId, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(kCryptoStreamId, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(0x01010101u, writer_->final_bytes_of_last_packet()); connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(0x02)); connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); - SendStreamDataToPeer(3, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet()); { @@ -2559,7 +2633,7 @@ TEST_P(QuicConnectionTest, SendHandshakeMessages) { EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _)) .WillRepeatedly(testing::Return(QuicTime::Delta::Zero())); BlockOnNextWrite(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); // The packet should be serialized, but not queued. EXPECT_EQ(1u, connection_.NumQueuedPackets()); @@ -2582,7 +2656,7 @@ TEST_P(QuicConnectionTest, use_tagging_decrypter(); connection_.SetEncrypter(ENCRYPTION_NONE, new TaggingEncrypter(0x01)); QuicPacketNumber packet_number; - SendStreamDataToPeer(kCryptoStreamId, "foo", 0, !kFin, &packet_number); + SendStreamDataToPeer(kCryptoStreamId, "foo", 0, NO_FIN, &packet_number); // Simulate the retransmission alarm firing and the socket blocking. BlockOnNextWrite(); @@ -2607,12 +2681,12 @@ TEST_P(QuicConnectionTest, RetransmitPacketsWithInitialEncryption) { connection_.SetEncrypter(ENCRYPTION_NONE, new TaggingEncrypter(0x01)); connection_.SetDefaultEncryptionLevel(ENCRYPTION_NONE); - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(0x02)); connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); - SendStreamDataToPeer(2, "bar", 0, !kFin, nullptr); + SendStreamDataToPeer(2, "bar", 0, NO_FIN, nullptr); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION); @@ -2620,6 +2694,7 @@ TEST_P(QuicConnectionTest, RetransmitPacketsWithInitialEncryption) { TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) { // SetFromConfig is always called after construction from InitializeSession. + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; connection_.SetFromConfig(config); @@ -2649,6 +2724,7 @@ TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) { TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) { // SetFromConfig is always called after construction from InitializeSession. + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; config.set_max_undecryptable_packets(100); @@ -2686,11 +2762,11 @@ TEST_P(QuicConnectionTest, TestRetransmitOrder) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&first_packet_size), Return(true))); - connection_.SendStreamDataWithString(3, "first_packet", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "first_packet", 0, NO_FIN, nullptr); QuicByteCount second_packet_size; EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&second_packet_size), Return(true))); - connection_.SendStreamDataWithString(3, "second_packet", 12, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "second_packet", 12, NO_FIN, nullptr); 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)); @@ -2714,7 +2790,7 @@ TEST_P(QuicConnectionTest, TestRetransmitOrder) { TEST_P(QuicConnectionTest, SetRTOAfterWritingToSocket) { BlockOnNextWrite(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); // Make sure that RTO is not started when the packet is queued. EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); @@ -2729,8 +2805,8 @@ TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); - connection_.SendStreamDataWithString(2, "foo", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(3, "bar", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(2, "foo", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(3, "bar", 0, NO_FIN, nullptr); QuicAlarm* retransmission_alarm = connection_.GetRetransmissionAlarm(); EXPECT_TRUE(retransmission_alarm->IsSet()); EXPECT_EQ(clock_.Now() + DefaultRetransmissionTime(), @@ -2772,7 +2848,7 @@ TEST_P(QuicConnectionTest, TestQueued) { EXPECT_EQ(0u, connection_.NumQueuedPackets()); BlockOnNextWrite(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, connection_.NumQueuedPackets()); // Unblock the writes and actually send. @@ -2787,6 +2863,7 @@ TEST_P(QuicConnectionTest, InitialTimeout) { EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet()); // SetFromConfig sets the initial timeouts before negotiation. + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; connection_.SetFromConfig(config); @@ -2826,7 +2903,7 @@ TEST_P(QuicConnectionTest, HandshakeTimeout) { EXPECT_TRUE(connection_.connected()); // Send and ack new data 3 seconds later to lengthen the idle timeout. - SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, kFin, nullptr); + SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, FIN, nullptr); clock_.AdvanceTime(QuicTime::Delta::FromSeconds(3)); QuicAckFrame frame = InitAckFrame(1); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); @@ -2864,7 +2941,7 @@ TEST_P(QuicConnectionTest, PingAfterSend) { // the ping alarm. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); - SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, kFin, nullptr); + SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, FIN, nullptr); EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(15), connection_.GetPingAlarm()->deadline()); @@ -2909,7 +2986,7 @@ TEST_P(QuicConnectionTest, ReducedPingTimeout) { // the ping alarm. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); - SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, kFin, nullptr); + SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, FIN, nullptr); EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(10), connection_.GetPingAlarm()->deadline()); @@ -2963,7 +3040,7 @@ TEST_P(QuicConnectionTest, SendMtuDiscoveryPacket) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&size_before_mtu_change), Return(true))) .WillOnce(Return(true)); - connection_.SendStreamDataWithString(3, data, 0, kFin, nullptr); + connection_.SendStreamDataWithString(3, data, 0, FIN, nullptr); EXPECT_EQ(3u, creator_->packet_number()); EXPECT_EQ(kDefaultMaxPacketSize, size_before_mtu_change); @@ -2976,7 +3053,7 @@ TEST_P(QuicConnectionTest, SendMtuDiscoveryPacket) { // Send the same data again. Check that it fits into a single packet now. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - connection_.SendStreamDataWithString(3, data, 0, kFin, nullptr); + connection_.SendStreamDataWithString(3, data, 0, FIN, nullptr); EXPECT_EQ(4u, creator_->packet_number()); } @@ -2987,7 +3064,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryDisabled) { const QuicPacketCount number_of_packets = kPacketsBetweenMtuProbesBase * 2; for (QuicPacketCount i = 0; i < number_of_packets; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); EXPECT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); EXPECT_EQ(0u, connection_.mtu_probe_count()); } @@ -3002,13 +3079,12 @@ TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) { // Send enough packets so that the next one triggers path MTU discovery. for (QuicPacketCount i = 0; i < kPacketsBetweenMtuProbesBase - 1; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } // Trigger the probe. - SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, - /*fin=*/false, nullptr); + SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, NO_FIN, nullptr); ASSERT_TRUE(connection_.GetMtuDiscoveryAlarm()->IsSet()); QuicByteCount probe_size; EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) @@ -3029,7 +3105,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) { // Send more packets, and ensure that none of them sets the alarm. for (QuicPacketCount i = 0; i < 4 * kPacketsBetweenMtuProbesBase; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } @@ -3067,7 +3143,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryFailed) { EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)) .Times(AnyNumber()); for (QuicPacketCount i = 0; i < number_of_packets; i++) { - SendStreamDataToPeer(3, "!", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, "!", i, NO_FIN, nullptr); clock_.AdvanceTime(rtt); // Receive an ACK, which marks all data packets as received, and all MTU @@ -3118,13 +3194,12 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterLimited) { // Send enough packets so that the next one triggers path MTU discovery. for (QuicPacketCount i = 0; i < kPacketsBetweenMtuProbesBase - 1; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } // Trigger the probe. - SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, - /*fin=*/false, nullptr); + SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, NO_FIN, nullptr); ASSERT_TRUE(connection_.GetMtuDiscoveryAlarm()->IsSet()); QuicByteCount probe_size; EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) @@ -3146,7 +3221,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterLimited) { // Send more packets, and ensure that none of them sets the alarm. for (QuicPacketCount i = 0; i < 4 * kPacketsBetweenMtuProbesBase; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } @@ -3166,13 +3241,12 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterFailed) { // Send enough packets so that the next one triggers path MTU discovery. for (QuicPacketCount i = 0; i < kPacketsBetweenMtuProbesBase - 1; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } // Trigger the probe. - SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, - /*fin=*/false, nullptr); + SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, NO_FIN, nullptr); ASSERT_TRUE(connection_.GetMtuDiscoveryAlarm()->IsSet()); writer_->SimulateNextPacketTooLarge(); connection_.GetMtuDiscoveryAlarm()->Fire(); @@ -3211,12 +3285,11 @@ TEST_P(QuicConnectionTest, NoMtuDiscoveryAfterConnectionClosed) { // Send enough packets so that the next one triggers path MTU discovery. for (QuicPacketCount i = 0; i < kPacketsBetweenMtuProbesBase - 1; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } - SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, - /*fin=*/false, nullptr); + SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, NO_FIN, nullptr); EXPECT_TRUE(connection_.GetMtuDiscoveryAlarm()->IsSet()); EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)); @@ -3227,6 +3300,7 @@ TEST_P(QuicConnectionTest, NoMtuDiscoveryAfterConnectionClosed) { TEST_P(QuicConnectionTest, TimeoutAfterSend) { EXPECT_TRUE(connection_.connected()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; connection_.SetFromConfig(config); @@ -3240,13 +3314,13 @@ TEST_P(QuicConnectionTest, TimeoutAfterSend) { // When we send a packet, the timeout will change to 5ms + // kInitialIdleTimeoutSecs. clock_.AdvanceTime(five_ms); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // Now send more data. This will not move the timeout becase // no data has been recieved since the previous write. clock_.AdvanceTime(five_ms); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // The original alarm will fire. We should not time out because we had a @@ -3273,6 +3347,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterSend) { TEST_P(QuicConnectionTest, TimeoutAfterRetransmission) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_TRUE(connection_.connected()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; connection_.SetFromConfig(config); @@ -3295,7 +3370,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterRetransmission) { const QuicTime send_time = start_time + five_ms; clock_.AdvanceTime(five_ms); ASSERT_EQ(send_time, clock_.Now()); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // Move forward 5 ms and receive a packet, which will move the timeout @@ -3347,6 +3422,7 @@ TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) { // Same test as above, but complete a handshake which enables silent close, // causing no connection close packet to be sent. EXPECT_TRUE(connection_.connected()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; @@ -3377,13 +3453,13 @@ TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) { // When we send a packet, the timeout will change to 5ms + // kInitialIdleTimeoutSecs. clock_.AdvanceTime(five_ms); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // Now send more data. This will not move the timeout becase // no data has been recieved since the previous write. clock_.AdvanceTime(five_ms); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // The original alarm will fire. We should not time out because we had a @@ -3409,6 +3485,7 @@ TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) { TEST_P(QuicConnectionTest, TimeoutAfterReceive) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_TRUE(connection_.connected()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; connection_.SetFromConfig(config); @@ -3419,9 +3496,9 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceive) { const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5); QuicTime default_timeout = clock_.ApproximateNow() + initial_idle_timeout; - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, NO_FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); @@ -3457,6 +3534,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceive) { TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_TRUE(connection_.connected()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; connection_.SetFromConfig(config); @@ -3471,10 +3549,10 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) { QuicTime default_timeout = clock_.ApproximateNow() + initial_idle_timeout; EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, NO_FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); @@ -3504,7 +3582,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber()); for (int i = 0; i < 100 && connection_.connected(); ++i) { QUIC_LOG(INFO) << "sending data packet"; - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); connection_.GetTimeoutAlarm()->Fire(); clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); @@ -3516,6 +3594,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) { TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) { connection_.SetMaxTailLossProbes(2); EXPECT_TRUE(connection_.connected()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; QuicTagVector connection_options; @@ -3524,7 +3603,7 @@ TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) { connection_.SetFromConfig(config); // Send stream data. - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_CALL(visitor_, OnPathDegrading()); // Fire the retransmission alarm 6 times, twice for TLP and 4 times for RTO. @@ -3546,6 +3625,41 @@ TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) { EXPECT_FALSE(connection_.connected()); } +TEST_P(QuicConnectionTest, TimeoutAfter3ClientRTOs) { + FLAGS_quic_reloadable_flag_quic_enable_3rtos = true; + connection_.SetMaxTailLossProbes(2); + EXPECT_TRUE(connection_.connected()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + QuicConfig config; + QuicTagVector connection_options; + connection_options.push_back(k3RTO); + config.SetConnectionOptionsToSend(connection_options); + connection_.SetFromConfig(config); + + // Send stream data. + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); + + EXPECT_CALL(visitor_, OnPathDegrading()); + // Fire the retransmission alarm 4 times, twice for TLP and 2 times for RTO. + for (int i = 0; i < 4; ++i) { + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); + connection_.GetRetransmissionAlarm()->Fire(); + EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); + EXPECT_TRUE(connection_.connected()); + } + + EXPECT_EQ(2u, connection_.sent_packet_manager().GetConsecutiveTlpCount()); + EXPECT_EQ(2u, connection_.sent_packet_manager().GetConsecutiveRtoCount()); + // This time, we should time out. + EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_TOO_MANY_RTOS, _, + ConnectionCloseSource::FROM_SELF)); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); + connection_.GetRetransmissionAlarm()->Fire(); + EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet()); + EXPECT_FALSE(connection_.connected()); +} + TEST_P(QuicConnectionTest, SendScheduler) { // Test that if we send a packet without delay, it is not queued. QuicPacket* packet = ConstructDataPacket(1, !kHasStopWaiting); @@ -3587,7 +3701,7 @@ TEST_P(QuicConnectionTest, TestQueueLimitsOnSendStreamData) { .WillOnce(testing::Return(QuicTime::Delta::FromMicroseconds(10))); const string payload(payload_length, 'a'); EXPECT_EQ(0u, - connection_.SendStreamDataWithString(3, payload, 0, !kFin, nullptr) + connection_.SendStreamDataWithString(3, payload, 0, NO_FIN, nullptr) .bytes_consumed); EXPECT_EQ(0u, connection_.NumQueuedPackets()); } @@ -3612,19 +3726,20 @@ TEST_P(QuicConnectionTest, LoopThroughSendingPackets) { // The first stream frame will have 2 fewer overhead bytes than the other six. const string payload(payload_length * 7 + 2, 'a'); EXPECT_EQ(payload.size(), - connection_.SendStreamDataWithString(1, payload, 0, !kFin, nullptr) + connection_.SendStreamDataWithString(1, payload, 0, NO_FIN, nullptr) .bytes_consumed); } TEST_P(QuicConnectionTest, LoopThroughSendingPacketsWithTruncation) { // Set up a larger payload than will fit in one packet. const string payload(connection_.max_packet_length(), 'a'); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()).Times(AnyNumber()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber()); // Now send some packets with no truncation. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); EXPECT_EQ(payload.size(), - connection_.SendStreamDataWithString(3, payload, 0, !kFin, nullptr) + connection_.SendStreamDataWithString(3, payload, 0, NO_FIN, nullptr) .bytes_consumed); // Track the size of the second packet here. The overhead will be the largest // we see in this test, due to the non-truncated connection id. @@ -3636,7 +3751,7 @@ TEST_P(QuicConnectionTest, LoopThroughSendingPacketsWithTruncation) { connection_.SetFromConfig(config); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); EXPECT_EQ(payload.size(), - connection_.SendStreamDataWithString(3, payload, 0, !kFin, nullptr) + connection_.SendStreamDataWithString(3, payload, 0, NO_FIN, nullptr) .bytes_consumed); // Just like above, we save 8 bytes on payload, and 8 on truncation. EXPECT_EQ(non_truncated_packet_size, writer_->last_packet_size() + 8 * 2); @@ -3675,6 +3790,7 @@ TEST_P(QuicConnectionTest, SendDelayedAck) { } TEST_P(QuicConnectionTest, SendDelayedAckDecimation) { + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); QuicConnectionPeer::SetAckMode(&connection_, QuicConnection::ACK_DECIMATION); const size_t kMinRttMs = 40; @@ -3730,6 +3846,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) { } TEST_P(QuicConnectionTest, SendDelayedAckDecimationEighthRtt) { + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); QuicConnectionPeer::SetAckMode(&connection_, QuicConnection::ACK_DECIMATION); QuicConnectionPeer::SetAckDecimationDelay(&connection_, 0.125); @@ -3786,6 +3903,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationEighthRtt) { } TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) { + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); QuicConnectionPeer::SetAckMode( &connection_, QuicConnection::ACK_DECIMATION_WITH_REORDERING); @@ -3850,6 +3968,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) { } TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) { + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); QuicConnectionPeer::SetAckMode( &connection_, QuicConnection::ACK_DECIMATION_WITH_REORDERING); @@ -3931,6 +4050,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) { } TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReorderingEighthRtt) { + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); QuicConnectionPeer::SetAckMode( &connection_, QuicConnection::ACK_DECIMATION_WITH_REORDERING); QuicConnectionPeer::SetAckDecimationDelay(&connection_, 0.125); @@ -3997,6 +4117,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReorderingEighthRtt) { TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReorderingEighthRtt) { + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); QuicConnectionPeer::SetAckMode( &connection_, QuicConnection::ACK_DECIMATION_WITH_REORDERING); QuicConnectionPeer::SetAckDecimationDelay(&connection_, 0.125); @@ -4144,7 +4265,7 @@ TEST_P(QuicConnectionTest, NoAckOnOldNacks) { TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingPacket) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); ProcessPacket(1); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); // Check that ack is bundled with outgoing data and that delayed ack // alarm is reset. @@ -4162,14 +4283,14 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingPacket) { TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingCryptoPacket) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); ProcessPacket(1); - connection_.SendStreamDataWithString(kCryptoStreamId, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kCryptoStreamId, "foo", 0, NO_FIN, nullptr); // Check that ack is bundled with outgoing crypto data. if (GetParam().no_stop_waiting) { - EXPECT_EQ(2u, writer_->frame_count()); + EXPECT_EQ(3u, writer_->frame_count()); EXPECT_TRUE(writer_->stop_waiting_frames().empty()); } else { - EXPECT_EQ(3u, writer_->frame_count()); + EXPECT_EQ(4u, writer_->frame_count()); EXPECT_FALSE(writer_->stop_waiting_frames().empty()); } EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); @@ -4180,11 +4301,11 @@ TEST_P(QuicConnectionTest, BlockAndBufferOnFirstCHLOPacketOfTwo) { ProcessPacket(1); BlockOnNextWrite(); writer_->set_is_write_blocked_data_buffered(true); - connection_.SendStreamDataWithString(kCryptoStreamId, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kCryptoStreamId, "foo", 0, NO_FIN, nullptr); EXPECT_TRUE(writer_->IsWriteBlocked()); EXPECT_FALSE(connection_.HasQueuedData()); - connection_.SendStreamDataWithString(kCryptoStreamId, "bar", 3, !kFin, + connection_.SendStreamDataWithString(kCryptoStreamId, "bar", 3, NO_FIN, nullptr); EXPECT_TRUE(writer_->IsWriteBlocked()); EXPECT_TRUE(connection_.HasQueuedData()); @@ -4202,13 +4323,14 @@ TEST_P(QuicConnectionTest, BundleAckForSecondCHLO) { ProcessPacket(2); // Check that ack is sent and that delayed ack alarm is reset. if (GetParam().no_stop_waiting) { - EXPECT_EQ(2u, writer_->frame_count()); + EXPECT_EQ(3u, writer_->frame_count()); EXPECT_TRUE(writer_->stop_waiting_frames().empty()); } else { - EXPECT_EQ(3u, writer_->frame_count()); + EXPECT_EQ(4u, writer_->frame_count()); EXPECT_FALSE(writer_->stop_waiting_frames().empty()); } EXPECT_EQ(1u, writer_->stream_frames().size()); + EXPECT_EQ(1u, writer_->padding_frames().size()); EXPECT_FALSE(writer_->ack_frames().empty()); EXPECT_EQ(2u, writer_->ack_frames().front().largest_observed); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); @@ -4230,13 +4352,14 @@ TEST_P(QuicConnectionTest, BundleAckForSecondCHLOTwoPacketReject) { } // Check that ack is sent and that delayed ack alarm is reset. if (GetParam().no_stop_waiting) { - EXPECT_EQ(2u, writer_->frame_count()); + EXPECT_EQ(3u, writer_->frame_count()); EXPECT_TRUE(writer_->stop_waiting_frames().empty()); } else { - EXPECT_EQ(3u, writer_->frame_count()); + EXPECT_EQ(4u, writer_->frame_count()); EXPECT_FALSE(writer_->stop_waiting_frames().empty()); } EXPECT_EQ(1u, writer_->stream_frames().size()); + EXPECT_EQ(1u, writer_->padding_frames().size()); EXPECT_FALSE(writer_->ack_frames().empty()); EXPECT_EQ(2u, writer_->ack_frames().front().largest_observed); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); @@ -4244,9 +4367,9 @@ TEST_P(QuicConnectionTest, BundleAckForSecondCHLOTwoPacketReject) { TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, NO_FIN, nullptr); // Ack the second packet, which will retransmit the first packet. QuicAckFrame ack = InitAckFrame(2); @@ -4323,10 +4446,11 @@ TEST_P(QuicConnectionTest, SendWhenDisconnected) { TEST_P(QuicConnectionTest, PublicReset) { QuicPublicResetPacket header; - header.public_header.connection_id = connection_id_; + // Public reset packet in only built by server. + header.public_header.connection_id = + GetPeerInMemoryConnectionId(connection_id_); header.public_header.reset_flag = true; header.public_header.version_flag = false; - header.rejected_packet_number = 10101; std::unique_ptr<QuicEncryptedPacket> packet( framer_.BuildPublicResetPacket(header)); std::unique_ptr<QuicReceivedPacket> received( @@ -4390,7 +4514,8 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacket) { peer_framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED); QuicPacketHeader header; - header.public_header.connection_id = connection_id_; + header.public_header.connection_id = + GetPeerInMemoryConnectionId(connection_id_); header.public_header.version_flag = true; header.packet_number = 12; @@ -4425,7 +4550,8 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacketSocketBlocked) { peer_framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED); QuicPacketHeader header; - header.public_header.connection_id = connection_id_; + header.public_header.connection_id = + GetPeerInMemoryConnectionId(connection_id_); header.public_header.version_flag = true; header.packet_number = 12; @@ -4467,7 +4593,8 @@ TEST_P(QuicConnectionTest, peer_framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED); QuicPacketHeader header; - header.public_header.connection_id = connection_id_; + header.public_header.connection_id = + GetPeerInMemoryConnectionId(connection_id_); header.public_header.version_flag = true; header.packet_number = 12; @@ -4496,8 +4623,8 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) { // Send a version negotiation packet. std::unique_ptr<QuicEncryptedPacket> encrypted( - peer_framer_.BuildVersionNegotiationPacket(connection_id_, - AllSupportedVersions())); + peer_framer_.BuildVersionNegotiationPacket( + GetPeerInMemoryConnectionId(connection_id_), AllSupportedVersions())); std::unique_ptr<QuicReceivedPacket> received( ConstructReceivedPacket(*encrypted, QuicTime::Zero())); connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received); @@ -4505,7 +4632,8 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) { // Now force another packet. The connection should transition into // NEGOTIATED_VERSION state and tell the packet creator to StopSendingVersion. QuicPacketHeader header; - header.public_header.connection_id = connection_id_; + header.public_header.connection_id = + GetPeerInMemoryConnectionId(connection_id_); header.packet_number = 12; header.public_header.version_flag = false; QuicFrames frames; @@ -4531,8 +4659,8 @@ TEST_P(QuicConnectionTest, BadVersionNegotiation) { OnConnectionClosed(QUIC_INVALID_VERSION_NEGOTIATION_PACKET, _, ConnectionCloseSource::FROM_SELF)); std::unique_ptr<QuicEncryptedPacket> encrypted( - framer_.BuildVersionNegotiationPacket(connection_id_, - AllSupportedVersions())); + framer_.BuildVersionNegotiationPacket( + GetPeerInMemoryConnectionId(connection_id_), AllSupportedVersions())); std::unique_ptr<QuicReceivedPacket> received( ConstructReceivedPacket(*encrypted, QuicTime::Zero())); connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received); @@ -4542,11 +4670,11 @@ TEST_P(QuicConnectionTest, CheckSendStats) { connection_.SetMaxTailLossProbes(0); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - connection_.SendStreamDataWithString(3, "first", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "first", 0, NO_FIN, nullptr); size_t first_packet_size = writer_->last_packet_size(); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - connection_.SendStreamDataWithString(5, "second", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(5, "second", 0, NO_FIN, nullptr); size_t second_packet_size = writer_->last_packet_size(); // 2 retransmissions due to rto, 1 due to explicit nack. @@ -4588,7 +4716,8 @@ TEST_P(QuicConnectionTest, CheckSendStats) { TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) { // Construct a packet with stream frame and connection close frame. QuicPacketHeader header; - header.public_header.connection_id = connection_id_; + header.public_header.connection_id = + GetPeerInMemoryConnectionId(connection_id_); header.packet_number = 1; header.public_header.version_flag = false; @@ -4648,7 +4777,7 @@ TEST_P(QuicConnectionTest, ConnectionCloseWhenWritable) { EXPECT_FALSE(writer_->IsWriteBlocked()); // Send a packet. - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(0u, connection_.NumQueuedPackets()); EXPECT_EQ(1u, writer_->packets_write_attempts()); @@ -4665,7 +4794,7 @@ TEST_P(QuicConnectionTest, ConnectionCloseGettingWriteBlocked) { TEST_P(QuicConnectionTest, ConnectionCloseWhenWriteBlocked) { BlockOnNextWrite(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, connection_.NumQueuedPackets()); EXPECT_EQ(1u, writer_->packets_write_attempts()); EXPECT_TRUE(writer_->IsWriteBlocked()); @@ -4681,7 +4810,7 @@ TEST_P(QuicConnectionTest, AckNotifierTriggerCallback) { EXPECT_CALL(*listener, OnPacketAcked(_, _)).Times(1); // Send some data, which will register the listener to be notified. - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, listener); // Process an ACK from the server which should trigger the callback. EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); @@ -4698,11 +4827,11 @@ TEST_P(QuicConnectionTest, AckNotifierFailToTriggerCallback) { // Send some data, which will register the listener to be notified. This will // not be ACKed and so the listener should never be called. - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, listener); // Send some other data which we will ACK. - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(1, "bar", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(1, "bar", 0, NO_FIN, nullptr); // Now we receive ACK for packets 2 and 3, but importantly missing packet 1 // which we registered to be notified about. @@ -4725,10 +4854,10 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) { EXPECT_CALL(*listener, OnPacketAcked(3, _)).Times(1); // Send four packets, and register to be notified on ACK of packet 2. - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener); - connection_.SendStreamDataWithString(3, "baz", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(3, "qux", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(3, "bar", 0, NO_FIN, listener); + connection_.SendStreamDataWithString(3, "baz", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(3, "qux", 0, NO_FIN, nullptr); // Now we receive ACK for packets 1, 3, and 4 and lose 2. QuicAckFrame frame = InitAckFrame(4); @@ -4761,7 +4890,7 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackForAckAfterRTO) { QuicTime default_retransmission_time = clock_.ApproximateNow() + DefaultRetransmissionTime(); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, listener); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, listener); EXPECT_EQ(1u, stop_waiting()->least_unacked); EXPECT_EQ(1u, writer_->header().packet_number); @@ -4798,10 +4927,10 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackForAckOfNackedPacket) { new StrictMock<MockAckListener>()); // Send four packets, and register to be notified on ACK of packet 2. - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener); - connection_.SendStreamDataWithString(3, "baz", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(3, "qux", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(3, "bar", 0, NO_FIN, listener); + connection_.SendStreamDataWithString(3, "baz", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(3, "qux", 0, NO_FIN, nullptr); // Now we receive ACK for packets 1, 3, and 4 and lose 2. QuicAckFrame frame = InitAckFrame(4); @@ -4892,7 +5021,7 @@ TEST_P(QuicConnectionTest, NoDataNoFin) { // Regression test for b/18594622 QuicReferenceCountedPointer<MockAckListener> listener(new MockAckListener); EXPECT_QUIC_BUG( - connection_.SendStreamDataWithString(3, "", 0, !kFin, listener), + connection_.SendStreamDataWithString(3, "", 0, NO_FIN, listener), "Attempt to send empty stream frame"); } @@ -4907,7 +5036,7 @@ TEST_P(QuicConnectionTest, DoNotSendGoAwayTwice) { TEST_P(QuicConnectionTest, ReevaluateTimeUntilSendOnAck) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); // Evaluate CanWrite, and have it return a non-Zero value. @@ -4968,7 +5097,7 @@ TEST_P(QuicConnectionTest, SendingUnencryptedStreamDataFails) { _, ConnectionCloseSource::FROM_SELF)); struct iovec iov; QuicIOVector data_iov(MakeIOVector("", &iov)); - EXPECT_QUIC_BUG(connection_.SendStreamData(3, data_iov, 0, kFin, nullptr), + EXPECT_QUIC_BUG(connection_.SendStreamData(3, data_iov, 0, FIN, nullptr), "Cannot send stream data without encryption."); EXPECT_FALSE(connection_.connected()); } @@ -4979,7 +5108,7 @@ TEST_P(QuicConnectionTest, OnPathDegrading) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&packet_size), Return(true))); - connection_.SendStreamDataWithString(3, "packet", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "packet", 0, NO_FIN, nullptr); size_t num_timeouts = kMinTimeoutsBeforePathDegrading + QuicSentPacketManagerPeer::GetMaxTailLossProbes( @@ -5055,7 +5184,7 @@ TEST_P(QuicConnectionTest, CloseConnectionOnPacketTooLarge) { EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PACKET_WRITE_ERROR, _, ConnectionCloseSource::FROM_SELF)) .Times(1); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); } TEST_P(QuicConnectionTest, AlwaysGetPacketTooLarge) { @@ -5065,7 +5194,7 @@ TEST_P(QuicConnectionTest, AlwaysGetPacketTooLarge) { EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PACKET_WRITE_ERROR, _, ConnectionCloseSource::FROM_SELF)) .Times(1); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); } // Verify that if connection has no outstanding data, it notifies the send @@ -5118,7 +5247,7 @@ TEST_P(QuicConnectionTest, DonotForceSendingAckOnPacketTooLarge) { // Simulate data packet causes write error. EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PACKET_WRITE_ERROR, _, _)); SimulateNextPacketTooLarge(); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, writer_->frame_count()); EXPECT_FALSE(writer_->connection_close_frames().empty()); // Ack frame is not bundled in connection close packet. diff --git a/chromium/net/quic/core/quic_constants.h b/chromium/net/quic/core/quic_constants.h index 9cf0e6c7a34..8fcf115de00 100644 --- a/chromium/net/quic/core/quic_constants.h +++ b/chromium/net/quic/core/quic_constants.h @@ -180,6 +180,9 @@ const size_t kDiversificationNonceSize = 32; // This will likely have to be tuned. const QuicPacketNumber kMaxPacketGap = 5000; +// The maximum number of random padding bytes to add. +const QuicByteCount kMaxNumRandomPaddingBytes = 256; + } // namespace net #endif // NET_QUIC_CORE_QUIC_CONSTANTS_H_ diff --git a/chromium/net/quic/core/quic_crypto_client_stream.cc b/chromium/net/quic/core/quic_crypto_client_stream.cc index ee8d6432dd3..837ebeb5da7 100644 --- a/chromium/net/quic/core/quic_crypto_client_stream.cc +++ b/chromium/net/quic/core/quic_crypto_client_stream.cc @@ -11,10 +11,10 @@ #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/crypto/crypto_utils.h" #include "net/quic/core/crypto/null_encrypter.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_session.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_str_cat.h" diff --git a/chromium/net/quic/core/quic_crypto_client_stream_test.cc b/chromium/net/quic/core/quic_crypto_client_stream_test.cc index e0b99839fde..495438e9441 100644 --- a/chromium/net/quic/core/quic_crypto_client_stream_test.cc +++ b/chromium/net/quic/core/quic_crypto_client_stream_test.cc @@ -9,17 +9,16 @@ #include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h" #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_server_id.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/quic_stream_peer.h" #include "net/quic/test_tools/quic_stream_sequencer_peer.h" #include "net/quic/test_tools/quic_test_utils.h" #include "net/quic/test_tools/simple_quic_framer.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; @@ -32,7 +31,7 @@ namespace { const char kServerHostname[] = "test.example.com"; const uint16_t kServerPort = 443; -class QuicCryptoClientStreamTest : public ::testing::Test { +class QuicCryptoClientStreamTest : public QuicTest { public: QuicCryptoClientStreamTest() : server_id_(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED), @@ -64,7 +63,9 @@ class QuicCryptoClientStreamTest : public ::testing::Test { framer.ConstructHandshakeMessage(message_, perspective)); } - QuicCryptoClientStream* stream() { return session_->GetCryptoStream(); } + QuicCryptoClientStream* stream() { + return session_->GetMutableCryptoStream(); + } MockQuicConnectionHelper server_helper_; MockQuicConnectionHelper client_helper_; @@ -350,7 +351,7 @@ TEST_F(QuicCryptoClientStreamTest, NoTokenBindingInPrivacyMode) { EXPECT_EQ(0u, stream()->crypto_negotiated_params().token_binding_key_param); } -class QuicCryptoClientStreamStatelessTest : public ::testing::Test { +class QuicCryptoClientStreamStatelessTest : public QuicTest { public: QuicCryptoClientStreamStatelessTest() : client_crypto_config_(crypto_test_utils::ProofVerifierForTesting()), @@ -372,14 +373,14 @@ class QuicCryptoClientStreamStatelessTest : public ::testing::Test { } QuicCryptoServerStream* server_stream() { - return server_session_->GetCryptoStream(); + return server_session_->GetMutableCryptoStream(); } void AdvanceHandshakeWithFakeServer() { - client_session_->GetCryptoStream()->CryptoConnect(); - crypto_test_utils::AdvanceHandshake(client_connection_, - client_session_->GetCryptoStream(), 0, - server_connection_, server_stream(), 0); + client_session_->GetMutableCryptoStream()->CryptoConnect(); + crypto_test_utils::AdvanceHandshake( + client_connection_, client_session_->GetMutableCryptoStream(), 0, + server_connection_, server_stream(), 0); } // Initializes the server_stream_ for stateless rejects. @@ -399,8 +400,6 @@ class QuicCryptoClientStreamStatelessTest : public ::testing::Test { FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support = true; } - QuicFlagSaver flags_; // Save/restore all QUIC flag values. - MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; @@ -432,8 +431,8 @@ TEST_F(QuicCryptoClientStreamStatelessTest, StatelessReject) { EXPECT_EQ(1, server_stream()->NumHandshakeMessages()); EXPECT_EQ(0, server_stream()->NumHandshakeMessagesWithServerNonces()); - EXPECT_FALSE(client_session_->GetCryptoStream()->encryption_established()); - EXPECT_FALSE(client_session_->GetCryptoStream()->handshake_confirmed()); + EXPECT_FALSE(client_session_->IsEncryptionEstablished()); + EXPECT_FALSE(client_session_->IsCryptoHandshakeConfirmed()); // Even though the handshake was not complete, the cached client_state is // complete, and can be used for a subsequent successful handshake. EXPECT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0))); @@ -445,7 +444,7 @@ TEST_F(QuicCryptoClientStreamStatelessTest, StatelessReject) { client_state->GetNextServerDesignatedConnectionId(); QuicConnectionId expected_id = server_session_->connection()->random_generator()->RandUint64(); - EXPECT_EQ(expected_id, server_designated_id); + EXPECT_EQ(GetPeerInMemoryConnectionId(expected_id), server_designated_id); EXPECT_FALSE(client_state->has_server_designated_connection_id()); } diff --git a/chromium/net/quic/core/quic_crypto_server_stream.cc b/chromium/net/quic/core/quic_crypto_server_stream.cc index 49594d6781d..6912d2f8836 100644 --- a/chromium/net/quic/core/quic_crypto_server_stream.cc +++ b/chromium/net/quic/core/quic_crypto_server_stream.cc @@ -12,9 +12,9 @@ #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/proto/cached_network_parameters.pb.h" #include "net/quic/core/quic_config.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_session.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_string_piece.h" #include "net/quic/platform/api/quic_text_utils.h" @@ -97,6 +97,7 @@ QuicCryptoServerStream::QuicCryptoServerStream( use_stateless_rejects_if_peer_supported_( use_stateless_rejects_if_peer_supported), peer_supports_stateless_rejects_(false), + zero_rtt_attempted_(false), chlo_packet_size_(0), validate_client_hello_cb_(nullptr), process_client_hello_cb_(nullptr) { @@ -143,8 +144,7 @@ void QuicCryptoServerStream::OnHandshakeMessage( } if (validate_client_hello_cb_ != nullptr || - (base::GetFlag(FLAGS_quic_reloadable_flag_fix_quic_callback_crash) && - process_client_hello_cb_ != nullptr)) { + process_client_hello_cb_ != nullptr) { // 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. @@ -162,7 +162,7 @@ void QuicCryptoServerStream::OnHandshakeMessage( DCHECK(process_client_hello_cb_ == nullptr); validate_client_hello_cb_ = cb.get(); crypto_config_->ValidateClientHello( - message, session()->connection()->peer_address().host(), + message, GetClientAddress().host(), session()->connection()->self_address(), version(), session()->connection()->clock(), signed_config_, std::move(cb)); } @@ -301,8 +301,7 @@ void QuicCryptoServerStream::SendServerConfigUpdate( crypto_config_->BuildServerConfigUpdateMessage( session()->connection()->version(), chlo_hash_, previous_source_address_tokens_, session()->connection()->self_address(), - session()->connection()->peer_address().host(), - session()->connection()->clock(), + GetClientAddress().host(), session()->connection()->clock(), session()->connection()->random_generator(), compressed_certs_cache_, *crypto_negotiated_params_, cached_network_params, (session()->config()->HasReceivedConnectionOptions() @@ -375,6 +374,10 @@ bool QuicCryptoServerStream::PeerSupportsStatelessRejects() const { return peer_supports_stateless_rejects_; } +bool QuicCryptoServerStream::ZeroRttAttempted() const { + return zero_rtt_attempted_; +} + void QuicCryptoServerStream::SetPeerSupportsStatelessRejects( bool peer_supports_stateless_rejects) { peer_supports_stateless_rejects_ = peer_supports_stateless_rejects; @@ -415,10 +418,16 @@ void QuicCryptoServerStream::ProcessClientHello( nullptr); return; } - if (!result->info.server_nonce.empty()) { ++num_handshake_messages_with_server_nonces_; } + + if (num_handshake_messages_ == 1) { + // Client attempts zero RTT handshake by sending a non-inchoate CHLO. + QuicStringPiece public_value; + zero_rtt_attempted_ = message.GetStringPiece(kPUBS, &public_value); + } + // Store the bandwidth estimate from the client. if (result->cached_network_params.bandwidth_estimate_bytes_per_second() > 0) { previous_cached_network_params_.reset( @@ -434,7 +443,7 @@ void QuicCryptoServerStream::ProcessClientHello( GenerateConnectionIdForReject(use_stateless_rejects_in_crypto_config); crypto_config_->ProcessClientHello( result, /*reject_only=*/false, connection->connection_id(), - connection->self_address(), connection->peer_address(), version(), + connection->self_address(), GetClientAddress(), version(), connection->supported_versions(), use_stateless_rejects_in_crypto_config, server_designated_connection_id, connection->clock(), connection->random_generator(), compressed_certs_cache_, @@ -471,4 +480,8 @@ QuicConnectionId QuicCryptoServerStream::GenerateConnectionIdForReject( session()->connection()->connection_id()); } +const QuicSocketAddress QuicCryptoServerStream::GetClientAddress() { + return session()->connection()->peer_address(); +} + } // namespace net diff --git a/chromium/net/quic/core/quic_crypto_server_stream.h b/chromium/net/quic/core/quic_crypto_server_stream.h index 4701be7a25a..3f83675380a 100644 --- a/chromium/net/quic/core/quic_crypto_server_stream.h +++ b/chromium/net/quic/core/quic_crypto_server_stream.h @@ -57,6 +57,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream { virtual uint8_t NumHandshakeMessagesWithServerNonces() const = 0; virtual bool UseStatelessRejectsIfPeerSupported() const = 0; virtual bool PeerSupportsStatelessRejects() const = 0; + virtual bool ZeroRttAttempted() const = 0; virtual void SetPeerSupportsStatelessRejects(bool set) = 0; virtual const CachedNetworkParameters* PreviousCachedNetworkParams() const = 0; @@ -112,6 +113,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream const CachedNetworkParameters* PreviousCachedNetworkParams() const override; bool UseStatelessRejectsIfPeerSupported() const override; bool PeerSupportsStatelessRejects() const override; + bool ZeroRttAttempted() const override; void SetPeerSupportsStatelessRejects( bool peer_supports_stateless_rejects) override; void SetPreviousCachedNetworkParams( @@ -137,6 +139,9 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream // before going through the parameter negotiation step. virtual void OverrideQuicConfigDefaults(QuicConfig* config); + // Returns client address used to generate and validate source address token. + virtual const QuicSocketAddress GetClientAddress(); + private: friend class test::QuicCryptoServerStreamPeer; @@ -260,6 +265,11 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream // becomes the default. bool peer_supports_stateless_rejects_; + // True if client attempts 0-rtt handshake (which can succeed or fail). If + // stateless rejects are used, this variable will be false for the stateless + // rejected connection and true for subsequent connections. + bool zero_rtt_attempted_; + // Size of the packet containing the most recently received CHLO. QuicByteCount chlo_packet_size_; diff --git a/chromium/net/quic/core/quic_crypto_server_stream_test.cc b/chromium/net/quic/core/quic_crypto_server_stream_test.cc index ad3c54e530f..b60c22d1c55 100644 --- a/chromium/net/quic/core/quic_crypto_server_stream_test.cc +++ b/chromium/net/quic/core/quic_crypto_server_stream_test.cc @@ -18,19 +18,18 @@ #include "net/quic/core/crypto/quic_encrypter.h" #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/quic_crypto_client_stream.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_session.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_socket_address.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/failing_proof_source.h" #include "net/quic/test_tools/fake_proof_source.h" #include "net/quic/test_tools/quic_crypto_server_config_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { class QuicConnection; @@ -57,7 +56,7 @@ namespace { const char kServerHostname[] = "test.example.com"; const uint16_t kServerPort = 443; -class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> { +class QuicCryptoServerStreamTest : public QuicTestWithParam<bool> { public: QuicCryptoServerStreamTest() : QuicCryptoServerStreamTest(crypto_test_utils::ProofSourceForTesting()) { @@ -106,11 +105,11 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> { } QuicCryptoServerStream* server_stream() { - return server_session_->GetCryptoStream(); + return server_session_->GetMutableCryptoStream(); } QuicCryptoClientStream* client_stream() { - return client_session_->GetCryptoStream(); + return client_session_->GetMutableCryptoStream(); } // Initializes a fake client, and all its associated state, for @@ -155,8 +154,6 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> { } protected: - QuicFlagSaver flags_; // Save/restore all QUIC flag values. - // Every connection gets its own MockQuicConnectionHelper and // MockAlarmFactory, tracked separately from the server and client state so // their lifetimes persist through the whole test. @@ -257,7 +254,8 @@ TEST_P(QuicCryptoServerStreamTest, StatelessRejectAfterCHLO) { client_state->GetNextServerDesignatedConnectionId(); const QuicConnectionId expected_id = server_connection_->random_generator()->RandUint64(); - EXPECT_EQ(expected_id, server_designated_connection_id); + EXPECT_EQ(GetPeerInMemoryConnectionId(expected_id), + server_designated_connection_id); EXPECT_FALSE(client_state->has_server_designated_connection_id()); ASSERT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0))); } @@ -284,7 +282,8 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) { client_state->GetNextServerDesignatedConnectionId(); const QuicConnectionId expected_id = server_connection_->random_generator()->RandUint64(); - EXPECT_EQ(expected_id, server_designated_connection_id); + EXPECT_EQ(GetPeerInMemoryConnectionId(expected_id), + server_designated_connection_id); EXPECT_FALSE(client_state->has_server_designated_connection_id()); ASSERT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0))); @@ -334,6 +333,7 @@ TEST_P(QuicCryptoServerStreamTest, ZeroRTT) { // Do a first handshake in order to prime the client config with the server's // information. AdvanceHandshakeWithFakeClient(); + EXPECT_FALSE(server_stream()->ZeroRttAttempted()); // Now do another handshake, hopefully in 0-RTT. QUIC_LOG(INFO) << "Resetting for 0-RTT handshake attempt"; @@ -346,6 +346,7 @@ TEST_P(QuicCryptoServerStreamTest, ZeroRTT) { client_connection_, client_stream(), server_connection_, server_stream()); EXPECT_EQ(1, client_stream()->num_sent_client_hellos()); + EXPECT_TRUE(server_stream()->ZeroRttAttempted()); } TEST_P(QuicCryptoServerStreamTest, FailByPolicy) { @@ -533,7 +534,6 @@ INSTANTIATE_TEST_CASE_P(YetMoreTests, TEST_P(QuicCryptoServerStreamTestWithFakeProofSource, MultipleChlo) { Initialize(); GetFakeProofSource()->Activate(); - base::SetFlag(&FLAGS_quic_reloadable_flag_fix_quic_callback_crash, true); EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _)) .WillOnce(testing::Return(true)); diff --git a/chromium/net/quic/core/quic_crypto_stream.cc b/chromium/net/quic/core/quic_crypto_stream.cc index ee8660a8ce8..60ab8433921 100644 --- a/chromium/net/quic/core/quic_crypto_stream.cc +++ b/chromium/net/quic/core/quic_crypto_stream.cc @@ -9,10 +9,10 @@ #include "net/quic/core/crypto/crypto_handshake.h" #include "net/quic/core/crypto/crypto_utils.h" #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_session.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" using std::string; diff --git a/chromium/net/quic/core/quic_crypto_stream_test.cc b/chromium/net/quic/core/quic_crypto_stream_test.cc index 7457c0eec31..9850a8cd43f 100644 --- a/chromium/net/quic/core/quic_crypto_stream_test.cc +++ b/chromium/net/quic/core/quic_crypto_stream_test.cc @@ -13,11 +13,10 @@ #include "net/quic/core/crypto/crypto_handshake.h" #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/platform/api/quic_socket_address.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/quic_stream_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; @@ -42,7 +41,7 @@ class MockQuicCryptoStream : public QuicCryptoStream { DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoStream); }; -class QuicCryptoStreamTest : public ::testing::Test { +class QuicCryptoStreamTest : public QuicTest { public: QuicCryptoStreamTest() : connection_(new MockQuicConnection(&helper_, diff --git a/chromium/net/quic/core/quic_data_reader.cc b/chromium/net/quic/core/quic_data_reader.cc index 5f2c483338b..c748efcabf1 100644 --- a/chromium/net/quic/core/quic_data_reader.cc +++ b/chromium/net/quic/core/quic_data_reader.cc @@ -5,33 +5,72 @@ #include "net/quic/core/quic_data_reader.h" #include "net/base/int128.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" -#include "net/quic/platform/api/quic_endian.h" +#include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net { -#define ENDPOINT \ - (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ") - QuicDataReader::QuicDataReader(const char* data, const size_t len, - Perspective perspective) - : data_(data), len_(len), pos_(0), perspective_(perspective) { - QUIC_DVLOG(1) << ENDPOINT << "QuicDataReader"; + Perspective perspective, + Endianness endianness) + : data_(data), + len_(len), + pos_(0), + perspective_(perspective), + endianness_(endianness) {} + +bool QuicDataReader::ReadUInt8(uint8_t* result) { + return ReadBytes(result, sizeof(*result)); } bool QuicDataReader::ReadUInt16(uint16_t* result) { - return ReadBytes(result, sizeof(*result)); + if (!ReadBytes(result, sizeof(*result))) { + return false; + } + if (endianness_ == NETWORK_BYTE_ORDER) { + *result = QuicEndian::NetToHost16(*result); + } + return true; } bool QuicDataReader::ReadUInt32(uint32_t* result) { - return ReadBytes(result, sizeof(*result)); + if (!ReadBytes(result, sizeof(*result))) { + return false; + } + if (endianness_ == NETWORK_BYTE_ORDER) { + *result = QuicEndian::NetToHost32(*result); + } + return true; } bool QuicDataReader::ReadUInt64(uint64_t* result) { - return ReadBytes(result, sizeof(*result)); + if (!ReadBytes(result, sizeof(*result))) { + return false; + } + if (endianness_ == NETWORK_BYTE_ORDER) { + *result = QuicEndian::NetToHost64(*result); + } + return true; +} + +bool QuicDataReader::ReadBytesToUInt64(size_t num_bytes, uint64_t* result) { + if (num_bytes > sizeof(*result)) { + return false; + } + if (endianness_ == HOST_BYTE_ORDER) { + return ReadBytes(result, num_bytes); + } + + if (!ReadBytes(reinterpret_cast<char*>(result) + sizeof(*result) - num_bytes, + num_bytes)) { + return false; + } + *result = QuicEndian::NetToHost64(*result); + return true; } bool QuicDataReader::ReadUFloat16(uint64_t* result) { @@ -95,11 +134,11 @@ bool QuicDataReader::ReadStringPiece(QuicStringPiece* result, size_t size) { } bool QuicDataReader::ReadConnectionId(uint64_t* connection_id) { - if (!ReadUInt64(connection_id)) { + if (!ReadBytes(connection_id, sizeof(*connection_id))) { return false; } - if (FLAGS_quic_restart_flag_quic_big_endian_connection_id) { + if (QuicUtils::IsConnectionIdWireFormatBigEndian(perspective_)) { *connection_id = QuicEndian::NetToHost64(*connection_id); } @@ -154,4 +193,13 @@ void QuicDataReader::OnFailure() { pos_ = len_; } +uint8_t QuicDataReader::PeekByte() const { + if (pos_ >= len_) { + QUIC_BUG << "Reading is done, cannot peek next byte. Tried to read pos = " + << pos_ << " buffer length = " << len_; + return 0; + } + return data_[pos_]; +} + } // namespace net diff --git a/chromium/net/quic/core/quic_data_reader.h b/chromium/net/quic/core/quic_data_reader.h index 9507ec19bf4..755f2fcc66f 100644 --- a/chromium/net/quic/core/quic_data_reader.h +++ b/chromium/net/quic/core/quic_data_reader.h @@ -11,6 +11,7 @@ #include "base/macros.h" #include "net/base/int128.h" #include "net/quic/core/quic_types.h" +#include "net/quic/platform/api/quic_endian.h" #include "net/quic/platform/api/quic_export.h" #include "net/quic/platform/api/quic_string_piece.h" @@ -33,26 +34,26 @@ namespace net { class QUIC_EXPORT_PRIVATE QuicDataReader { public: // Caller must provide an underlying buffer to work on. - QuicDataReader(const char* data, const size_t len, Perspective perspective); + QuicDataReader(const char* data, + const size_t len, + Perspective perspective, + Endianness endianness); // Empty destructor. ~QuicDataReader() {} - // Reads a 16-bit unsigned integer into the given output parameter. - // Forwards the internal iterator on success. - // Returns true on success, false otherwise. + // Reads an 8/16/32/64-bit unsigned integer into the given output + // parameter. Forwards the internal iterator on success. Returns true on + // success, false otherwise. + bool ReadUInt8(uint8_t* result); bool ReadUInt16(uint16_t* result); - - // Reads a 32-bit unsigned integer into the given output parameter. - // Forwards the internal iterator on success. - // Returns true on success, false otherwise. bool ReadUInt32(uint32_t* result); - - // Reads a 64-bit unsigned integer into the given output parameter. - // Forwards the internal iterator on success. - // Returns true on success, false otherwise. bool ReadUInt64(uint64_t* result); + // Reads |num_bytes| bytes in the correct byte order into least significant + // bytes of |result|. + bool ReadBytesToUInt64(size_t num_bytes, uint64_t* result); + // Reads a 16-bit unsigned float into the given output parameter. // Forwards the internal iterator on success. // Returns true on success, false otherwise. @@ -118,6 +119,14 @@ class QUIC_EXPORT_PRIVATE QuicDataReader { // Returns the number of bytes remaining to be read. size_t BytesRemaining() const; + // Returns the next byte that to be read. Must not be called when there are no + // bytes to be read. + // + // DOES NOT forward the internal iterator. + uint8_t PeekByte() const; + + void set_endianness(Endianness endianness) { endianness_ = endianness; } + private: // Returns true if the underlying buffer has enough room to read the given // amount of bytes. @@ -140,6 +149,9 @@ class QUIC_EXPORT_PRIVATE QuicDataReader { // representation must be consistent. Perspective perspective_; + // The endianness to read integers and floating numbers. + Endianness endianness_; + DISALLOW_COPY_AND_ASSIGN(QuicDataReader); }; diff --git a/chromium/net/quic/core/quic_data_writer.cc b/chromium/net/quic/core/quic_data_writer.cc index 3ac6450ba00..3290dba4711 100644 --- a/chromium/net/quic/core/quic_data_writer.cc +++ b/chromium/net/quic/core/quic_data_writer.cc @@ -7,21 +7,21 @@ #include <algorithm> #include <limits> -#include "net/quic/core/quic_flags.h" -#include "net/quic/platform/api/quic_endian.h" +#include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net { -#define ENDPOINT \ - (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ") - QuicDataWriter::QuicDataWriter(size_t size, char* buffer, - Perspective perspective) - : buffer_(buffer), capacity_(size), length_(0), perspective_(perspective) { - QUIC_DVLOG(1) << ENDPOINT << "QuicDataReader"; -} + Perspective perspective, + Endianness endianness) + : buffer_(buffer), + capacity_(size), + length_(0), + perspective_(perspective), + endianness_(endianness) {} QuicDataWriter::~QuicDataWriter() {} @@ -34,23 +34,39 @@ bool QuicDataWriter::WriteUInt8(uint8_t value) { } bool QuicDataWriter::WriteUInt16(uint16_t value) { + if (endianness_ == NETWORK_BYTE_ORDER) { + value = QuicEndian::HostToNet16(value); + } return WriteBytes(&value, sizeof(value)); } bool QuicDataWriter::WriteUInt32(uint32_t value) { + if (endianness_ == NETWORK_BYTE_ORDER) { + value = QuicEndian::HostToNet32(value); + } return WriteBytes(&value, sizeof(value)); } -bool QuicDataWriter::WriteUInt48(uint64_t value) { - uint16_t hi = static_cast<uint16_t>(value >> 32); - uint32_t lo = static_cast<uint32_t>(value); - return WriteUInt32(lo) && WriteUInt16(hi); -} - bool QuicDataWriter::WriteUInt64(uint64_t value) { + if (endianness_ == NETWORK_BYTE_ORDER) { + value = QuicEndian::HostToNet64(value); + } return WriteBytes(&value, sizeof(value)); } +bool QuicDataWriter::WriteBytesToUInt64(size_t num_bytes, uint64_t value) { + if (num_bytes > sizeof(value)) { + return false; + } + if (endianness_ == HOST_BYTE_ORDER) { + return WriteBytes(&value, num_bytes); + } + + value = QuicEndian::HostToNet64(value); + return WriteBytes(reinterpret_cast<char*>(&value) + sizeof(value) - num_bytes, + num_bytes); +} + bool QuicDataWriter::WriteUFloat16(uint64_t value) { uint16_t result; if (value < (UINT64_C(1) << kUFloat16MantissaEffectiveBits)) { @@ -87,6 +103,9 @@ bool QuicDataWriter::WriteUFloat16(uint64_t value) { result = static_cast<uint16_t>(value + (exponent << kUFloat16MantissaBits)); } + if (endianness_ == NETWORK_BYTE_ORDER) { + result = QuicEndian::HostToNet16(result); + } return WriteBytes(&result, sizeof(result)); } @@ -149,12 +168,16 @@ void QuicDataWriter::WritePadding() { length_ = capacity_; } +bool QuicDataWriter::WritePaddingBytes(size_t count) { + return WriteRepeatedByte(0x00, count); +} + bool QuicDataWriter::WriteConnectionId(uint64_t connection_id) { - if (FLAGS_quic_restart_flag_quic_big_endian_connection_id) { + if (QuicUtils::IsConnectionIdWireFormatBigEndian(perspective_)) { connection_id = QuicEndian::HostToNet64(connection_id); } - return WriteUInt64(connection_id); + return WriteBytes(&connection_id, sizeof(connection_id)); } bool QuicDataWriter::WriteTag(uint32_t tag) { diff --git a/chromium/net/quic/core/quic_data_writer.h b/chromium/net/quic/core/quic_data_writer.h index a7faca2ad45..8c0f400da79 100644 --- a/chromium/net/quic/core/quic_data_writer.h +++ b/chromium/net/quic/core/quic_data_writer.h @@ -12,6 +12,7 @@ #include "base/macros.h" #include "net/base/int128.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/platform/api/quic_endian.h" #include "net/quic/platform/api/quic_export.h" #include "net/quic/platform/api/quic_string_piece.h" @@ -25,7 +26,10 @@ namespace net { class QUIC_EXPORT_PRIVATE QuicDataWriter { public: // Creates a QuicDataWriter where |buffer| is not owned. - QuicDataWriter(size_t size, char* buffer, Perspective perspective); + QuicDataWriter(size_t size, + char* buffer, + Perspective perspective, + Endianness endianness); ~QuicDataWriter(); @@ -36,13 +40,18 @@ class QUIC_EXPORT_PRIVATE QuicDataWriter { char* data(); // Methods for adding to the payload. These values are appended to the end - // of the QuicDataWriter payload. Note - binary integers are written in - // host byte order (little endian) not network byte order (big endian). + // of the QuicDataWriter payload. + + // Writes 8/16/32/64-bit unsigned integers. bool WriteUInt8(uint8_t value); bool WriteUInt16(uint16_t value); bool WriteUInt32(uint32_t value); - bool WriteUInt48(uint64_t value); bool WriteUInt64(uint64_t value); + + // Writes least significant |num_bytes| of a 64-bit unsigned integer in the + // correct byte order. + bool WriteBytesToUInt64(size_t num_bytes, uint64_t value); + // Write unsigned floating point corresponding to the value. Large values are // clamped to the maximum representable (kUFloat16MaxValue). Values that can // not be represented directly are rounded down. @@ -52,6 +61,8 @@ class QUIC_EXPORT_PRIVATE QuicDataWriter { bool WriteRepeatedByte(uint8_t byte, size_t count); // Fills the remaining buffer with null characters. void WritePadding(); + // Write padding of |count| bytes. + bool WritePaddingBytes(size_t count); // Write connection ID as a 64-bit unsigned integer to the payload. // TODO(fayang): Remove this method and use WriteUInt64() once deprecating @@ -82,6 +93,9 @@ class QUIC_EXPORT_PRIVATE QuicDataWriter { // representation must be consistent. Perspective perspective_; + // The endianness to write integers and floating numbers. + Endianness endianness_; + DISALLOW_COPY_AND_ASSIGN(QuicDataWriter); }; diff --git a/chromium/net/quic/core/quic_data_writer_test.cc b/chromium/net/quic/core/quic_data_writer_test.cc index bc1d0ad262c..e44a12b1dd5 100644 --- a/chromium/net/quic/core/quic_data_writer_test.cc +++ b/chromium/net/quic/core/quic_data_writer_test.cc @@ -7,15 +7,43 @@ #include <cstdint> #include "net/quic/core/quic_data_reader.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { namespace test { namespace { -class QuicDataWriterTest : public ::testing::TestWithParam<Perspective> {}; +char* AsChars(unsigned char* data) { + return reinterpret_cast<char*>(data); +} + +struct TestParams { + TestParams(Perspective perspective, Endianness endianness) + : perspective(perspective), endianness(endianness) {} + + Perspective perspective; + Endianness endianness; +}; + +std::vector<TestParams> GetTestParams() { + std::vector<TestParams> params; + for (Perspective perspective : + {Perspective::IS_CLIENT, Perspective::IS_SERVER}) { + for (Endianness endianness : {NETWORK_BYTE_ORDER, HOST_BYTE_ORDER}) { + params.push_back(TestParams(perspective, endianness)); + } + } + return params; +} + +class QuicDataWriterTest : public QuicTestWithParam<TestParams> {}; + +INSTANTIATE_TEST_CASE_P(QuicDataWriterTests, + QuicDataWriterTest, + ::testing::ValuesIn(GetTestParams())); TEST_P(QuicDataWriterTest, SanityCheckUFloat16Consts) { // Check the arithmetic on the constants - otherwise the values below make @@ -98,10 +126,14 @@ TEST_P(QuicDataWriterTest, WriteUFloat16) { for (int i = 0; i < num_test_cases; ++i) { char buffer[2]; - QuicDataWriter writer(2, buffer, GetParam()); + QuicDataWriter writer(2, buffer, GetParam().perspective, + GetParam().endianness); EXPECT_TRUE(writer.WriteUFloat16(test_cases[i].decoded)); - EXPECT_EQ(test_cases[i].encoded, - *reinterpret_cast<uint16_t*>(writer.data())); + uint16_t result = *reinterpret_cast<uint16_t*>(writer.data()); + if (GetParam().endianness == NETWORK_BYTE_ORDER) { + result = QuicEndian::HostToNet16(result); + } + EXPECT_EQ(test_cases[i].encoded, result); } } @@ -158,8 +190,12 @@ TEST_P(QuicDataWriterTest, ReadUFloat16) { int num_test_cases = sizeof(test_cases) / sizeof(test_cases[0]); for (int i = 0; i < num_test_cases; ++i) { - QuicDataReader reader(reinterpret_cast<char*>(&test_cases[i].encoded), 2, - GetParam()); + uint16_t encoded_ufloat = test_cases[i].encoded; + if (GetParam().endianness == NETWORK_BYTE_ORDER) { + encoded_ufloat = QuicEndian::HostToNet16(encoded_ufloat); + } + QuicDataReader reader(reinterpret_cast<char*>(&encoded_ufloat), 2, + GetParam().perspective, GetParam().endianness); uint64_t value; EXPECT_TRUE(reader.ReadUFloat16(&value)); EXPECT_EQ(test_cases[i].decoded, value); @@ -171,33 +207,48 @@ TEST_P(QuicDataWriterTest, RoundTripUFloat16) { uint64_t previous_value = 0; for (uint16_t i = 1; i < 0xFFFF; ++i) { // Read the two bytes. - QuicDataReader reader(reinterpret_cast<char*>(&i), 2, GetParam()); + uint16_t read_number = i; + if (GetParam().endianness == NETWORK_BYTE_ORDER) { + read_number = QuicEndian::HostToNet16(read_number); + } + QuicDataReader reader(reinterpret_cast<char*>(&read_number), 2, + GetParam().perspective, GetParam().endianness); uint64_t value; // All values must be decodable. EXPECT_TRUE(reader.ReadUFloat16(&value)); // Check that small numbers represent themselves - if (i < 4097) + if (i < 4097) { EXPECT_EQ(i, value); + } // Check there's monotonic growth. EXPECT_LT(previous_value, value); // Check that precision is within 0.5% away from the denormals. - if (i > 2000) + if (i > 2000) { EXPECT_GT(previous_value * 1005, value * 1000); + } // Check we're always within the promised range. EXPECT_LT(value, UINT64_C(0x3FFC0000000)); previous_value = value; char buffer[6]; - QuicDataWriter writer(6, buffer, GetParam()); + QuicDataWriter writer(6, buffer, GetParam().perspective, + GetParam().endianness); EXPECT_TRUE(writer.WriteUFloat16(value - 1)); EXPECT_TRUE(writer.WriteUFloat16(value)); EXPECT_TRUE(writer.WriteUFloat16(value + 1)); // Check minimal decoding (previous decoding has previous encoding). - EXPECT_EQ(i - 1, *reinterpret_cast<uint16_t*>(writer.data())); + uint16_t encoded1 = *reinterpret_cast<uint16_t*>(writer.data()); + uint16_t encoded2 = *reinterpret_cast<uint16_t*>(writer.data() + 2); + uint16_t encoded3 = *reinterpret_cast<uint16_t*>(writer.data() + 4); + if (GetParam().endianness == NETWORK_BYTE_ORDER) { + encoded1 = QuicEndian::NetToHost16(encoded1); + encoded2 = QuicEndian::NetToHost16(encoded2); + encoded3 = QuicEndian::NetToHost16(encoded3); + } + EXPECT_EQ(i - 1, encoded1); // Check roundtrip. - EXPECT_EQ(i, *reinterpret_cast<uint16_t*>(writer.data() + 2)); + EXPECT_EQ(i, encoded2); // Check next decoding. - EXPECT_EQ(i < 4096 ? i + 1 : i, - *reinterpret_cast<uint16_t*>(writer.data() + 4)); + EXPECT_EQ(i < 4096 ? i + 1 : i, encoded3); } } @@ -211,16 +262,19 @@ TEST_P(QuicDataWriterTest, WriteConnectionId) { }; const int kBufferLength = sizeof(connection_id); char buffer[kBufferLength]; - QuicDataWriter writer(kBufferLength, buffer, GetParam()); + QuicDataWriter writer(kBufferLength, buffer, GetParam().perspective, + GetParam().endianness); writer.WriteConnectionId(connection_id); test::CompareCharArraysWithHexError( "connection_id", buffer, kBufferLength, - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? big_endian - : little_endian, + QuicUtils::IsConnectionIdWireFormatBigEndian(GetParam().perspective) + ? big_endian + : little_endian, kBufferLength); uint64_t read_connection_id; - QuicDataReader reader(buffer, kBufferLength, GetParam()); + QuicDataReader reader(buffer, kBufferLength, GetParam().perspective, + GetParam().endianness); reader.ReadConnectionId(&read_connection_id); EXPECT_EQ(connection_id, read_connection_id); } @@ -231,17 +285,315 @@ TEST_P(QuicDataWriterTest, WriteTag) { }; const int kBufferLength = sizeof(QuicTag); char buffer[kBufferLength]; - QuicDataWriter writer(kBufferLength, buffer, GetParam()); + QuicDataWriter writer(kBufferLength, buffer, GetParam().perspective, + GetParam().endianness); writer.WriteTag(kCHLO); test::CompareCharArraysWithHexError("CHLO", buffer, kBufferLength, CHLO, kBufferLength); QuicTag read_chlo; - QuicDataReader reader(buffer, kBufferLength, GetParam()); + QuicDataReader reader(buffer, kBufferLength, GetParam().perspective, + GetParam().endianness); reader.ReadTag(&read_chlo); EXPECT_EQ(kCHLO, read_chlo); } +TEST_P(QuicDataWriterTest, Write16BitUnsignedIntegers) { + char little_endian16[] = {0x22, 0x11}; + char big_endian16[] = {0x11, 0x22}; + char buffer16[2]; + { + uint16_t in_memory16 = 0x1122; + QuicDataWriter writer(2, buffer16, GetParam().perspective, + GetParam().endianness); + writer.WriteUInt16(in_memory16); + test::CompareCharArraysWithHexError( + "uint16_t", buffer16, 2, + GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian16 + : little_endian16, + 2); + + uint16_t read_number16; + QuicDataReader reader(buffer16, 2, GetParam().perspective, + GetParam().endianness); + reader.ReadUInt16(&read_number16); + EXPECT_EQ(in_memory16, read_number16); + } + + { + uint64_t in_memory16 = 0x0000000000001122; + QuicDataWriter writer(2, buffer16, GetParam().perspective, + GetParam().endianness); + writer.WriteBytesToUInt64(2, in_memory16); + test::CompareCharArraysWithHexError( + "uint16_t", buffer16, 2, + GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian16 + : little_endian16, + 2); + + uint64_t read_number16 = 0u; + QuicDataReader reader(buffer16, 2, GetParam().perspective, + GetParam().endianness); + reader.ReadBytesToUInt64(2, &read_number16); + EXPECT_EQ(in_memory16, read_number16); + } +} + +TEST_P(QuicDataWriterTest, Write24BitUnsignedIntegers) { + char little_endian24[] = {0x33, 0x22, 0x11}; + char big_endian24[] = {0x11, 0x22, 0x33}; + char buffer24[3]; + uint64_t in_memory24 = 0x0000000000112233; + QuicDataWriter writer(3, buffer24, GetParam().perspective, + GetParam().endianness); + writer.WriteBytesToUInt64(3, in_memory24); + test::CompareCharArraysWithHexError( + "uint24", buffer24, 3, + GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian24 + : little_endian24, + 3); + + uint64_t read_number24 = 0u; + QuicDataReader reader(buffer24, 3, GetParam().perspective, + GetParam().endianness); + reader.ReadBytesToUInt64(3, &read_number24); + EXPECT_EQ(in_memory24, read_number24); +} + +TEST_P(QuicDataWriterTest, Write32BitUnsignedIntegers) { + char little_endian32[] = {0x44, 0x33, 0x22, 0x11}; + char big_endian32[] = {0x11, 0x22, 0x33, 0x44}; + char buffer32[4]; + { + uint32_t in_memory32 = 0x11223344; + QuicDataWriter writer(4, buffer32, GetParam().perspective, + GetParam().endianness); + writer.WriteUInt32(in_memory32); + test::CompareCharArraysWithHexError( + "uint32_t", buffer32, 4, + GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian32 + : little_endian32, + 4); + + uint32_t read_number32; + QuicDataReader reader(buffer32, 4, GetParam().perspective, + GetParam().endianness); + reader.ReadUInt32(&read_number32); + EXPECT_EQ(in_memory32, read_number32); + } + + { + uint64_t in_memory32 = 0x11223344; + QuicDataWriter writer(4, buffer32, GetParam().perspective, + GetParam().endianness); + writer.WriteBytesToUInt64(4, in_memory32); + test::CompareCharArraysWithHexError( + "uint32_t", buffer32, 4, + GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian32 + : little_endian32, + 4); + + uint64_t read_number32 = 0u; + QuicDataReader reader(buffer32, 4, GetParam().perspective, + GetParam().endianness); + reader.ReadBytesToUInt64(4, &read_number32); + EXPECT_EQ(in_memory32, read_number32); + } +} + +TEST_P(QuicDataWriterTest, Write40BitUnsignedIntegers) { + uint64_t in_memory40 = 0x0000001122334455; + char little_endian40[] = {0x55, 0x44, 0x33, 0x22, 0x11}; + char big_endian40[] = {0x11, 0x22, 0x33, 0x44, 0x55}; + char buffer40[5]; + QuicDataWriter writer(5, buffer40, GetParam().perspective, + GetParam().endianness); + writer.WriteBytesToUInt64(5, in_memory40); + test::CompareCharArraysWithHexError( + "uint40", buffer40, 5, + GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian40 + : little_endian40, + 5); + + uint64_t read_number40 = 0u; + QuicDataReader reader(buffer40, 5, GetParam().perspective, + GetParam().endianness); + reader.ReadBytesToUInt64(5, &read_number40); + EXPECT_EQ(in_memory40, read_number40); +} + +TEST_P(QuicDataWriterTest, Write48BitUnsignedIntegers) { + uint64_t in_memory48 = 0x0000112233445566; + char little_endian48[] = {0x66, 0x55, 0x44, 0x33, 0x22, 0x11}; + char big_endian48[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + char buffer48[6]; + QuicDataWriter writer(6, buffer48, GetParam().perspective, + GetParam().endianness); + writer.WriteBytesToUInt64(6, in_memory48); + test::CompareCharArraysWithHexError( + "uint48", buffer48, 6, + GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian48 + : little_endian48, + 6); + + uint64_t read_number48 = 0u; + QuicDataReader reader(buffer48, 6, GetParam().perspective, + GetParam().endianness); + reader.ReadBytesToUInt64(6., &read_number48); + EXPECT_EQ(in_memory48, read_number48); +} + +TEST_P(QuicDataWriterTest, Write56BitUnsignedIntegers) { + uint64_t in_memory56 = 0x0011223344556677; + char little_endian56[] = {0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11}; + char big_endian56[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + char buffer56[7]; + QuicDataWriter writer(7, buffer56, GetParam().perspective, + GetParam().endianness); + writer.WriteBytesToUInt64(7, in_memory56); + test::CompareCharArraysWithHexError( + "uint56", buffer56, 7, + GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian56 + : little_endian56, + 7); + + uint64_t read_number56 = 0u; + QuicDataReader reader(buffer56, 7, GetParam().perspective, + GetParam().endianness); + reader.ReadBytesToUInt64(7, &read_number56); + EXPECT_EQ(in_memory56, read_number56); +} + +TEST_P(QuicDataWriterTest, Write64BitUnsignedIntegers) { + uint64_t in_memory64 = 0x1122334455667788; + unsigned char little_endian64[] = {0x88, 0x77, 0x66, 0x55, + 0x44, 0x33, 0x22, 0x11}; + unsigned char big_endian64[] = {0x11, 0x22, 0x33, 0x44, + 0x55, 0x66, 0x77, 0x88}; + char buffer64[8]; + QuicDataWriter writer(8, buffer64, GetParam().perspective, + GetParam().endianness); + writer.WriteBytesToUInt64(8, in_memory64); + test::CompareCharArraysWithHexError( + "uint64_t", buffer64, 8, + GetParam().endianness == NETWORK_BYTE_ORDER ? AsChars(big_endian64) + : AsChars(little_endian64), + 8); + + uint64_t read_number64 = 0u; + QuicDataReader reader(buffer64, 8, GetParam().perspective, + GetParam().endianness); + reader.ReadBytesToUInt64(8, &read_number64); + EXPECT_EQ(in_memory64, read_number64); + + QuicDataWriter writer2(8, buffer64, GetParam().perspective, + GetParam().endianness); + writer2.WriteUInt64(in_memory64); + test::CompareCharArraysWithHexError( + "uint64_t", buffer64, 8, + GetParam().endianness == NETWORK_BYTE_ORDER ? AsChars(big_endian64) + : AsChars(little_endian64), + 8); + read_number64 = 0u; + QuicDataReader reader2(buffer64, 8, GetParam().perspective, + GetParam().endianness); + reader2.ReadUInt64(&read_number64); + EXPECT_EQ(in_memory64, read_number64); +} + +TEST_P(QuicDataWriterTest, WriteIntegers) { + char buf[43]; + uint8_t i8 = 0x01; + uint16_t i16 = 0x0123; + uint32_t i32 = 0x01234567; + uint64_t i64 = 0x0123456789ABCDEF; + QuicDataWriter writer(46, buf, GetParam().perspective, GetParam().endianness); + for (size_t i = 0; i < 10; ++i) { + switch (i) { + case 0u: + EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64)); + break; + case 1u: + EXPECT_TRUE(writer.WriteUInt8(i8)); + EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64)); + break; + case 2u: + EXPECT_TRUE(writer.WriteUInt16(i16)); + EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64)); + break; + case 3u: + EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64)); + break; + case 4u: + EXPECT_TRUE(writer.WriteUInt32(i32)); + EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64)); + break; + case 5u: + case 6u: + case 7u: + case 8u: + EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64)); + break; + default: + EXPECT_FALSE(writer.WriteBytesToUInt64(i, i64)); + } + } + + QuicDataReader reader(buf, 46, GetParam().perspective, GetParam().endianness); + for (size_t i = 0; i < 10; ++i) { + uint8_t read8; + uint16_t read16; + uint32_t read32; + uint64_t read64 = 0u; + switch (i) { + case 0u: + EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64)); + EXPECT_EQ(0u, read64); + break; + case 1u: + EXPECT_TRUE(reader.ReadUInt8(&read8)); + EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64)); + EXPECT_EQ(i8, read8); + EXPECT_EQ(0xEFu, read64); + break; + case 2u: + EXPECT_TRUE(reader.ReadUInt16(&read16)); + EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64)); + EXPECT_EQ(i16, read16); + EXPECT_EQ(0xCDEFu, read64); + break; + case 3u: + EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64)); + EXPECT_EQ(0xABCDEFu, read64); + break; + case 4u: + EXPECT_TRUE(reader.ReadUInt32(&read32)); + EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64)); + EXPECT_EQ(i32, read32); + EXPECT_EQ(0x89ABCDEFu, read64); + break; + case 5u: + EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64)); + EXPECT_EQ(0x6789ABCDEFu, read64); + break; + case 6u: + EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64)); + EXPECT_EQ(0x456789ABCDEFu, read64); + break; + case 7u: + EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64)); + EXPECT_EQ(0x23456789ABCDEFu, read64); + break; + case 8u: + EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64)); + EXPECT_EQ(0x0123456789ABCDEFu, read64); + break; + default: + EXPECT_FALSE(reader.ReadBytesToUInt64(i, &read64)); + } + } +} + } // namespace } // namespace test } // namespace net diff --git a/chromium/net/quic/core/quic_error_codes.cc b/chromium/net/quic/core/quic_error_codes.cc index ca87175ad91..2f734e524b0 100644 --- a/chromium/net/quic/core/quic_error_codes.cc +++ b/chromium/net/quic/core/quic_error_codes.cc @@ -113,7 +113,6 @@ const char* QuicErrorCodeToString(QuicErrorCode error) { RETURN_STRING_LITERAL(QUIC_CONNECTION_CANCELLED); RETURN_STRING_LITERAL(QUIC_BAD_PACKET_LOSS_RATE); RETURN_STRING_LITERAL(QUIC_PUBLIC_RESETS_POST_HANDSHAKE); - RETURN_STRING_LITERAL(QUIC_TIMEOUTS_WITH_OPEN_STREAMS); RETURN_STRING_LITERAL(QUIC_FAILED_TO_SERIALIZE_PACKET); RETURN_STRING_LITERAL(QUIC_TOO_MANY_AVAILABLE_STREAMS); RETURN_STRING_LITERAL(QUIC_UNENCRYPTED_FEC_DATA); diff --git a/chromium/net/quic/core/quic_error_codes.h b/chromium/net/quic/core/quic_error_codes.h index 38750a587bc..2a6f335bb45 100644 --- a/chromium/net/quic/core/quic_error_codes.h +++ b/chromium/net/quic/core/quic_error_codes.h @@ -174,8 +174,6 @@ enum QuicErrorCode { QUIC_BAD_PACKET_LOSS_RATE = 71, // Disabled QUIC because of too many PUBLIC_RESETs post handshake. QUIC_PUBLIC_RESETS_POST_HANDSHAKE = 73, - // Disabled QUIC because of too many timeouts with streams open. - QUIC_TIMEOUTS_WITH_OPEN_STREAMS = 74, // Closed because we failed to serialize a packet. QUIC_FAILED_TO_SERIALIZE_PACKET = 75, // QUIC timed out after too many RTOs. diff --git a/chromium/net/quic/core/quic_error_codes_test.cc b/chromium/net/quic/core/quic_error_codes_test.cc index 0694fefdf83..acb408484e6 100644 --- a/chromium/net/quic/core/quic_error_codes_test.cc +++ b/chromium/net/quic/core/quic_error_codes_test.cc @@ -4,19 +4,20 @@ #include "net/quic/core/quic_error_codes.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { namespace { -TEST(QuicUtilsTest, QuicRstStreamErrorCodeToString) { +class QuicErrorCodesTest : public QuicTest {}; + +TEST_F(QuicErrorCodesTest, QuicRstStreamErrorCodeToString) { EXPECT_STREQ("QUIC_BAD_APPLICATION_PAYLOAD", QuicRstStreamErrorCodeToString(QUIC_BAD_APPLICATION_PAYLOAD)); } -TEST(QuicUtilsTest, QuicErrorCodeToString) { +TEST_F(QuicErrorCodesTest, QuicErrorCodeToString) { EXPECT_STREQ("QUIC_NO_ERROR", QuicErrorCodeToString(QUIC_NO_ERROR)); } diff --git a/chromium/net/quic/core/quic_flags.cc b/chromium/net/quic/core/quic_flags.cc deleted file mode 100644 index f53537db090..00000000000 --- a/chromium/net/quic/core/quic_flags.cc +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/quic/core/quic_flags.h" - -#define QUIC_FLAG(type, flag, value) type flag = value; -#include "net/quic/core/quic_flags_list.h" -#undef QUIC_FLAG diff --git a/chromium/net/quic/core/quic_flags.h b/chromium/net/quic/core/quic_flags.h deleted file mode 100644 index a1a5ff36c0d..00000000000 --- a/chromium/net/quic/core/quic_flags.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_QUIC_CORE_QUIC_FLAGS_H_ -#define NET_QUIC_CORE_QUIC_FLAGS_H_ - -#include <cstdint> -#include <string> - -#include "net/quic/platform/api/quic_export.h" - -#define QUIC_FLAG(type, flag, value) QUIC_EXPORT_PRIVATE extern type flag; -#include "net/quic/core/quic_flags_list.h" -#undef QUIC_FLAG - -// API compatibility with new-style flags. -namespace base { - -inline bool GetFlag(bool flag) { - return flag; -} -inline int32_t GetFlag(int32_t flag) { - return flag; -} -inline int64_t GetFlag(int64_t flag) { - return flag; -} -inline uint64_t GetFlag(uint64_t flag) { - return flag; -} -inline double GetFlag(double flag) { - return flag; -} -inline std::string GetFlag(const std::string& flag) { - return flag; -} - -inline void SetFlag(bool* f, bool v) { - *f = v; -} -inline void SetFlag(int32_t* f, int32_t v) { - *f = v; -} -inline void SetFlag(int64_t* f, int64_t v) { - *f = v; -} -inline void SetFlag(uint64_t* f, uint64_t v) { - *f = v; -} -inline void SetFlag(double* f, double v) { - *f = v; -} -inline void SetFlag(std::string* f, const std::string& v) { - *f = v; -} - -} // namespace base - -#endif // NET_QUIC_CORE_QUIC_FLAGS_H_ diff --git a/chromium/net/quic/core/quic_flags_list.h b/chromium/net/quic/core/quic_flags_list.h index 3924bc839a1..03af2f62c1c 100644 --- a/chromium/net/quic/core/quic_flags_list.h +++ b/chromium/net/quic/core/quic_flags_list.h @@ -62,9 +62,6 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame, true) -// If true, re-enables QUIC_VERSION_36. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_36_v3, true) - // If true, only open limited number of quic sessions per epoll event. Leave the // rest to next event. QUIC_FLAG(bool, @@ -87,13 +84,7 @@ QUIC_FLAG(bool, // packet if insertion fails. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_create_session_after_insertion, - false) - -// If true, rejected packet number is removed from public reset packet. -QUIC_FLAG( - bool, - FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset, - false) + true) // If true, v33 QUIC client uses 1 bit to specify 8-byte connection id in // public flag. @@ -108,7 +99,7 @@ QUIC_FLAG(bool, FLAGS_quic_allow_chlo_buffering, true) // If true, fix some casts that were causing off-by-one errors in QUIC's cubic // "convex" increases. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode, false) +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_cubic_convex_mode, true) // If true, GFE sends SETTINGS_MAX_HEADER_LIST_SIZE to the client at the // beginning of a connection. @@ -117,27 +108,10 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_send_max_header_list_size, true) // If true, fix quantization of CubicBytes while performing convex increases. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization, - false) - -// If true, Makes GFE respect the connection options for initial flow control -// window larger than 32 KB. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_large_ifw_options, true) + true) // If true, fix Cubic\'s use of kBetaLastMax for n-connection emulation. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_beta_last_max, false) - -// If true, enable QUIC v37. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_37, true) - -// If true, disables QUIC v34. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_34, true) - -// If true, enable quic version 38 -QUIC_FLAG(bool, FLAGS_quic_enable_version_38, false) - -// When true, ensures the session's flow control window is always at least 1.5x -// larger than the largest stream flow control window. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_flow_control_invariant, true) +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_beta_last_max, true) // If greater than zero, mean RTT variation is multiplied by the specified // factor and added to the congestion window limit. @@ -146,15 +120,6 @@ QUIC_FLAG(double, FLAGS_quic_bbr_rtt_variation_weight, 0.0f) // Congestion window gain for QUIC BBR during PROBE_BW phase. QUIC_FLAG(double, FLAGS_quic_bbr_cwnd_gain, 2.0f) -// If true, bidi streaming is always enabled in QUIC. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming, - false) - -// If true, allows the 1RTT and 2RTT connection options to reduce the time -// in BBR STARTUP to 1 or 2 RTTs with no bandwidth increase from 3. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_allow_2_rtt_bbr_startup, false) - // If true, do not send or process stop waiting frames in QUIC if the NSTP // connection option is provided. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_no_stop_waiting_frames, false) @@ -162,26 +127,6 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_no_stop_waiting_frames, false) // Allows one self address change. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_allow_one_address_change, false) -// If true, no longer send or process the SRBF value in QuicConfig. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer, false) - -// If true, multipath bit is not used in public flag. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_remove_multipath_bit, false) - -// Allow QUIC's flow control autotuning to increase the window as -// quickly for the first adjustment as in subsequent ones. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune, - false) - -// Only consider using the ack spacing in QUIC BBR if 2 packets are acked at -// once. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2, false) - -// If true, 8-byte connection ID in public header is read and written in big -// endian. -QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_big_endian_connection_id, false) - // If true, QUIC BBR stores a max filtered number of bytes delivered at a rate // faster than the sending rate. QUIC_FLAG(bool, @@ -192,7 +137,7 @@ QUIC_FLAG(bool, // the frequency to once every 30ms. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_cubic_per_ack_updates, - false) + true) // Support bandwidth resumption in QUIC BBR. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_bandwidth_resumption, false) @@ -200,6 +145,77 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_bandwidth_resumption, false) // Add the equivalent number of bytes as 3 TCP TSO segments to QUIC's BBR CWND. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd, false) -// Fix a crash that occurs when a client sends multiple CHLOs close together on -// the same connection. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_fix_quic_callback_crash, true) +// If true, enable version 38 which supports new PADDING frame and respects NSTP +// connection option. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_38, true) + +// If true, enable QUIC v39. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_39, true) + +// If true, on client side, 8-byte connection ID in public header is read and +// written in big endian. +QUIC_FLAG(bool, + FLAGS_quic_restart_flag_quic_big_endian_connection_id_client, + false) + +// If true, on server side, 8-byte connection ID in public header is read and +// written in big endian. +QUIC_FLAG(bool, + FLAGS_quic_restart_flag_quic_big_endian_connection_id_server, + false) + +// Simplify QUIC\'s adaptive time loss detection to measure the necessary +// reordering window for every spurious retransmit. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_adaptive_time_loss, false) + +// If true, enable random padding of size [1, 256] when response body is +// compressed for QUIC version >= 38. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_random_padding, false) + +// Use conservation in PROBE_BW ouside of super-unity gain and immediately +// preceeding cycle. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_extra_conservation, false) + +// Increase BBR's inflight limit if recent ack rate is low. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_slow_recent_delivery, false) + +// Congestion window gain for QUIC BBR during slow delivery. +QUIC_FLAG(double, FLAGS_quic_bbr_slow_delivery_cwnd_gain, 4.0f) + +// Threshold multiplier below which delivery is considered slow. +QUIC_FLAG(double, FLAGS_quic_bbr_slow_delivery_threshold_multiplier, 0.5f) + +// If true, update state if trailing headers with a :final-offset key are +// received for a previously closed QUIC stream. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_final_offset_from_trailers, + false) + +// If enabled, use refactored stream creation methods. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_refactor_stream_creation, false) + +// A second take on fixing QUIC BBR packet conservation. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_fix_conservation2, false) + +// If true, GFEs generate and validate source address token using the actual +// client IP for proxied session. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_use_client_address_for_stk_in_proxy, + false) + +// If true, export a varz mapping QUIC non 0-rtt handshake with corresponding +// frontend service. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_account_handshake, false) + +// Allows the 3RTO QUIC connection option to close a QUIC connection after +// 3RTOs if there are no open streams. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_3rtos, false) + +// If true, enable experiment for testing PCC congestion-control. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_pcc, false) + +// If true, enable QUIC v40. +QUIC_FLAG(bool, FLAGS_quic_enable_version_40, false) + +// If true, use the more CPU efficient bandwidth sampler datastructure. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_faster_bandwidth_sampler, false) diff --git a/chromium/net/quic/core/quic_flow_controller.cc b/chromium/net/quic/core/quic_flow_controller.cc index 1c27276a1cd..b63349f9662 100644 --- a/chromium/net/quic/core/quic_flow_controller.cc +++ b/chromium/net/quic/core/quic_flow_controller.cc @@ -7,10 +7,10 @@ #include <cstdint> #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_str_cat.h" @@ -186,9 +186,7 @@ void QuicFlowController::MaybeSendWindowUpdate() { QuicStreamOffset available_window = receive_window_offset_ - bytes_consumed_; QuicByteCount threshold = WindowUpdateThreshold(); - if (FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune && - !prev_window_update_time_.IsInitialized()) { - QUIC_FLAG_COUNT(quic_reloadable_flag_quic_flow_control_faster_autotune); + if (!prev_window_update_time_.IsInitialized()) { // Treat the initial window as if it is a window update, so if 1/2 the // window is used in less than 2 RTTs, the window is increased. prev_window_update_time_ = connection_->clock()->ApproximateNow(); @@ -202,10 +200,11 @@ void QuicFlowController::MaybeSendWindowUpdate() { } MaybeIncreaseMaxWindowSize(); - SendWindowUpdate(available_window); + UpdateReceiveWindowOffsetAndSendWindowUpdate(available_window); } -void QuicFlowController::SendWindowUpdate(QuicStreamOffset available_window) { +void QuicFlowController::UpdateReceiveWindowOffsetAndSendWindowUpdate( + QuicStreamOffset available_window) { // Update our receive window. receive_window_offset_ += (receive_window_size_ - available_window); @@ -216,8 +215,7 @@ void QuicFlowController::SendWindowUpdate(QuicStreamOffset available_window) { << ", and receive window size: " << receive_window_size_ << ". New receive window offset is: " << receive_window_offset_; - // Inform the peer of our new receive window. - connection_->SendWindowUpdate(id_, receive_window_offset_); + SendWindowUpdate(); } void QuicFlowController::MaybeSendBlocked() { @@ -250,9 +248,12 @@ bool QuicFlowController::UpdateSendWindowOffset( << " current offset: " << send_window_offset_ << " bytes_sent: " << bytes_sent_; - const bool blocked = IsBlocked(); + // The flow is now unblocked but could have also been unblocked + // before. Return true iff this update caused a change from blocked + // to unblocked. + const bool was_previously_blocked = IsBlocked(); send_window_offset_ = new_send_window_offset; - return blocked; + return was_previously_blocked; } void QuicFlowController::EnsureWindowAtLeast(QuicByteCount window_size) { @@ -262,7 +263,7 @@ void QuicFlowController::EnsureWindowAtLeast(QuicByteCount window_size) { QuicStreamOffset available_window = receive_window_offset_ - bytes_consumed_; IncreaseWindowSize(); - SendWindowUpdate(available_window); + UpdateReceiveWindowOffsetAndSendWindowUpdate(available_window); } bool QuicFlowController::IsBlocked() const { @@ -289,4 +290,8 @@ void QuicFlowController::UpdateReceiveWindowSize(QuicStreamOffset size) { receive_window_offset_ = size; } +void QuicFlowController::SendWindowUpdate() { + connection_->SendWindowUpdate(id_, receive_window_offset_); +} + } // namespace net diff --git a/chromium/net/quic/core/quic_flow_controller.h b/chromium/net/quic/core/quic_flow_controller.h index b955da15302..f183741ada3 100644 --- a/chromium/net/quic/core/quic_flow_controller.h +++ b/chromium/net/quic/core/quic_flow_controller.h @@ -62,8 +62,10 @@ class QUIC_EXPORT_PRIVATE QuicFlowController // Called when bytes are sent to the peer. void AddBytesSent(QuicByteCount bytes_sent); - // Set a new send window offset. - // Returns true if this increases send_window_offset_ and is now blocked. + // Increases |send_window_offset_| if |new_send_window_offset| is + // greater than the current value. Returns true if this increase + // also causes us to change from a blocked state to unblocked. In + // all other cases, returns false. bool UpdateSendWindowOffset(QuicStreamOffset new_send_window_offset); // QuicFlowControllerInterface. @@ -81,6 +83,9 @@ class QUIC_EXPORT_PRIVATE QuicFlowController // Returns true if flow control receive limits have been violated by the peer. bool FlowControlViolation(); + // Inform the peer of new receive window. + void SendWindowUpdate(); + QuicByteCount bytes_consumed() const { return bytes_consumed_; } QuicStreamOffset highest_received_byte_offset() const { @@ -111,7 +116,8 @@ class QUIC_EXPORT_PRIVATE QuicFlowController void MaybeIncreaseMaxWindowSize(); // Updates the current offset and sends a window update frame. - void SendWindowUpdate(QuicStreamOffset available_window); + void UpdateReceiveWindowOffsetAndSendWindowUpdate( + QuicStreamOffset available_window); // Double the window size as long as we haven't hit the max window size. void IncreaseWindowSize(); @@ -176,8 +182,7 @@ class QUIC_EXPORT_PRIVATE QuicFlowController // Used to dynamically enable receive window auto-tuning. bool auto_tune_receive_window_; - // The session's flow controller. null if this is stream id 0 or - // FLAGS_quic_reloadable_flag_quic_flow_control_invariant is false. + // The session's flow controller. null if this is stream id 0. // Not owned. QuicFlowControllerInterface* session_flow_controller_; diff --git a/chromium/net/quic/core/quic_flow_controller_test.cc b/chromium/net/quic/core/quic_flow_controller_test.cc index ee80f755f6e..0c17adb3062 100644 --- a/chromium/net/quic/core/quic_flow_controller_test.cc +++ b/chromium/net/quic/core/quic_flow_controller_test.cc @@ -7,11 +7,11 @@ #include <memory> #include "net/quic/platform/api/quic_str_cat.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_connection_peer.h" #include "net/quic/test_tools/quic_flow_controller_peer.h" #include "net/quic/test_tools/quic_sent_packet_manager_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" using testing::_; @@ -32,15 +32,13 @@ class MockFlowController : public QuicFlowControllerInterface { DISALLOW_COPY_AND_ASSIGN(MockFlowController); }; -class QuicFlowControllerTest : public ::testing::Test { +class QuicFlowControllerTest : public QuicTest { public: QuicFlowControllerTest() : stream_id_(1234), send_window_(kInitialSessionFlowControlWindowForTest), receive_window_(kInitialSessionFlowControlWindowForTest), - connection_(&helper_, &alarm_factory_, Perspective::IS_CLIENT) { - FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune = true; - } + connection_(&helper_, &alarm_factory_, Perspective::IS_CLIENT) {} void Initialize() { flow_controller_.reset(new QuicFlowController( @@ -57,7 +55,6 @@ class QuicFlowControllerTest : public ::testing::Test { MockAlarmFactory alarm_factory_; MockQuicConnection connection_; MockFlowController session_flow_controller_; - QuicFlagSaver flag_saver_; }; TEST_F(QuicFlowControllerTest, SendingBytes) { @@ -168,13 +165,7 @@ TEST_F(QuicFlowControllerTest, OnlySendBlockedFrameOncePerOffset) { TEST_F(QuicFlowControllerTest, ReceivingBytesFastIncreasesFlowWindow) { // This test will generate two WINDOW_UPDATE frames. - if (FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune) { - EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, ::testing::_)) - .Times(1); - } else { - EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, ::testing::_)) - .Times(2); - } + EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, ::testing::_)).Times(1); Initialize(); flow_controller_->set_auto_tune_receive_window(true); @@ -204,32 +195,16 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesFastIncreasesFlowWindow) { EXPECT_FALSE(flow_controller_->FlowControlViolation()); EXPECT_EQ(kInitialSessionFlowControlWindowForTest - receive_offset, QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get())); - if (FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune) { - EXPECT_CALL( - session_flow_controller_, - EnsureWindowAtLeast(kInitialSessionFlowControlWindowForTest * 2 * 1.5)); - } + EXPECT_CALL( + session_flow_controller_, + EnsureWindowAtLeast(kInitialSessionFlowControlWindowForTest * 2 * 1.5)); // Consume enough bytes to send a WINDOW_UPDATE frame. flow_controller_->AddBytesConsumed(threshold + 1); // Result is that once again we have a fully open receive window. EXPECT_FALSE(flow_controller_->FlowControlViolation()); - if (FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune) { - EXPECT_EQ( - 2 * kInitialSessionFlowControlWindowForTest, - QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get())); - } else { - EXPECT_EQ( - kInitialSessionFlowControlWindowForTest, - QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get())); - - // Move time forward, but by less than two RTTs. Then receive and consume - // some more, forcing a second WINDOW_UPDATE with an increased max window - // size. - EXPECT_CALL( - session_flow_controller_, - EnsureWindowAtLeast(kInitialSessionFlowControlWindowForTest * 2 * 1.5)); - } + EXPECT_EQ(2 * kInitialSessionFlowControlWindowForTest, + QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get())); connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2 * kRtt - 1)); receive_offset += threshold + 1; @@ -296,13 +271,7 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesFastNoAutoTune) { TEST_F(QuicFlowControllerTest, ReceivingBytesNormalStableFlowWindow) { // This test will generate two WINDOW_UPDATE frames. - if (FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune) { - EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, ::testing::_)) - .Times(1); - } else { - EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, ::testing::_)) - .Times(2); - } + EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, ::testing::_)).Times(1); Initialize(); flow_controller_->set_auto_tune_receive_window(true); @@ -331,24 +300,15 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesNormalStableFlowWindow) { EXPECT_FALSE(flow_controller_->FlowControlViolation()); EXPECT_EQ(kInitialSessionFlowControlWindowForTest - receive_offset, QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get())); - if (FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune) { - EXPECT_CALL( - session_flow_controller_, - EnsureWindowAtLeast(kInitialSessionFlowControlWindowForTest * 2 * 1.5)); - } + EXPECT_CALL( + session_flow_controller_, + EnsureWindowAtLeast(kInitialSessionFlowControlWindowForTest * 2 * 1.5)); flow_controller_->AddBytesConsumed(threshold + 1); // Result is that once again we have a fully open receive window. EXPECT_FALSE(flow_controller_->FlowControlViolation()); - if (FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune) { - EXPECT_EQ( - 2 * kInitialSessionFlowControlWindowForTest, - QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get())); - } else { - EXPECT_EQ( - kInitialSessionFlowControlWindowForTest, - QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get())); - } + EXPECT_EQ(2 * kInitialSessionFlowControlWindowForTest, + QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get())); // Move time forward, but by more than two RTTs. Then receive and consume // some more, forcing a second WINDOW_UPDATE with unchanged max window size. @@ -362,11 +322,7 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesNormalStableFlowWindow) { QuicByteCount new_threshold = QuicFlowControllerPeer::WindowUpdateThreshold(flow_controller_.get()); - if (FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune) { - EXPECT_EQ(new_threshold, 2 * threshold); - } else { - EXPECT_EQ(new_threshold, threshold); - } + EXPECT_EQ(new_threshold, 2 * threshold); } TEST_F(QuicFlowControllerTest, ReceivingBytesNormalNoAutoTune) { diff --git a/chromium/net/quic/core/quic_framer.cc b/chromium/net/quic/core/quic_framer.cc index fc8e239c1d4..84337191eb7 100644 --- a/chromium/net/quic/core/quic_framer.cc +++ b/chromium/net/quic/core/quic_framer.cc @@ -17,12 +17,12 @@ #include "net/quic/core/crypto/quic_encrypter.h" #include "net/quic/core/quic_data_reader.h" #include "net/quic/core/quic_data_writer.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_socket_address_coder.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_aligned.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_map_util.h" #include "net/quic/platform/api/quic_ptr_util.h" @@ -36,12 +36,6 @@ namespace { #define ENDPOINT \ (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ") -// Mask to select the lowest 48 bits of a packet number. -const QuicPacketNumber k6ByteSequenceNumberMask = UINT64_C(0x0000FFFFFFFFFFFF); -const QuicPacketNumber k4ByteSequenceNumberMask = UINT64_C(0x00000000FFFFFFFF); -const QuicPacketNumber k2ByteSequenceNumberMask = UINT64_C(0x000000000000FFFF); -const QuicPacketNumber k1ByteSequenceNumberMask = UINT64_C(0x00000000000000FF); - // Number of bits the packet number length bits are shifted from the right // edge of the public header. const uint8_t kPublicHeaderSequenceNumberShift = 4; @@ -319,7 +313,7 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header, const QuicFrames& frames, char* buffer, size_t packet_length) { - QuicDataWriter writer(packet_length, buffer, perspective_); + QuicDataWriter writer(packet_length, buffer, perspective_, endianness()); if (!AppendPacketHeader(header, &writer)) { QUIC_BUG << "AppendPacketHeader failed"; return 0; @@ -336,7 +330,11 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header, switch (frame.type) { case PADDING_FRAME: - writer.WritePadding(); + if (!AppendPaddingFrame(frame.padding_frame, &writer)) { + QUIC_BUG << "AppendPaddingFrame of " + << frame.padding_frame.num_padding_bytes << " failed"; + return 0; + } break; case STREAM_FRAME: if (!AppendStreamFrame(*frame.stream_frame, no_stream_frame_length, @@ -413,9 +411,6 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildPublicResetPacket( CryptoHandshakeMessage reset; reset.set_tag(kPRST); reset.SetValue(kRNON, packet.nonce_proof); - if (!FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset) { - reset.SetValue(kRSEQ, packet.rejected_packet_number); - } if (packet.client_address.host().address_family() != IpAddressFamily::IP_UNSPEC) { // packet.client_address is non-empty. @@ -432,7 +427,10 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildPublicResetPacket( size_t len = kPublicFlagsSize + PACKET_8BYTE_CONNECTION_ID + reset_serialized.length(); std::unique_ptr<char[]> buffer(new char[len]); - QuicDataWriter writer(len, buffer.get(), Perspective::IS_SERVER); + // Endianness is not a concern here, as writer is not going to write integers + // or floating numbers. + QuicDataWriter writer(len, buffer.get(), Perspective::IS_SERVER, + NETWORK_BYTE_ORDER); uint8_t flags = static_cast<uint8_t>(PACKET_PUBLIC_FLAGS_RST | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID); @@ -462,7 +460,10 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket( DCHECK(!versions.empty()); size_t len = GetVersionNegotiationPacketSize(versions.size()); std::unique_ptr<char[]> buffer(new char[len]); - QuicDataWriter writer(len, buffer.get(), Perspective::IS_SERVER); + // Endianness is not a concern here, version negotiation packet does not have + // integers or floating numbers. + QuicDataWriter writer(len, buffer.get(), Perspective::IS_SERVER, + NETWORK_BYTE_ORDER); uint8_t flags = static_cast<uint8_t>( PACKET_PUBLIC_FLAGS_VERSION | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID | @@ -486,7 +487,8 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket( } bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) { - QuicDataReader reader(packet.data(), packet.length(), perspective_); + QuicDataReader reader(packet.data(), packet.length(), perspective_, + endianness()); visitor_->OnPacket(); @@ -512,6 +514,9 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) { } } + // framer's version may change, reset reader's endianness. + reader.set_endianness(endianness()); + bool rv; if (perspective_ == Perspective::IS_CLIENT && public_header.version_flag) { rv = ProcessVersionNegotiationPacket(&reader, &public_header); @@ -574,7 +579,8 @@ bool QuicFramer::ProcessDataPacket(QuicDataReader* encrypted_reader, return RaiseError(QUIC_DECRYPTION_FAILURE); } - QuicDataReader reader(decrypted_buffer, decrypted_length, perspective_); + QuicDataReader reader(decrypted_buffer, decrypted_length, perspective_, + endianness()); // Set the last packet number after we have decrypted the packet // so we are confident is not attacker controlled. @@ -649,12 +655,9 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header, if (header.public_header.version_flag) { public_flags |= PACKET_PUBLIC_FLAGS_VERSION; } - if (header.public_header.multipath_flag) { - public_flags |= PACKET_PUBLIC_FLAGS_MULTIPATH; - } public_flags |= - GetSequenceNumberFlags(header.public_header.packet_number_length) + GetPacketNumberFlags(header.public_header.packet_number_length) << kPublicHeaderSequenceNumberShift; if (header.public_header.nonce != nullptr) { @@ -699,8 +702,8 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header, return false; } - if (!AppendPacketSequenceNumber(header.public_header.packet_number_length, - header.packet_number, writer)) { + if (!AppendPacketNumber(header.public_header.packet_number_length, + header.packet_number, writer)) { return false; } @@ -768,19 +771,12 @@ bool QuicFramer::ProcessPublicHeader(QuicDataReader* reader, return false; } - public_header->multipath_flag = - (public_flags & PACKET_PUBLIC_FLAGS_MULTIPATH) != 0; public_header->reset_flag = (public_flags & PACKET_PUBLIC_FLAGS_RST) != 0; public_header->version_flag = (public_flags & PACKET_PUBLIC_FLAGS_VERSION) != 0; if (validate_flags_ && !public_header->version_flag && - public_flags > (FLAGS_quic_reloadable_flag_quic_remove_multipath_bit - ? PACKET_PUBLIC_FLAGS_MAX_WITHOUT_MULTIPATH_FLAG - : PACKET_PUBLIC_FLAGS_MAX)) { - if (FLAGS_quic_reloadable_flag_quic_remove_multipath_bit) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_remove_multipath_bit, 1, 2); - } + public_flags > PACKET_PUBLIC_FLAGS_MAX) { set_detailed_error("Illegal public flags value."); return false; } @@ -821,13 +817,7 @@ bool QuicFramer::ProcessPublicHeader(QuicDataReader* reader, // If not, this raises an error. last_version_tag_ = version_tag; QuicVersion version = QuicTagToQuicVersion(version_tag); - if (version == quic_version_ && - public_flags > (FLAGS_quic_reloadable_flag_quic_remove_multipath_bit - ? PACKET_PUBLIC_FLAGS_MAX_WITHOUT_MULTIPATH_FLAG - : PACKET_PUBLIC_FLAGS_MAX)) { - if (FLAGS_quic_reloadable_flag_quic_remove_multipath_bit) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_remove_multipath_bit, 1, 2); - } + if (version == quic_version_ && public_flags > PACKET_PUBLIC_FLAGS_MAX) { set_detailed_error("Illegal public flags value."); return false; } @@ -856,7 +846,7 @@ bool QuicFramer::ProcessPublicHeader(QuicDataReader* reader, } // static -QuicPacketNumberLength QuicFramer::GetMinSequenceNumberLength( +QuicPacketNumberLength QuicFramer::GetMinPacketNumberLength( QuicPacketNumber packet_number) { if (packet_number < 1 << (PACKET_1BYTE_PACKET_NUMBER * 8)) { return PACKET_1BYTE_PACKET_NUMBER; @@ -870,7 +860,7 @@ QuicPacketNumberLength QuicFramer::GetMinSequenceNumberLength( } // static -uint8_t QuicFramer::GetSequenceNumberFlags( +uint8_t QuicFramer::GetPacketNumberFlags( QuicPacketNumberLength packet_number_length) { switch (packet_number_length) { case PACKET_1BYTE_PACKET_NUMBER: @@ -922,7 +912,7 @@ bool QuicFramer::ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader, QuicPacketHeader* header) { QuicPacketNumber base_packet_number = largest_packet_number_; - if (!ProcessPacketSequenceNumber( + if (!ProcessAndCalculatePacketNumber( encrypted_reader, header->public_header.packet_number_length, base_packet_number, &header->packet_number)) { set_detailed_error("Unable to read packet number."); @@ -942,13 +932,13 @@ bool QuicFramer::ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader, return true; } -bool QuicFramer::ProcessPacketSequenceNumber( +bool QuicFramer::ProcessAndCalculatePacketNumber( QuicDataReader* reader, QuicPacketNumberLength packet_number_length, QuicPacketNumber base_packet_number, QuicPacketNumber* packet_number) { QuicPacketNumber wire_packet_number = 0u; - if (!reader->ReadBytes(&wire_packet_number, packet_number_length)) { + if (!reader->ReadBytesToUInt64(packet_number_length, &wire_packet_number)) { return false; } @@ -1013,12 +1003,14 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader, switch (frame_type) { case PADDING_FRAME: { - QuicPaddingFrame frame(reader->BytesRemaining()); + QuicPaddingFrame frame; + ProcessPaddingFrame(reader, &frame); if (!visitor_->OnPaddingFrame(frame)) { QUIC_DVLOG(1) << "Visitor asked to stop further processing."; + // Returning true since there was no parsing error. + return true; } - // We're done with the packet. - return true; + continue; } case RST_STREAM_FRAME: { @@ -1151,14 +1143,15 @@ bool QuicFramer::ProcessStreamFrame(QuicDataReader* reader, frame->fin = (stream_flags & kQuicStreamFinMask) == kQuicStreamFinShift; - frame->stream_id = 0; - if (!reader->ReadBytes(&frame->stream_id, stream_id_length)) { + uint64_t stream_id = 0; + if (!reader->ReadBytesToUInt64(stream_id_length, &stream_id)) { set_detailed_error("Unable to read stream_id."); return false; } + frame->stream_id = static_cast<QuicStreamId>(stream_id); frame->offset = 0; - if (!reader->ReadBytes(&frame->offset, offset_length)) { + if (!reader->ReadBytesToUInt64(offset_length, &frame->offset)) { set_detailed_error("Unable to read offset."); return false; } @@ -1196,7 +1189,8 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, frame_type >>= kQuicHasMultipleAckBlocksShift; bool has_ack_blocks = frame_type & kQuicHasMultipleAckBlocksMask; - if (!reader->ReadBytes(&ack_frame->largest_observed, largest_acked_length)) { + if (!reader->ReadBytesToUInt64(largest_acked_length, + &ack_frame->largest_observed)) { set_detailed_error("Unable to read largest acked."); return false; } @@ -1216,14 +1210,14 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, uint8_t num_ack_blocks = 0; if (has_ack_blocks) { - if (!reader->ReadBytes(&num_ack_blocks, 1)) { + if (!reader->ReadUInt8(&num_ack_blocks)) { set_detailed_error("Unable to read num of ack blocks."); return false; } } - size_t first_block_length = 0; - if (!reader->ReadBytes(&first_block_length, ack_block_length)) { + uint64_t first_block_length = 0; + if (!reader->ReadBytesToUInt64(ack_block_length, &first_block_length)) { set_detailed_error("Unable to read first ack block length."); return false; } @@ -1233,13 +1227,13 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, if (num_ack_blocks > 0) { for (size_t i = 0; i < num_ack_blocks; ++i) { - size_t gap = 0; - if (!reader->ReadBytes(&gap, PACKET_1BYTE_PACKET_NUMBER)) { + uint8_t gap = 0; + if (!reader->ReadUInt8(&gap)) { set_detailed_error("Unable to read gap to next ack block."); return false; } - size_t current_block_length = 0; - if (!reader->ReadBytes(¤t_block_length, ack_block_length)) { + uint64_t current_block_length = 0; + if (!reader->ReadBytesToUInt64(ack_block_length, ¤t_block_length)) { set_detailed_error("Unable to ack block length."); return false; } @@ -1261,15 +1255,14 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, bool QuicFramer::ProcessTimestampsInAckFrame(QuicDataReader* reader, QuicAckFrame* ack_frame) { uint8_t num_received_packets; - if (!reader->ReadBytes(&num_received_packets, 1)) { + if (!reader->ReadUInt8(&num_received_packets)) { set_detailed_error("Unable to read num received packets."); return false; } if (num_received_packets > 0) { uint8_t delta_from_largest_observed; - if (!reader->ReadBytes(&delta_from_largest_observed, - PACKET_1BYTE_PACKET_NUMBER)) { + if (!reader->ReadUInt8(&delta_from_largest_observed)) { set_detailed_error("Unable to read sequence delta in received packets."); return false; } @@ -1278,7 +1271,7 @@ bool QuicFramer::ProcessTimestampsInAckFrame(QuicDataReader* reader, // Time delta from the framer creation. uint32_t time_delta_us; - if (!reader->ReadBytes(&time_delta_us, sizeof(time_delta_us))) { + if (!reader->ReadUInt32(&time_delta_us)) { set_detailed_error("Unable to read time delta in received packets."); return false; } @@ -1290,8 +1283,7 @@ bool QuicFramer::ProcessTimestampsInAckFrame(QuicDataReader* reader, std::make_pair(seq_num, creation_time_ + last_timestamp_)); for (uint8_t i = 1; i < num_received_packets; ++i) { - if (!reader->ReadBytes(&delta_from_largest_observed, - PACKET_1BYTE_PACKET_NUMBER)) { + if (!reader->ReadUInt8(&delta_from_largest_observed)) { set_detailed_error( "Unable to read sequence delta in received packets."); return false; @@ -1319,8 +1311,8 @@ bool QuicFramer::ProcessStopWaitingFrame(QuicDataReader* reader, const QuicPacketHeader& header, QuicStopWaitingFrame* stop_waiting) { QuicPacketNumber least_unacked_delta = 0; - if (!reader->ReadBytes(&least_unacked_delta, - header.public_header.packet_number_length)) { + if (!reader->ReadBytesToUInt64(header.public_header.packet_number_length, + &least_unacked_delta)) { set_detailed_error("Unable to read least unacked delta."); return false; } @@ -1438,6 +1430,23 @@ bool QuicFramer::ProcessBlockedFrame(QuicDataReader* reader, return true; } +void QuicFramer::ProcessPaddingFrame(QuicDataReader* reader, + QuicPaddingFrame* frame) { + if (quic_version_ <= QUIC_VERSION_37) { + frame->num_padding_bytes = reader->BytesRemaining() + 1; + reader->ReadRemainingPayload(); + return; + } + // Type byte has been read. + frame->num_padding_bytes = 1; + uint8_t next_byte; + while (!reader->IsDoneReading() && reader->PeekByte() == 0x00) { + reader->ReadBytes(&next_byte, 1); + DCHECK_EQ(0x00, next_byte); + ++frame->num_padding_bytes; + } +} + // static QuicStringPiece QuicFramer::GetAssociatedDataFromEncryptedPacket( QuicVersion version, @@ -1628,9 +1637,9 @@ size_t QuicFramer::GetAckFrameSize( AckFrameInfo ack_info = GetAckFrameInfo(ack); QuicPacketNumberLength largest_acked_length = - GetMinSequenceNumberLength(ack.largest_observed); + GetMinPacketNumberLength(ack.largest_observed); QuicPacketNumberLength ack_block_length = - GetMinSequenceNumberLength(ack_info.max_block_length); + GetMinPacketNumberLength(ack_info.max_block_length); ack_size = GetMinAckFrameSize(quic_version_, largest_acked_length); // First ack block length. @@ -1734,32 +1743,38 @@ bool QuicFramer::AppendTypeByte(const QuicFrame& frame, } // static -bool QuicFramer::AppendPacketSequenceNumber( - QuicPacketNumberLength packet_number_length, - QuicPacketNumber packet_number, - QuicDataWriter* writer) { - // Ensure the entire packet number can be written. - if (writer->capacity() - writer->length() < - static_cast<size_t>(packet_number_length)) { +bool QuicFramer::AppendPacketNumber(QuicPacketNumberLength packet_number_length, + QuicPacketNumber packet_number, + QuicDataWriter* writer) { + size_t length = packet_number_length; + if (length != 1 && length != 2 && length != 4 && length != 6) { + QUIC_BUG << "Invalid packet_number_length: " << length; return false; } - switch (packet_number_length) { - case PACKET_1BYTE_PACKET_NUMBER: - return writer->WriteUInt8(packet_number & k1ByteSequenceNumberMask); - break; - case PACKET_2BYTE_PACKET_NUMBER: - return writer->WriteUInt16(packet_number & k2ByteSequenceNumberMask); - break; - case PACKET_4BYTE_PACKET_NUMBER: - return writer->WriteUInt32(packet_number & k4ByteSequenceNumberMask); - break; - case PACKET_6BYTE_PACKET_NUMBER: - return writer->WriteUInt48(packet_number & k6ByteSequenceNumberMask); - break; - default: - DCHECK(false) << "packet_number_length: " << packet_number_length; - return false; + return writer->WriteBytesToUInt64(packet_number_length, packet_number); +} + +// static +bool QuicFramer::AppendStreamId(size_t stream_id_length, + QuicStreamId stream_id, + QuicDataWriter* writer) { + if (stream_id_length == 0 || stream_id_length > 4) { + QUIC_BUG << "Invalid stream_id_length: " << stream_id_length; + return false; + } + return writer->WriteBytesToUInt64(stream_id_length, stream_id); +} + +// static +bool QuicFramer::AppendStreamOffset(size_t offset_length, + QuicStreamOffset offset, + QuicDataWriter* writer) { + if (offset_length == 1 || offset_length > 8) { + QUIC_BUG << "Invalid stream_offset_length: " << offset_length; + return false; } + + return writer->WriteBytesToUInt64(offset_length, offset); } // static @@ -1767,18 +1782,20 @@ bool QuicFramer::AppendAckBlock(uint8_t gap, QuicPacketNumberLength length_length, QuicPacketNumber length, QuicDataWriter* writer) { - return AppendPacketSequenceNumber(PACKET_1BYTE_PACKET_NUMBER, gap, writer) && - AppendPacketSequenceNumber(length_length, length, writer); + return writer->WriteUInt8(gap) && + AppendPacketNumber(length_length, length, writer); } bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame, bool no_stream_frame_length, QuicDataWriter* writer) { - if (!writer->WriteBytes(&frame.stream_id, GetStreamIdSize(frame.stream_id))) { + if (!AppendStreamId(GetStreamIdSize(frame.stream_id), frame.stream_id, + writer)) { QUIC_BUG << "Writing stream id size failed."; return false; } - if (!writer->WriteBytes(&frame.offset, GetStreamOffsetSize(frame.offset))) { + if (!AppendStreamOffset(GetStreamOffsetSize(frame.offset), frame.offset, + writer)) { QUIC_BUG << "Writing offset size failed."; return false; } @@ -1807,9 +1824,9 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame, const AckFrameInfo new_ack_info = GetAckFrameInfo(frame); QuicPacketNumber largest_acked = frame.largest_observed; QuicPacketNumberLength largest_acked_length = - GetMinSequenceNumberLength(largest_acked); + GetMinPacketNumberLength(largest_acked); QuicPacketNumberLength ack_block_length = - GetMinSequenceNumberLength(new_ack_info.max_block_length); + GetMinPacketNumberLength(new_ack_info.max_block_length); // Calculate available bytes for timestamps and ack blocks. int32_t available_timestamp_and_ack_block_bytes = writer->capacity() - writer->length() - ack_block_length - @@ -1826,11 +1843,11 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame, // Largest acked length. type_byte <<= kQuicSequenceNumberLengthShift; - type_byte |= GetSequenceNumberFlags(largest_acked_length); + type_byte |= GetPacketNumberFlags(largest_acked_length); // Ack block length. type_byte <<= kQuicSequenceNumberLengthShift; - type_byte |= GetSequenceNumberFlags(ack_block_length); + type_byte |= GetPacketNumberFlags(ack_block_length); type_byte |= kQuicFrameTypeAckMask; @@ -1839,8 +1856,7 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame, } // Largest acked. - if (!AppendPacketSequenceNumber(largest_acked_length, largest_acked, - writer)) { + if (!AppendPacketNumber(largest_acked_length, largest_acked, writer)) { return false; } @@ -1871,8 +1887,8 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame, } // First ack block length. - if (!AppendPacketSequenceNumber(ack_block_length, - new_ack_info.first_block_length, writer)) { + if (!AppendPacketNumber(ack_block_length, new_ack_info.first_block_length, + writer)) { return false; } @@ -1978,8 +1994,7 @@ bool QuicFramer::AppendTimestampToAckFrame(const QuicAckFrame& frame, return false; } - if (!writer->WriteUInt8(delta_from_largest_observed & - k1ByteSequenceNumberMask)) { + if (!writer->WriteUInt8(delta_from_largest_observed)) { return false; } @@ -1988,7 +2003,7 @@ bool QuicFramer::AppendTimestampToAckFrame(const QuicAckFrame& frame, uint32_t time_delta_us = static_cast<uint32_t>((it->second - creation_time_).ToMicroseconds() & (time_epoch_delta_us - 1)); - if (!writer->WriteBytes(&time_delta_us, sizeof(time_delta_us))) { + if (!writer->WriteUInt32(time_delta_us)) { return false; } @@ -2002,8 +2017,7 @@ bool QuicFramer::AppendTimestampToAckFrame(const QuicAckFrame& frame, return false; } - if (!writer->WriteUInt8(delta_from_largest_observed & - k1ByteSequenceNumberMask)) { + if (!writer->WriteUInt8(delta_from_largest_observed)) { return false; } @@ -2034,8 +2048,8 @@ bool QuicFramer::AppendStopWaitingFrame(const QuicPacketHeader& header, << " version:" << quic_version_; return false; } - if (!AppendPacketSequenceNumber(header.public_header.packet_number_length, - least_unacked_delta, writer)) { + if (!AppendPacketNumber(header.public_header.packet_number_length, + least_unacked_delta, writer)) { QUIC_BUG << " seq failed: " << header.public_header.packet_number_length; return false; } @@ -2111,6 +2125,25 @@ bool QuicFramer::AppendBlockedFrame(const QuicBlockedFrame& frame, return true; } +bool QuicFramer::AppendPaddingFrame(const QuicPaddingFrame& frame, + QuicDataWriter* writer) { + if (quic_version_ <= QUIC_VERSION_37) { + writer->WritePadding(); + return true; + } + + if (frame.num_padding_bytes == 0) { + return false; + } + if (frame.num_padding_bytes < 0) { + QUIC_BUG_IF(frame.num_padding_bytes != -1); + writer->WritePadding(); + return true; + } + // Please note, num_padding_bytes includes type byte which has been written. + return writer->WritePaddingBytes(frame.num_padding_bytes - 1); +} + bool QuicFramer::RaiseError(QuicErrorCode error) { QUIC_DLOG(INFO) << ENDPOINT << "Error: " << QuicErrorCodeToString(error) << " detail: " << detailed_error_; @@ -2119,4 +2152,8 @@ bool QuicFramer::RaiseError(QuicErrorCode error) { return false; } +Endianness QuicFramer::endianness() const { + return quic_version_ > QUIC_VERSION_38 ? NETWORK_BYTE_ORDER : HOST_BYTE_ORDER; +} + } // namespace net diff --git a/chromium/net/quic/core/quic_framer.h b/chromium/net/quic/core/quic_framer.h index 2ca8ea15e17..f244191f038 100644 --- a/chromium/net/quic/core/quic_framer.h +++ b/chromium/net/quic/core/quic_framer.h @@ -12,6 +12,7 @@ #include "base/macros.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/platform/api/quic_endian.h" #include "net/quic/platform/api/quic_export.h" #include "net/quic/platform/api/quic_string_piece.h" @@ -312,7 +313,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer { const std::string& detailed_error() { return detailed_error_; } // The minimum packet number length required to represent |packet_number|. - static QuicPacketNumberLength GetMinSequenceNumberLength( + static QuicPacketNumberLength GetMinPacketNumberLength( QuicPacketNumber packet_number); void SetSupportedVersions(const QuicVersionVector& versions) { @@ -320,6 +321,9 @@ class QUIC_EXPORT_PRIVATE QuicFramer { quic_version_ = versions[0]; } + // Returns byte order to read/write integers and floating numbers. + Endianness endianness() const; + void set_validate_flags(bool value) { validate_flags_ = value; } Perspective perspective() const { return perspective_; } @@ -364,10 +368,14 @@ class QUIC_EXPORT_PRIVATE QuicFramer { bool ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader, QuicPacketHeader* header); - bool ProcessPacketSequenceNumber(QuicDataReader* reader, - QuicPacketNumberLength packet_number_length, - QuicPacketNumber base_packet_number, - QuicPacketNumber* packet_number); + // First processes possibly truncated packet number. Calculates the full + // packet number from the truncated one and the last seen packet number, and + // stores it to |packet_number|. + bool ProcessAndCalculatePacketNumber( + QuicDataReader* reader, + QuicPacketNumberLength packet_number_length, + QuicPacketNumber base_packet_number, + QuicPacketNumber* packet_number); bool ProcessFrameData(QuicDataReader* reader, const QuicPacketHeader& header); bool ProcessStreamFrame(QuicDataReader* reader, uint8_t frame_type, @@ -386,6 +394,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer { bool ProcessWindowUpdateFrame(QuicDataReader* reader, QuicWindowUpdateFrame* frame); bool ProcessBlockedFrame(QuicDataReader* reader, QuicBlockedFrame* frame); + void ProcessPaddingFrame(QuicDataReader* reader, QuicPaddingFrame* frame); bool DecryptPayload(QuicDataReader* encrypted_reader, const QuicPacketHeader& header, @@ -424,10 +433,15 @@ class QUIC_EXPORT_PRIVATE QuicFramer { bool last_frame_in_packet, QuicPacketNumberLength packet_number_length); - static bool AppendPacketSequenceNumber( - QuicPacketNumberLength packet_number_length, - QuicPacketNumber packet_number, - QuicDataWriter* writer); + static bool AppendPacketNumber(QuicPacketNumberLength packet_number_length, + QuicPacketNumber packet_number, + QuicDataWriter* writer); + static bool AppendStreamId(size_t stream_id_length, + QuicStreamId stream_id, + QuicDataWriter* writer); + static bool AppendStreamOffset(size_t offset_length, + QuicStreamOffset offset, + QuicDataWriter* writer); // Appends a single ACK block to |writer| and returns true if the block was // successfully appended. @@ -436,7 +450,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer { QuicPacketNumber length, QuicDataWriter* writer); - static uint8_t GetSequenceNumberFlags( + static uint8_t GetPacketNumberFlags( QuicPacketNumberLength packet_number_length); static AckFrameInfo GetAckFrameInfo(const QuicAckFrame& frame); @@ -460,6 +474,8 @@ class QUIC_EXPORT_PRIVATE QuicFramer { QuicDataWriter* writer); bool AppendBlockedFrame(const QuicBlockedFrame& frame, QuicDataWriter* writer); + bool AppendPaddingFrame(const QuicPaddingFrame& frame, + QuicDataWriter* writer); bool RaiseError(QuicErrorCode error); diff --git a/chromium/net/quic/core/quic_framer_test.cc b/chromium/net/quic/core/quic_framer_test.cc index cf757fa6d2a..9a69d92c271 100644 --- a/chromium/net/quic/core/quic_framer_test.cc +++ b/chromium/net/quic/core/quic_framer_test.cc @@ -15,14 +15,14 @@ #include "net/quic/core/crypto/null_encrypter.h" #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_framer_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; using testing::Return; @@ -31,6 +31,7 @@ using testing::_; namespace net { namespace test { +namespace { const QuicPacketNumber kEpoch = UINT64_C(1) << 48; const QuicPacketNumber kMask = kEpoch - 1; @@ -288,7 +289,7 @@ class TestQuicVisitor : public QuicFramerVisitorInterface { std::vector<std::unique_ptr<string>> stream_data_; }; -class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> { +class QuicFramerTest : public QuicTestWithParam<QuicVersion> { public: QuicFramerTest() : encrypter_(new test::TestEncrypter()), @@ -437,7 +438,6 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> { return BuildUnsizedDataPacket(&framer_, header, frames, packet_size); } - QuicFlagSaver flags_; // Save/restore all QUIC flag values. test::TestEncrypter* encrypter_; test::TestDecrypter* decrypter_; QuicVersion version_; @@ -446,6 +446,26 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> { test::TestQuicVisitor visitor_; }; +// Helper function to get index of packets in hex format. +// For each packet in hex format, integers and floating numbers are in big +// endian for v38 and up, and connection ID is in big endian according to +// perspective and flags. +// There are 4 combinations: +// 0 : little endian connection ID, little endian integers/floating numbers. +// 1 : big endian connection ID, little endian integers/floating numbers. +// 2 : little endian connection ID, big endian integers/floating numbers. +// 3 : big endian connection ID, big endian integers/floating numbers. +size_t GetPacketIndex(QuicVersion version, Perspective perspective) { + size_t index = 0; + if (QuicUtils::IsConnectionIdWireFormatBigEndian(perspective)) { + index = 1; + } + if (version > QUIC_VERSION_38) { + index += 2; + } + return index; +} + // Run all framer tests with all supported versions of QUIC. INSTANTIATE_TEST_CASE_P(QuicFramerTests, QuicFramerTest, @@ -591,10 +611,11 @@ TEST_P(QuicFramerTest, LargePacket) { memset(packet + header_size, 0, kMaxPacketSize - header_size); QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) ? arraysize(packet_cid_be) : arraysize(packet), false); @@ -626,21 +647,35 @@ TEST_P(QuicFramerTest, PacketHeader) { // packet number 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_FALSE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(kConnectionId, visitor_.header_->public_header.connection_id); - EXPECT_FALSE(visitor_.header_->public_header.multipath_flag); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number); @@ -659,10 +694,8 @@ TEST_P(QuicFramerTest, PacketHeader) { } else { expected_error = "Unable to read packet number."; } - CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet, - i, expected_error, QUIC_INVALID_PACKET_HEADER); + CheckProcessingFails(packets[index], i, expected_error, + QUIC_INVALID_PACKET_HEADER); } } @@ -678,14 +711,24 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) { 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, }; + + unsigned char packet39[] = { + // public flags (0 byte connection_id) + 0x30, + // connection_id + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + }; // clang-format on - QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); + QuicEncryptedPacket encrypted( + AsChars(framer_.version() > QUIC_VERSION_38 ? packet39 : packet), + arraysize(packet), false); EXPECT_FALSE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(kConnectionId, visitor_.header_->public_header.connection_id); - EXPECT_FALSE(visitor_.header_->public_header.multipath_flag); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number); @@ -705,7 +748,9 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) { } else { expected_error = "Unable to read packet number."; } - CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); + CheckProcessingFails( + framer_.version() > QUIC_VERSION_38 ? packet39 : packet, i, + expected_error, QUIC_INVALID_PACKET_HEADER); } } @@ -732,21 +777,39 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) { // packet number 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, }; + + unsigned char packet39[] = { + // public flags (version) + 0x39, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // version tag + 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(), + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + }; + + unsigned char packet_cid_be39[] = { + // public flags (version) + 0x39, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // version tag + 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(), + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_FALSE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(kConnectionId, visitor_.header_->public_header.connection_id); - EXPECT_FALSE(visitor_.header_->public_header.multipath_flag); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_TRUE(visitor_.header_->public_header.version_flag); EXPECT_EQ(GetParam(), visitor_.header_->public_header.versions[0]); @@ -768,10 +831,8 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) { } else { expected_error = "Unable to read packet number."; } - CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet, - i, expected_error, QUIC_INVALID_PACKET_HEADER); + CheckProcessingFails(packets[index], i, expected_error, + QUIC_INVALID_PACKET_HEADER); } } @@ -796,21 +857,35 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) { // packet number 0xBC, 0x9A, 0x78, 0x56, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id and 4 byte packet number) + 0x28, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x56, 0x78, 0x9A, 0xBC, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id and 4 byte packet number) + 0x28, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x56, 0x78, 0x9A, 0xBC, + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_FALSE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(kConnectionId, visitor_.header_->public_header.connection_id); - EXPECT_FALSE(visitor_.header_->public_header.multipath_flag); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number); @@ -829,10 +904,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) { } else { expected_error = "Unable to read packet number."; } - CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet, - i, expected_error, QUIC_INVALID_PACKET_HEADER); + CheckProcessingFails(packets[index], i, expected_error, + QUIC_INVALID_PACKET_HEADER); } } @@ -857,21 +930,35 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) { // packet number 0xBC, 0x9A, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id and 2 byte packet number) + 0x18, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x9A, 0xBC, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id and 2 byte packet number) + 0x18, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x9A, 0xBC, + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_FALSE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(kConnectionId, visitor_.header_->public_header.connection_id); - EXPECT_FALSE(visitor_.header_->public_header.multipath_flag); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER, @@ -892,10 +979,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) { } else { expected_error = "Unable to read packet number."; } - CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet, - i, expected_error, QUIC_INVALID_PACKET_HEADER); + CheckProcessingFails(packets[index], i, expected_error, + QUIC_INVALID_PACKET_HEADER); } } @@ -923,10 +1008,11 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) { // clang-format on QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) ? arraysize(packet_cid_be) : arraysize(packet), false); @@ -934,7 +1020,6 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) { EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(kConnectionId, visitor_.header_->public_header.connection_id); - EXPECT_FALSE(visitor_.header_->public_header.multipath_flag); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, @@ -955,10 +1040,11 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) { } else { expected_error = "Unable to read packet number."; } - CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet, - i, expected_error, QUIC_INVALID_PACKET_HEADER); + CheckProcessingFails( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet, + i, expected_error, QUIC_INVALID_PACKET_HEADER); } } @@ -1024,8 +1110,7 @@ TEST_P(QuicFramerTest, PacketWithDiversificationNonce) { // clang-format off unsigned char packet[] = { // public flags: includes nonce flag - static_cast<unsigned char>( - FLAGS_quic_reloadable_flag_quic_remove_multipath_bit ? 0x3C : 0x7C), + 0x3C, // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // nonce @@ -1043,8 +1128,7 @@ TEST_P(QuicFramerTest, PacketWithDiversificationNonce) { unsigned char packet_cid_be[] = { // public flags: includes nonce flag - static_cast<unsigned char>( - FLAGS_quic_reloadable_flag_quic_remove_multipath_bit ? 0x3C : 0x7C), + 0x3C, // connection_id 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, // nonce @@ -1059,30 +1143,63 @@ TEST_P(QuicFramerTest, PacketWithDiversificationNonce) { 0x00, 0x00, 0x00, 0x00, 0x00 }; + + unsigned char packet39[] = { + // public flags: includes nonce flag + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // nonce + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (padding) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + unsigned char packet_cid_be39[] = { + // public flags: includes nonce flag + 0x3C, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // nonce + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (padding) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); ASSERT_TRUE(visitor_.public_header_->nonce != nullptr); for (char i = 0; i < 32; ++i) { EXPECT_EQ(i, (*visitor_.public_header_->nonce)[static_cast<size_t>(i)]); } + EXPECT_EQ(1u, visitor_.padding_frames_.size()); + EXPECT_EQ(5, visitor_.padding_frames_[0]->num_padding_bytes); }; TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) { // clang-format off unsigned char packet[] = { // public flags (8 byte connection_id, version flag and an unknown flag) - static_cast<unsigned char>( - FLAGS_quic_reloadable_flag_quic_remove_multipath_bit ? 0x39 : 0x79), + 0x39, // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, @@ -1099,8 +1216,7 @@ TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) { unsigned char packet_cid_be[] = { // public flags (8 byte connection_id, version flag and an unknown flag) - static_cast<unsigned char>( - FLAGS_quic_reloadable_flag_quic_remove_multipath_bit ? 0x39 : 0x79), + 0x39, // connection_id 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, // version tag @@ -1113,20 +1229,52 @@ TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) { 0x00, 0x00, 0x00, 0x00, 0x00 }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id, version flag and an unknown flag) + 0x39, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // version tag + 'Q', '0', '0', '0', + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id, version flag and an unknown flag) + 0x39, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // version tag + 'Q', '0', '0', '0', + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(0, visitor_.frame_count_); EXPECT_EQ(1, visitor_.version_mismatch_); + EXPECT_EQ(1u, visitor_.padding_frames_.size()); + EXPECT_EQ(5, visitor_.padding_frames_[0]->num_padding_bytes); }; TEST_P(QuicFramerTest, PaddingFrame) { @@ -1187,11 +1335,16 @@ TEST_P(QuicFramerTest, PaddingFrame) { }; // clang-format on + if (framer_.version() > QUIC_VERSION_37) { + return; + } + QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) ? arraysize(packet_cid_be) : arraysize(packet), false); @@ -1203,16 +1356,162 @@ TEST_P(QuicFramerTest, PaddingFrame) { ASSERT_EQ(0u, visitor_.stream_frames_.size()); EXPECT_EQ(0u, visitor_.ack_frames_.size()); + EXPECT_EQ(1u, visitor_.padding_frames_.size()); + EXPECT_EQ(28, visitor_.padding_frames_[0]->num_padding_bytes); // A packet with no frames is not acceptable. CheckProcessingFails( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet, GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER), "Packet has no frames.", QUIC_MISSING_PAYLOAD); } +TEST_P(QuicFramerTest, NewPaddingFrame) { + // clang-format off + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + + // paddings + 0x00, 0x00, + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x04, 0x03, 0x02, 0x01, + // offset + 0x54, 0x76, 0x10, 0x32, + 0xDC, 0xFE, 0x98, 0xBA, + // data length + 0x0c, 0x00, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + // paddings + 0x00, 0x00, + }; + + unsigned char packet_cid_be[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + + // paddings + 0x00, 0x00, + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x04, 0x03, 0x02, 0x01, + // offset + 0x54, 0x76, 0x10, 0x32, + 0xDC, 0xFE, 0x98, 0xBA, + // data length + 0x0c, 0x00, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + // paddings + 0x00, 0x00, + }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // paddings + 0x00, 0x00, + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + // paddings + 0x00, 0x00, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // paddings + 0x00, 0x00, + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + // paddings + 0x00, 0x00, + }; + // clang-format on + + if (framer_.version() <= QUIC_VERSION_37) { + return; + } + + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); + EXPECT_TRUE(framer_.ProcessPacket(encrypted)); + EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); + ASSERT_TRUE(visitor_.header_.get()); + EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, + !kIncludeDiversificationNonce)); + + ASSERT_EQ(1u, visitor_.stream_frames_.size()); + EXPECT_EQ(0u, visitor_.ack_frames_.size()); + EXPECT_EQ(2u, visitor_.padding_frames_.size()); + EXPECT_EQ(2, visitor_.padding_frames_[0]->num_padding_bytes); + EXPECT_EQ(2, visitor_.padding_frames_[1]->num_padding_bytes); + EXPECT_EQ(kStreamId, visitor_.stream_frames_[0]->stream_id); + EXPECT_TRUE(visitor_.stream_frames_[0]->fin); + EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset); + CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get()); +} + TEST_P(QuicFramerTest, StreamFrame) { // clang-format off unsigned char packet[] = { @@ -1263,16 +1562,61 @@ TEST_P(QuicFramerTest, StreamFrame) { 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -1288,10 +1632,8 @@ TEST_P(QuicFramerTest, StreamFrame) { CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get()); // Now test framing boundaries. - CheckStreamFrameBoundaries( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, - kQuicMaxStreamIdSize, !kIncludeVersion); + CheckStreamFrameBoundaries(packets[index], kQuicMaxStreamIdSize, + !kIncludeVersion); } TEST_P(QuicFramerTest, MissingDiversificationNonce) { @@ -1350,16 +1692,62 @@ TEST_P(QuicFramerTest, MissingDiversificationNonce) { 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_FALSE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error()); } @@ -1414,16 +1802,62 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) { 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFE, + // stream id + 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFE, + // stream id + 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -1441,10 +1875,7 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) { // Now test framing boundaries. const size_t stream_id_size = 3; - CheckStreamFrameBoundaries( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, - stream_id_size, !kIncludeVersion); + CheckStreamFrameBoundaries(packets[index], stream_id_size, !kIncludeVersion); } TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) { @@ -1497,16 +1928,62 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) { 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFD, + // stream id + 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFD, + // stream id + 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -1524,10 +2001,7 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) { // Now test framing boundaries. const size_t stream_id_size = 2; - CheckStreamFrameBoundaries( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, - stream_id_size, !kIncludeVersion); + CheckStreamFrameBoundaries(packets[index], stream_id_size, !kIncludeVersion); } TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) { @@ -1580,16 +2054,62 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) { 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFC, + // stream id + 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFC, + // stream id + 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -1607,10 +2127,7 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) { // Now test framing boundaries. const size_t stream_id_size = 1; - CheckStreamFrameBoundaries( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, - stream_id_size, !kIncludeVersion); + CheckStreamFrameBoundaries(packets[index], stream_id_size, !kIncludeVersion); } TEST_P(QuicFramerTest, StreamFrameWithVersion) { @@ -1667,16 +2184,66 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) { 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet39[] = { + // public flags (version, 8 byte connection_id) + 0x39, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // version tag + 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(), + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + + unsigned char packet_cid_be39[] = { + // public flags (version, 8 byte connection_id) + 0x39, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // version tag + 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(), + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -1694,10 +2261,8 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) { CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get()); // Now test framing boundaries. - CheckStreamFrameBoundaries( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, - kQuicMaxStreamIdSize, kIncludeVersion); + CheckStreamFrameBoundaries(packets[index], kQuicMaxStreamIdSize, + kIncludeVersion); } TEST_P(QuicFramerTest, RejectPacket) { @@ -1752,16 +2317,62 @@ TEST_P(QuicFramerTest, RejectPacket) { 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -1793,10 +2404,11 @@ TEST_P(QuicFramerTest, RejectPublicHeader) { // clang-format on QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) ? arraysize(packet_cid_be) : arraysize(packet), false); @@ -1850,16 +2462,55 @@ TEST_P(QuicFramerTest, AckFrameOneAckBlock) { // num timestamps. 0x00, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (ack frame) + // (one ack block, 2 byte largest observed, 2 byte block length) + 0x45, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x12, 0x34, + // num timestamps. + 0x00, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (ack frame) + // (one ack block, 2 byte largest observed, 2 byte block length) + 0x45, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x12, 0x34, + // num timestamps. + 0x00, + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -1895,8 +2546,7 @@ TEST_P(QuicFramerTest, AckFrameOneAckBlock) { expected_error = "Unable to read num received packets."; } CheckProcessingFails( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, + packets[index], i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER), @@ -1999,16 +2649,107 @@ TEST_P(QuicFramerTest, AckFrameTwoTimeStampsMultipleAckBlocks) { // Delta time. 0x10, 0x32, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (ack frame) + // (more than one ack block, 2 byte largest observed, 2 byte block length) + 0x65, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // num ack blocks ranges. + 0x04, + // first ack block length. + 0x00, 0x01, + // gap to next block. + 0x01, + // ack block length. + 0x0e, 0xaf, + // gap to next block. + 0xff, + // ack block length. + 0x00, 0x00, + // gap to next block. + 0x91, + // ack block length. + 0x01, 0xea, + // gap to next block. + 0x05, + // ack block length. + 0x00, 0x04, + // Number of timestamps. + 0x02, + // Delta from largest observed. + 0x01, + // Delta time. + 0x76, 0x54, 0x32, 0x10, + // Delta from largest observed. + 0x02, + // Delta time. + 0x32, 0x10, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (ack frame) + // (more than one ack block, 2 byte largest observed, 2 byte block length) + 0x65, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // num ack blocks ranges. + 0x04, + // first ack block length. + 0x00, 0x01, + // gap to next block. + 0x01, + // ack block length. + 0x0e, 0xaf, + // gap to next block. + 0xff, + // ack block length. + 0x00, 0x00, + // gap to next block. + 0x91, + // ack block length. + 0x01, 0xea, + // gap to next block. + 0x05, + // ack block length. + 0x00, 0x04, + // Number of timestamps. + 0x02, + // Delta from largest observed. + 0x01, + // Delta time. + 0x76, 0x54, 0x32, 0x10, + // Delta from largest observed. + 0x02, + // Delta time. + 0x32, 0x10, + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -2095,8 +2836,7 @@ TEST_P(QuicFramerTest, AckFrameTwoTimeStampsMultipleAckBlocks) { } CheckProcessingFails( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, + packets[index], i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER), @@ -2136,16 +2876,44 @@ TEST_P(QuicFramerTest, NewStopWaitingFrame) { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xA8, + // frame type (stop waiting frame) + 0x06, + // least packet number awaiting an ack, delta from packet number. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xA8, + // frame type (stop waiting frame) + 0x06, + // least packet number awaiting an ack, delta from packet number. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -2163,8 +2931,7 @@ TEST_P(QuicFramerTest, NewStopWaitingFrame) { string expected_error; expected_error = "Unable to read least unacked delta."; CheckProcessingFails( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, + packets[index], i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER), @@ -2218,16 +2985,58 @@ TEST_P(QuicFramerTest, RstStreamFrameQuic) { // error code 0x01, 0x00, 0x00, 0x00, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (rst stream frame) + 0x01, + // stream id + 0x01, 0x02, 0x03, 0x04, + + // sent byte offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + + // error code + 0x00, 0x00, 0x00, 0x01, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (rst stream frame) + 0x01, + // stream id + 0x01, 0x02, 0x03, 0x04, + + // sent byte offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + + // error code + 0x00, 0x00, 0x00, 0x01, + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -2253,8 +3062,7 @@ TEST_P(QuicFramerTest, RstStreamFrameQuic) { expected_error = "Unable to read rst stream error code."; } CheckProcessingFails( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, + packets[index], i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER), @@ -2310,16 +3118,60 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) { 'I', ' ', 'c', 'a', 'n', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (connection close frame) + 0x02, + // error code + 0x00, 0x00, 0x00, 0x11, + + // error details length + 0x00, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (connection close frame) + 0x02, + // error code + 0x00, 0x00, 0x00, 0x11, + + // error details length + 0x00, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n', + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -2344,8 +3196,7 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) { expected_error = "Unable to read connection close error details."; } CheckProcessingFails( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, + packets[index], i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER), @@ -2403,16 +3254,62 @@ TEST_P(QuicFramerTest, GoAwayFrame) { 'I', ' ', 'c', 'a', 'n', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (go away frame) + 0x03, + // error code + 0x00, 0x00, 0x00, 0x09, + // stream id + 0x01, 0x02, 0x03, 0x04, + // error details length + 0x00, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (go away frame) + 0x03, + // error code + 0x00, 0x00, 0x00, 0x09, + // stream id + 0x01, 0x02, 0x03, 0x04, + // error details length + 0x00, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n', + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -2438,8 +3335,7 @@ TEST_P(QuicFramerTest, GoAwayFrame) { expected_error = "Unable to read goaway reason."; } CheckProcessingFails( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, + packets[index], i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER), @@ -2485,16 +3381,50 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) { 0x54, 0x76, 0x10, 0x32, 0xDC, 0xFE, 0x98, 0xBA, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (window update frame) + 0x04, + // stream id + 0x01, 0x02, 0x03, 0x04, + // byte offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (window update frame) + 0x04, + // stream id + 0x01, 0x02, 0x03, 0x04, + // byte offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -2515,8 +3445,7 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) { expected_error = "Unable to read window byte_offset."; } CheckProcessingFails( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, + packets[index], i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER), @@ -2556,16 +3485,44 @@ TEST_P(QuicFramerTest, BlockedFrame) { // stream id 0x04, 0x03, 0x02, 0x01, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (blocked frame) + 0x05, + // stream id + 0x01, 0x02, 0x03, 0x04, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (blocked frame) + 0x05, + // stream id + 0x01, 0x02, 0x03, 0x04, + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -2580,8 +3537,7 @@ TEST_P(QuicFramerTest, BlockedFrame) { ++i) { string expected_error = "Unable to read stream_id."; CheckProcessingFails( - FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet, + packets[index], i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER), @@ -2617,16 +3573,40 @@ TEST_P(QuicFramerTest, PingFrame) { // frame type (ping frame) 0x07, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (ping frame) + 0x07, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (ping frame) + 0x07, + }; // clang-format on - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -2694,10 +3674,11 @@ TEST_P(QuicFramerTest, PublicResetPacketV33) { // clang-format on QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) ? arraysize(packet_cid_be) : arraysize(packet), false); @@ -2709,13 +3690,12 @@ TEST_P(QuicFramerTest, PublicResetPacketV33) { EXPECT_TRUE(visitor_.public_reset_packet_->public_header.reset_flag); EXPECT_FALSE(visitor_.public_reset_packet_->public_header.version_flag); EXPECT_EQ(kNonceProof, visitor_.public_reset_packet_->nonce_proof); - EXPECT_EQ(0u, visitor_.public_reset_packet_->rejected_packet_number); EXPECT_EQ( IpAddressFamily::IP_UNSPEC, visitor_.public_reset_packet_->client_address.host().address_family()); // Now test framing boundaries. - if (!FLAGS_quic_restart_flag_quic_big_endian_connection_id) { + if (!QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())) { for (size_t i = 0; i < arraysize(packet); ++i) { string expected_error; QUIC_DLOG(INFO) << "iteration: " << i; @@ -2812,10 +3792,11 @@ TEST_P(QuicFramerTest, PublicResetPacket) { // clang-format on QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) ? arraysize(packet_cid_be) : arraysize(packet), false); @@ -2827,13 +3808,12 @@ TEST_P(QuicFramerTest, PublicResetPacket) { EXPECT_TRUE(visitor_.public_reset_packet_->public_header.reset_flag); EXPECT_FALSE(visitor_.public_reset_packet_->public_header.version_flag); EXPECT_EQ(kNonceProof, visitor_.public_reset_packet_->nonce_proof); - EXPECT_EQ(0u, visitor_.public_reset_packet_->rejected_packet_number); EXPECT_EQ( IpAddressFamily::IP_UNSPEC, visitor_.public_reset_packet_->client_address.host().address_family()); // Now test framing boundaries. - if (!FLAGS_quic_restart_flag_quic_big_endian_connection_id) { + if (!QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())) { for (size_t i = 0; i < arraysize(packet); ++i) { string expected_error; QUIC_DLOG(INFO) << "iteration: " << i; @@ -2932,13 +3912,14 @@ TEST_P(QuicFramerTest, PublicResetPacketWithTrailingJunk) { // clang-format on string expected_error = "Unable to read reset message."; - CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet, - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - expected_error, QUIC_INVALID_PUBLIC_RST_PACKET); + CheckProcessingFails( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet, + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? arraysize(packet_cid_be) + : arraysize(packet), + expected_error, QUIC_INVALID_PUBLIC_RST_PACKET); } TEST_P(QuicFramerTest, PublicResetPacketWithClientAddress) { @@ -3012,10 +3993,11 @@ TEST_P(QuicFramerTest, PublicResetPacketWithClientAddress) { // clang-format on QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) ? arraysize(packet_cid_be) : arraysize(packet), false); @@ -3027,13 +4009,12 @@ TEST_P(QuicFramerTest, PublicResetPacketWithClientAddress) { EXPECT_TRUE(visitor_.public_reset_packet_->public_header.reset_flag); EXPECT_FALSE(visitor_.public_reset_packet_->public_header.version_flag); EXPECT_EQ(kNonceProof, visitor_.public_reset_packet_->nonce_proof); - EXPECT_EQ(0u, visitor_.public_reset_packet_->rejected_packet_number); EXPECT_EQ("4.31.198.44", visitor_.public_reset_packet_->client_address.host().ToString()); EXPECT_EQ(443, visitor_.public_reset_packet_->client_address.port()); // Now test framing boundaries. - if (!FLAGS_quic_restart_flag_quic_big_endian_connection_id) { + if (!QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())) { for (size_t i = 0; i < arraysize(packet); ++i) { string expected_error; QUIC_DLOG(INFO) << "iteration: " << i; @@ -3100,10 +4081,11 @@ TEST_P(QuicFramerTest, VersionNegotiationPacket) { QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) ? arraysize(packet_cid_be) : arraysize(packet), false); @@ -3124,10 +4106,11 @@ TEST_P(QuicFramerTest, VersionNegotiationPacket) { expected_error = "Unable to read supported version in negotiation."; error_code = QUIC_INVALID_VERSION_NEGOTIATION_PACKET; } - CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet, - i, expected_error, error_code); + CheckProcessingFails( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet, + i, expected_error, error_code); } } @@ -3158,10 +4141,11 @@ TEST_P(QuicFramerTest, OldVersionNegotiationPacket) { QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) ? arraysize(packet_cid_be) : arraysize(packet), false); @@ -3182,10 +4166,11 @@ TEST_P(QuicFramerTest, OldVersionNegotiationPacket) { expected_error = "Unable to read supported version in negotiation."; error_code = QUIC_INVALID_VERSION_NEGOTIATION_PACKET; } - CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet, - i, expected_error, error_code); + CheckProcessingFails( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet, + i, expected_error, error_code); } } @@ -3227,27 +4212,195 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) { 0x00, 0x00, 0x00, 0x00, 0x00 }; + + unsigned char packet39[kMaxPacketSize] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + unsigned char packet_cid_be39[kMaxPacketSize] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + uint64_t header_size = GetPacketHeaderSize( framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER); - memset((FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet) + - header_size + 1, - 0x00, kMaxPacketSize - header_size - 1); + memset((packets[index]) + header_size + 1, 0x00, + kMaxPacketSize - header_size - 1); std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); +} + +TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) { + if (framer_.version() <= QUIC_VERSION_37) { + return; + } + QuicPacketHeader header; + header.public_header.connection_id = kConnectionId; + header.public_header.reset_flag = false; + header.public_header.version_flag = false; + header.packet_number = kPacketNumber; + + QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset, + QuicStringPiece("hello world!")); + QuicPaddingFrame padding_frame(2); + QuicFrames frames = {QuicFrame(padding_frame), QuicFrame(&stream_frame), + QuicFrame(padding_frame)}; + + // clang-format off + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + + // paddings + 0x00, 0x00, + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x04, 0x03, 0x02, 0x01, + // offset + 0x54, 0x76, 0x10, 0x32, + 0xDC, 0xFE, 0x98, 0xBA, + // data length + 0x0c, 0x00, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + // paddings + 0x00, 0x00, + }; + + unsigned char packet_cid_be[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + + // paddings + 0x00, 0x00, + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x04, 0x03, 0x02, 0x01, + // offset + 0x54, 0x76, 0x10, 0x32, + 0xDC, 0xFE, 0x98, 0xBA, + // data length + 0x0c, 0x00, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + // paddings + 0x00, 0x00, + }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // paddings + 0x00, 0x00, + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + // paddings + 0x00, 0x00, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // paddings + 0x00, 0x00, + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + // paddings + 0x00, 0x00, + }; + // clang-format on + + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) { @@ -3287,27 +4440,50 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) { 0x00, 0x00, 0x00, 0x00, 0x00 }; + + unsigned char packet39[kMaxPacketSize] = { + // public flags (8 byte connection_id and 4 byte packet number) + 0x28, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x56, 0x78, 0x9A, 0xBC, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + unsigned char packet_cid_be39[kMaxPacketSize] = { + // public flags (8 byte connection_id and 4 byte packet number) + 0x28, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x56, 0x78, 0x9A, 0xBC, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + uint64_t header_size = GetPacketHeaderSize( framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_4BYTE_PACKET_NUMBER); - memset((FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet) + - header_size + 1, - 0x00, kMaxPacketSize - header_size - 1); + memset((packets[index]) + header_size + 1, 0x00, + kMaxPacketSize - header_size - 1); std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) { @@ -3347,27 +4523,50 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) { 0x00, 0x00, 0x00, 0x00, 0x00 }; + + unsigned char packet39[kMaxPacketSize] = { + // public flags (8 byte connection_id and 2 byte packet number) + 0x18, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x9A, 0xBC, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + unsigned char packet_cid_be39[kMaxPacketSize] = { + // public flags (8 byte connection_id and 2 byte packet number) + 0x18, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x9A, 0xBC, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + uint64_t header_size = GetPacketHeaderSize( framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_2BYTE_PACKET_NUMBER); - memset((FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet) + - header_size + 1, - 0x00, kMaxPacketSize - header_size - 1); + memset((packets[index]) + header_size + 1, 0x00, + kMaxPacketSize - header_size - 1); std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) { @@ -3412,8 +4611,9 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) { uint64_t header_size = GetPacketHeaderSize( framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_1BYTE_PACKET_NUMBER); - memset((FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be - : packet) + + memset((QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet) + header_size + 1, 0x00, kMaxPacketSize - header_size - 1); @@ -3422,10 +4622,11 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) { test::CompareCharArraysWithHexError( "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) ? arraysize(packet_cid_be) : arraysize(packet)); } @@ -3487,19 +4688,62 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) { 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin and no length) + 0xDF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin and no length) + 0xDF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) { @@ -3555,20 +4799,60 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) { // data 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet39[] = { + // public flags (version, 8 byte connection_id) + static_cast<unsigned char>( + FLAGS_quic_reloadable_flag_quic_remove_v33_hacks2 ? 0x39 : 0x3D), + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // version tag + 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(), + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (stream frame with fin and no length) + 0xDF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54, + // data + 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', + }; + + unsigned char packet_cid_be39[] = { + // public flags (version, 8 byte connection_id) + static_cast<unsigned char>( + FLAGS_quic_reloadable_flag_quic_remove_v33_hacks2 ? 0x39 : 0x3D), + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // version tag + 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(), + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (stream frame with fin and no length) + 0xDF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54, + // data + 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) { @@ -3598,10 +4882,11 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) { SupportedVersions(GetParam()))); test::CompareCharArraysWithHexError( "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) ? arraysize(packet_cid_be) : arraysize(packet)); } @@ -3663,19 +4948,59 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) { // num timestamps. 0x00, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (ack frame) + // (no ack blocks, 2 byte largest observed, 2 byte block length) + 0x45, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x12, 0x34, + // num timestamps. + 0x00, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (ack frame) + // (no ack blocks, 2 byte largest observed, 2 byte block length) + 0x45, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x12, 0x34, + // num timestamps. + 0x00, + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) { @@ -3774,19 +5099,95 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) { // num timestamps. 0x00, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (ack frame) + // (has ack blocks, 2 byte largest observed, 2 byte block length) + 0x65, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // num ack blocks ranges. + 0x04, + // first ack block length. + 0x00, 0x01, + // gap to next block. + 0x01, + // ack block length. + 0x0e, 0xaf, + // gap to next block. + 0xff, + // ack block length. + 0x00, 0x00, + // gap to next block. + 0x91, + // ack block length. + 0x01, 0xea, + // gap to next block. + 0x05, + // ack block length. + 0x00, 0x04, + // num timestamps. + 0x00, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (ack frame) + // (has ack blocks, 2 byte largest observed, 2 byte block length) + 0x65, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // num ack blocks ranges. + 0x04, + // first ack block length. + 0x00, 0x01, + // gap to next block. + 0x01, + // ack block length. + 0x0e, 0xaf, + // gap to next block. + 0xff, + // ack block length. + 0x00, 0x00, + // gap to next block. + 0x91, + // ack block length. + 0x01, 0xea, + // gap to next block. + 0x05, + // ack block length. + 0x00, 0x04, + // num timestamps. + 0x00, + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildAckFramePacketMaxAckBlocks) { @@ -3994,19 +5395,203 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMaxAckBlocks) { // num timestamps. 0x00, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + // frame type (ack frame) + // (has ack blocks, 2 byte largest observed, 2 byte block length) + 0x65, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // num ack blocks ranges. + 0xff, + // first ack block length. + 0x0f, 0xdd, + // 255 = 4 * 63 + 3 + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + // num timestamps. + 0x00, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + // frame type (ack frame) + // (has ack blocks, 2 byte largest observed, 2 byte block length) + 0x65, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // num ack blocks ranges. + 0xff, + // first ack block length. + 0x0f, 0xdd, + // 255 = 4 * 63 + 3 + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + // num timestamps. + 0x00, + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildNewStopWaitingPacket) { @@ -4052,19 +5637,48 @@ TEST_P(QuicFramerTest, BuildNewStopWaitingPacket) { 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (stop waiting frame) + 0x06, + // least packet number awaiting an ack, delta from packet number. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, + + // frame type (stop waiting frame) + 0x06, + // least packet number awaiting an ack, delta from packet number. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildRstFramePacketQuic) { @@ -4120,21 +5734,60 @@ TEST_P(QuicFramerTest, BuildRstFramePacketQuic) { // error code 0x08, 0x07, 0x06, 0x05, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (rst stream frame) + 0x01, + // stream id + 0x01, 0x02, 0x03, 0x04, + // sent byte offset + 0x08, 0x07, 0x06, 0x05, + 0x04, 0x03, 0x02, 0x01, + // error code + 0x05, 0x06, 0x07, 0x08, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (rst stream frame) + 0x01, + // stream id + 0x01, 0x02, 0x03, 0x04, + // sent byte offset + 0x08, 0x07, 0x06, 0x05, + 0x04, 0x03, 0x02, 0x01, + // error code + 0x05, 0x06, 0x07, 0x08, + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + QuicFrames frames = {QuicFrame(&rst_frame)}; std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildCloseFramePacket) { @@ -4195,19 +5848,62 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) { 'I', ' ', 'c', 'a', 'n', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (connection close frame) + 0x02, + // error code + 0x05, 0x06, 0x07, 0x08, + // error details length + 0x00, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (connection close frame) + 0x02, + // error code + 0x05, 0x06, 0x07, 0x08, + // error details length + 0x00, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n', + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildGoAwayPacket) { @@ -4273,19 +5969,66 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) { 'I', ' ', 'c', 'a', 'n', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (go away frame) + 0x03, + // error code + 0x05, 0x06, 0x07, 0x08, + // stream id + 0x01, 0x02, 0x03, 0x04, + // error details length + 0x00, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (go away frame) + 0x03, + // error code + 0x05, 0x06, 0x07, 0x08, + // stream id + 0x01, 0x02, 0x03, 0x04, + // error details length + 0x00, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n', + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildWindowUpdatePacket) { @@ -4338,19 +6081,54 @@ TEST_P(QuicFramerTest, BuildWindowUpdatePacket) { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (window update frame) + 0x04, + // stream id + 0x01, 0x02, 0x03, 0x04, + // byte offset + 0x11, 0x22, 0x33, 0x44, + 0x55, 0x66, 0x77, 0x88, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (window update frame) + 0x04, + // stream id + 0x01, 0x02, 0x03, 0x04, + // byte offset + 0x11, 0x22, 0x33, 0x44, + 0x55, 0x66, 0x77, 0x88, + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildBlockedPacket) { @@ -4396,19 +6174,48 @@ TEST_P(QuicFramerTest, BuildBlockedPacket) { // stream id 0x04, 0x03, 0x02, 0x01, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (blocked frame) + 0x05, + // stream id + 0x01, 0x02, 0x03, 0x04, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (blocked frame) + 0x05, + // stream id + 0x01, 0x02, 0x03, 0x04, + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildPingPacket) { @@ -4447,19 +6254,44 @@ TEST_P(QuicFramerTest, BuildPingPacket) { // frame type (ping frame) 0x07, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (ping frame) + 0x07, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (ping frame) + 0x07, + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } // Test that the MTU discovery packet is serialized correctly as a PING packet. @@ -4499,19 +6331,44 @@ TEST_P(QuicFramerTest, BuildMtuDiscoveryPacket) { // frame type (ping frame) 0x07, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (ping frame) + 0x07, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (ping frame) + 0x07, + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packets[index]), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildPublicResetPacketOld) { @@ -4520,7 +6377,6 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketOld) { reset_packet.public_header.connection_id = kConnectionId; reset_packet.public_header.reset_flag = true; reset_packet.public_header.version_flag = false; - reset_packet.rejected_packet_number = kPacketNumber; reset_packet.nonce_proof = kNonceProof; // clang-format off @@ -4532,57 +6388,6 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketOld) { 0x98, 0xBA, 0xDC, 0xFE, // message tag (kPRST) 'P', 'R', 'S', 'T', - // num_entries (2) + padding - 0x02, 0x00, 0x00, 0x00, - // tag kRNON - 'R', 'N', 'O', 'N', - // end offset 8 - 0x08, 0x00, 0x00, 0x00, - // tag kRSEQ - 'R', 'S', 'E', 'Q', - // end offset 16 - 0x10, 0x00, 0x00, 0x00, - // nonce proof - 0x89, 0x67, 0x45, 0x23, - 0x01, 0xEF, 0xCD, 0xAB, - // rejected packet number - 0xBC, 0x9A, 0x78, 0x56, - 0x34, 0x12, 0x00, 0x00, - }; - - unsigned char packet_cid_be[] = { - // public flags (public reset, 8 byte ConnectionId) - 0x0E, - // connection_id - 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, - // message tag (kPRST) - 'P', 'R', 'S', 'T', - // num_entries (2) + padding - 0x02, 0x00, 0x00, 0x00, - // tag kRNON - 'R', 'N', 'O', 'N', - // end offset 8 - 0x08, 0x00, 0x00, 0x00, - // tag kRSEQ - 'R', 'S', 'E', 'Q', - // end offset 16 - 0x10, 0x00, 0x00, 0x00, - // nonce proof - 0x89, 0x67, 0x45, 0x23, - 0x01, 0xEF, 0xCD, 0xAB, - // rejected packet number - 0xBC, 0x9A, 0x78, 0x56, - 0x34, 0x12, 0x00, 0x00, - }; - - unsigned char packet_no_rejected_packet_number[] = { - // public flags (public reset, 8 byte ConnectionId) - 0x0E, - // connection_id - 0x10, 0x32, 0x54, 0x76, - 0x98, 0xBA, 0xDC, 0xFE, - // message tag (kPRST) - 'P', 'R', 'S', 'T', // num_entries (1) + padding 0x01, 0x00, 0x00, 0x00, // tag kRNON @@ -4594,7 +6399,7 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketOld) { 0x01, 0xEF, 0xCD, 0xAB, }; - unsigned char packet_no_rejected_packet_number_cid_be[] = { + unsigned char packet_cid_be[] = { // public flags (public reset, 8 byte ConnectionId) 0x0E, // connection_id @@ -4616,25 +6421,15 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketOld) { std::unique_ptr<QuicEncryptedPacket> data( framer_.BuildPublicResetPacket(reset_packet)); ASSERT_TRUE(data != nullptr); - if (FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset) { - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_no_rejected_packet_number_cid_be - : packet_no_rejected_packet_number), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_no_rejected_packet_number_cid_be) - : arraysize(packet_no_rejected_packet_number)); - } else { - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); - } + test::CompareCharArraysWithHexError( + "constructed packet", data->data(), data->length(), + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? arraysize(packet_cid_be) + : arraysize(packet)); } TEST_P(QuicFramerTest, BuildPublicResetPacket) { @@ -4643,96 +6438,45 @@ TEST_P(QuicFramerTest, BuildPublicResetPacket) { reset_packet.public_header.connection_id = kConnectionId; reset_packet.public_header.reset_flag = true; reset_packet.public_header.version_flag = false; - reset_packet.rejected_packet_number = kPacketNumber; reset_packet.nonce_proof = kNonceProof; // clang-format off unsigned char packet[] = { - // public flags (public reset, 8 byte ConnectionId) - 0x0A, - // connection_id - 0x10, 0x32, 0x54, 0x76, - 0x98, 0xBA, 0xDC, 0xFE, - // message tag (kPRST) - 'P', 'R', 'S', 'T', - // num_entries (2) + padding - 0x02, 0x00, 0x00, 0x00, - // tag kRNON - 'R', 'N', 'O', 'N', - // end offset 8 - 0x08, 0x00, 0x00, 0x00, - // tag kRSEQ - 'R', 'S', 'E', 'Q', - // end offset 16 - 0x10, 0x00, 0x00, 0x00, - // nonce proof - 0x89, 0x67, 0x45, 0x23, - 0x01, 0xEF, 0xCD, 0xAB, - // rejected packet number - 0xBC, 0x9A, 0x78, 0x56, - 0x34, 0x12, 0x00, 0x00, + // public flags (public reset, 8 byte ConnectionId) + 0x0A, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // message tag (kPRST) + 'P', 'R', 'S', 'T', + // num_entries (1) + padding + 0x01, 0x00, 0x00, 0x00, + // tag kRNON + 'R', 'N', 'O', 'N', + // end offset 8 + 0x08, 0x00, 0x00, 0x00, + // nonce proof + 0x89, 0x67, 0x45, 0x23, + 0x01, 0xEF, 0xCD, 0xAB, }; unsigned char packet_cid_be[] = { - // public flags (public reset, 8 byte ConnectionId) - 0x0A, - // connection_id - 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, - // message tag (kPRST) - 'P', 'R', 'S', 'T', - // num_entries (2) + padding - 0x02, 0x00, 0x00, 0x00, - // tag kRNON - 'R', 'N', 'O', 'N', - // end offset 8 - 0x08, 0x00, 0x00, 0x00, - // tag kRSEQ - 'R', 'S', 'E', 'Q', - // end offset 16 - 0x10, 0x00, 0x00, 0x00, - // nonce proof - 0x89, 0x67, 0x45, 0x23, - 0x01, 0xEF, 0xCD, 0xAB, - // rejected packet number - 0xBC, 0x9A, 0x78, 0x56, - 0x34, 0x12, 0x00, 0x00, - }; - - unsigned char packet_no_rejected_packet_number[] = { - // public flags (public reset, 8 byte ConnectionId) - 0x0A, - // connection_id - 0x10, 0x32, 0x54, 0x76, - 0x98, 0xBA, 0xDC, 0xFE, - // message tag (kPRST) - 'P', 'R', 'S', 'T', - // num_entries (1) + padding - 0x01, 0x00, 0x00, 0x00, - // tag kRNON - 'R', 'N', 'O', 'N', - // end offset 8 - 0x08, 0x00, 0x00, 0x00, - // nonce proof - 0x89, 0x67, 0x45, 0x23, - 0x01, 0xEF, 0xCD, 0xAB, - }; - - unsigned char packet_no_rejected_packet_number_cid_be[] = { - // public flags (public reset, 8 byte ConnectionId) - 0x0A, - // connection_id - 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, - // message tag (kPRST) - 'P', 'R', 'S', 'T', - // num_entries (1) + padding - 0x01, 0x00, 0x00, 0x00, - // tag kRNON - 'R', 'N', 'O', 'N', - // end offset 8 - 0x08, 0x00, 0x00, 0x00, - // nonce proof - 0x89, 0x67, 0x45, 0x23, - 0x01, 0xEF, 0xCD, 0xAB, + // public flags (public reset, 8 byte ConnectionId) + 0x0A, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, + 0x76, 0x54, 0x32, 0x10, + // message tag (kPRST) + 'P', 'R', 'S', 'T', + // num_entries (1) + padding + 0x01, 0x00, 0x00, 0x00, + // tag kRNON + 'R', 'N', 'O', 'N', + // end offset 8 + 0x08, 0x00, 0x00, 0x00, + // nonce proof + 0x89, 0x67, 0x45, 0x23, + 0x01, 0xEF, 0xCD, 0xAB, }; // clang-format on @@ -4740,25 +6484,15 @@ TEST_P(QuicFramerTest, BuildPublicResetPacket) { framer_.BuildPublicResetPacket(reset_packet)); ASSERT_TRUE(data != nullptr); - if (FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset) { - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_no_rejected_packet_number_cid_be - : packet_no_rejected_packet_number), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_no_rejected_packet_number_cid_be) - : arraysize(packet_no_rejected_packet_number)); - } else { - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); - } + test::CompareCharArraysWithHexError( + "constructed packet", data->data(), data->length(), + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? arraysize(packet_cid_be) + : arraysize(packet)); } TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) { @@ -4767,80 +6501,12 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) { reset_packet.public_header.connection_id = kConnectionId; reset_packet.public_header.reset_flag = true; reset_packet.public_header.version_flag = false; - reset_packet.rejected_packet_number = kPacketNumber; reset_packet.nonce_proof = kNonceProof; reset_packet.client_address = QuicSocketAddress(QuicIpAddress::Loopback4(), 0x1234); // clang-format off unsigned char packet[] = { - // public flags (public reset, 8 byte ConnectionId) - 0x0A, - // connection_id - 0x10, 0x32, 0x54, 0x76, - 0x98, 0xBA, 0xDC, 0xFE, - // message tag (kPRST) - 'P', 'R', 'S', 'T', - // num_entries (3) + padding - 0x03, 0x00, 0x00, 0x00, - // tag kRNON - 'R', 'N', 'O', 'N', - // end offset 8 - 0x08, 0x00, 0x00, 0x00, - // tag kRSEQ - 'R', 'S', 'E', 'Q', - // end offset 16 - 0x10, 0x00, 0x00, 0x00, - // tag kCADR - 'C', 'A', 'D', 'R', - // end offset 24 - 0x18, 0x00, 0x00, 0x00, - // nonce proof - 0x89, 0x67, 0x45, 0x23, - 0x01, 0xEF, 0xCD, 0xAB, - // rejected packet number - 0xBC, 0x9A, 0x78, 0x56, - 0x34, 0x12, 0x00, 0x00, - // client address - 0x02, 0x00, - 0x7F, 0x00, 0x00, 0x01, - 0x34, 0x12, - }; - - unsigned char packet_cid_be[] = { - // public flags (public reset, 8 byte ConnectionId) - 0x0A, - // connection_id - 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, - // message tag (kPRST) - 'P', 'R', 'S', 'T', - // num_entries (3) + padding - 0x03, 0x00, 0x00, 0x00, - // tag kRNON - 'R', 'N', 'O', 'N', - // end offset 8 - 0x08, 0x00, 0x00, 0x00, - // tag kRSEQ - 'R', 'S', 'E', 'Q', - // end offset 16 - 0x10, 0x00, 0x00, 0x00, - // tag kCADR - 'C', 'A', 'D', 'R', - // end offset 24 - 0x18, 0x00, 0x00, 0x00, - // nonce proof - 0x89, 0x67, 0x45, 0x23, - 0x01, 0xEF, 0xCD, 0xAB, - // rejected packet number - 0xBC, 0x9A, 0x78, 0x56, - 0x34, 0x12, 0x00, 0x00, - // client address - 0x02, 0x00, - 0x7F, 0x00, 0x00, 0x01, - 0x34, 0x12, - }; - - unsigned char packet_no_rejected_packet_number[] = { // public flags (public reset, 8 byte ConnectionId) 0x0A, // connection_id @@ -4867,11 +6533,12 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) { 0x34, 0x12, }; - unsigned char packet_no_rejected_packet_number_cid_be[] = { + unsigned char packet_cid_be[] = { // public flags (public reset, 8 byte ConnectionId) 0x0A, // connection_id - 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + 0xFE, 0xDC, 0xBA, 0x98, + 0x76, 0x54, 0x32, 0x10, // message tag (kPRST) 'P', 'R', 'S', 'T', // num_entries (2) + padding @@ -4898,27 +6565,16 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) { framer_.BuildPublicResetPacket(reset_packet)); ASSERT_TRUE(data != nullptr); - if (FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset) { - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_no_rejected_packet_number_cid_be - : packet_no_rejected_packet_number), - - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_no_rejected_packet_number_cid_be) - : arraysize(packet_no_rejected_packet_number)); - } else { - test::CompareCharArraysWithHexError( - "constructed packet", data->data(), data->length(), - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); - } + test::CompareCharArraysWithHexError( + "constructed packet", data->data(), data->length(), + AsChars( + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? packet_cid_be + : packet), + + QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective()) + ? arraysize(packet_cid_be) + : arraysize(packet)); } TEST_P(QuicFramerTest, EncryptPacket) { @@ -4956,16 +6612,46 @@ TEST_P(QuicFramerTest, EncryptPacket) { 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // redundancy + 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // redundancy + 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); std::unique_ptr<QuicPacket> raw(new QuicPacket( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false, PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, + AsChars(packets[index]), arraysize(packet), false, + PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER)); char buffer[kMaxPacketSize]; size_t encrypted_length = framer_.EncryptPayload( @@ -5014,16 +6700,51 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) { 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', }; + + unsigned char packet39[] = { + // public flags (version, 8 byte connection_id) + 0x39, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // version tag + 'Q', '.', '1', '0', + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // redundancy + 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', + }; + + unsigned char packet_cid_be39[] = { + // public flags (version, 8 byte connection_id) + 0x39, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // version tag + 'Q', '.', '1', '0', + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // redundancy + 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + std::unique_ptr<QuicPacket> raw(new QuicPacket( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false, PACKET_8BYTE_CONNECTION_ID, kIncludeVersion, + AsChars(packets[index]), arraysize(packet), false, + PACKET_8BYTE_CONNECTION_ID, kIncludeVersion, !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER)); char buffer[kMaxPacketSize]; size_t encrypted_length = framer_.EncryptPayload( @@ -5213,8 +6934,88 @@ TEST_P(QuicFramerTest, StopPacketProcessing) { 0xBE, 0x9A, 0x78, 0x56, 0x34, 0x12, }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + + // frame type (ack frame) + 0x40, + // least packet number awaiting an ack + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xA0, + // largest observed packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBF, + // num missing packets + 0x01, + // missing packet + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBE, + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x38, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + + // frame type (ack frame) + 0x40, + // least packet number awaiting an ack + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xA0, + // largest observed packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBF, + // num missing packets + 0x01, + // missing packet + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBE, + }; // clang-format on + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + MockFramerVisitor visitor; framer_.set_visitor(&visitor); EXPECT_CALL(visitor, OnPacket()); @@ -5226,14 +7027,8 @@ TEST_P(QuicFramerTest, StopPacketProcessing) { EXPECT_CALL(visitor, OnUnauthenticatedHeader(_)).WillOnce(Return(true)); EXPECT_CALL(visitor, OnDecryptedPacket(_)); - QuicEncryptedPacket encrypted( - AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet), - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet), - false); + QuicEncryptedPacket encrypted(AsChars(packets[index]), arraysize(packet), + false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); } @@ -5402,15 +7197,67 @@ TEST_P(QuicFramerTest, FramerFuzzTest) { 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet39[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + // private flags + 0x00, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + + unsigned char packet_cid_be39[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBC, + // private flags + 0x00, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0xBA, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; // clang-format on - QuicFramerFuzzFunc(FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? packet_cid_be - : packet, - FLAGS_quic_restart_flag_quic_big_endian_connection_id - ? arraysize(packet_cid_be) - : arraysize(packet)); + unsigned char* packets[] = {packet, packet_cid_be, packet39, packet_cid_be39}; + size_t index = GetPacketIndex(framer_.version(), framer_.perspective()); + + QuicFramerFuzzFunc(packets[index], arraysize(packet)); } +} // namespace } // namespace test } // namespace net diff --git a/chromium/net/quic/core/quic_header_list.cc b/chromium/net/quic/core/quic_header_list.cc index ad8f999b2cf..69f783adee6 100644 --- a/chromium/net/quic/core/quic_header_list.cc +++ b/chromium/net/quic/core/quic_header_list.cc @@ -4,8 +4,8 @@ #include "net/quic/core/quic_header_list.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/platform/api/quic_flags.h" using std::string; @@ -39,10 +39,6 @@ void QuicHeaderList::OnHeader(QuicStringPiece name, QuicStringPiece value) { } } -void QuicHeaderList::OnHeaderBlockEnd(size_t uncompressed_header_bytes) { - OnHeaderBlockEnd(uncompressed_header_bytes, uncompressed_header_bytes); -} - void QuicHeaderList::OnHeaderBlockEnd(size_t uncompressed_header_bytes, size_t compressed_header_bytes) { uncompressed_header_bytes_ = uncompressed_header_bytes; diff --git a/chromium/net/quic/core/quic_header_list.h b/chromium/net/quic/core/quic_header_list.h index 07aaeac3901..1de6ad2bf3e 100644 --- a/chromium/net/quic/core/quic_header_list.h +++ b/chromium/net/quic/core/quic_header_list.h @@ -8,12 +8,14 @@ #include <algorithm> #include <deque> #include <functional> +#include <string> +#include <utility> #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_export.h" #include "net/quic/platform/api/quic_string_piece.h" -#include "net/spdy/spdy_header_block.h" -#include "net/spdy/spdy_headers_handler_interface.h" +#include "net/spdy/core/spdy_header_block.h" +#include "net/spdy/core/spdy_headers_handler_interface.h" namespace net { @@ -33,7 +35,6 @@ class QUIC_EXPORT_PRIVATE QuicHeaderList : public SpdyHeadersHandlerInterface { // From SpdyHeadersHandlerInteface. void OnHeaderBlockStart() override; void OnHeader(QuicStringPiece name, QuicStringPiece value) override; - void OnHeaderBlockEnd(size_t uncompressed_header_bytes) override; void OnHeaderBlockEnd(size_t uncompressed_header_bytes, size_t compressed_header_bytes) override; diff --git a/chromium/net/quic/core/quic_header_list_test.cc b/chromium/net/quic/core/quic_header_list_test.cc index 42e2c4f9f56..39666a2cd41 100644 --- a/chromium/net/quic/core/quic_header_list_test.cc +++ b/chromium/net/quic/core/quic_header_list_test.cc @@ -4,16 +4,18 @@ #include "net/quic/core/quic_header_list.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; namespace net { +class QuicHeaderListTest : public QuicTest {}; + // This test verifies that QuicHeaderList accumulates header pairs in order. -TEST(QuicHeaderListTest, OnHeader) { +TEST_F(QuicHeaderListTest, OnHeader) { QuicHeaderList headers; headers.OnHeader("foo", "bar"); headers.OnHeader("april", "fools"); @@ -22,29 +24,31 @@ TEST(QuicHeaderListTest, OnHeader) { EXPECT_EQ("{ foo=bar, april=fools, beep=, }", headers.DebugString()); } -TEST(QuicHeaderListTest, TooLarge) { +TEST_F(QuicHeaderListTest, TooLarge) { QuicHeaderList headers; string key = "key"; string value(1 << 18, '1'); headers.OnHeader(key, value); - headers.OnHeaderBlockEnd(key.size() + value.size()); + size_t total_bytes = key.size() + value.size(); + headers.OnHeaderBlockEnd(total_bytes, total_bytes); EXPECT_TRUE(headers.empty()); EXPECT_EQ("{ }", headers.DebugString()); } -TEST(QuicHeaderListTest, NotTooLarge) { +TEST_F(QuicHeaderListTest, NotTooLarge) { QuicHeaderList headers; headers.set_max_uncompressed_header_bytes(1 << 20); string key = "key"; string value(1 << 18, '1'); headers.OnHeader(key, value); - headers.OnHeaderBlockEnd(key.size() + value.size()); + size_t total_bytes = key.size() + value.size(); + headers.OnHeaderBlockEnd(total_bytes, total_bytes); EXPECT_FALSE(headers.empty()); } // This test verifies that QuicHeaderList is copyable and assignable. -TEST(QuicHeaderListTest, IsCopyableAndAssignable) { +TEST_F(QuicHeaderListTest, IsCopyableAndAssignable) { QuicHeaderList headers; headers.OnHeader("foo", "bar"); headers.OnHeader("april", "fools"); diff --git a/chromium/net/quic/core/quic_headers_stream.cc b/chromium/net/quic/core/quic_headers_stream.cc index 00c769c5266..38e3ff48f3a 100644 --- a/chromium/net/quic/core/quic_headers_stream.cc +++ b/chromium/net/quic/core/quic_headers_stream.cc @@ -4,8 +4,8 @@ #include "net/quic/core/quic_headers_stream.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_spdy_session.h" +#include "net/quic/platform/api/quic_flags.h" namespace net { diff --git a/chromium/net/quic/core/quic_headers_stream.h b/chromium/net/quic/core/quic_headers_stream.h index 40684a02047..b28a7a45a7c 100644 --- a/chromium/net/quic/core/quic_headers_stream.h +++ b/chromium/net/quic/core/quic_headers_stream.h @@ -13,7 +13,7 @@ #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_stream.h" #include "net/quic/platform/api/quic_export.h" -#include "net/spdy/spdy_framer.h" +#include "net/spdy/core/spdy_framer.h" namespace net { diff --git a/chromium/net/quic/core/quic_headers_stream_test.cc b/chromium/net/quic/core/quic_headers_stream_test.cc index 056f34b266e..a2e16a42461 100644 --- a/chromium/net/quic/core/quic_headers_stream_test.cc +++ b/chromium/net/quic/core/quic_headers_stream_test.cc @@ -10,24 +10,24 @@ #include <tuple> #include <utility> -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" #include "net/quic/core/spdy_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_str_cat.h" #include "net/quic/platform/api/quic_string_piece.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_connection_peer.h" #include "net/quic/test_tools/quic_spdy_session_peer.h" #include "net/quic/test_tools/quic_stream_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "net/spdy/spdy_alt_svc_wire_format.h" -#include "net/spdy/spdy_flags.h" -#include "net/spdy/spdy_protocol.h" -#include "net/spdy/spdy_test_utils.h" +#include "net/spdy/chromium/spdy_flags.h" +#include "net/spdy/core/spdy_alt_svc_wire_format.h" +#include "net/spdy/core/spdy_protocol.h" +#include "net/spdy/core/spdy_test_utils.h" #include "net/test/gtest_util.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; using testing::_; @@ -135,15 +135,12 @@ class ForceHolAckListener : public QuicAckListenerInterface { enum Http2DecoderChoice { HTTP2_DECODER_SPDY, - HTTP2_DECODER_NESTED_SPDY, HTTP2_DECODER_NEW }; std::ostream& operator<<(std::ostream& os, Http2DecoderChoice v) { switch (v) { case HTTP2_DECODER_SPDY: return os << "SPDY"; - case HTTP2_DECODER_NESTED_SPDY: - return os << "NESTED_SPDY"; case HTTP2_DECODER_NEW: return os << "NEW"; } @@ -173,15 +170,9 @@ struct TestParams { hpack_decoder(testing::get<3>(params)) { switch (http2_decoder) { case HTTP2_DECODER_SPDY: - FLAGS_use_nested_spdy_framer_decoder = false; - FLAGS_chromium_http2_flag_spdy_use_http2_frame_decoder_adapter = false; - break; - case HTTP2_DECODER_NESTED_SPDY: - FLAGS_use_nested_spdy_framer_decoder = true; FLAGS_chromium_http2_flag_spdy_use_http2_frame_decoder_adapter = false; break; case HTTP2_DECODER_NEW: - FLAGS_use_nested_spdy_framer_decoder = false; FLAGS_chromium_http2_flag_spdy_use_http2_frame_decoder_adapter = true; // Http2FrameDecoderAdapter needs the new header methods, else // --use_http2_frame_decoder_adapter=true will be ignored. @@ -207,7 +198,7 @@ struct TestParams { HpackDecoderChoice hpack_decoder; }; -class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> { +class QuicHeadersStreamTest : public QuicTestWithParam<TestParamsTuple> { public: // Constructing the test_params_ object will set the necessary flags before // the MockQuicConnection is constructed, which we need because the latter @@ -233,6 +224,17 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> { EXPECT_EQ(version(), session_.connection()->version()); EXPECT_TRUE(headers_stream_ != nullptr); connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); + client_id_1_ = + QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0); + client_id_2_ = + QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 1); + client_id_3_ = + QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 2); + next_stream_id_ = QuicSpdySessionPeer::NextStreamId(session_); + } + + QuicStreamId GetNthClientInitiatedId(int n) { + return QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, n); } QuicConsumedData SaveIov(const QuicIOVector& data) { @@ -298,7 +300,7 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> { for (const auto& p : header_list) { headers_handler_->OnHeader(p.first, p.second); } - headers_handler_->OnHeaderBlockEnd(size); + headers_handler_->OnHeaderBlockEnd(size, size); } void WriteAndExpectRequestHeaders(QuicStreamId stream_id, @@ -317,7 +319,7 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> { bool is_request) { // Write the headers and capture the outgoing data EXPECT_CALL(session_, - WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + WritevData(headers_stream_, kHeadersStreamId, _, _, NO_FIN, _)) .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov))); QuicSpdySessionPeer::WriteHeadersImpl( &session_, stream_id, headers_.Clone(), fin, priority, nullptr); @@ -370,12 +372,13 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> { QuicConnectionPeer::TearDownLocalConnectionState(connection_); } - QuicStreamId NextPromisedStreamId() { return next_promised_stream_id_ += 2; } + QuicStreamId NextPromisedStreamId() { + return next_promised_stream_id_ += next_stream_id_; + } static const bool kFrameComplete = true; static const bool kHasPriority = true; - QuicFlagSaver flags_; // Save/restore all QUIC flag values. const TestParams test_params_; MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; @@ -392,6 +395,10 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> { StrictMock<MockVisitor> visitor_; QuicStreamFrame stream_frame_; QuicStreamId next_promised_stream_id_; + QuicStreamId client_id_1_; + QuicStreamId client_id_2_; + QuicStreamId client_id_3_; + QuicStreamId next_stream_id_; }; // Run all tests with each version, perspective (client or server), @@ -403,7 +410,6 @@ INSTANTIATE_TEST_CASE_P( ::testing::Values(Perspective::IS_CLIENT, Perspective::IS_SERVER), ::testing::Values(HTTP2_DECODER_SPDY, - HTTP2_DECODER_NESTED_SPDY, HTTP2_DECODER_NEW), ::testing::Values(HPACK_DECODER_SPDY, HPACK_DECODER3))); @@ -412,8 +418,8 @@ TEST_P(QuicHeadersStreamTest, StreamId) { } TEST_P(QuicHeadersStreamTest, WriteHeaders) { - for (QuicStreamId stream_id = kClientDataStreamId1; - stream_id < kClientDataStreamId3; stream_id += 2) { + for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_; + stream_id += next_stream_id_) { for (bool fin : kFins) { if (perspective() == Perspective::IS_SERVER) { WriteAndExpectResponseHeaders(stream_id, fin); @@ -428,13 +434,13 @@ TEST_P(QuicHeadersStreamTest, WriteHeaders) { } TEST_P(QuicHeadersStreamTest, WritePushPromises) { - for (QuicStreamId stream_id = kClientDataStreamId1; - stream_id < kClientDataStreamId3; stream_id += 2) { + for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_; + stream_id += next_stream_id_) { QuicStreamId promised_stream_id = NextPromisedStreamId(); if (perspective() == Perspective::IS_SERVER) { // Write the headers and capture the outgoing data - EXPECT_CALL(session_, - WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _, + NO_FIN, _)) .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov))); session_.WritePushPromise(stream_id, promised_stream_id, headers_.Clone()); @@ -460,8 +466,8 @@ TEST_P(QuicHeadersStreamTest, WritePushPromises) { } TEST_P(QuicHeadersStreamTest, ProcessRawData) { - for (QuicStreamId stream_id = kClientDataStreamId1; - stream_id < kClientDataStreamId3; stream_id += 2) { + for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_; + stream_id += next_stream_id_) { for (bool fin : {false, true}) { for (SpdyPriority priority = 0; priority < 7; ++priority) { // Replace with "WriteHeadersAndSaveData" @@ -494,8 +500,8 @@ TEST_P(QuicHeadersStreamTest, ProcessRawData) { TEST_P(QuicHeadersStreamTest, ProcessPushPromise) { if (perspective() == Perspective::IS_SERVER) return; - for (QuicStreamId stream_id = kClientDataStreamId1; - stream_id < kClientDataStreamId3; stream_id += 2) { + for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_; + stream_id += next_stream_id_) { QuicStreamId promised_stream_id = NextPromisedStreamId(); SpdyPushPromiseIR push_promise(stream_id, promised_stream_id, headers_.Clone()); @@ -539,9 +545,8 @@ TEST_P(QuicHeadersStreamTest, ProcessPushPromiseDisabledSetting) { "Unsupported field of HTTP/2 SETTINGS frame: 2", _)); } headers_stream_->OnStreamFrame(stream_frame_); - EXPECT_EQ( - session_.server_push_enabled(), - (perspective() == Perspective::IS_CLIENT && version() > QUIC_VERSION_34)); + EXPECT_EQ(session_.server_push_enabled(), + perspective() == Perspective::IS_CLIENT); } TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) { @@ -549,7 +554,7 @@ TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) { InSequence seq; bool fin = true; for (int stream_num = 0; stream_num < 10; stream_num++) { - QuicStreamId stream_id = QuicClientDataStreamId(stream_num); + QuicStreamId stream_id = GetNthClientInitiatedId(stream_num); // Replace with "WriteHeadersAndSaveData" SpdySerializedFrame frame; if (perspective() == Perspective::IS_SERVER) { @@ -583,7 +588,7 @@ TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) { { InSequence seq; for (int stream_num = 0; stream_num < 10; ++stream_num) { - stream_id = QuicClientDataStreamId(stream_num); + stream_id = GetNthClientInitiatedId(stream_num); if (perspective() == Perspective::IS_SERVER) { SpdyHeadersIR headers_frame(stream_id, headers_.Clone()); headers_frame.set_fin(fin); @@ -626,8 +631,8 @@ TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) { headers_["key0"] = string(1 << 13, '.'); headers_["key1"] = string(1 << 13, '.'); headers_["key2"] = string(1 << 13, '.'); - for (QuicStreamId stream_id = kClientDataStreamId1; - stream_id < kClientDataStreamId3; stream_id += 2) { + for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_; + stream_id += next_stream_id_) { for (bool fin : {false, true}) { for (SpdyPriority priority = 0; priority < 7; ++priority) { // Replace with "WriteHeadersAndSaveData" @@ -857,8 +862,8 @@ TEST_P(QuicHeadersStreamTest, HpackDecoderDebugVisitor) { headers_["key0"] = string(1 << 1, '.'); headers_["key1"] = string(1 << 2, '.'); headers_["key2"] = string(1 << 3, '.'); - for (QuicStreamId stream_id = kClientDataStreamId1; - stream_id < kClientDataStreamId3; stream_id += 2) { + for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_; + stream_id += next_stream_id_) { for (bool fin : {false, true}) { for (SpdyPriority priority = 0; priority < 7; ++priority) { // Replace with "WriteHeadersAndSaveData" @@ -908,8 +913,8 @@ TEST_P(QuicHeadersStreamTest, HpackEncoderDebugVisitor) { QuicSpdySessionPeer::SetHpackEncoderDebugVisitor( &session_, std::move(hpack_encoder_visitor)); - for (QuicStreamId stream_id = kClientDataStreamId1; - stream_id < kClientDataStreamId3; stream_id += 2) { + for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_; + stream_id += next_stream_id_) { for (bool fin : {false, true}) { if (perspective() == Perspective::IS_SERVER) { WriteAndExpectResponseHeaders(stream_id, fin); @@ -926,7 +931,7 @@ TEST_P(QuicHeadersStreamTest, HpackEncoderDebugVisitor) { } TEST_P(QuicHeadersStreamTest, WritevStreamData) { - QuicStreamId id = kClientDataStreamId1; + QuicStreamId id = client_id_1_; QuicStreamOffset offset = 0; struct iovec iov; @@ -944,8 +949,8 @@ TEST_P(QuicHeadersStreamTest, WritevStreamData) { if (use_ack_listener) { ack_listener = new ForceHolAckListener(); } - EXPECT_CALL(session_, - WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _, + NO_FIN, _)) .WillRepeatedly(WithArgs<2, 5>(Invoke( this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener))); @@ -983,19 +988,19 @@ TEST_P(QuicHeadersStreamTest, WritevStreamDataFinOnly) { string data; EXPECT_CALL(session_, - WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + WritevData(headers_stream_, kHeadersStreamId, _, _, NO_FIN, _)) .WillOnce(WithArgs<2, 5>( Invoke(this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener))); QuicConsumedData consumed_data = session_.WritevStreamData( - kClientDataStreamId1, MakeIOVector(data, &iov), 0, true, nullptr); + client_id_1_, MakeIOVector(data, &iov), 0, true, nullptr); EXPECT_EQ(consumed_data.bytes_consumed, 0u); EXPECT_EQ(consumed_data.fin_consumed, true); } TEST_P(QuicHeadersStreamTest, WritevStreamDataSendBlocked) { - QuicStreamId id = kClientDataStreamId1; + QuicStreamId id = client_id_1_; QuicStreamOffset offset = 0; struct iovec iov; @@ -1015,7 +1020,7 @@ TEST_P(QuicHeadersStreamTest, WritevStreamDataSendBlocked) { // In that case, |WritevStreamData| should consume just one // HTTP/2 data frame's worth of data. EXPECT_CALL(session_, - WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + WritevData(headers_stream_, kHeadersStreamId, _, _, NO_FIN, _)) .WillOnce( WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIovShort))); diff --git a/chromium/net/quic/core/quic_one_block_arena_test.cc b/chromium/net/quic/core/quic_one_block_arena_test.cc index 2a81c219b96..54a73e59cca 100644 --- a/chromium/net/quic/core/quic_one_block_arena_test.cc +++ b/chromium/net/quic/core/quic_one_block_arena_test.cc @@ -7,9 +7,8 @@ #include <cstdint> #include "net/quic/platform/api/quic_containers.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { namespace { @@ -20,13 +19,15 @@ struct TestObject { uint32_t value; }; -TEST(QuicOneBlockArenaTest, AllocateSuccess) { +class QuicOneBlockArenaTest : public QuicTest {}; + +TEST_F(QuicOneBlockArenaTest, AllocateSuccess) { QuicOneBlockArena<1024> arena; QuicArenaScopedPtr<TestObject> ptr = arena.New<TestObject>(); EXPECT_TRUE(ptr.is_from_arena()); } -TEST(QuicOneBlockArenaTest, Exhaust) { +TEST_F(QuicOneBlockArenaTest, Exhaust) { QuicOneBlockArena<1024> arena; for (size_t i = 0; i < 1024 / kMaxAlign; ++i) { QuicArenaScopedPtr<TestObject> ptr = arena.New<TestObject>(); @@ -38,7 +39,7 @@ TEST(QuicOneBlockArenaTest, Exhaust) { EXPECT_FALSE(ptr.is_from_arena()); } -TEST(QuicOneBlockArenaTest, NoOverlaps) { +TEST_F(QuicOneBlockArenaTest, NoOverlaps) { QuicOneBlockArena<1024> arena; std::vector<QuicArenaScopedPtr<TestObject>> objects; QuicIntervalSet<uintptr_t> used; diff --git a/chromium/net/quic/core/quic_packet_creator.cc b/chromium/net/quic/core/quic_packet_creator.cc index bcafa95014d..213249f36f1 100644 --- a/chromium/net/quic/core/quic_packet_creator.cc +++ b/chromium/net/quic/core/quic_packet_creator.cc @@ -10,10 +10,11 @@ #include "base/macros.h" #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/quic_data_writer.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_aligned.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_string_piece.h" @@ -44,7 +45,9 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id, connection_id_(connection_id), packet_(0, PACKET_1BYTE_PACKET_NUMBER, nullptr, 0, false, false), latched_flag_no_stop_waiting_frames_( - FLAGS_quic_reloadable_flag_quic_no_stop_waiting_frames) { + FLAGS_quic_reloadable_flag_quic_no_stop_waiting_frames), + pending_padding_bytes_(0), + needs_full_padding_(false) { SetMaxPacketLength(kDefaultMaxPacketSize); } @@ -112,7 +115,7 @@ void QuicPacketCreator::UpdatePacketNumberLength( packet_.packet_number + 1 - least_packet_awaited_by_peer; const uint64_t delta = std::max(current_delta, max_packets_in_flight); packet_.packet_number_length = - QuicFramer::GetMinSequenceNumberLength(delta * 4); + QuicFramer::GetMinPacketNumberLength(delta * 4); } bool QuicPacketCreator::ConsumeData(QuicStreamId id, @@ -150,8 +153,9 @@ bool QuicPacketCreator::ConsumeData(QuicStreamId id, return false; } if (needs_full_padding) { - packet_.num_padding_bytes = -1; + needs_full_padding_ = true; } + return true; } @@ -279,7 +283,11 @@ void QuicPacketCreator::ReserializeAllFrames( // Temporarily set the packet number length and change the encryption level. packet_.packet_number_length = retransmission.packet_number_length; - packet_.num_padding_bytes = retransmission.num_padding_bytes; + if (retransmission.num_padding_bytes == -1) { + // Only retransmit padding when original packet needs full padding. Padding + // from pending_padding_bytes_ are not retransmitted. + needs_full_padding_ = true; + } // Only preserve the original encryption level if it's a handshake packet or // if we haven't gone forward secure. if (retransmission.has_crypto_handshake || @@ -307,7 +315,7 @@ void QuicPacketCreator::ReserializeAllFrames( } void QuicPacketCreator::Flush() { - if (!HasPendingFrames()) { + if (!HasPendingFrames() && pending_padding_bytes_ == 0) { return; } @@ -342,6 +350,7 @@ void QuicPacketCreator::ClearPacket() { DCHECK(packet_.retransmittable_frames.empty()); packet_.listeners.clear(); packet_.largest_acked = 0; + needs_full_padding_ = false; } void QuicPacketCreator::CreateAndSerializeStreamFrame( @@ -358,7 +367,7 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame( FillPacketHeader(&header); QUIC_CACHELINE_ALIGNED char encrypted_buffer[kMaxPacketSize]; QuicDataWriter writer(arraysize(encrypted_buffer), encrypted_buffer, - framer_->perspective()); + framer_->perspective(), framer_->endianness()); if (!framer_->AppendPacketHeader(header, &writer)) { QUIC_BUG << "AppendPacketHeader failed"; return; @@ -455,7 +464,7 @@ bool QuicPacketCreator::AddSavedFrame(const QuicFrame& frame) { bool QuicPacketCreator::AddPaddedSavedFrame(const QuicFrame& frame) { if (AddFrame(frame, /*save_retransmittable_frames=*/true)) { - packet_.num_padding_bytes = -1; + needs_full_padding_ = true; return true; } return false; @@ -471,7 +480,8 @@ void QuicPacketCreator::AddAckListener( void QuicPacketCreator::SerializePacket(char* encrypted_buffer, size_t encrypted_buffer_len) { DCHECK_LT(0u, encrypted_buffer_len); - QUIC_BUG_IF(queued_frames_.empty()) << "Attempt to serialize empty packet"; + QUIC_BUG_IF(queued_frames_.empty() && pending_padding_bytes_ == 0) + << "Attempt to serialize empty packet"; QuicPacketHeader header; // FillPacketHeader increments packet_number_. FillPacketHeader(&header); @@ -536,7 +546,6 @@ SerializedPacket QuicPacketCreator::NoPacket() { void QuicPacketCreator::FillPacketHeader(QuicPacketHeader* header) { header->public_header.connection_id = connection_id_; header->public_header.connection_id_length = connection_id_length_; - header->public_header.multipath_flag = false; header->public_header.reset_flag = false; header->public_header.version_flag = send_version_in_packet_; if (IncludeNonceInPublicHeader()) { @@ -616,15 +625,29 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame, } void QuicPacketCreator::MaybeAddPadding() { - if (packet_.num_padding_bytes == 0) { + // The current packet should have no padding bytes because padding is only + // added when this method is called just before the packet is serialized. + DCHECK_EQ(0, packet_.num_padding_bytes); + if (BytesFree() == 0) { + // Don't pad full packets. return; } - if (BytesFree() == 0) { - // Don't pad full packets. + if (!needs_full_padding_ && pending_padding_bytes_ == 0) { + // Do not need padding. return; } + if (needs_full_padding_) { + // Full padding does not consume pending padding bytes. + packet_.num_padding_bytes = -1; + } else { + packet_.num_padding_bytes = + std::min<int16_t>(pending_padding_bytes_, BytesFree()); + pending_padding_bytes_ -= packet_.num_padding_bytes; + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_random_padding); + } + bool success = AddFrame(QuicFrame(QuicPaddingFrame(packet_.num_padding_bytes)), false); DCHECK(success); @@ -635,4 +658,8 @@ bool QuicPacketCreator::IncludeNonceInPublicHeader() { packet_.encryption_level == ENCRYPTION_INITIAL; } +void QuicPacketCreator::AddPendingPadding(QuicByteCount size) { + pending_padding_bytes_ += size; +} + } // namespace net diff --git a/chromium/net/quic/core/quic_packet_creator.h b/chromium/net/quic/core/quic_packet_creator.h index 68b70d42ff4..33b81d25f2b 100644 --- a/chromium/net/quic/core/quic_packet_creator.h +++ b/chromium/net/quic/core/quic_packet_creator.h @@ -202,6 +202,10 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator { // Sets the maximum packet length. void SetMaxPacketLength(QuicByteCount length); + // Increases pending_padding_bytes by |size|. Pending padding will be sent by + // MaybeAddPadding(). + void AddPendingPadding(QuicByteCount size); + void set_debug_delegate(DebugDelegate* debug_delegate) { debug_delegate_ = debug_delegate; } @@ -210,6 +214,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator { return latched_flag_no_stop_waiting_frames_; } + QuicByteCount pending_padding_bytes() const { return pending_padding_bytes_; } + private: friend class test::QuicPacketCreatorPeer; @@ -242,9 +248,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator { // saves the |frame| in the next SerializedPacket. bool AddFrame(const QuicFrame& frame, bool save_retransmittable_frames); - // Adds a padding frame to the current packet only if the current packet - // contains a handshake message, and there is sufficient room to fit a - // padding frame. + // Adds a padding frame to the current packet (if there is space) when (1) + // current packet needs full padding or (2) there are pending paddings. void MaybeAddPadding(); // Serializes all frames which have been added and adds any which should be @@ -303,6 +308,16 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator { // The latched value of FLAGS_quic_reloadable_flag_quic_no_stop_waiting_frames bool latched_flag_no_stop_waiting_frames_; + // Pending padding bytes to send. Pending padding bytes will be sent in next + // packet(s) (after all other frames) if current constructed packet does not + // have room to send all of them. + QuicByteCount pending_padding_bytes_; + + // Indicates whether current constructed packet needs full padding to max + // packet size. Please note, full padding does not consume pending padding + // bytes. + bool needs_full_padding_; + DISALLOW_COPY_AND_ASSIGN(QuicPacketCreator); }; diff --git a/chromium/net/quic/core/quic_packet_creator_test.cc b/chromium/net/quic/core/quic_packet_creator_test.cc index 69cf24d467f..ae317668d60 100644 --- a/chromium/net/quic/core/quic_packet_creator_test.cc +++ b/chromium/net/quic/core/quic_packet_creator_test.cc @@ -18,11 +18,10 @@ #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/quic/platform/api/quic_string_piece.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_framer_peer.h" #include "net/quic/test_tools/quic_packet_creator_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; using testing::DoAll; @@ -36,6 +35,8 @@ namespace net { namespace test { namespace { +const QuicStreamId kGetNthClientInitiatedStreamId1 = kHeadersStreamId + 2; + // Run tests with combinations of {QuicVersion, ToggleVersionSerialization}. struct TestParams { TestParams(QuicVersion version, @@ -87,7 +88,7 @@ class MockDelegate : public QuicPacketCreator::DelegateInterface { DISALLOW_COPY_AND_ASSIGN(MockDelegate); }; -class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> { +class QuicPacketCreatorTest : public QuicTestWithParam<TestParams> { public: void ClearSerializedPacketForTests(SerializedPacket* serialized_packet) { if (serialized_packet == nullptr) { @@ -189,8 +190,8 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> { // Returns the number of bytes consumed by the non-data fields of a stream // frame, assuming it is the last frame in the packet size_t GetStreamFrameOverhead() { - return QuicFramer::GetMinStreamFrameSize(kClientDataStreamId1, kOffset, - true); + return QuicFramer::GetMinStreamFrameSize(kGetNthClientInitiatedStreamId1, + kOffset, true); } QuicIOVector MakeIOVectorFromStringPiece(QuicStringPiece s) { @@ -210,7 +211,6 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> { static const QuicStreamOffset kOffset = 1u; - QuicFlagSaver flags_; // Save/restore all QUIC flag values. char buffer_[kMaxPacketSize]; QuicFrames frames_; QuicFramer server_framer_; @@ -359,7 +359,7 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithFullPadding) { delete frame.stream_frame; } -TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSpecifiedPadding) { +TEST_P(QuicPacketCreatorTest, DoNotRetransmitPendingPadding) { QuicFrame frame; QuicIOVector io_vector(MakeIOVectorFromStringPiece("fake message data")); QuicPacketCreatorPeer::CreateStreamFrame(&creator_, kCryptoStreamId, @@ -381,6 +381,20 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSpecifiedPadding) { packet_size = serialized_packet_.encrypted_length; } + { + InSequence s; + EXPECT_CALL(framer_visitor_, OnPacket()); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); + EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); + EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); + // Pending paddings are not retransmitted. + EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)).Times(0); + EXPECT_CALL(framer_visitor_, OnPacketComplete()); + } + ProcessPacket(serialized_packet_); + const int kNumPaddingBytes2 = 44; QuicFrames frames; frames.push_back(frame); @@ -393,8 +407,7 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSpecifiedPadding) { .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); creator_.ReserializeAllFrames(retransmission, buffer, kMaxPacketSize); - EXPECT_EQ(packet_size + kNumPaddingBytes2 - kNumPaddingBytes1, - serialized_packet_.encrypted_length); + EXPECT_EQ(packet_size, serialized_packet_.encrypted_length); delete frame.stream_frame; } @@ -503,16 +516,17 @@ TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) { for (size_t i = overhead; i < overhead + 100; ++i) { creator_.SetMaxPacketLength(i); const bool should_have_room = i > overhead + GetStreamFrameOverhead(); - ASSERT_EQ(should_have_room, - creator_.HasRoomForStreamFrame(kClientDataStreamId1, kOffset)); + ASSERT_EQ(should_have_room, creator_.HasRoomForStreamFrame( + kGetNthClientInitiatedStreamId1, kOffset)); if (should_have_room) { QuicFrame frame; QuicIOVector io_vector(MakeIOVectorFromStringPiece("testdata")); EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillRepeatedly(Invoke( this, &QuicPacketCreatorTest::ClearSerializedPacketForTests)); - ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u, - kOffset, false, false, &frame)); + ASSERT_TRUE(creator_.ConsumeData(kGetNthClientInitiatedStreamId1, + io_vector, 0u, kOffset, false, false, + &frame)); ASSERT_TRUE(frame.stream_frame); size_t bytes_consumed = frame.stream_frame->data_length; EXPECT_LT(0u, bytes_consumed); @@ -533,8 +547,8 @@ TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) { size_t bytes_free = delta > 0 ? 0 : 0 - delta; QuicFrame frame; QuicIOVector io_vector(MakeIOVectorFromStringPiece(data)); - ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u, - kOffset, false, false, &frame)); + ASSERT_TRUE(creator_.ConsumeData(kGetNthClientInitiatedStreamId1, io_vector, + 0u, kOffset, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); // BytesFree() returns bytes available for the next frame, which will @@ -602,8 +616,8 @@ TEST_P(QuicPacketCreatorTest, NonCryptoStreamFramePacketNonPadding) { QuicIOVector io_vector(MakeIOVectorFromStringPiece(data)); EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u, - kOffset, false, false, &frame)); + ASSERT_TRUE(creator_.ConsumeData(kGetNthClientInitiatedStreamId1, io_vector, + 0u, kOffset, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); size_t bytes_consumed = frame.stream_frame->data_length; EXPECT_LT(0u, bytes_consumed); @@ -853,6 +867,169 @@ TEST_P(QuicPacketCreatorTest, ChloTooLarge) { "Client hello won't fit in a single packet."); } +TEST_P(QuicPacketCreatorTest, PendingPadding) { + EXPECT_EQ(0u, creator_.pending_padding_bytes()); + creator_.AddPendingPadding(kMaxNumRandomPaddingBytes * 10); + EXPECT_EQ(kMaxNumRandomPaddingBytes * 10, creator_.pending_padding_bytes()); + + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly( + Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + // Flush all paddings. + while (creator_.pending_padding_bytes() > 0) { + creator_.Flush(); + { + InSequence s; + EXPECT_CALL(framer_visitor_, OnPacket()); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); + EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); + EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); + EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)); + EXPECT_CALL(framer_visitor_, OnPacketComplete()); + } + // Packet only contains padding. + ProcessPacket(serialized_packet_); + } + EXPECT_EQ(0u, creator_.pending_padding_bytes()); +} + +TEST_P(QuicPacketCreatorTest, FullPaddingDoesNotConsumePendingPadding) { + creator_.AddPendingPadding(kMaxNumRandomPaddingBytes); + QuicFrame frame; + QuicIOVector io_vector(MakeIOVectorFromStringPiece("test")); + ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, 0u, false, + /*needs_full_padding=*/true, &frame)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.Flush(); + EXPECT_EQ(kMaxNumRandomPaddingBytes, creator_.pending_padding_bytes()); +} + +TEST_P(QuicPacketCreatorTest, SendPendingPaddingInRetransmission) { + QuicStreamFrame* stream_frame = new QuicStreamFrame( + kCryptoStreamId, /*fin=*/false, 0u, QuicStringPiece()); + QuicFrames frames; + frames.push_back(QuicFrame(stream_frame)); + char buffer[kMaxPacketSize]; + QuicPendingRetransmission retransmission( + CreateRetransmission(frames, true, /*num_padding_bytes=*/0, + ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.AddPendingPadding(kMaxNumRandomPaddingBytes); + creator_.ReserializeAllFrames(retransmission, buffer, kMaxPacketSize); + EXPECT_EQ(0u, creator_.pending_padding_bytes()); + { + InSequence s; + EXPECT_CALL(framer_visitor_, OnPacket()); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); + EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); + EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); + EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)); + EXPECT_CALL(framer_visitor_, OnPacketComplete()); + } + ProcessPacket(serialized_packet_); + delete stream_frame; +} + +TEST_P(QuicPacketCreatorTest, SendPacketAfterFullPaddingRetransmission) { + // Making sure needs_full_padding gets reset after a full padding + // retransmission. + EXPECT_EQ(0u, creator_.pending_padding_bytes()); + QuicFrame frame; + QuicIOVector io_vector( + MakeIOVectorFromStringPiece("fake handshake message data")); + QuicPacketCreatorPeer::CreateStreamFrame(&creator_, kCryptoStreamId, + io_vector, 0u, 0u, false, &frame); + QuicFrames frames; + frames.push_back(frame); + char buffer[kMaxPacketSize]; + QuicPendingRetransmission retransmission(CreateRetransmission( + frames, true, /*num_padding_bytes=*/-1, ENCRYPTION_NONE, + QuicPacketCreatorPeer::GetPacketNumberLength(&creator_))); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly( + Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.ReserializeAllFrames(retransmission, buffer, kMaxPacketSize); + EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.encrypted_length); + { + InSequence s; + EXPECT_CALL(framer_visitor_, OnPacket()); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); + EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); + EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); + // Full padding. + EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)); + EXPECT_CALL(framer_visitor_, OnPacketComplete()); + } + ProcessPacket(serialized_packet_); + delete frame.stream_frame; + + creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, 0u, false, false, + &frame); + creator_.Flush(); + { + InSequence s; + EXPECT_CALL(framer_visitor_, OnPacket()); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); + EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); + EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); + // needs_full_padding gets reset. + EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)).Times(0); + EXPECT_CALL(framer_visitor_, OnPacketComplete()); + } + ProcessPacket(serialized_packet_); +} + +TEST_P(QuicPacketCreatorTest, ConsumeDataAndRandomPadding) { + const QuicByteCount kStreamFramePayloadSize = 100u; + // Set the packet size be enough for one stream frame with 0 stream offset + + // 1. + size_t length = GetPacketHeaderOverhead(client_framer_.version()) + + GetEncryptionOverhead() + + QuicFramer::GetMinStreamFrameSize( + kCryptoStreamId, 0, /*last_frame_in_packet=*/false) + + kStreamFramePayloadSize + 1; + creator_.SetMaxPacketLength(length); + creator_.AddPendingPadding(kMaxNumRandomPaddingBytes); + QuicByteCount pending_padding_bytes = creator_.pending_padding_bytes(); + QuicFrame frame; + char buf[kStreamFramePayloadSize + 1] = {}; + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly( + Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + // Send stream frame of size kStreamFramePayloadSize. + creator_.ConsumeData(kCryptoStreamId, + MakeIOVectorFromStringPiece( + QuicStringPiece(buf, kStreamFramePayloadSize)), + 0u, 0u, false, false, &frame); + creator_.Flush(); + delete frame.stream_frame; + // 1 byte padding is sent. + EXPECT_EQ(pending_padding_bytes - 1, creator_.pending_padding_bytes()); + // Send stream frame of size kStreamFramePayloadSize + 1. + creator_.ConsumeData(kCryptoStreamId, + MakeIOVectorFromStringPiece( + QuicStringPiece(buf, kStreamFramePayloadSize + 1)), + 0u, 0u, false, false, &frame); + // No padding is sent. + creator_.Flush(); + delete frame.stream_frame; + EXPECT_EQ(pending_padding_bytes - 1, creator_.pending_padding_bytes()); + // Flush all paddings. + while (creator_.pending_padding_bytes() > 0) { + creator_.Flush(); + } + EXPECT_EQ(0u, creator_.pending_padding_bytes()); +} + } // namespace } // namespace test } // namespace net diff --git a/chromium/net/quic/core/quic_packet_generator.cc b/chromium/net/quic/core/quic_packet_generator.cc index 025b54d573d..7487cde8fa4 100644 --- a/chromium/net/quic/core/quic_packet_generator.cc +++ b/chromium/net/quic/core/quic_packet_generator.cc @@ -6,6 +6,7 @@ #include <cstdint> +#include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_logging.h" @@ -14,13 +15,15 @@ namespace net { QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id, QuicFramer* framer, + QuicRandom* random_generator, QuicBufferAllocator* buffer_allocator, DelegateInterface* delegate) : delegate_(delegate), packet_creator_(connection_id, framer, buffer_allocator, delegate), batch_mode_(false), should_send_ack_(false), - should_send_stop_waiting_(false) {} + should_send_stop_waiting_(false), + random_generator_(random_generator) {} QuicPacketGenerator::~QuicPacketGenerator() { DeleteFrames(&queued_control_frames_); @@ -51,9 +54,10 @@ QuicConsumedData QuicPacketGenerator::ConsumeData( QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { bool has_handshake = (id == kCryptoStreamId); + bool fin = state != NO_FIN; QUIC_BUG_IF(has_handshake && fin) << "Handshake packets should never send a fin"; // To make reasoning about crypto frames easier, we don't combine them with @@ -93,6 +97,9 @@ QuicConsumedData QuicPacketGenerator::ConsumeData( } total_bytes_consumed += bytes_consumed; fin_consumed = fin && total_bytes_consumed == iov.total_length; + if (fin_consumed && state == FIN_AND_PADDING) { + AddRandomPadding(); + } DCHECK(total_bytes_consumed == iov.total_length || (bytes_consumed > 0 && packet_creator_.HasPendingFrames())); @@ -174,9 +181,10 @@ void QuicPacketGenerator::GenerateMtuDiscoveryPacket( } bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const { - DCHECK(HasPendingFrames()); + DCHECK(HasPendingFrames() || packet_creator_.pending_padding_bytes() > 0); HasRetransmittableData retransmittable = - (should_send_ack_ || should_send_stop_waiting_) + (should_send_ack_ || should_send_stop_waiting_ || + packet_creator_.pending_padding_bytes() > 0) ? NO_RETRANSMITTABLE_DATA : HAS_RETRANSMITTABLE_DATA; if (retransmittable == HAS_RETRANSMITTABLE_DATA) { @@ -222,6 +230,7 @@ void QuicPacketGenerator::StartBatchOperations() { void QuicPacketGenerator::FinishBatchOperations() { batch_mode_ = false; SendQueuedFrames(/*flush=*/false); + SendRemainingPendingPadding(); } void QuicPacketGenerator::FlushAllQueuedFrames() { @@ -327,4 +336,21 @@ void QuicPacketGenerator::SetEncrypter(EncryptionLevel level, packet_creator_.SetEncrypter(level, encrypter); } +void QuicPacketGenerator::AddRandomPadding() { + packet_creator_.AddPendingPadding( + random_generator_->RandUint64() % kMaxNumRandomPaddingBytes + 1); +} + +void QuicPacketGenerator::SendRemainingPendingPadding() { + while (packet_creator_.pending_padding_bytes() > 0 && !HasQueuedFrames() && + CanSendWithNextPendingFrameAddition()) { + packet_creator_.Flush(); + } +} + +bool QuicPacketGenerator::HasRetransmittableFrames() const { + return !queued_control_frames_.empty() || + packet_creator_.HasPendingRetransmittableFrames(); +} + } // namespace net diff --git a/chromium/net/quic/core/quic_packet_generator.h b/chromium/net/quic/core/quic_packet_generator.h index 676691c5513..43bffc1f4a4 100644 --- a/chromium/net/quic/core/quic_packet_generator.h +++ b/chromium/net/quic/core/quic_packet_generator.h @@ -73,6 +73,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator { QuicPacketGenerator(QuicConnectionId connection_id, QuicFramer* framer, + QuicRandom* random_generator, QuicBufferAllocator* buffer_allocator, DelegateInterface* delegate); @@ -92,11 +93,14 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator { // mode, these packets will also be sent during this call. // |delegate| (if not nullptr) will be informed once all packets sent as a // result of this call are ACKed by the peer. + // When |state| is FIN_AND_PADDING, random padding of size [1, 256] will be + // added after stream frames. If current constructed packet cannot + // accommodate, the padding will overflow to the next packet(s). QuicConsumedData ConsumeData( QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); // Sends as many data only packets as allowed by the send algorithm and the @@ -158,6 +162,10 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator { // Sets the encrypter to use for the encryption level. void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter); + // Returns true if there are control frames or current constructed packet has + // pending retransmittable frames. + bool HasRetransmittableFrames() const; + // Sets the encryption level that will be applied to new packets. void set_encryption_level(EncryptionLevel level); @@ -196,6 +204,13 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator { // fit into current open packet. bool AddNextPendingFrame(); + // Adds a random amount of padding (between 1 to 256 bytes). + void AddRandomPadding(); + + // Sends remaining pending padding. + // Pending paddings should only be sent when there is nothing else to send. + void SendRemainingPendingPadding(); + DelegateInterface* delegate_; QuicPacketCreator packet_creator_; @@ -213,6 +228,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator { // retransmitted. QuicStopWaitingFrame pending_stop_waiting_frame_; + QuicRandom* random_generator_; + DISALLOW_COPY_AND_ASSIGN(QuicPacketGenerator); }; diff --git a/chromium/net/quic/core/quic_packet_generator_test.cc b/chromium/net/quic/core/quic_packet_generator_test.cc index 990888359cf..d72e191c4cd 100644 --- a/chromium/net/quic/core/quic_packet_generator_test.cc +++ b/chromium/net/quic/core/quic_packet_generator_test.cc @@ -17,12 +17,12 @@ #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/quic/platform/api/quic_string_piece.h" +#include "net/quic/platform/api/quic_test.h" +#include "net/quic/test_tools/mock_random.h" #include "net/quic/test_tools/quic_packet_creator_peer.h" #include "net/quic/test_tools/quic_packet_generator_peer.h" #include "net/quic/test_tools/quic_test_utils.h" #include "net/quic/test_tools/simple_quic_framer.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; using testing::InSequence; @@ -85,7 +85,8 @@ struct PacketContents { num_stop_waiting_frames(0), num_stream_frames(0), num_ping_frames(0), - num_mtu_discovery_frames(0) {} + num_mtu_discovery_frames(0), + num_padding_frames(0) {} size_t num_ack_frames; size_t num_connection_close_frames; @@ -95,17 +96,22 @@ struct PacketContents { size_t num_stream_frames; size_t num_ping_frames; size_t num_mtu_discovery_frames; + size_t num_padding_frames; }; } // namespace -class QuicPacketGeneratorTest : public ::testing::Test { +class QuicPacketGeneratorTest : public QuicTest { public: QuicPacketGeneratorTest() : framer_(AllSupportedVersions(), QuicTime::Zero(), Perspective::IS_CLIENT), - generator_(42, &framer_, &buffer_allocator_, &delegate_), + generator_(42, + &framer_, + &random_generator_, + &buffer_allocator_, + &delegate_), creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)) { creator_->SetEncrypter(ENCRYPTION_FORWARD_SECURE, new NullEncrypter(Perspective::IS_CLIENT)); @@ -145,7 +151,8 @@ class QuicPacketGeneratorTest : public ::testing::Test { contents.num_ping_frames; size_t num_frames = contents.num_ack_frames + contents.num_stop_waiting_frames + - contents.num_mtu_discovery_frames + num_retransmittable_frames; + contents.num_mtu_discovery_frames + contents.num_padding_frames + + num_retransmittable_frames; if (num_retransmittable_frames == 0) { ASSERT_TRUE(packet.retransmittable_frames.empty()); @@ -170,6 +177,8 @@ class QuicPacketGeneratorTest : public ::testing::Test { simple_framer_.stream_frames().size()); EXPECT_EQ(contents.num_stop_waiting_frames, simple_framer_.stop_waiting_frames().size()); + EXPECT_EQ(contents.num_padding_frames, + simple_framer_.padding_frames().size()); // From the receiver's perspective, MTU discovery frames are ping frames. EXPECT_EQ(contents.num_ping_frames + contents.num_mtu_discovery_frames, @@ -207,6 +216,7 @@ class QuicPacketGeneratorTest : public ::testing::Test { } QuicFramer framer_; + MockRandom random_generator_; SimpleBufferAllocator buffer_allocator_; StrictMock<MockDelegate> delegate_; QuicPacketGenerator generator_; @@ -230,6 +240,7 @@ TEST_F(QuicPacketGeneratorTest, ShouldSendAck_NotWritable) { generator_.SetShouldSendAck(false); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); } TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldNotFlush) { @@ -245,6 +256,7 @@ TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldNotFlush) { generator_.SetShouldSendAck(false); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); } TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) { @@ -257,6 +269,7 @@ TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) { generator_.SetShouldSendAck(false); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); PacketContents contents; contents.num_ack_frames = 1; @@ -288,6 +301,7 @@ TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritable) { generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); } TEST_F(QuicPacketGeneratorTest, AddControlFrame_OnlyAckWritable) { @@ -295,6 +309,7 @@ TEST_F(QuicPacketGeneratorTest, AddControlFrame_OnlyAckWritable) { generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); } TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) { @@ -303,6 +318,7 @@ TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) { generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); } TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) { @@ -311,13 +327,16 @@ TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) { generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); generator_.FinishBatchOperations(); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); generator_.FlushAllQueuedFrames(); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); PacketContents contents; contents.num_rst_stream_frames = 1; @@ -332,6 +351,7 @@ TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) { generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); PacketContents contents; contents.num_rst_stream_frames = 1; @@ -342,10 +362,11 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_NotWritable) { delegate_.SetCanNotWrite(); QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, true, nullptr); + kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, FIN, nullptr); EXPECT_EQ(0u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); } TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) { @@ -353,10 +374,11 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) { generator_.StartBatchOperations(); QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, true, nullptr); + kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, FIN, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); } TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) { @@ -365,10 +387,11 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) { EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, true, nullptr); + kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, FIN, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); PacketContents contents; contents.num_stream_frames = 1; @@ -385,12 +408,14 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake) { EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); QuicConsumedData consumed = generator_.ConsumeData( - kCryptoStreamId, MakeIOVectorFromStringPiece("foo"), 0, false, nullptr); + kCryptoStreamId, MakeIOVectorFromStringPiece("foo"), 0, NO_FIN, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); PacketContents contents; contents.num_stream_frames = 1; + contents.num_padding_frames = 1; CheckPacketContains(contents, 0); ASSERT_EQ(1u, packets_.size()); @@ -401,7 +426,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake) { TEST_F(QuicPacketGeneratorTest, ConsumeData_EmptyData) { EXPECT_QUIC_BUG( generator_.ConsumeData(kHeadersStreamId, MakeIOVectorFromStringPiece(""), - 0, false, nullptr), + 0, NO_FIN, nullptr), "Attempt to consume empty data without FIN."); } @@ -411,12 +436,13 @@ TEST_F(QuicPacketGeneratorTest, generator_.StartBatchOperations(); generator_.ConsumeData(kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), - 2, true, nullptr); + 2, FIN, nullptr); QuicConsumedData consumed = generator_.ConsumeData( - 3, MakeIOVectorFromStringPiece("quux"), 7, false, nullptr); + 3, MakeIOVectorFromStringPiece("quux"), 7, NO_FIN, nullptr); EXPECT_EQ(4u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); } TEST_F(QuicPacketGeneratorTest, ConsumeData_BatchOperations) { @@ -424,18 +450,20 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_BatchOperations) { generator_.StartBatchOperations(); generator_.ConsumeData(kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), - 2, true, nullptr); + 2, FIN, nullptr); QuicConsumedData consumed = generator_.ConsumeData( - 3, MakeIOVectorFromStringPiece("quux"), 7, false, nullptr); + 3, MakeIOVectorFromStringPiece("quux"), 7, NO_FIN, nullptr); EXPECT_EQ(4u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); // Now both frames will be flushed out. EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); generator_.FinishBatchOperations(); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); PacketContents contents; contents.num_stream_frames = 2; @@ -468,21 +496,24 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) { // Queue enough data to prevent a stream frame with a non-zero offset from // fitting. QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 0, false, nullptr); + kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 0, NO_FIN, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); // This frame will not fit with the existing frame, causing the queued frame // to be serialized, and it will be added to a new open packet. consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVectorFromStringPiece("bar"), 3, true, nullptr); + kHeadersStreamId, MakeIOVectorFromStringPiece("bar"), 3, FIN, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); creator_->Flush(); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); PacketContents contents; contents.num_stream_frames = 1; @@ -502,6 +533,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeDataFastPath) { EXPECT_EQ(10000u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); PacketContents contents; contents.num_stream_frames = 1; @@ -514,6 +546,7 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) { generator_.SetShouldSendAck(false); generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); delegate_.SetCanWriteAnything(); @@ -524,7 +557,7 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) { .WillOnce(Return(QuicFrame(&ack_frame_))); // Send some data and a control frame - generator_.ConsumeData(3, MakeIOVectorFromStringPiece("quux"), 7, false, + generator_.ConsumeData(3, MakeIOVectorFromStringPiece("quux"), 7, NO_FIN, nullptr); generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame())); @@ -533,6 +566,7 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) { .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); generator_.FinishBatchOperations(); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); PacketContents contents; contents.num_ack_frames = 1; @@ -548,6 +582,7 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) { generator_.SetShouldSendAck(false); generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); delegate_.SetCanWriteAnything(); @@ -569,13 +604,14 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) { // Send enough data to exceed one packet size_t data_len = kDefaultMaxPacketSize + 100; QuicConsumedData consumed = - generator_.ConsumeData(3, CreateData(data_len), 0, true, nullptr); + generator_.ConsumeData(3, CreateData(data_len), 0, FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame())); generator_.FinishBatchOperations(); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); // The first packet should have the queued data and part of the stream data. PacketContents contents; @@ -618,11 +654,11 @@ TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) { .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), - /*offset=*/2, - /*fin=*/true, nullptr); + /*offset=*/2, FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); // We expect three packets, and first two of them have to be of packet_len // size. We check multiple packets (instead of just one) because we want to @@ -653,11 +689,11 @@ TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) { // Send two packets before packet size change. QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), - /*offset=*/2, - /*fin=*/false, nullptr); + /*offset=*/2, NO_FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); // Make sure we already have two packets. ASSERT_EQ(2u, packets_.size()); @@ -668,11 +704,11 @@ TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) { // Send a packet after packet size change. consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), - 2 + data_len, - /*fin=*/true, nullptr); + 2 + data_len, FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); // We expect first data chunk to get fragmented, but the second one to fit // into a single packet. @@ -697,11 +733,11 @@ TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) { // should not cause packet serialization. QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(first_write_len), - /*offset=*/2, - /*fin=*/false, nullptr); + /*offset=*/2, NO_FIN, nullptr); EXPECT_EQ(first_write_len, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); // Make sure we have no packets so far. ASSERT_EQ(0u, packets_.size()); @@ -716,6 +752,7 @@ TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) { generator_.SetMaxPacketLength(packet_len); EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength()); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); // We expect to see exactly one packet serialized after that, because we send // a value somewhat exceeding new max packet size, and the tail data does not @@ -727,11 +764,11 @@ TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) { // trigger serialization of one packet, and queue another one. consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(second_write_len), - /*offset=*/2 + first_write_len, - /*fin=*/true, nullptr); + /*offset=*/2 + first_write_len, FIN, nullptr); EXPECT_EQ(second_write_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); // We expect the first packet to be underfilled, and the second packet be up // to the new max packet size. @@ -756,11 +793,13 @@ TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_Simple) { generator_.GenerateMtuDiscoveryPacket(target_mtu, nullptr); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); ASSERT_EQ(1u, packets_.size()); EXPECT_EQ(target_mtu, packets_[0].encrypted_length); PacketContents contents; contents.num_mtu_discovery_frames = 1; + contents.num_padding_frames = 1; CheckPacketContains(contents, 0); } @@ -785,23 +824,24 @@ TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) { // Send data before the MTU probe. QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), - /*offset=*/2, - /*fin=*/false, nullptr); + /*offset=*/2, NO_FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); // Send the MTU probe. generator_.GenerateMtuDiscoveryPacket(target_mtu, nullptr); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); // Send data after the MTU probe. consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), - /*offset=*/2 + data_len, - /*fin=*/true, nullptr); + /*offset=*/2 + data_len, FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); ASSERT_EQ(5u, packets_.size()); EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length); @@ -810,6 +850,7 @@ TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) { PacketContents probe_contents; probe_contents.num_mtu_discovery_frames = 1; + probe_contents.num_padding_frames = 1; CheckPacketHasSingleStreamFrame(0); CheckPacketHasSingleStreamFrame(1); @@ -836,6 +877,7 @@ TEST_F(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) { EXPECT_CALL(delegate_, PopulateStopWaitingFrame(_)); // Generator should have queued control frames, and creator should be empty. EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); EXPECT_FALSE(creator_->HasPendingFrames()); // This will not serialize any packets, because of the invalid frame. @@ -852,7 +894,7 @@ TEST_F(QuicPacketGeneratorTest, ConnectionCloseFrameLargerThanPacketSize) { delegate_.SetCanWriteAnything(); QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame(); frame->error_code = QUIC_PACKET_WRITE_ERROR; - char buf[2000]; + char buf[2000] = {}; QuicStringPiece error_details(buf, 2000); frame->error_details = error_details.as_string(); EXPECT_CALL(delegate_, @@ -860,6 +902,147 @@ TEST_F(QuicPacketGeneratorTest, ConnectionCloseFrameLargerThanPacketSize) { "Single frame cannot fit into a packet", _)); EXPECT_QUIC_BUG(generator_.AddControlFrame(QuicFrame(frame)), ""); EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); +} + +TEST_F(QuicPacketGeneratorTest, RandomPaddingAfterFinSingleStreamSinglePacket) { + const QuicByteCount kStreamFramePayloadSize = 100u; + char buf[kStreamFramePayloadSize] = {}; + const QuicStreamId kDataStreamId = 5; + // Set the packet size be enough for one stream frame with 0 stream offset and + // max size of random padding. + size_t length = NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) + + GetPacketHeaderSize( + framer_.version(), creator_->connection_id_length(), + kIncludeVersion, !kIncludeDiversificationNonce, + QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) + + QuicFramer::GetMinStreamFrameSize( + kDataStreamId, 0, /*last_frame_in_packet=*/false) + + kStreamFramePayloadSize + kMaxNumRandomPaddingBytes; + generator_.SetMaxPacketLength(length); + delegate_.SetCanWriteAnything(); + generator_.StartBatchOperations(); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + QuicConsumedData consumed = + generator_.ConsumeData(kDataStreamId, + MakeIOVectorFromStringPiece( + QuicStringPiece(buf, kStreamFramePayloadSize)), + 0, FIN_AND_PADDING, nullptr); + generator_.FinishBatchOperations(); + EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed); + EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); + + EXPECT_EQ(1u, packets_.size()); + PacketContents contents; + // The packet has both stream and padding frames. + contents.num_padding_frames = 1; + contents.num_stream_frames = 1; + CheckPacketContains(contents, 0); +} + +TEST_F(QuicPacketGeneratorTest, + RandomPaddingAfterFinSingleStreamMultiplePackets) { + const QuicByteCount kStreamFramePayloadSize = 100u; + char buf[kStreamFramePayloadSize] = {}; + const QuicStreamId kDataStreamId = 5; + // Set the packet size be enough for one stream frame with 0 stream offset + + // 1. One or more packets will accommodate. + size_t length = NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) + + GetPacketHeaderSize( + framer_.version(), creator_->connection_id_length(), + kIncludeVersion, !kIncludeDiversificationNonce, + QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) + + QuicFramer::GetMinStreamFrameSize( + kDataStreamId, 0, /*last_frame_in_packet=*/false) + + kStreamFramePayloadSize + 1; + generator_.SetMaxPacketLength(length); + delegate_.SetCanWriteAnything(); + generator_.StartBatchOperations(); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + QuicConsumedData consumed = + generator_.ConsumeData(kDataStreamId, + MakeIOVectorFromStringPiece( + QuicStringPiece(buf, kStreamFramePayloadSize)), + 0, FIN_AND_PADDING, nullptr); + generator_.FinishBatchOperations(); + EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed); + EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); + + EXPECT_LE(1u, packets_.size()); + PacketContents contents; + // The first packet has both stream and padding frames. + contents.num_stream_frames = 1; + contents.num_padding_frames = 1; + CheckPacketContains(contents, 0); + + for (size_t i = 1; i < packets_.size(); ++i) { + // Following packets only have paddings. + contents.num_stream_frames = 0; + contents.num_padding_frames = 1; + CheckPacketContains(contents, i); + } +} + +TEST_F(QuicPacketGeneratorTest, + RandomPaddingAfterFinMultipleStreamsMultiplePackets) { + const QuicByteCount kStreamFramePayloadSize = 100u; + char buf[kStreamFramePayloadSize] = {}; + const QuicStreamId kDataStreamId1 = 5; + const QuicStreamId kDataStreamId2 = 6; + // Set the packet size be enough for first frame with 0 stream offset + second + // frame + 1 byte payload. two or more packets will accommodate. + size_t length = NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) + + GetPacketHeaderSize( + framer_.version(), creator_->connection_id_length(), + kIncludeVersion, !kIncludeDiversificationNonce, + QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) + + QuicFramer::GetMinStreamFrameSize( + kDataStreamId1, 0, /*last_frame_in_packet=*/false) + + kStreamFramePayloadSize + + QuicFramer::GetMinStreamFrameSize( + kDataStreamId1, 0, /*last_frame_in_packet=*/false) + + 1; + generator_.SetMaxPacketLength(length); + delegate_.SetCanWriteAnything(); + generator_.StartBatchOperations(); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + QuicConsumedData consumed = + generator_.ConsumeData(kDataStreamId1, + MakeIOVectorFromStringPiece( + QuicStringPiece(buf, kStreamFramePayloadSize)), + 0, FIN_AND_PADDING, nullptr); + EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed); + consumed = generator_.ConsumeData(kDataStreamId2, + MakeIOVectorFromStringPiece(QuicStringPiece( + buf, kStreamFramePayloadSize)), + 0, FIN_AND_PADDING, nullptr); + EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed); + generator_.FinishBatchOperations(); + EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); + + EXPECT_LE(2u, packets_.size()); + PacketContents contents; + // The first packet has two stream frames. + contents.num_stream_frames = 2; + CheckPacketContains(contents, 0); + + // The second packet has one stream frame and padding frames. + contents.num_stream_frames = 1; + contents.num_padding_frames = 1; + CheckPacketContains(contents, 1); + + for (size_t i = 2; i < packets_.size(); ++i) { + // Following packets only have paddings. + contents.num_stream_frames = 0; + contents.num_padding_frames = 1; + CheckPacketContains(contents, i); + } } } // namespace test diff --git a/chromium/net/quic/core/quic_packets.cc b/chromium/net/quic/core/quic_packets.cc index cdd6325627a..579aa8cad5f 100644 --- a/chromium/net/quic/core/quic_packets.cc +++ b/chromium/net/quic/core/quic_packets.cc @@ -4,9 +4,9 @@ #include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" #include "net/quic/core/quic_versions.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_str_cat.h" #include "net/quic/platform/api/quic_text_utils.h" @@ -52,7 +52,6 @@ size_t GetStartOfEncryptedData(QuicVersion version, QuicPacketPublicHeader::QuicPacketPublicHeader() : connection_id(0), connection_id_length(PACKET_8BYTE_CONNECTION_ID), - multipath_flag(false), reset_flag(false), version_flag(false), packet_number_length(PACKET_6BYTE_PACKET_NUMBER), @@ -70,12 +69,11 @@ QuicPacketHeader::QuicPacketHeader(const QuicPacketPublicHeader& header) QuicPacketHeader::QuicPacketHeader(const QuicPacketHeader& other) = default; -QuicPublicResetPacket::QuicPublicResetPacket() - : nonce_proof(0), rejected_packet_number(0) {} +QuicPublicResetPacket::QuicPublicResetPacket() : nonce_proof(0) {} QuicPublicResetPacket::QuicPublicResetPacket( const QuicPacketPublicHeader& header) - : public_header(header), nonce_proof(0), rejected_packet_number(0) {} + : public_header(header), nonce_proof(0) {} std::ostream& operator<<(std::ostream& os, const QuicPacketHeader& header) { os << "{ connection_id: " << header.public_header.connection_id diff --git a/chromium/net/quic/core/quic_packets.h b/chromium/net/quic/core/quic_packets.h index 95bef7c254d..d097a0cbbaa 100644 --- a/chromium/net/quic/core/quic_packets.h +++ b/chromium/net/quic/core/quic_packets.h @@ -64,9 +64,6 @@ struct QUIC_EXPORT_PRIVATE QuicPacketPublicHeader { // public flags. QuicConnectionId connection_id; QuicConnectionIdLength connection_id_length; - // TODO(fayang): Remove multipath_flag when deprecating - // quic_reloadable_flag_quic_remove_multipath_bit. - bool multipath_flag; bool reset_flag; bool version_flag; QuicPacketNumberLength packet_number_length; @@ -96,9 +93,6 @@ struct QUIC_EXPORT_PRIVATE QuicPublicResetPacket { QuicPacketPublicHeader public_header; QuicPublicResetNonceProof nonce_proof; - // TODO(fayang): remove rejected_packet_number when deprecating - // FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset. - QuicPacketNumber rejected_packet_number; QuicSocketAddress client_address; }; diff --git a/chromium/net/quic/core/quic_received_packet_manager_test.cc b/chromium/net/quic/core/quic_received_packet_manager_test.cc index 2f2c7a779da..2b0f24ad41c 100644 --- a/chromium/net/quic/core/quic_received_packet_manager_test.cc +++ b/chromium/net/quic/core/quic_received_packet_manager_test.cc @@ -9,7 +9,7 @@ #include <vector> #include "net/quic/core/quic_connection_stats.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { @@ -35,8 +35,7 @@ std::vector<TestParams> GetTestParams() { return params; } -class QuicReceivedPacketManagerTest - : public ::testing::TestWithParam<TestParams> { +class QuicReceivedPacketManagerTest : public QuicTestWithParam<TestParams> { protected: QuicReceivedPacketManagerTest() : received_manager_(&stats_) {} diff --git a/chromium/net/quic/core/quic_sent_packet_manager.cc b/chromium/net/quic/core/quic_sent_packet_manager.cc index a3084734ae4..9b3b3dc9b94 100644 --- a/chromium/net/quic/core/quic_sent_packet_manager.cc +++ b/chromium/net/quic/core/quic_sent_packet_manager.cc @@ -13,9 +13,9 @@ #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/proto/cached_network_parameters.pb.h" #include "net/quic/core/quic_connection_stats.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_pending_retransmission.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_map_util.h" @@ -117,8 +117,18 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) { } } else if (config.HasClientRequestedIndependentOption(kBYTE, perspective_)) { SetSendAlgorithm(kCubic); + } else if (FLAGS_quic_reloadable_flag_quic_enable_pcc && + config.HasClientRequestedIndependentOption(kTPCC, perspective_)) { + SetSendAlgorithm(kPCC); } - using_pacing_ = !FLAGS_quic_disable_pacing_for_perf_tests; + + // The PCCSender implements its own version of pacing through the + // SendAlgorithm::TimeUntilSend() function. Do not wrap a + // PacingSender around it, since wrapping a PacingSender around an + // already paced SendAlgorithm produces a DCHECK. TODO(fayang): + // Change this if/when the PCCSender uses the PacingSender. + using_pacing_ = !FLAGS_quic_disable_pacing_for_perf_tests && + send_algorithm_->GetCongestionControlType() != kPCC; if (config.HasClientSentConnectionOption(k1CON, perspective_)) { send_algorithm_->SetNumEmulatedConnections(1); @@ -796,9 +806,8 @@ const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const { static_cast<int64_t>(0.5 * srtt.ToMilliseconds()))); } if (!unacked_packets_.HasMultipleInFlightPackets()) { - return std::max(2 * srtt, - 1.5 * srtt + QuicTime::Delta::FromMilliseconds( - kMinRetransmissionTimeMs / 2)); + return std::max(2 * srtt, 1.5 * srtt + QuicTime::Delta::FromMilliseconds( + kMinRetransmissionTimeMs / 2)); } return QuicTime::Delta::FromMilliseconds( std::max(kMinTailLossProbeTimeoutMs, diff --git a/chromium/net/quic/core/quic_sent_packet_manager_test.cc b/chromium/net/quic/core/quic_sent_packet_manager_test.cc index 9a544a2b196..25608411d03 100644 --- a/chromium/net/quic/core/quic_sent_packet_manager_test.cc +++ b/chromium/net/quic/core/quic_sent_packet_manager_test.cc @@ -6,14 +6,14 @@ #include <memory> -#include "net/quic/core/quic_flags.h" +#include "net/quic/core/quic_pending_retransmission.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_string_piece.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_config_peer.h" #include "net/quic/test_tools/quic_sent_packet_manager_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" using testing::AnyNumber; using testing::ElementsAre; @@ -55,7 +55,7 @@ class MockDebugDelegate : public QuicSentPacketManager::DebugDelegate { QuicTime detection_time)); }; -class QuicSentPacketManagerTest : public ::testing::Test { +class QuicSentPacketManagerTest : public QuicTest { protected: QuicSentPacketManagerTest() : manager_(Perspective::IS_SERVER, &clock_, &stats_, kCubicBytes, kNack), @@ -269,7 +269,6 @@ class QuicSentPacketManagerTest : public ::testing::Test { frame->packets.Remove(lower, higher); } - QuicFlagSaver flags_; // Save/restore all QUIC flag values. QuicSentPacketManager manager_; MockClock clock_; QuicConnectionStats stats_; @@ -968,6 +967,7 @@ TEST_F(QuicSentPacketManagerTest, NewRetransmissionTimeout) { QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); client_config.SetConnectionOptionsToSend(options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); EXPECT_CALL(*send_algorithm_, PacingRate(_)) .WillRepeatedly(Return(QuicBandwidth::Zero())); @@ -1118,6 +1118,7 @@ TEST_F(QuicSentPacketManagerTest, QuicTagVector options; options.push_back(kCONH); QuicConfigPeer::SetReceivedConnectionOptions(&config, options); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); manager_.SetFromConfig(config); @@ -1359,6 +1360,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateTimeLossDetectionFromOptions) { QuicTagVector options; options.push_back(kTIME); QuicConfigPeer::SetReceivedConnectionOptions(&config, options); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); manager_.SetFromConfig(config); @@ -1378,6 +1380,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateCongestionControlFromOptions) { manager_.SetFromConfig(config); EXPECT_EQ(kReno, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) ->GetCongestionControlType()); + EXPECT_TRUE(QuicSentPacketManagerPeer::UsingPacing(&manager_)); options.clear(); options.push_back(kTBBR); @@ -1386,6 +1389,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateCongestionControlFromOptions) { manager_.SetFromConfig(config); EXPECT_EQ(kBBR, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) ->GetCongestionControlType()); + EXPECT_TRUE(QuicSentPacketManagerPeer::UsingPacing(&manager_)); options.clear(); options.push_back(kBYTE); @@ -1394,6 +1398,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateCongestionControlFromOptions) { manager_.SetFromConfig(config); EXPECT_EQ(kCubic, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) ->GetCongestionControlType()); + EXPECT_TRUE(QuicSentPacketManagerPeer::UsingPacing(&manager_)); options.clear(); options.push_back(kRENO); @@ -1403,10 +1408,55 @@ TEST_F(QuicSentPacketManagerTest, NegotiateCongestionControlFromOptions) { manager_.SetFromConfig(config); EXPECT_EQ(kRenoBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) ->GetCongestionControlType()); + EXPECT_TRUE(QuicSentPacketManagerPeer::UsingPacing(&manager_)); + + // Test with PCC enabled and disabled. + FLAGS_quic_reloadable_flag_quic_enable_pcc = false; + const CongestionControlType prior_cc_type = + QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) + ->GetCongestionControlType(); + options.clear(); + options.push_back(kTPCC); + QuicConfigPeer::SetReceivedConnectionOptions(&config, options); + EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + manager_.SetFromConfig(config); + // No change will be made to the congestion-control algorithm. + // Defaults to current type, as set in previous test. + EXPECT_NE(kPCC, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) + ->GetCongestionControlType()); + EXPECT_EQ(prior_cc_type, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) + ->GetCongestionControlType()); + EXPECT_TRUE(QuicSentPacketManagerPeer::UsingPacing(&manager_)); + + FLAGS_quic_reloadable_flag_quic_enable_pcc = true; + options.clear(); + options.push_back(kTPCC); + QuicConfigPeer::SetReceivedConnectionOptions(&config, options); + EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + manager_.SetFromConfig(config); + // Don't check the tag, since the actual implementation is + // platform-specific (i.e. it may be stubbed out). If the + // implementation does return PCC as the type, however, make sure + // that the packet manager does NOT wrap it with a PacingSender. + const bool should_pace = QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) + ->GetCongestionControlType() != kPCC; + EXPECT_EQ(should_pace, QuicSentPacketManagerPeer::UsingPacing(&manager_)); + + // Make sure that the flag for disabling pacing actually works. + FLAGS_quic_disable_pacing_for_perf_tests = true; + options.clear(); + options.push_back(kBYTE); + QuicConfigPeer::SetReceivedConnectionOptions(&config, options); + EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + manager_.SetFromConfig(config); + EXPECT_EQ(kCubic, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) + ->GetCongestionControlType()); + EXPECT_FALSE(QuicSentPacketManagerPeer::UsingPacing(&manager_)); } TEST_F(QuicSentPacketManagerTest, NegotiateClientCongestionControlFromOptions) { FLAGS_quic_reloadable_flag_quic_allow_new_bbr = true; + FLAGS_quic_reloadable_flag_quic_enable_pcc = true; QuicConfig config; QuicTagVector options; @@ -1415,6 +1465,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateClientCongestionControlFromOptions) { QuicSentPacketManagerPeer::GetSendAlgorithm(manager_); options.push_back(kRENO); config.SetClientConnectionOptions(options); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); manager_.SetFromConfig(config); @@ -1461,6 +1512,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNumConnectionsFromOptions) { QuicConfigPeer::SetReceivedConnectionOptions(&config, options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); EXPECT_CALL(*send_algorithm_, SetNumEmulatedConnections(1)); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); manager_.SetFromConfig(config); @@ -1469,6 +1521,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNumConnectionsFromOptions) { client_config.SetConnectionOptionsToSend(options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); EXPECT_CALL(*send_algorithm_, SetNumEmulatedConnections(1)); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); manager_.SetFromConfig(client_config); } @@ -1483,6 +1536,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNConnectionFromOptions) { options.push_back(kNCON); QuicConfigPeer::SetReceivedConnectionOptions(&config, options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); manager_.SetFromConfig(config); @@ -1497,6 +1551,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtServer) { options.push_back(kNTLP); QuicConfigPeer::SetReceivedConnectionOptions(&config, options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); manager_.SetFromConfig(config); EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_)); @@ -1510,6 +1565,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtClient) { QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); client_config.SetConnectionOptionsToSend(options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); manager_.SetFromConfig(client_config); EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_)); @@ -1522,6 +1578,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtServer) { options.push_back(kTLPR); QuicConfigPeer::SetReceivedConnectionOptions(&config, options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); manager_.SetFromConfig(config); EXPECT_TRUE( @@ -1536,6 +1593,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtClient) { QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); client_config.SetConnectionOptionsToSend(options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); manager_.SetFromConfig(client_config); EXPECT_TRUE( @@ -1550,6 +1608,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtServer) { options.push_back(kNRTO); QuicConfigPeer::SetReceivedConnectionOptions(&config, options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); manager_.SetFromConfig(config); EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_)); @@ -1564,6 +1623,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtClient) { QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); client_config.SetConnectionOptionsToSend(options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); manager_.SetFromConfig(client_config); EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_)); @@ -1577,6 +1637,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateUndoFromOptionsAtServer) { options.push_back(kUNDO); QuicConfigPeer::SetReceivedConnectionOptions(&config, options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); manager_.SetFromConfig(config); EXPECT_TRUE(QuicSentPacketManagerPeer::GetUndoRetransmits(&manager_)); @@ -1629,6 +1690,7 @@ TEST_F(QuicSentPacketManagerTest, NegotiateUndoFromOptionsAtClient) { QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); client_config.SetConnectionOptionsToSend(options); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); manager_.SetFromConfig(client_config); EXPECT_TRUE(QuicSentPacketManagerPeer::GetUndoRetransmits(&manager_)); @@ -1641,6 +1703,7 @@ TEST_F(QuicSentPacketManagerTest, UseInitialRoundTripTimeToSend) { QuicConfig config; config.SetInitialRoundTripTimeUsToSend(initial_rtt_us); + EXPECT_CALL(*send_algorithm_, GetCongestionControlType()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); manager_.SetFromConfig(config); diff --git a/chromium/net/quic/core/quic_server_id_test.cc b/chromium/net/quic/core/quic_server_id_test.cc index 95eeb670f3c..abf05a3edd4 100644 --- a/chromium/net/quic/core/quic_server_id_test.cc +++ b/chromium/net/quic/core/quic_server_id_test.cc @@ -4,7 +4,7 @@ #include "net/quic/core/quic_server_id.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" using std::string; @@ -12,7 +12,9 @@ namespace net { namespace { -TEST(QuicServerIdTest, ToString) { +class QuicServerIdTest : public QuicTest {}; + +TEST_F(QuicServerIdTest, ToString) { HostPortPair google_host_port_pair("google.com", 10); QuicServerId google_server_id(google_host_port_pair, PRIVACY_MODE_DISABLED); @@ -24,7 +26,7 @@ TEST(QuicServerIdTest, ToString) { EXPECT_EQ("https://google.com:10/private", private_server_id_str); } -TEST(QuicServerIdTest, LessThan) { +TEST_F(QuicServerIdTest, LessThan) { QuicServerId a_10_https(HostPortPair("a.com", 10), PRIVACY_MODE_DISABLED); QuicServerId a_11_https(HostPortPair("a.com", 11), PRIVACY_MODE_DISABLED); QuicServerId b_10_https(HostPortPair("b.com", 10), PRIVACY_MODE_DISABLED); @@ -86,7 +88,7 @@ TEST(QuicServerIdTest, LessThan) { } } -TEST(QuicServerIdTest, Equals) { +TEST_F(QuicServerIdTest, Equals) { PrivacyMode left_privacy; PrivacyMode right_privacy; for (int i = 0; i < 2; i++) { diff --git a/chromium/net/quic/core/quic_server_session_base.cc b/chromium/net/quic/core/quic_server_session_base.cc index 60e6794bc65..2524e5c1963 100644 --- a/chromium/net/quic/core/quic_server_session_base.cc +++ b/chromium/net/quic/core/quic_server_session_base.cc @@ -6,9 +6,9 @@ #include "net/quic/core/proto/cached_network_parameters.pb.h" #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_stream.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_string_piece.h" @@ -195,6 +195,7 @@ void QuicServerSessionBase::OnCongestionWindowChange(QuicTime now) { } bool QuicServerSessionBase::ShouldCreateIncomingDynamicStream(QuicStreamId id) { + DCHECK(!FLAGS_quic_reloadable_flag_quic_refactor_stream_creation); if (!connection()->connected()) { QUIC_BUG << "ShouldCreateIncomingDynamicStream called when disconnected"; return false; @@ -211,6 +212,7 @@ bool QuicServerSessionBase::ShouldCreateIncomingDynamicStream(QuicStreamId id) { } bool QuicServerSessionBase::ShouldCreateOutgoingDynamicStream() { + DCHECK(!FLAGS_quic_reloadable_flag_quic_refactor_stream_creation); if (!connection()->connected()) { QUIC_BUG << "ShouldCreateOutgoingDynamicStream called when disconnected"; return false; @@ -227,7 +229,12 @@ bool QuicServerSessionBase::ShouldCreateOutgoingDynamicStream() { return true; } -QuicCryptoServerStreamBase* QuicServerSessionBase::GetCryptoStream() { +QuicCryptoServerStreamBase* QuicServerSessionBase::GetMutableCryptoStream() { + return crypto_stream_.get(); +} + +const QuicCryptoServerStreamBase* QuicServerSessionBase::GetCryptoStream() + const { return crypto_stream_.get(); } diff --git a/chromium/net/quic/core/quic_server_session_base.h b/chromium/net/quic/core/quic_server_session_base.h index 6b41e6570a4..2fbe9762e02 100644 --- a/chromium/net/quic/core/quic_server_session_base.h +++ b/chromium/net/quic/core/quic_server_session_base.h @@ -69,7 +69,9 @@ class QUIC_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession { protected: // QuicSession methods(override them with return type of QuicSpdyStream*): - QuicCryptoServerStreamBase* GetCryptoStream() override; + QuicCryptoServerStreamBase* GetMutableCryptoStream() override; + + const QuicCryptoServerStreamBase* GetCryptoStream() const override; // If an outgoing stream can be created, return true. // Return false when connection is closed or forward secure encryption hasn't diff --git a/chromium/net/quic/core/quic_server_session_base_test.cc b/chromium/net/quic/core/quic_server_session_base_test.cc index cbd13030ebd..596d2678333 100644 --- a/chromium/net/quic/core/quic_server_session_base_test.cc +++ b/chromium/net/quic/core/quic_server_session_base_test.cc @@ -14,8 +14,10 @@ #include "net/quic/core/quic_connection.h" #include "net/quic/core/quic_crypto_server_stream.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_socket_address.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/fake_proof_source.h" #include "net/quic/test_tools/quic_config_peer.h" @@ -32,8 +34,6 @@ #include "net/tools/quic/quic_epoll_connection_helper.h" #include "net/tools/quic/quic_simple_server_stream.h" #include "net/tools/quic/test_tools/mock_quic_session_visitor.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; using testing::StrictMock; @@ -80,6 +80,8 @@ class TestServerSession : public QuicServerSessionBase { ~TestServerSession() override { delete connection(); }; protected: + // TODO(ckrasic) - for two below, remove when + // quic_reloadable_flag_quic_refactor_stream_creation is deprecated. QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override { if (!ShouldCreateIncomingDynamicStream(id)) { return nullptr; @@ -102,6 +104,10 @@ class TestServerSession : public QuicServerSessionBase { return stream; } + std::unique_ptr<QuicStream> CreateStream(QuicStreamId id) override { + return QuicMakeUnique<QuicSimpleServerStream>(id, this, response_cache_); + } + QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( const QuicCryptoServerConfig* crypto_config, QuicCompressedCertsCache* compressed_certs_cache) override { @@ -117,7 +123,7 @@ class TestServerSession : public QuicServerSessionBase { const size_t kMaxStreamsForTest = 10; -class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> { +class QuicServerSessionBaseTest : public QuicTestWithParam<QuicVersion> { protected: QuicServerSessionBaseTest() : QuicServerSessionBaseTest(crypto_test_utils::ProofSourceForTesting()) {} @@ -151,6 +157,14 @@ class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> { visitor_ = QuicConnectionPeer::GetVisitor(connection_); } + QuicStreamId GetNthClientInitiatedId(int n) { + return QuicSpdySessionPeer::GetNthClientInitiatedStreamId(*session_, n); + } + + QuicStreamId GetNthServerInitiatedId(int n) { + return QuicSpdySessionPeer::GetNthServerInitiatedStreamId(*session_, n); + } + StrictMock<MockQuicSessionVisitor> owner_; StrictMock<MockQuicCryptoServerStreamHelper> stream_helper_; MockQuicConnectionHelper helper_; @@ -163,7 +177,6 @@ class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> { std::unique_ptr<TestServerSession> session_; std::unique_ptr<CryptoHandshakeMessage> handshake_message_; QuicConnectionVisitorInterface* visitor_; - QuicFlagSaver flags_; // Save/restore all QUIC flag values. }; // Compares CachedNetworkParameters. @@ -193,25 +206,23 @@ TEST_P(QuicServerSessionBaseTest, ServerPushDisabledByDefault) { session_->config()->HasReceivedConnectionOptions() && ContainsQuicTag(session_->config()->ReceivedConnectionOptions(), kSPSH)); session_->OnConfigNegotiated(); - if (GetParam() <= QUIC_VERSION_34) { - EXPECT_FALSE(session_->server_push_enabled()); - } else { - EXPECT_TRUE(session_->server_push_enabled()); - } + EXPECT_TRUE(session_->server_push_enabled()); } TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) { // Open a stream, then reset it. // Send two bytes of payload to open it. - QuicStreamFrame data1(kClientDataStreamId1, false, 0, QuicStringPiece("HT")); + QuicStreamFrame data1(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece("HT")); session_->OnStreamFrame(data1); EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); // Send a reset (and expect the peer to send a RST in response). - QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, - 0); - EXPECT_CALL(*connection_, - SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); + QuicRstStreamFrame rst1(GetNthClientInitiatedId(0), + QUIC_ERROR_PROCESSING_STREAM, 0); + EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); + EXPECT_CALL(*connection_, SendRstStream(GetNthClientInitiatedId(0), + QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst1); EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); @@ -225,15 +236,17 @@ TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) { TEST_P(QuicServerSessionBaseTest, NeverOpenStreamDueToReset) { // Send a reset (and expect the peer to send a RST in response). - QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, - 0); - EXPECT_CALL(*connection_, - SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); + QuicRstStreamFrame rst1(GetNthClientInitiatedId(0), + QUIC_ERROR_PROCESSING_STREAM, 0); + EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); + EXPECT_CALL(*connection_, SendRstStream(GetNthClientInitiatedId(0), + QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst1); EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); // Send two bytes of payload. - QuicStreamFrame data1(kClientDataStreamId1, false, 0, QuicStringPiece("HT")); + QuicStreamFrame data1(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece("HT")); visitor_->OnStreamFrame(data1); // The stream should never be opened, now that the reset is received. @@ -243,25 +256,29 @@ TEST_P(QuicServerSessionBaseTest, NeverOpenStreamDueToReset) { TEST_P(QuicServerSessionBaseTest, AcceptClosedStream) { // Send (empty) compressed headers followed by two bytes of data. - QuicStreamFrame frame1(kClientDataStreamId1, false, 0, + QuicStreamFrame frame1(GetNthClientInitiatedId(0), false, 0, QuicStringPiece("\1\0\0\0\0\0\0\0HT")); - QuicStreamFrame frame2(kClientDataStreamId2, false, 0, + QuicStreamFrame frame2(GetNthClientInitiatedId(1), false, 0, QuicStringPiece("\2\0\0\0\0\0\0\0HT")); visitor_->OnStreamFrame(frame1); visitor_->OnStreamFrame(frame2); EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams()); // Send a reset (and expect the peer to send a RST in response). - QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, 0); - EXPECT_CALL(*connection_, - SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); + QuicRstStreamFrame rst(GetNthClientInitiatedId(0), + QUIC_ERROR_PROCESSING_STREAM, 0); + EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); + EXPECT_CALL(*connection_, SendRstStream(GetNthClientInitiatedId(0), + QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst); // If we were tracking, we'd probably want to reject this because it's data // past the reset point of stream 3. As it's a closed stream we just drop the // data on the floor, but accept the packet because it has data for stream 5. - QuicStreamFrame frame3(kClientDataStreamId1, false, 2, QuicStringPiece("TP")); - QuicStreamFrame frame4(kClientDataStreamId2, false, 2, QuicStringPiece("TP")); + QuicStreamFrame frame3(GetNthClientInitiatedId(0), false, 2, + QuicStringPiece("TP")); + QuicStreamFrame frame4(GetNthClientInitiatedId(1), false, 2, + QuicStringPiece("TP")); visitor_->OnStreamFrame(frame3); visitor_->OnStreamFrame(frame4); // The stream should never be opened, now that the reset is received. @@ -274,10 +291,6 @@ TEST_P(QuicServerSessionBaseTest, MaxOpenStreams) { // streams. The server accepts slightly more than the negotiated stream limit // to deal with rare cases where a client FIN/RST is lost. - if (GetParam() <= QUIC_VERSION_34) { - EXPECT_EQ(kMaxStreamsForTest, session_->max_open_incoming_streams()); - } - // The slightly increased stream limit is set during config negotiation. It // is either an increase of 10 over negotiated limit, or a fixed percentage // scaling, whichever is larger. Test both before continuing. @@ -287,23 +300,23 @@ TEST_P(QuicServerSessionBaseTest, MaxOpenStreams) { EXPECT_EQ(kMaxStreamsForTest + kMaxStreamsMinimumIncrement, session_->max_open_incoming_streams()); EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); - QuicStreamId stream_id = kClientDataStreamId1; + QuicStreamId stream_id = GetNthClientInitiatedId(0); // Open the max configured number of streams, should be no problem. for (size_t i = 0; i < kMaxStreamsForTest; ++i) { EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateDynamicStream( session_.get(), stream_id)); - stream_id += 2; + stream_id += QuicSpdySessionPeer::NextStreamId(*session_); } // Open more streams: server should accept slightly more than the limit. for (size_t i = 0; i < kMaxStreamsMinimumIncrement; ++i) { EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateDynamicStream( session_.get(), stream_id)); - stream_id += 2; + stream_id += QuicSpdySessionPeer::NextStreamId(*session_); } // Now violate the server's internal stream limit. - stream_id += 2; + stream_id += QuicSpdySessionPeer::NextStreamId(*session_); EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); EXPECT_CALL(*connection_, SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0)); // Even if the connection remains open, the stream creation should fail. @@ -316,10 +329,6 @@ TEST_P(QuicServerSessionBaseTest, MaxAvailableStreams) { // streams available. The server accepts slightly more than the negotiated // stream limit to deal with rare cases where a client FIN/RST is lost. - if (GetParam() <= QUIC_VERSION_34) { - // The slightly increased stream limit is set during config negotiation. - EXPECT_EQ(kMaxStreamsForTest, session_->max_open_incoming_streams()); - } session_->OnConfigNegotiated(); const size_t kAvailableStreamLimit = session_->MaxAvailableStreams(); EXPECT_EQ( @@ -331,11 +340,12 @@ TEST_P(QuicServerSessionBaseTest, MaxAvailableStreams) { EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateDynamicStream( - session_.get(), kClientDataStreamId1)); + session_.get(), GetNthClientInitiatedId(0))); // Establish available streams up to the server's limit. + QuicStreamId next_id = QuicSpdySessionPeer::NextStreamId(*session_); const int kLimitingStreamId = - kClientDataStreamId1 + (kAvailableStreamLimit)*2 + 2; + GetNthClientInitiatedId(kAvailableStreamLimit + 1); EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateDynamicStream( session_.get(), kLimitingStreamId)); @@ -345,7 +355,7 @@ TEST_P(QuicServerSessionBaseTest, MaxAvailableStreams) { // This forces stream kLimitingStreamId + 2 to become available, which // violates the quota. EXPECT_FALSE(QuicServerSessionBasePeer::GetOrCreateDynamicStream( - session_.get(), kLimitingStreamId + 4)); + session_.get(), kLimitingStreamId + 2 * next_id)); } // TODO(ckrasic): remove this when @@ -365,15 +375,21 @@ TEST_P(QuicServerSessionBaseTest, GetEvenIncomingError) { // Incoming streams on the server session must be odd. EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _)); EXPECT_EQ(nullptr, QuicServerSessionBasePeer::GetOrCreateDynamicStream( - session_.get(), 4)); + session_.get(), GetNthServerInitiatedId(0))); } TEST_P(QuicServerSessionBaseTest, GetStreamDisconnected) { // Don't create new streams if the connection is disconnected. QuicConnectionPeer::TearDownLocalConnectionState(connection_); - EXPECT_QUIC_BUG( - QuicServerSessionBasePeer::GetOrCreateDynamicStream(session_.get(), 5), - "ShouldCreateIncomingDynamicStream called when disconnected"); + if (FLAGS_quic_reloadable_flag_quic_refactor_stream_creation) { + EXPECT_EQ(nullptr, QuicServerSessionBasePeer::GetOrCreateDynamicStream( + session_.get(), GetNthClientInitiatedId(0))); + } else { + EXPECT_QUIC_BUG( + QuicServerSessionBasePeer::GetOrCreateDynamicStream( + session_.get(), GetNthClientInitiatedId(0)), + "ShouldCreateIncomingDynamicStream called when disconnected"); + } } class MockQuicCryptoServerStream : public QuicCryptoServerStream { @@ -522,7 +538,7 @@ TEST_P(QuicServerSessionBaseTest, BandwidthResumptionExperiment) { QuicTime::Delta::FromSeconds(kNumSecondsPerHour + 1)); QuicCryptoServerStream* crypto_stream = static_cast<QuicCryptoServerStream*>( - QuicSessionPeer::GetCryptoStream(session_.get())); + QuicSessionPeer::GetMutableCryptoStream(session_.get())); // No effect if no CachedNetworkParameters provided. EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0); diff --git a/chromium/net/quic/core/quic_session.cc b/chromium/net/quic/core/quic_session.cc index 5f106f20371..3afc985adf1 100644 --- a/chromium/net/quic/core/quic_session.cc +++ b/chromium/net/quic/core/quic_session.cc @@ -8,9 +8,9 @@ #include <utility> #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_flow_controller.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_map_util.h" #include "net/quic/platform/api/quic_str_cat.h" @@ -45,15 +45,14 @@ QuicSession::QuicSession(QuicConnection* connection, perspective() == Perspective::IS_SERVER, nullptr), currently_writing_stream_id_(0), - flow_control_invariant_( - FLAGS_quic_reloadable_flag_quic_flow_control_invariant) {} + respect_goaway_(true) {} void QuicSession::Initialize() { connection_->set_visitor(this); connection_->SetFromConfig(config_); - DCHECK_EQ(kCryptoStreamId, GetCryptoStream()->id()); - static_stream_map_[kCryptoStreamId] = GetCryptoStream(); + DCHECK_EQ(kCryptoStreamId, GetMutableCryptoStream()->id()); + static_stream_map_[kCryptoStreamId] = GetMutableCryptoStream(); } QuicSession::~QuicSession() { @@ -79,7 +78,7 @@ void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) { // us this offset. if (frame.fin) { QuicStreamOffset final_byte_offset = frame.offset + frame.data_length; - UpdateFlowControlOnFinalReceivedByteOffset(stream_id, final_byte_offset); + OnFinalByteOffsetReceived(stream_id, final_byte_offset); } return; } @@ -94,6 +93,10 @@ void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) { return; } + if (visitor_) { + visitor_->OnRstStreamReceived(frame); + } + QuicStream* stream = GetOrCreateDynamicStream(frame.stream_id); if (!stream) { HandleRstOnValidNonexistentStream(frame); @@ -286,14 +289,14 @@ QuicConsumedData QuicSession::WritevData( QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { // This check is an attempt to deal with potential memory corruption // in which |id| ends up set to 1 (the crypto stream id). If this happen // it might end up resulting in unencrypted stream data being sent. // While this is impossible to avoid given sufficient corruption, this // seems like a reasonable mitigation. - if (id == kCryptoStreamId && stream != GetCryptoStream()) { + if (id == kCryptoStreamId && stream != GetMutableCryptoStream()) { QUIC_BUG << "Stream id mismatch"; connection_->CloseConnection( QUIC_INTERNAL_ERROR, @@ -306,7 +309,7 @@ QuicConsumedData QuicSession::WritevData( // up write blocked until OnCanWrite is next called. return QuicConsumedData(0, false); } - QuicConsumedData data = connection_->SendStreamData(id, iov, offset, fin, + QuicConsumedData data = connection_->SendStreamData(id, iov, offset, state, std::move(ack_listener)); write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed); return data; @@ -392,7 +395,7 @@ void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) { connection_->SetNumOpenStreams(dynamic_stream_map_.size()); } -void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset( +void QuicSession::OnFinalByteOffsetReceived( QuicStreamId stream_id, QuicStreamOffset final_byte_offset) { std::map<QuicStreamId, QuicStreamOffset>::iterator it = @@ -423,28 +426,25 @@ void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset( } } -bool QuicSession::IsEncryptionEstablished() { +bool QuicSession::IsEncryptionEstablished() const { return GetCryptoStream()->encryption_established(); } -bool QuicSession::IsCryptoHandshakeConfirmed() { +bool QuicSession::IsCryptoHandshakeConfirmed() const { return GetCryptoStream()->handshake_confirmed(); } void QuicSession::OnConfigNegotiated() { connection_->SetFromConfig(config_); - const QuicVersion version = connection()->version(); uint32_t max_streams = 0; - if (version > QUIC_VERSION_34 && - config_.HasReceivedMaxIncomingDynamicStreams()) { + if (config_.HasReceivedMaxIncomingDynamicStreams()) { max_streams = config_.ReceivedMaxIncomingDynamicStreams(); } else { max_streams = config_.MaxStreamsPerConnection(); } set_max_open_outgoing_streams(max_streams); - if (FLAGS_quic_reloadable_flag_quic_large_ifw_options && - perspective() == Perspective::IS_SERVER) { + if (perspective() == Perspective::IS_SERVER) { if (config_.HasReceivedConnectionOptions()) { // The following variations change the initial receive flow control // window sizes. @@ -466,25 +466,18 @@ void QuicSession::OnConfigNegotiated() { } } - if (version <= QUIC_VERSION_34) { - // A small number of additional incoming streams beyond the limit should be - // allowed. This helps avoid early connection termination when FIN/RSTs for - // old streams are lost or arrive out of order. - // Use a minimum number of additional streams, or a percentage increase, - // whichever is larger. - uint32_t max_incoming_streams = - std::max(max_streams + kMaxStreamsMinimumIncrement, - static_cast<uint32_t>(max_streams * kMaxStreamsMultiplier)); - set_max_open_incoming_streams(max_incoming_streams); - } else { - uint32_t max_incoming_streams_to_send = - config_.GetMaxIncomingDynamicStreamsToSend(); - uint32_t max_incoming_streams = - std::max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement, - static_cast<uint32_t>(max_incoming_streams_to_send * - kMaxStreamsMultiplier)); - set_max_open_incoming_streams(max_incoming_streams); - } + // A small number of additional incoming streams beyond the limit should be + // allowed. This helps avoid early connection termination when FIN/RSTs for + // old streams are lost or arrive out of order. + // Use a minimum number of additional streams, or a percentage increase, + // whichever is larger. + uint32_t max_incoming_streams_to_send = + config_.GetMaxIncomingDynamicStreamsToSend(); + uint32_t max_incoming_streams = + std::max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement, + static_cast<uint32_t>(max_incoming_streams_to_send * + kMaxStreamsMultiplier)); + set_max_open_incoming_streams(max_incoming_streams); if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) { // Streams which were created before the SHLO was received (0-RTT @@ -541,8 +534,7 @@ void QuicSession::HandleRstOnValidNonexistentStream( if (IsClosedStream(frame.stream_id)) { // The RST frame contains the final byte offset for the stream: we can now // update the connection level flow controller if needed. - UpdateFlowControlOnFinalReceivedByteOffset(frame.stream_id, - frame.byte_offset); + OnFinalByteOffsetReceived(frame.stream_id, frame.byte_offset); } } @@ -729,6 +721,11 @@ QuicStream* QuicSession::GetOrCreateDynamicStream( if (!MaybeIncreaseLargestPeerStreamId(stream_id)) { return nullptr; } + + if (FLAGS_quic_reloadable_flag_quic_refactor_stream_creation) { + return MaybeCreateIncomingDynamicStream(stream_id); + } + // Check if the new number of open streams would cause the number of // open streams to exceed the limit. if (GetNumOpenIncomingStreams() >= max_open_incoming_streams()) { @@ -828,6 +825,10 @@ void QuicSession::PostProcessAfterData() { closed_streams_.clear(); } +void QuicSession::OnAckNeedsRetransmittableFrame() { + flow_controller_.SendWindowUpdate(); +} + size_t QuicSession::GetNumDynamicOutgoingStreams() const { DCHECK_GE(dynamic_stream_map_.size(), num_dynamic_incoming_streams_); return dynamic_stream_map_.size() - num_dynamic_incoming_streams_; @@ -871,4 +872,76 @@ bool QuicSession::IsIncomingStream(QuicStreamId id) const { return id % 2 != next_outgoing_stream_id_ % 2; } +bool QuicSession::ShouldCreateIncomingDynamicStream2(QuicStreamId id) { + DCHECK(FLAGS_quic_reloadable_flag_quic_refactor_stream_creation); + if (goaway_received() && respect_goaway_) { + QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " + << "Already received goaway."; + return false; + } + if (!IsIncomingStream(id)) { + QUIC_DLOG(INFO) << "invalid incoming stream id: " << id; + return false; + } + if (!connection()->connected()) { + QUIC_DLOG(INFO) + << "ShouldCreateIncomingDynamicStream called when disconnected"; + return false; + } + if (GetNumOpenIncomingStreams() >= max_open_incoming_streams()) { + DVLOG(1) << "Reset stream (refused) " << id; + SendRstStream(id, QUIC_REFUSED_STREAM, 0); + return false; + } + + return true; +} + +bool QuicSession::ShouldCreateOutgoingDynamicStream2() { + DCHECK(FLAGS_quic_reloadable_flag_quic_refactor_stream_creation); + if (!connection()->connected()) { + QUIC_DLOG(INFO) + << "ShouldCreateOutgoingDynamicStream called when disconnected"; + return false; + } + if (!IsEncryptionEstablished()) { + QUIC_DLOG(INFO) << "Encryption not established so no outgoing stream " + << "created."; + return false; + } + if (goaway_received() && respect_goaway_) { + QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " + << "Already received goaway."; + return false; + } + if (GetNumOpenOutgoingStreams() >= max_open_outgoing_streams()) { + QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " + << "Already " << GetNumOpenOutgoingStreams() << " open."; + return false; + } + return true; +} + +QuicStream* QuicSession::MaybeCreateIncomingDynamicStream(QuicStreamId id) { + if (!ShouldCreateIncomingDynamicStream2(id)) { + return nullptr; + } + return CreateAndActivateStream(id); +} + +QuicStream* QuicSession::MaybeCreateOutgoingDynamicStream( + SpdyPriority priority) { + if (!ShouldCreateOutgoingDynamicStream2()) { + return nullptr; + } + return CreateAndActivateStream(GetNextOutgoingStreamId()); +} + +QuicStream* QuicSession::CreateAndActivateStream(QuicStreamId id) { + std::unique_ptr<QuicStream> stream = CreateStream(id); + QuicStream* stream_ptr = stream.get(); + ActivateStream(std::move(stream)); + return stream_ptr; +} + } // namespace net diff --git a/chromium/net/quic/core/quic_session.h b/chromium/net/quic/core/quic_session.h index cba66a07d60..403f0e58cce 100644 --- a/chromium/net/quic/core/quic_session.h +++ b/chromium/net/quic/core/quic_session.h @@ -52,6 +52,9 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { // Called when the session has become write blocked. virtual void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) = 0; + + // Called when the session receives reset on a stream from the peer. + virtual void OnRstStreamReceived(const QuicRstStreamFrame& frame) = 0; }; // CryptoHandshakeEvent enumerates the events generated by a QuicCryptoStream. @@ -97,6 +100,8 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { // Deletes streams that are safe to be deleted now that it's safe to do so (no // other operations are being done on the streams at this time). void PostProcessAfterData() override; + // Adds a connection level WINDOW_UPDATE frame. + void OnAckNeedsRetransmittableFrame() override; bool WillingAndAbleToWrite() const override; bool HasPendingHandshake() const override; bool HasOpenDynamicStreams() const override; @@ -119,7 +124,7 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); // Called by streams when they want to close the stream in both directions. @@ -135,11 +140,11 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { // Returns true if outgoing packets will be encrypted, even if the server // hasn't confirmed the handshake yet. - virtual bool IsEncryptionEstablished(); + virtual bool IsEncryptionEstablished() const; // For a client, returns true if the server has confirmed our handshake. For // a server, returns true if a full, valid client hello has been received. - virtual bool IsCryptoHandshakeConfirmed(); + virtual bool IsCryptoHandshakeConfirmed() const; // Called by the QuicCryptoStream when a new QuicConfig has been negotiated. virtual void OnConfigNegotiated(); @@ -245,7 +250,9 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { // Returns true if this stream should yield writes to another blocked stream. bool ShouldYield(QuicStreamId stream_id); - bool flow_control_invariant() { return flow_control_invariant_; } + void set_respect_goaway(bool respect_goaway) { + respect_goaway_ = respect_goaway; + } protected: using StaticStreamMap = QuicSmallMap<QuicStreamId, QuicStream*, 2>; @@ -255,6 +262,28 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { using ClosedStreams = std::vector<std::unique_ptr<QuicStream>>; + // TODO(ckrasic) - For all *DynamicStream2 below, rename after + // quic_reloadable_flag_quic_refactor_stream_creation is deprecated. + + // Returns true if an incoming stream can be created. + virtual bool ShouldCreateIncomingDynamicStream2(QuicStreamId id); + + // Returns true if an outgoing stream can be created. + virtual bool ShouldCreateOutgoingDynamicStream2(); + + // Creates a new stream to handle a peer-initiated stream. + // Caller does not own the returned stream. + // Returns nullptr and does error handling if the stream can not be created. + virtual QuicStream* MaybeCreateIncomingDynamicStream(QuicStreamId id); + + // Create a new stream to handle a locally-initiated stream. + // Caller does not own the returned stream. + // Returns nullptr if max streams have already been opened. + virtual QuicStream* MaybeCreateOutgoingDynamicStream(SpdyPriority priority); + + // TODO(ckrasic) - For all Create*DynamicStream below, remove when + // quic_reloadable_flag_quic_refactor_stream_creation is deprecated. + // Creates a new stream to handle a peer-initiated stream. // Caller does not own the returned stream. // Returns nullptr and does error handling if the stream can not be created. @@ -266,7 +295,10 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { virtual QuicStream* CreateOutgoingDynamicStream(SpdyPriority priority) = 0; // Return the reserved crypto stream. - virtual QuicCryptoStream* GetCryptoStream() = 0; + virtual QuicCryptoStream* GetMutableCryptoStream() = 0; + + // Return the reserved crypto stream as a constant pointer. + virtual const QuicCryptoStream* GetCryptoStream() const = 0; // Adds |stream| to the dynamic stream map. virtual void ActivateStream(std::unique_ptr<QuicStream> stream); @@ -288,15 +320,23 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { // When a stream is closed locally, it may not yet know how many bytes the // peer sent on that stream. - // When this data arrives (via stream frame w. FIN, or RST) this method - // is called, and correctly updates the connection level flow controller. - void UpdateFlowControlOnFinalReceivedByteOffset( - QuicStreamId id, - QuicStreamOffset final_byte_offset); + // When this data arrives (via stream frame w. FIN, trailing headers, or RST) + // this method is called, and correctly updates the connection level flow + // controller. + virtual void OnFinalByteOffsetReceived(QuicStreamId id, + QuicStreamOffset final_byte_offset); // Return true if given stream is peer initiated. bool IsIncomingStream(QuicStreamId id) const; + // Unconditionally creates a stream. Subclasses should use this to + // provide streams appropriately subclassed from |QuicStream|, + // e.g. |QuicSpdySession::CreateStream()| creates a |QuicSpdyStream|. + virtual std::unique_ptr<QuicStream> CreateStream(QuicStreamId id) = 0; + + // Creates a stream and activates it, owned by the session. + QuicStream* CreateAndActivateStream(QuicStreamId id); + StaticStreamMap& static_streams() { return static_stream_map_; } const StaticStreamMap& static_streams() const { return static_stream_map_; } @@ -353,6 +393,8 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { virtual void HandleRstOnValidNonexistentStream( const QuicRstStreamFrame& frame); + bool respect_goaway() const { return respect_goaway_; } + private: friend class test::QuicSessionPeer; @@ -438,8 +480,10 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { // call stack of OnCanWrite. QuicStreamId currently_writing_stream_id_; - // Latched value of quic_reloadable_flag_quic_flow_control_invariant. - const bool flow_control_invariant_; + // If this is set to false, the session will ignore peer GOAWAYs and + // allow the creation of outgoing streams regardless of the high + // chance they will fail. + bool respect_goaway_; DISALLOW_COPY_AND_ASSIGN(QuicSession); }; diff --git a/chromium/net/quic/core/quic_session_test.cc b/chromium/net/quic/core/quic_session_test.cc index a5451e79170..a5025626fb9 100644 --- a/chromium/net/quic/core/quic_session_test.cc +++ b/chromium/net/quic/core/quic_session_test.cc @@ -13,14 +13,15 @@ #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/crypto/null_encrypter.h" #include "net/quic/core/quic_crypto_stream.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_stream.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_map_util.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_str_cat.h" #include "net/quic/platform/api/quic_string_piece.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_config_peer.h" #include "net/quic/test_tools/quic_connection_peer.h" #include "net/quic/test_tools/quic_flow_controller_peer.h" @@ -29,11 +30,9 @@ #include "net/quic/test_tools/quic_spdy_stream_peer.h" #include "net/quic/test_tools/quic_stream_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "net/spdy/spdy_framer.h" +#include "net/spdy/core/spdy_framer.h" #include "net/test/gtest_util.h" -#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock_mutant.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; using testing::CreateFunctor; @@ -73,6 +72,10 @@ class TestCryptoStream : public QuicCryptoStream { session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); } + void set_encryption_established(bool value) { + encryption_established_ = value; + } + MOCK_METHOD0(OnCanWrite, void()); }; @@ -125,7 +128,13 @@ class TestSession : public QuicSpdySession { ~TestSession() override { delete connection(); } - TestCryptoStream* GetCryptoStream() override { return &crypto_stream_; } + TestCryptoStream* GetMutableCryptoStream() override { + return &crypto_stream_; + } + + const TestCryptoStream* GetCryptoStream() const override { + return &crypto_stream_; + } TestStream* CreateOutgoingDynamicStream(SpdyPriority priority) override { TestStream* stream = new TestStream(GetNextOutgoingStreamId(), this); @@ -154,6 +163,15 @@ class TestSession : public QuicSpdySession { bool ShouldCreateOutgoingDynamicStream() override { return true; } + TestStream* MaybeCreateOutgoingDynamicStream(SpdyPriority priority) override { + return static_cast<TestStream*>( + QuicSpdySession::MaybeCreateOutgoingDynamicStream(priority)); + } + + std::unique_ptr<QuicStream> CreateStream(QuicStreamId id) override { + return QuicMakeUnique<TestStream>(id, this); + } + bool IsClosedStream(QuicStreamId id) { return QuicSession::IsClosedStream(id); } @@ -167,12 +185,13 @@ class TestSession : public QuicSpdySession { QuicStreamId id, QuicIOVector data, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) override { + bool fin = state != NO_FIN; QuicConsumedData consumed(data.total_length, fin); if (!writev_consumes_all_data_) { - consumed = QuicSession::WritevData(stream, id, data, offset, fin, + consumed = QuicSession::WritevData(stream, id, data, offset, state, std::move(ack_listener)); } stream->set_stream_bytes_written(stream->stream_bytes_written() + @@ -194,9 +213,8 @@ class TestSession : public QuicSpdySession { if (stream->id() != kCryptoStreamId) { this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); } - QuicConsumedData consumed = - WritevData(stream, stream->id(), MakeIOVector("not empty", &iov), 0, - true, nullptr); + QuicConsumedData consumed = WritevData( + stream, stream->id(), MakeIOVector("not empty", &iov), 0, FIN, nullptr); return consumed; } @@ -206,7 +224,7 @@ class TestSession : public QuicSpdySession { iov.iov_base = nullptr; // should not be read. iov.iov_len = static_cast<size_t>(bytes); return WritevData(stream, stream->id(), QuicIOVector(&iov, 1, bytes), 0, - true, nullptr); + FIN, nullptr); } using QuicSession::PostProcessAfterData; @@ -217,7 +235,7 @@ class TestSession : public QuicSpdySession { bool writev_consumes_all_data_; }; -class QuicSessionTestBase : public ::testing::TestWithParam<QuicVersion> { +class QuicSessionTestBase : public QuicTestWithParam<QuicVersion> { protected: explicit QuicSessionTestBase(Perspective perspective) : connection_( @@ -258,6 +276,9 @@ class QuicSessionTestBase : public ::testing::TestWithParam<QuicVersion> { "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr" "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo "; connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); + if (FLAGS_quic_reloadable_flag_quic_refactor_stream_creation) { + session_.GetMutableCryptoStream()->set_encryption_established(true); + } } void CheckClosedStreams() { @@ -278,7 +299,16 @@ class QuicSessionTestBase : public ::testing::TestWithParam<QuicVersion> { QuicVersion version() const { return connection_->version(); } - QuicFlagSaver flags_; // Save/restore all QUIC flag values. + QuicStreamId GetNthClientInitiatedId(int n) { + return QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, n); + } + + QuicStreamId GetNthServerInitiatedId(int n) { + return QuicSpdySessionPeer::GetNthServerInitiatedStreamId(session_, n); + } + + QuicStreamId NextId() { return QuicSpdySessionPeer::NextStreamId(session_); } + MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; StrictMock<MockQuicConnection>* connection_; @@ -304,7 +334,7 @@ TEST_P(QuicSessionTestServer, PeerAddress) { TEST_P(QuicSessionTestServer, IsCryptoHandshakeConfirmed) { EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed()); CryptoHandshakeMessage message; - session_.GetCryptoStream()->OnHandshakeMessage(message); + session_.GetMutableCryptoStream()->OnHandshakeMessage(message); EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed()); } @@ -326,20 +356,21 @@ TEST_P(QuicSessionTestServer, AvailableStreams) { TEST_P(QuicSessionTestServer, IsClosedStreamLocallyCreated) { TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority); - EXPECT_EQ(2u, stream2->id()); - TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority); - EXPECT_EQ(4u, stream4->id()); + EXPECT_EQ(GetNthServerInitiatedId(0), stream2->id()); + QuicSpdyStream* stream4 = + session_.CreateOutgoingDynamicStream(kDefaultPriority); + EXPECT_EQ(GetNthServerInitiatedId(1), stream4->id()); CheckClosedStreams(); - CloseStream(4); + CloseStream(GetNthServerInitiatedId(0)); CheckClosedStreams(); - CloseStream(2); + CloseStream(GetNthServerInitiatedId(1)); CheckClosedStreams(); } TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) { - QuicStreamId stream_id1 = kClientDataStreamId1; - QuicStreamId stream_id2 = kClientDataStreamId2; + QuicStreamId stream_id1 = GetNthClientInitiatedId(0); + QuicStreamId stream_id2 = GetNthClientInitiatedId(1); session_.GetOrCreateDynamicStream(stream_id1); session_.GetOrCreateDynamicStream(stream_id2); @@ -356,7 +387,7 @@ TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) { } TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) { - QuicStreamId stream_id = kClientDataStreamId1; + QuicStreamId stream_id = GetNthClientInitiatedId(0); session_.GetOrCreateDynamicStream(stream_id); EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); EXPECT_NE(nullptr, @@ -365,11 +396,11 @@ TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) { } TEST_P(QuicSessionTestServer, TooManyAvailableStreams) { - QuicStreamId stream_id1 = kClientDataStreamId1; + QuicStreamId stream_id1 = GetNthClientInitiatedId(0); QuicStreamId stream_id2; EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1)); // A stream ID which is too large to create. - stream_id2 = stream_id1 + 2 * session_.MaxAvailableStreams() + 4; + stream_id2 = GetNthClientInitiatedId(2 * session_.MaxAvailableStreams() + 4); EXPECT_CALL(*connection_, CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _)); EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2)); @@ -379,7 +410,7 @@ TEST_P(QuicSessionTestServer, ManyAvailableStreams) { // When max_open_streams_ is 200, should be able to create 200 streams // out-of-order, that is, creating the one with the largest stream ID first. QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200); - QuicStreamId stream_id = kClientDataStreamId1; + QuicStreamId stream_id = GetNthClientInitiatedId(0); // Create one stream. session_.GetOrCreateDynamicStream(stream_id); EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); @@ -393,8 +424,10 @@ TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) { // Close the stream. EXPECT_CALL(*connection_, SendRstStream(closed_stream_id, _, _)); stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD); + string msg = + QuicStrCat("Marking unknown stream ", closed_stream_id, " blocked."); EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id), - "Marking unknown stream 2 blocked."); + msg); } TEST_P(QuicSessionTestServer, OnCanWrite) { @@ -525,7 +558,7 @@ TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) { EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)) .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0))); } - session_.GetCryptoStream()->OnHandshakeMessage(msg); + session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); // Drive congestion control manually. MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>; @@ -680,7 +713,7 @@ TEST_P(QuicSessionTestServer, BufferedHandshake) { // Due to prioritization, we *should* be asked to write the crypto stream // first. // Don't re-register the crypto stream (which signals complete writing). - TestCryptoStream* crypto_stream = session_.GetCryptoStream(); + TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream(); EXPECT_CALL(*crypto_stream, OnCanWrite()); EXPECT_CALL(*stream2, OnCanWrite()) @@ -754,7 +787,7 @@ TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) { // The crypto and headers streams should be called even though we are // connection flow control blocked. - TestCryptoStream* crypto_stream = session_.GetCryptoStream(); + TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream(); EXPECT_CALL(*crypto_stream, OnCanWrite()); TestHeadersStream* headers_stream = new TestHeadersStream(&session_); QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream); @@ -789,20 +822,21 @@ TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) { EXPECT_EQ(kInitialIdleTimeoutSecs + 3, QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); CryptoHandshakeMessage msg; - session_.GetCryptoStream()->OnHandshakeMessage(msg); + session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); EXPECT_EQ(kMaximumIdleTimeoutSecs + 3, QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); } TEST_P(QuicSessionTestServer, RstStreamBeforeHeadersDecompressed) { // Send two bytes of payload. - QuicStreamFrame data1(kClientDataStreamId1, false, 0, QuicStringPiece("HT")); + QuicStreamFrame data1(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece("HT")); session_.OnStreamFrame(data1); EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams()); - EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, _, _)); - QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, - 0); + EXPECT_CALL(*connection_, SendRstStream(GetNthClientInitiatedId(0), _, _)); + QuicRstStreamFrame rst1(GetNthClientInitiatedId(0), + QUIC_ERROR_PROCESSING_STREAM, 0); session_.OnRstStream(rst1); EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); // Connection should remain alive. @@ -836,7 +870,7 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) { // Now complete the crypto handshake, resulting in an increased flow control // send window. CryptoHandshakeMessage msg; - session_.GetCryptoStream()->OnHandshakeMessage(msg); + session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); // Stream is now unblocked. EXPECT_FALSE(stream2->flow_controller()->IsBlocked()); @@ -848,7 +882,7 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) { // Test that if the crypto stream is flow control blocked, then if the SHLO // contains a larger send window offset, the stream becomes unblocked. session_.set_writev_consumes_all_data(true); - TestCryptoStream* crypto_stream = session_.GetCryptoStream(); + TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream(); EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); @@ -881,7 +915,7 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) { // Now complete the crypto handshake, resulting in an increased flow control // send window. CryptoHandshakeMessage msg; - session_.GetCryptoStream()->OnHandshakeMessage(msg); + session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); // Stream is now unblocked and will no longer have buffered data. EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); @@ -900,7 +934,7 @@ TEST_P(QuicSessionTestServer, // Test that if the header stream is flow control blocked, then if the SHLO // contains a larger send window offset, the stream becomes unblocked. session_.set_writev_consumes_all_data(true); - TestCryptoStream* crypto_stream = session_.GetCryptoStream(); + TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream(); EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); @@ -935,7 +969,7 @@ TEST_P(QuicSessionTestServer, // Now complete the crypto handshake, resulting in an increased flow control // send window. CryptoHandshakeMessage msg; - session_.GetCryptoStream()->OnHandshakeMessage(msg); + session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); // Stream is now unblocked and will no longer have buffered data. EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); @@ -1094,7 +1128,6 @@ TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) { // Test negotiation of custom server initial flow control window. TEST_P(QuicSessionTestServer, CustomFlowControlWindow) { - FLAGS_quic_reloadable_flag_quic_large_ifw_options = true; QuicTagVector copt; copt.push_back(kIFW7); QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt); @@ -1152,12 +1185,12 @@ TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) { // with a FIN or RST then we send an RST to refuse streams. const QuicStreamId kMaxStreams = 5; QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams); - const QuicStreamId kFirstStreamId = kClientDataStreamId1; - const QuicStreamId kFinalStreamId = kClientDataStreamId1 + 2 * kMaxStreams; - + const QuicStreamId kFirstStreamId = GetNthClientInitiatedId(0); + const QuicStreamId kFinalStreamId = GetNthClientInitiatedId(kMaxStreams); // Create kMaxStreams data streams, and close them all without receiving a // FIN or a RST_STREAM from the client. - for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += 2) { + const QuicStreamId kNextId = QuicSpdySessionPeer::NextStreamId(session_); + for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += kNextId) { QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT")); session_.OnStreamFrame(data1); // EXPECT_EQ(1u, session_.GetNumOpenStreams()); @@ -1186,10 +1219,10 @@ TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) { QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams); // Create kMaxStreams + 1 data streams, and mark them draining. - const QuicStreamId kFirstStreamId = kClientDataStreamId1; + const QuicStreamId kFirstStreamId = GetNthClientInitiatedId(0); const QuicStreamId kFinalStreamId = - kClientDataStreamId1 + 2 * kMaxStreams + 1; - for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += 2) { + GetNthClientInitiatedId(2 * kMaxStreams + 1); + for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += NextId()) { QuicStreamFrame data1(i, true, 0, QuicStringPiece("HT")); session_.OnStreamFrame(data1); EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams()); diff --git a/chromium/net/quic/core/quic_simple_buffer_allocator_test.cc b/chromium/net/quic/core/quic_simple_buffer_allocator_test.cc index 69cfad9d1fb..3549997006c 100644 --- a/chromium/net/quic/core/quic_simple_buffer_allocator_test.cc +++ b/chromium/net/quic/core/quic_simple_buffer_allocator_test.cc @@ -5,27 +5,28 @@ #include "net/quic/core/quic_simple_buffer_allocator.h" #include "net/quic/core/quic_packets.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" using ::testing::Eq; namespace net { namespace { -TEST(SimpleBufferAllocatorTest, NewDelete) { +class SimpleBufferAllocatorTest : public QuicTest {}; + +TEST_F(SimpleBufferAllocatorTest, NewDelete) { SimpleBufferAllocator alloc; char* buf = alloc.New(4); EXPECT_NE(nullptr, buf); alloc.Delete(buf); } -TEST(SimpleBufferAllocatorTest, DeleteNull) { +TEST_F(SimpleBufferAllocatorTest, DeleteNull) { SimpleBufferAllocator alloc; alloc.Delete(nullptr); } -TEST(SimpleBufferAllocatorTest, StoreInUniqueStreamBuffer) { +TEST_F(SimpleBufferAllocatorTest, StoreInUniqueStreamBuffer) { SimpleBufferAllocator alloc; UniqueStreamBuffer buf = NewStreamBuffer(&alloc, 4); buf.reset(); diff --git a/chromium/net/quic/core/quic_socket_address_coder_test.cc b/chromium/net/quic/core/quic_socket_address_coder_test.cc index 548fde2eb7a..5a36b5b71a3 100644 --- a/chromium/net/quic/core/quic_socket_address_coder_test.cc +++ b/chromium/net/quic/core/quic_socket_address_coder_test.cc @@ -4,14 +4,16 @@ #include "net/quic/core/quic_socket_address_coder.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" using std::string; namespace net { namespace test { -TEST(QuicSocketAddressCoderTest, EncodeIPv4) { +class QuicSocketAddressCoderTest : public QuicTest {}; + +TEST_F(QuicSocketAddressCoderTest, EncodeIPv4) { QuicIpAddress ip; ip.FromString("4.31.198.44"); QuicSocketAddressCoder coder(QuicSocketAddress(ip, 0x1234)); @@ -20,7 +22,7 @@ TEST(QuicSocketAddressCoderTest, EncodeIPv4) { EXPECT_EQ(expected, serialized); } -TEST(QuicSocketAddressCoderTest, EncodeIPv6) { +TEST_F(QuicSocketAddressCoderTest, EncodeIPv6) { QuicIpAddress ip; ip.FromString("2001:700:300:1800::f"); QuicSocketAddressCoder coder(QuicSocketAddress(ip, 0x5678)); @@ -34,7 +36,7 @@ TEST(QuicSocketAddressCoderTest, EncodeIPv6) { EXPECT_EQ(expected, serialized); } -TEST(QuicSocketAddressCoderTest, DecodeIPv4) { +TEST_F(QuicSocketAddressCoderTest, DecodeIPv4) { string serialized("\x02\x00\x04\x1f\xc6\x2c\x34\x12", 8); QuicSocketAddressCoder coder; ASSERT_TRUE(coder.Decode(serialized.data(), serialized.length())); @@ -44,7 +46,7 @@ TEST(QuicSocketAddressCoderTest, DecodeIPv4) { EXPECT_EQ(0x1234, coder.port()); } -TEST(QuicSocketAddressCoderTest, DecodeIPv6) { +TEST_F(QuicSocketAddressCoderTest, DecodeIPv6) { string serialized( "\x0a\x00" "\x20\x01\x07\x00\x03\x00\x18\x00" @@ -62,7 +64,7 @@ TEST(QuicSocketAddressCoderTest, DecodeIPv6) { EXPECT_EQ(0x5678, coder.port()); } -TEST(QuicSocketAddressCoderTest, DecodeBad) { +TEST_F(QuicSocketAddressCoderTest, DecodeBad) { string serialized( "\x0a\x00" "\x20\x01\x07\x00\x03\x00\x18\x00" @@ -95,7 +97,7 @@ TEST(QuicSocketAddressCoderTest, DecodeBad) { EXPECT_TRUE(serialized.empty()); } -TEST(QuicSocketAddressCoderTest, EncodeAndDecode) { +TEST_F(QuicSocketAddressCoderTest, EncodeAndDecode) { struct { const char* ip_literal; uint16_t port; diff --git a/chromium/net/quic/core/quic_spdy_session.cc b/chromium/net/quic/core/quic_spdy_session.cc index 61d16c9020a..ec533eade73 100644 --- a/chromium/net/quic/core/quic_spdy_session.cc +++ b/chromium/net/quic/core/quic_spdy_session.cc @@ -9,11 +9,13 @@ #include <string> #include <utility> -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_headers_stream.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_str_cat.h" +#include "net/quic/platform/api/quic_text_utils.h" using std::string; @@ -393,7 +395,35 @@ void QuicSpdySession::OnStreamHeaderList(QuicStreamId stream_id, size_t frame_len, const QuicHeaderList& header_list) { QuicSpdyStream* stream = GetSpdyDataStream(stream_id); - if (!stream) { + if (stream == nullptr) { + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_final_offset_from_trailers, 1, + 3); + if (FLAGS_quic_reloadable_flag_quic_final_offset_from_trailers) { + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_final_offset_from_trailers, 2, + 3); + // The stream no longer exists, but trailing headers may contain the final + // byte offset necessary for flow control and open stream accounting. + size_t final_byte_offset = 0; + for (const auto& header : header_list) { + const string& header_key = header.first; + const string& header_value = header.second; + if (header_key == kFinalOffsetHeaderKey) { + if (!QuicTextUtils::StringToSizeT(header_value, &final_byte_offset)) { + connection()->CloseConnection( + QUIC_INVALID_HEADERS_STREAM_DATA, + "Trailers are malformed (no final offset)", + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + return; + } + DVLOG(1) << "Received final byte offset in trailers for stream " + << stream_id << ", which no longer exists."; + OnFinalByteOffsetReceived(stream_id, final_byte_offset); + QUIC_FLAG_COUNT_N( + quic_reloadable_flag_quic_final_offset_from_trailers, 3, 3); + } + } + } + // It's quite possible to receive headers after a stream has been reset. return; } @@ -609,10 +639,8 @@ void QuicSpdySession::OnConfigNegotiated() { kStreamReceiveWindowLimit); } - if (version > QUIC_VERSION_34) { - server_push_enabled_ = - FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default; - } + server_push_enabled_ = + FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default; } void QuicSpdySession::OnStreamFrameData(QuicStreamId stream_id, @@ -775,4 +803,20 @@ void QuicSpdySession::CloseConnectionWithDetails(QuicErrorCode error, error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); } +QuicSpdyStream* QuicSpdySession::MaybeCreateIncomingDynamicStream( + QuicStreamId id) { + return static_cast<QuicSpdyStream*>( + QuicSession::MaybeCreateIncomingDynamicStream(id)); +} + +QuicSpdyStream* QuicSpdySession::MaybeCreateOutgoingDynamicStream( + SpdyPriority priority) { + auto* stream = static_cast<QuicSpdyStream*>( + QuicSession::MaybeCreateOutgoingDynamicStream(priority)); + if (stream) { + stream->SetPriority(priority); + } + return stream; +} + } // namespace net diff --git a/chromium/net/quic/core/quic_spdy_session.h b/chromium/net/quic/core/quic_spdy_session.h index 7ec0a01c1d2..17115a76139 100644 --- a/chromium/net/quic/core/quic_spdy_session.h +++ b/chromium/net/quic/core/quic_spdy_session.h @@ -163,6 +163,9 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession : public QuicSession { size_t set_max_uncompressed_header_bytes); protected: + // TODO(ckrasic) - remove these two when + // FLAGS_quic_reloadable_flag_quic_refactor_stream_creation is + // deprecated. // Override CreateIncomingDynamicStream() and CreateOutgoingDynamicStream() // with QuicSpdyStream return type to make sure that all data streams are // QuicSpdyStreams. @@ -170,8 +173,16 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession : public QuicSession { QuicSpdyStream* CreateOutgoingDynamicStream(SpdyPriority priority) override = 0; + QuicSpdyStream* MaybeCreateIncomingDynamicStream(QuicStreamId id) override; + QuicSpdyStream* MaybeCreateOutgoingDynamicStream( + SpdyPriority priority) override; + QuicSpdyStream* GetSpdyDataStream(const QuicStreamId stream_id); + // TODO(ckrasic) - remove these two when + // FLAGS_quic_reloadable_flag_quic_refactor_stream_creation is + // depreacted. + // If an incoming stream can be created, return true. virtual bool ShouldCreateIncomingDynamicStream(QuicStreamId id) = 0; diff --git a/chromium/net/quic/core/quic_spdy_stream.cc b/chromium/net/quic/core/quic_spdy_stream.cc index 76c480a5afe..a1034f0664c 100644 --- a/chromium/net/quic/core/quic_spdy_stream.cc +++ b/chromium/net/quic/core/quic_spdy_stream.cc @@ -27,7 +27,6 @@ QuicSpdyStream::QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session) : QuicStream(id, spdy_session), spdy_session_(spdy_session), visitor_(nullptr), - allow_bidirectional_data_(false), headers_decompressed_(false), priority_(kDefaultPriority), trailers_decompressed_(false), diff --git a/chromium/net/quic/core/quic_spdy_stream.h b/chromium/net/quic/core/quic_spdy_stream.h index 247af4d7509..2e4d2fca144 100644 --- a/chromium/net/quic/core/quic_spdy_stream.h +++ b/chromium/net/quic/core/quic_spdy_stream.h @@ -17,14 +17,14 @@ #include "base/macros.h" #include "net/base/iovec.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_header_list.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_stream.h" #include "net/quic/core/quic_stream_sequencer.h" #include "net/quic/platform/api/quic_export.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_socket_address.h" -#include "net/spdy/spdy_framer.h" +#include "net/spdy/core/spdy_framer.h" namespace net { @@ -174,15 +174,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream : public QuicStream { // will be available. bool IsClosed() { return sequencer()->IsClosed(); } - void set_allow_bidirectional_data(bool value) { - allow_bidirectional_data_ = value; - } - - bool allow_bidirectional_data() const { - return FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming || - allow_bidirectional_data_; - } - using QuicStream::CloseWriteSide; protected: @@ -214,9 +205,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream : public QuicStream { QuicSpdySession* spdy_session_; Visitor* visitor_; - // If true, allow sending of a request to continue while the response is - // arriving. - bool allow_bidirectional_data_; // True if the headers have been completely decompressed. bool headers_decompressed_; // The priority of the stream, once parsed. diff --git a/chromium/net/quic/core/quic_spdy_stream_test.cc b/chromium/net/quic/core/quic_spdy_stream_test.cc index a34b0c78244..63aaa89671c 100644 --- a/chromium/net/quic/core/quic_spdy_stream_test.cc +++ b/chromium/net/quic/core/quic_spdy_stream_test.cc @@ -13,13 +13,12 @@ #include "net/quic/core/spdy_utils.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_string_piece.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/quic/test_tools/quic_flow_controller_peer.h" -#include "net/quic/test_tools/quic_session_peer.h" +#include "net/quic/test_tools/quic_spdy_session_peer.h" #include "net/quic/test_tools/quic_stream_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; using testing::AnyNumber; @@ -64,7 +63,7 @@ class TestStream : public QuicSpdyStream { string data_; }; -class QuicSpdyStreamTest : public ::testing::TestWithParam<QuicVersion> { +class QuicSpdyStreamTest : public QuicTestWithParam<QuicVersion> { public: QuicSpdyStreamTest() { headers_[":host"] = "www.google.com"; @@ -101,10 +100,10 @@ class QuicSpdyStreamTest : public ::testing::TestWithParam<QuicVersion> { &helper_, &alarm_factory_, Perspective::IS_SERVER, SupportedVersions(GetParam())); session_.reset(new testing::StrictMock<MockQuicSpdySession>(connection_)); - stream_ = new TestStream(kClientDataStreamId1, session_.get(), + stream_ = new TestStream(GetNthClientInitiatedId(0), session_.get(), stream_should_process_data); session_->ActivateStream(QuicWrapUnique(stream_)); - stream2_ = new TestStream(kClientDataStreamId2, session_.get(), + stream2_ = new TestStream(GetNthClientInitiatedId(1), session_.get(), stream_should_process_data); session_->ActivateStream(QuicWrapUnique(stream2_)); } @@ -115,8 +114,11 @@ class QuicSpdyStreamTest : public ::testing::TestWithParam<QuicVersion> { return h; } + QuicStreamId GetNthClientInitiatedId(int n) { + return QuicSpdySessionPeer::GetNthClientInitiatedStreamId(*session_, n); + } + protected: - QuicFlagSaver flags_; // Save/restore all QUIC flag values. MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; MockQuicConnection* connection_; @@ -250,7 +252,8 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBody) { QuicHeaderList headers = ProcessHeaders(false, headers_); EXPECT_EQ(headers, stream_->header_list()); stream_->ConsumeHeaderList(); - QuicStreamFrame frame(kClientDataStreamId1, false, 0, QuicStringPiece(body)); + QuicStreamFrame frame(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece(body)); stream_->OnStreamFrame(frame); EXPECT_EQ(QuicHeaderList(), stream_->header_list()); EXPECT_EQ(body, stream_->data()); @@ -268,7 +271,7 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragments) { size_t remaining_data = body.size() - offset; QuicStringPiece fragment(body.data() + offset, std::min(fragment_size, remaining_data)); - QuicStreamFrame frame(kClientDataStreamId1, false, offset, + QuicStreamFrame frame(GetNthClientInitiatedId(0), false, offset, QuicStringPiece(fragment)); stream_->OnStreamFrame(frame); } @@ -286,13 +289,13 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragmentsSplit) { stream_->ConsumeHeaderList(); QuicStringPiece fragment1(body.data(), split_point); - QuicStreamFrame frame1(kClientDataStreamId1, false, 0, + QuicStreamFrame frame1(GetNthClientInitiatedId(0), false, 0, QuicStringPiece(fragment1)); stream_->OnStreamFrame(frame1); QuicStringPiece fragment2(body.data() + split_point, body.size() - split_point); - QuicStreamFrame frame2(kClientDataStreamId1, false, split_point, + QuicStreamFrame frame2(GetNthClientInitiatedId(0), false, split_point, QuicStringPiece(fragment2)); stream_->OnStreamFrame(frame2); @@ -306,7 +309,8 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyReadv) { string body = "this is the body"; ProcessHeaders(false, headers_); - QuicStreamFrame frame(kClientDataStreamId1, false, 0, QuicStringPiece(body)); + QuicStreamFrame frame(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece(body)); stream_->OnStreamFrame(frame); stream_->ConsumeHeaderList(); @@ -327,7 +331,8 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyMarkConsumed) { string body = "this is the body"; ProcessHeaders(false, headers_); - QuicStreamFrame frame(kClientDataStreamId1, false, 0, QuicStringPiece(body)); + QuicStreamFrame frame(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece(body)); stream_->OnStreamFrame(frame); stream_->ConsumeHeaderList(); @@ -346,7 +351,8 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyIncrementalReadv) { string body = "this is the body"; ProcessHeaders(false, headers_); - QuicStreamFrame frame(kClientDataStreamId1, false, 0, QuicStringPiece(body)); + QuicStreamFrame frame(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece(body)); stream_->OnStreamFrame(frame); stream_->ConsumeHeaderList(); @@ -367,7 +373,8 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) { string body = "this is the body"; ProcessHeaders(false, headers_); - QuicStreamFrame frame(kClientDataStreamId1, false, 0, QuicStringPiece(body)); + QuicStreamFrame frame(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece(body)); stream_->OnStreamFrame(frame); stream_->ConsumeHeaderList(); @@ -404,7 +411,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) { const uint64_t kOverflow = 15; string body(kWindow + kOverflow, 'a'); - EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)); + EXPECT_CALL(*connection_, SendBlocked(GetNthClientInitiatedId(0))); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(kWindow, true))); stream_->WriteOrBufferData(body, false, nullptr); @@ -442,7 +449,8 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) { string body(kWindow / 3, 'a'); ProcessHeaders(false, headers_); - QuicStreamFrame frame1(kClientDataStreamId1, false, 0, QuicStringPiece(body)); + QuicStreamFrame frame1(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece(body)); stream_->OnStreamFrame(frame1); EXPECT_EQ(kWindow - (kWindow / 3), QuicFlowControllerPeer::ReceiveWindowSize( stream_->flow_controller())); @@ -450,7 +458,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) { // Now receive another frame which results in the receive window being over // half full. This should all be buffered, decreasing the receive window but // not sending WINDOW_UPDATE. - QuicStreamFrame frame2(kClientDataStreamId1, false, kWindow / 3, + QuicStreamFrame frame2(GetNthClientInitiatedId(0), false, kWindow / 3, QuicStringPiece(body)); stream_->OnStreamFrame(frame2); EXPECT_EQ( @@ -478,7 +486,8 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) { ProcessHeaders(false, headers_); stream_->ConsumeHeaderList(); - QuicStreamFrame frame1(kClientDataStreamId1, false, 0, QuicStringPiece(body)); + QuicStreamFrame frame1(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece(body)); stream_->OnStreamFrame(frame1); EXPECT_EQ(kWindow - (kWindow / 3), QuicFlowControllerPeer::ReceiveWindowSize( stream_->flow_controller())); @@ -487,10 +496,10 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) { // half full. This will trigger the stream to increase its receive window // offset and send a WINDOW_UPDATE. The result will be again an available // window of kWindow bytes. - QuicStreamFrame frame2(kClientDataStreamId1, false, kWindow / 3, + QuicStreamFrame frame2(GetNthClientInitiatedId(0), false, kWindow / 3, QuicStringPiece(body)); EXPECT_CALL(*connection_, - SendWindowUpdate(kClientDataStreamId1, + SendWindowUpdate(GetNthClientInitiatedId(0), QuicFlowControllerPeer::ReceiveWindowOffset( stream_->flow_controller()) + 2 * kWindow / 3)); @@ -532,22 +541,25 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) { // Each stream gets a quarter window of data. This should not trigger a // WINDOW_UPDATE for either stream, nor for the connection. string body(kWindow / 4, 'a'); - QuicStreamFrame frame1(kClientDataStreamId1, false, 0, QuicStringPiece(body)); + QuicStreamFrame frame1(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece(body)); stream_->OnStreamFrame(frame1); - QuicStreamFrame frame2(kClientDataStreamId2, false, 0, QuicStringPiece(body)); + QuicStreamFrame frame2(GetNthClientInitiatedId(1), false, 0, + QuicStringPiece(body)); stream2_->OnStreamFrame(frame2); // Now receive a further single byte on one stream - again this does not // trigger a stream WINDOW_UPDATE, but now the connection flow control window // is over half full and thus a connection WINDOW_UPDATE is sent. - EXPECT_CALL(*connection_, SendWindowUpdate(kClientDataStreamId1, _)).Times(0); - EXPECT_CALL(*connection_, SendWindowUpdate(kClientDataStreamId2, _)).Times(0); + EXPECT_CALL(*connection_, SendWindowUpdate(GetNthClientInitiatedId(0), _)) + .Times(0); + EXPECT_CALL(*connection_, SendWindowUpdate(GetNthClientInitiatedId(1), _)) + .Times(0); EXPECT_CALL(*connection_, - SendWindowUpdate(0, - QuicFlowControllerPeer::ReceiveWindowOffset( - session_->flow_controller()) + - 1 + kWindow / 2)); - QuicStreamFrame frame3(kClientDataStreamId1, false, (kWindow / 4), + SendWindowUpdate(0, QuicFlowControllerPeer::ReceiveWindowOffset( + session_->flow_controller()) + + 1 + kWindow / 2)); + QuicStreamFrame frame3(GetNthClientInitiatedId(0), false, (kWindow / 4), QuicStringPiece("a")); stream_->OnStreamFrame(frame3); } @@ -569,7 +581,8 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlViolation) { // Receive data to overflow the window, violating flow control. string body(kWindow + 1, 'a'); - QuicStreamFrame frame(kClientDataStreamId1, false, 0, QuicStringPiece(body)); + QuicStreamFrame frame(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece(body)); EXPECT_CALL(*connection_, CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _)); stream_->OnStreamFrame(frame); @@ -607,7 +620,8 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlViolation) { // Send enough data to overflow the connection level flow control window. string body(kConnectionWindow + 1, 'a'); EXPECT_LT(body.size(), kStreamWindow); - QuicStreamFrame frame(kClientDataStreamId1, false, 0, QuicStringPiece(body)); + QuicStreamFrame frame(GetNthClientInitiatedId(0), false, 0, + QuicStringPiece(body)); EXPECT_CALL(*connection_, CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _)); @@ -629,7 +643,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) { string body = ""; bool fin = true; - EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)).Times(0); + EXPECT_CALL(*connection_, SendBlocked(GetNthClientInitiatedId(0))).Times(0); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(0, fin))); @@ -711,7 +725,7 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) { EXPECT_FALSE(stream_->IsDoneReading()); // Receive and consume body. - QuicStreamFrame frame(kClientDataStreamId1, /*fin=*/false, 0, body); + QuicStreamFrame frame(GetNthClientInitiatedId(0), /*fin=*/false, 0, body); stream_->OnStreamFrame(frame); EXPECT_EQ(body, stream_->data()); EXPECT_TRUE(stream_->IsDoneReading()); @@ -792,7 +806,7 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterBodyWithFin) { stream_->ConsumeHeaderList(); // Receive body data, with FIN. - QuicStreamFrame frame(kClientDataStreamId1, /*fin=*/true, 0, "body"); + QuicStreamFrame frame(GetNthClientInitiatedId(0), /*fin=*/true, 0, "body"); stream_->OnStreamFrame(frame); // Receive trailing headers after FIN already received. @@ -816,7 +830,7 @@ TEST_P(QuicSpdyStreamTest, ClosingStreamWithNoTrailers) { // Receive and consume body with FIN set, and no trailers. const string kBody = string(1024, 'x'); - QuicStreamFrame frame(kClientDataStreamId1, /*fin=*/true, 0, kBody); + QuicStreamFrame frame(GetNthClientInitiatedId(0), /*fin=*/true, 0, kBody); stream_->OnStreamFrame(frame); EXPECT_TRUE(stream_->IsDoneReading()); diff --git a/chromium/net/quic/core/quic_stream.cc b/chromium/net/quic/core/quic_stream.cc index a7ab1afe662..733a805084f 100644 --- a/chromium/net/quic/core/quic_stream.cc +++ b/chromium/net/quic/core/quic_stream.cc @@ -70,12 +70,11 @@ QuicStream::QuicStream(QuicStreamId id, QuicSession* session) GetReceivedFlowControlWindow(session), GetInitialStreamFlowControlWindowToSend(session), session_->flow_controller()->auto_tune_receive_window(), - session_->flow_control_invariant() - ? session_->flow_controller() - : nullptr), + session_->flow_controller()), connection_flow_controller_(session_->flow_controller()), stream_contributes_to_connection_flow_control_(true), - busy_counter_(0) { + busy_counter_(0), + add_random_padding_after_fin_(false) { SetFromConfig(); } @@ -358,7 +357,11 @@ QuicConsumedData QuicStream::WritevDataInner( QuicStreamOffset offset, bool fin, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { - return session()->WritevData(this, id(), iov, offset, fin, + StreamSendingState state = fin ? FIN : NO_FIN; + if (fin && add_random_padding_after_fin_) { + state = FIN_AND_PADDING; + } + return session()->WritevData(this, id(), iov, offset, state, std::move(ack_listener)); } @@ -485,4 +488,8 @@ void QuicStream::UpdateSendWindowOffset(QuicStreamOffset new_window) { } } +void QuicStream::AddRandomPaddingAfterFin() { + add_random_padding_after_fin_ = true; +} + } // namespace net diff --git a/chromium/net/quic/core/quic_stream.h b/chromium/net/quic/core/quic_stream.h index 5133fa9f301..df1ebf0277b 100644 --- a/chromium/net/quic/core/quic_stream.h +++ b/chromium/net/quic/core/quic_stream.h @@ -186,6 +186,9 @@ class QUIC_EXPORT_PRIVATE QuicStream { bool fin, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); + // Adds random padding after the fin is consumed for this stream. + void AddRandomPaddingAfterFin(); + protected: // Sends as many bytes in the first |count| buffers of |iov| to the connection // as the connection will consume. @@ -317,6 +320,10 @@ class QUIC_EXPORT_PRIVATE QuicStream { // For debugging only. size_t busy_counter_; + // Indicates whether paddings will be added after the fin is consumed for this + // stream. + bool add_random_padding_after_fin_; + DISALLOW_COPY_AND_ASSIGN(QuicStream); }; diff --git a/chromium/net/quic/core/quic_stream_sequencer_buffer.cc b/chromium/net/quic/core/quic_stream_sequencer_buffer.cc index 09fd43d31bb..3706d38805c 100644 --- a/chromium/net/quic/core/quic_stream_sequencer_buffer.cc +++ b/chromium/net/quic/core/quic_stream_sequencer_buffer.cc @@ -5,8 +5,9 @@ #include "net/quic/core/quic_stream_sequencer_buffer.h" #include "base/format_macros.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/core/quic_constants.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_str_cat.h" diff --git a/chromium/net/quic/core/quic_stream_sequencer_buffer_test.cc b/chromium/net/quic/core/quic_stream_sequencer_buffer_test.cc index 175c54f00be..88c9a0c391b 100644 --- a/chromium/net/quic/core/quic_stream_sequencer_buffer_test.cc +++ b/chromium/net/quic/core/quic_stream_sequencer_buffer_test.cc @@ -13,13 +13,12 @@ #include "base/macros.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_str_cat.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/quic_stream_sequencer_buffer_peer.h" #include "net/quic/test_tools/quic_test_utils.h" #include "net/test/gtest_util.h" -#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock_mutant.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; @@ -81,7 +80,6 @@ class QuicStreamSequencerBufferTest : public testing::Test { MockClock clock_; std::unique_ptr<QuicStreamSequencerBuffer> buffer_; std::unique_ptr<QuicStreamSequencerBufferPeer> helper_; - QuicFlagSaver flag_saver_; string error_details_; }; diff --git a/chromium/net/quic/core/quic_stream_sequencer_test.cc b/chromium/net/quic/core/quic_stream_sequencer_test.cc index a75ca27b0a7..f65394dc730 100644 --- a/chromium/net/quic/core/quic_stream_sequencer_test.cc +++ b/chromium/net/quic/core/quic_stream_sequencer_test.cc @@ -14,13 +14,13 @@ #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_string_piece.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" +#include "net/quic/test_tools/quic_spdy_session_peer.h" #include "net/quic/test_tools/quic_stream_sequencer_peer.h" #include "net/quic/test_tools/quic_test_utils.h" #include "net/test/gtest_util.h" -#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock_mutant.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; using testing::_; @@ -59,7 +59,7 @@ namespace { static const char kPayload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -class QuicStreamSequencerTest : public ::testing::Test { +class QuicStreamSequencerTest : public QuicTest { public: void ConsumeData(size_t num_bytes) { char buffer[1024]; @@ -570,13 +570,13 @@ TEST_F(QuicStreamSequencerTest, MarkConsumedWithMissingPacket) { TEST_F(QuicStreamSequencerTest, DontAcceptOverlappingFrames) { // The peer should never send us non-identical stream frames which contain // overlapping byte ranges - if they do, we close the connection. + QuicStreamId id = + QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0); - QuicStreamFrame frame1(kClientDataStreamId1, false, 1, - QuicStringPiece("hello")); + QuicStreamFrame frame1(id, false, 1, QuicStringPiece("hello")); sequencer_->OnStreamFrame(frame1); - QuicStreamFrame frame2(kClientDataStreamId1, false, 2, - QuicStringPiece("hello")); + QuicStreamFrame frame2(id, false, 2, QuicStringPiece("hello")); EXPECT_CALL(stream_, CloseConnectionWithDetails(QUIC_OVERLAPPING_STREAM_DATA, _)) .Times(1); @@ -670,7 +670,9 @@ TEST_F(QuicStreamSequencerTest, OnStreamFrameWithNullSource) { // connection with error. QuicStringPiece source; source.set(nullptr, 5u); - QuicStreamFrame frame(kClientDataStreamId1, false, 1, source); + QuicStreamFrame frame( + QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0), false, 1, + source); EXPECT_CALL(stream_, CloseConnectionWithDetails( QUIC_STREAM_SEQUENCER_INVALID_STATE, _)); sequencer_->OnStreamFrame(frame); diff --git a/chromium/net/quic/core/quic_stream_test.cc b/chromium/net/quic/core/quic_stream_test.cc index 4c7ade9206a..6e83daec66f 100644 --- a/chromium/net/quic/core/quic_stream_test.cc +++ b/chromium/net/quic/core/quic_stream_test.cc @@ -7,12 +7,13 @@ #include <memory> #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" #include "net/quic/core/quic_write_blocked_list.h" #include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_config_peer.h" #include "net/quic/test_tools/quic_connection_peer.h" #include "net/quic/test_tools/quic_flow_controller_peer.h" @@ -20,7 +21,6 @@ #include "net/quic/test_tools/quic_stream_peer.h" #include "net/quic/test_tools/quic_test_utils.h" #include "net/test/gtest_util.h" -#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock_mutant.h" using std::string; @@ -68,7 +68,7 @@ class TestStream : public QuicStream { string data_; }; -class QuicStreamTest : public ::testing::TestWithParam<bool> { +class QuicStreamTest : public QuicTestWithParam<bool> { public: QuicStreamTest() : initial_flow_control_window_bytes_(kMaxPacketSize), @@ -142,7 +142,7 @@ class QuicStreamTest : public ::testing::TestWithParam<bool> { QuicStreamId id, QuicIOVector /*iov*/, QuicStreamOffset /*offset*/, - bool /*fin*/, + StreamSendingState /*state*/, const QuicReferenceCountedPointer< QuicAckListenerInterface>& /*ack_listener*/) { session_->CloseStream(id); diff --git a/chromium/net/quic/core/quic_sustained_bandwidth_recorder_test.cc b/chromium/net/quic/core/quic_sustained_bandwidth_recorder_test.cc index a93b9db079b..3221ec49c39 100644 --- a/chromium/net/quic/core/quic_sustained_bandwidth_recorder_test.cc +++ b/chromium/net/quic/core/quic_sustained_bandwidth_recorder_test.cc @@ -6,13 +6,15 @@ #include "net/quic/core/quic_bandwidth.h" #include "net/quic/core/quic_time.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { namespace { -TEST(QuicSustainedBandwidthRecorderTest, BandwidthEstimates) { +class QuicSustainedBandwidthRecorderTest : public QuicTest {}; + +TEST_F(QuicSustainedBandwidthRecorderTest, BandwidthEstimates) { QuicSustainedBandwidthRecorder recorder; EXPECT_FALSE(recorder.HasEstimate()); @@ -91,7 +93,7 @@ TEST(QuicSustainedBandwidthRecorderTest, BandwidthEstimates) { EXPECT_EQ(recorder.MaxBandwidthTimestamp(), kSeconds); } -TEST(QuicSustainedBandwidthRecorderTest, SlowStart) { +TEST_F(QuicSustainedBandwidthRecorderTest, SlowStart) { // Verify that slow start status is correctly recorded. QuicSustainedBandwidthRecorder recorder; EXPECT_FALSE(recorder.HasEstimate()); diff --git a/chromium/net/quic/core/quic_tag_test.cc b/chromium/net/quic/core/quic_tag_test.cc index 92a51d7b185..7ddab1d6622 100644 --- a/chromium/net/quic/core/quic_tag_test.cc +++ b/chromium/net/quic/core/quic_tag_test.cc @@ -5,14 +5,15 @@ #include "net/quic/core/quic_tag.h" #include "net/quic/core/crypto/crypto_protocol.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" namespace net { namespace test { namespace { -TEST(QuicTagTest, TagToString) { +class QuicTagTest : public QuicTest {}; + +TEST_F(QuicTagTest, TagToString) { EXPECT_EQ("SCFG", QuicTagToString(kSCFG)); EXPECT_EQ("SNO ", QuicTagToString(kServerNonceTag)); EXPECT_EQ("CRT ", QuicTagToString(kCertificateTag)); @@ -22,7 +23,7 @@ TEST(QuicTagTest, TagToString) { EXPECT_EQ("525092931", QuicTagToString(MakeQuicTag('C', 'H', 'L', '\x1f'))); } -TEST(QuicTagTest, MakeQuicTag) { +TEST_F(QuicTagTest, MakeQuicTag) { QuicTag tag = MakeQuicTag('A', 'B', 'C', 'D'); char bytes[4]; memcpy(bytes, &tag, 4); diff --git a/chromium/net/quic/core/quic_time.h b/chromium/net/quic/core/quic_time.h index ee4a38c988f..18ef46f1170 100644 --- a/chromium/net/quic/core/quic_time.h +++ b/chromium/net/quic/core/quic_time.h @@ -24,6 +24,8 @@ namespace net { +class QuicClock; + // A QuicTime is a purely relative time. QuicTime values from different clocks // cannot be compared to each other. If you need an absolute time, see // QuicWallTime, below. @@ -104,8 +106,6 @@ class QUIC_EXPORT_PRIVATE QuicTime { friend class QuicClock; }; - explicit QuicTime(base::TimeTicks ticks) : time_(ticks.ToInternalValue()) {} - // Creates a new QuicTime with an internal value of 0. IsInitialized() // will return false for these times. static QUICTIME_CONSTEXPR QuicTime Zero() { return QuicTime(0); } @@ -124,6 +124,8 @@ class QUIC_EXPORT_PRIVATE QuicTime { inline bool IsInitialized() const { return 0 != time_; } private: + friend class QuicClock; + friend inline bool operator==(QuicTime lhs, QuicTime rhs); friend inline bool operator<(QuicTime lhs, QuicTime rhs); friend inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs); diff --git a/chromium/net/quic/core/quic_time_test.cc b/chromium/net/quic/core/quic_time_test.cc index 5324002e0e1..e8cd9f4de72 100644 --- a/chromium/net/quic/core/quic_time_test.cc +++ b/chromium/net/quic/core/quic_time_test.cc @@ -3,25 +3,27 @@ // found in the LICENSE file. #include "net/quic/core/quic_time.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/mock_clock.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { namespace test { -TEST(QuicTimeDeltaTest, Zero) { +class QuicTimeDeltaTest : public QuicTest {}; + +TEST_F(QuicTimeDeltaTest, Zero) { EXPECT_TRUE(QuicTime::Delta::Zero().IsZero()); EXPECT_FALSE(QuicTime::Delta::Zero().IsInfinite()); EXPECT_FALSE(QuicTime::Delta::FromMilliseconds(1).IsZero()); } -TEST(QuicTimeDeltaTest, Infinite) { +TEST_F(QuicTimeDeltaTest, Infinite) { EXPECT_TRUE(QuicTime::Delta::Infinite().IsInfinite()); EXPECT_FALSE(QuicTime::Delta::Zero().IsInfinite()); EXPECT_FALSE(QuicTime::Delta::FromMilliseconds(1).IsInfinite()); } -TEST(QuicTimeDeltaTest, FromTo) { +TEST_F(QuicTimeDeltaTest, FromTo) { EXPECT_EQ(QuicTime::Delta::FromMilliseconds(1), QuicTime::Delta::FromMicroseconds(1000)); EXPECT_EQ(QuicTime::Delta::FromSeconds(1), @@ -37,18 +39,18 @@ TEST(QuicTimeDeltaTest, FromTo) { QuicTime::Delta::FromSeconds(2).ToMicroseconds()); } -TEST(QuicTimeDeltaTest, Add) { +TEST_F(QuicTimeDeltaTest, Add) { EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2000), QuicTime::Delta::Zero() + QuicTime::Delta::FromMilliseconds(2)); } -TEST(QuicTimeDeltaTest, Subtract) { +TEST_F(QuicTimeDeltaTest, Subtract) { EXPECT_EQ(QuicTime::Delta::FromMicroseconds(1000), QuicTime::Delta::FromMilliseconds(2) - QuicTime::Delta::FromMilliseconds(1)); } -TEST(QuicTimeDeltaTest, Multiply) { +TEST_F(QuicTimeDeltaTest, Multiply) { int i = 2; EXPECT_EQ(QuicTime::Delta::FromMicroseconds(4000), QuicTime::Delta::FromMilliseconds(2) * i); @@ -67,20 +69,20 @@ TEST(QuicTimeDeltaTest, Multiply) { QuicTime::Delta::FromMicroseconds(12) * 0.2); } -TEST(QuicTimeDeltaTest, Max) { +TEST_F(QuicTimeDeltaTest, Max) { EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2000), std::max(QuicTime::Delta::FromMicroseconds(1000), QuicTime::Delta::FromMicroseconds(2000))); } -TEST(QuicTimeDeltaTest, NotEqual) { +TEST_F(QuicTimeDeltaTest, NotEqual) { EXPECT_TRUE(QuicTime::Delta::FromSeconds(0) != QuicTime::Delta::FromSeconds(1)); EXPECT_FALSE(QuicTime::Delta::FromSeconds(0) != QuicTime::Delta::FromSeconds(0)); } -TEST(QuicTimeDeltaTest, DebugValue) { +TEST_F(QuicTimeDeltaTest, DebugValue) { const QuicTime::Delta one_us = QuicTime::Delta::FromMicroseconds(1); const QuicTime::Delta one_ms = QuicTime::Delta::FromMilliseconds(1); const QuicTime::Delta one_s = QuicTime::Delta::FromSeconds(1); @@ -94,7 +96,7 @@ TEST(QuicTimeDeltaTest, DebugValue) { EXPECT_EQ("3000001us", (3 * one_s + one_us).ToDebugValue()); } -class QuicTimeTest : public ::testing::Test { +class QuicTimeTest : public QuicTest { protected: MockClock clock_; }; diff --git a/chromium/net/quic/core/quic_types.h b/chromium/net/quic/core/quic_types.h index 758081a66bb..eab0bc8398a 100644 --- a/chromium/net/quic/core/quic_types.h +++ b/chromium/net/quic/core/quic_types.h @@ -182,24 +182,13 @@ enum QuicPacketPublicFlags { PACKET_PUBLIC_FLAGS_4BYTE_PACKET = PACKET_FLAGS_4BYTE_PACKET << 4, PACKET_PUBLIC_FLAGS_6BYTE_PACKET = PACKET_FLAGS_6BYTE_PACKET << 4, - // TODO(fayang): Remove PACKET_PUBLIC_FLAGS_MULTIPATH when deprecating - // quic_reloadable_flag_quic_remove_multipath_bit. - // Bit 6: Does the packet header contain a path id? - PACKET_PUBLIC_FLAGS_MULTIPATH = 1 << 6, - // Reserved, unimplemented flags: // Bit 7: indicates the presence of a second flags byte. PACKET_PUBLIC_FLAGS_TWO_OR_MORE_BYTES = 1 << 7, - // TODO(fayang): Remove PACKET_PUBLIC_FLAGS_MAX and rename - // PACKET_PUBLIC_FLAGS_MAX_WITHOUT_MULTIPATH_FLAG when deprecating - // quic_reloadable_flag_quic_remove_multipath_bit. - // All bits set (bit 7 is not currently used): 01111111 - PACKET_PUBLIC_FLAGS_MAX = (1 << 7) - 1, - // All bits set (bits 6 and 7 are not currently used): 00111111 - PACKET_PUBLIC_FLAGS_MAX_WITHOUT_MULTIPATH_FLAG = (1 << 6) - 1, + PACKET_PUBLIC_FLAGS_MAX = (1 << 6) - 1, }; // The private flags are specified in one byte. @@ -223,6 +212,7 @@ enum CongestionControlType { kReno, kRenoBytes, kBBR, + kPCC }; enum LossDetectionType { @@ -261,6 +251,16 @@ enum PeerAddressChangeType { IPV6_TO_IPV6_CHANGE, }; +enum StreamSendingState { + // Sender has more data to send on this stream. + NO_FIN, + // Sender is done sending on this stream. + FIN, + // Sender is done sending on this stream and random padding needs to be + // appended after all stream frames. + FIN_AND_PADDING, +}; + } // namespace net #endif // NET_QUIC_CORE_QUIC_TYPES_H_ diff --git a/chromium/net/quic/core/quic_unacked_packet_map_test.cc b/chromium/net/quic/core/quic_unacked_packet_map_test.cc index 29c75bb6e4f..7fc9fc8f54b 100644 --- a/chromium/net/quic/core/quic_unacked_packet_map_test.cc +++ b/chromium/net/quic/core/quic_unacked_packet_map_test.cc @@ -4,8 +4,8 @@ #include "net/quic/core/quic_unacked_packet_map.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { namespace test { @@ -14,7 +14,7 @@ namespace { // Default packet length. const uint32_t kDefaultLength = 1000; -class QuicUnackedPacketMapTest : public ::testing::Test { +class QuicUnackedPacketMapTest : public QuicTest { protected: QuicUnackedPacketMapTest() : unacked_packets_(), diff --git a/chromium/net/quic/core/quic_utils.cc b/chromium/net/quic/core/quic_utils.cc index d68c55fb715..87f914f41e4 100644 --- a/chromium/net/quic/core/quic_utils.cc +++ b/chromium/net/quic/core/quic_utils.cc @@ -11,7 +11,7 @@ #include "base/containers/adapters.h" #include "base/logging.h" #include "net/quic/core/quic_constants.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" using std::string; @@ -208,4 +208,12 @@ PeerAddressChangeType QuicUtils::DetermineAddressChangeType( return IPV4_TO_IPV4_CHANGE; } +// static +bool QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective perspective) { + return (perspective == Perspective::IS_CLIENT && + FLAGS_quic_restart_flag_quic_big_endian_connection_id_client) || + (perspective == Perspective::IS_SERVER && + FLAGS_quic_restart_flag_quic_big_endian_connection_id_server); +} + } // namespace net diff --git a/chromium/net/quic/core/quic_utils.h b/chromium/net/quic/core/quic_utils.h index 723874f14cf..7395722528f 100644 --- a/chromium/net/quic/core/quic_utils.h +++ b/chromium/net/quic/core/quic_utils.h @@ -59,6 +59,12 @@ class QUIC_EXPORT_PRIVATE QuicUtils { const QuicSocketAddress& old_address, const QuicSocketAddress& new_address); + // Returns whether connection id needs to be read/write in big endian. + // TODO(fayang): Remove this method once deprecating + // FLAGS_quic_restart_flag_quic_big_endian_connection_id_client and + // FLAGS_quic_restart_flag_quic_big_endian_connection_id_server. + static bool IsConnectionIdWireFormatBigEndian(Perspective perspective); + private: DISALLOW_COPY_AND_ASSIGN(QuicUtils); }; diff --git a/chromium/net/quic/core/quic_utils_test.cc b/chromium/net/quic/core/quic_utils_test.cc index 201ae4b0de2..4f99397fbbe 100644 --- a/chromium/net/quic/core/quic_utils_test.cc +++ b/chromium/net/quic/core/quic_utils_test.cc @@ -5,7 +5,7 @@ #include "net/quic/core/quic_utils.h" #include "net/quic/core/crypto/crypto_protocol.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/quic/platform/api/quic_test.h" using std::string; @@ -13,7 +13,9 @@ namespace net { namespace test { namespace { -TEST(QuicUtilsTest, DetermineAddressChangeType) { +class QuicUtilsTest : public QuicTest {}; + +TEST_F(QuicUtilsTest, DetermineAddressChangeType) { const string kIPv4String1 = "1.2.3.4"; const string kIPv4String2 = "1.2.3.5"; const string kIPv4String3 = "1.1.3.5"; @@ -88,7 +90,7 @@ uint128 IncrementalHashReference(const void* data, size_t len) { return hash; } -TEST(QuicUtilsHashTest, ReferenceTest) { +TEST_F(QuicUtilsTest, ReferenceTest) { std::vector<uint8_t> data(32); for (size_t i = 0; i < data.size(); ++i) { data[i] = i % 255; diff --git a/chromium/net/quic/core/quic_version_manager.cc b/chromium/net/quic/core/quic_version_manager.cc index 02730158006..198976d1ec6 100644 --- a/chromium/net/quic/core/quic_version_manager.cc +++ b/chromium/net/quic/core/quic_version_manager.cc @@ -4,16 +4,15 @@ #include "net/quic/core/quic_version_manager.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_versions.h" +#include "net/quic/platform/api/quic_flags.h" namespace net { QuicVersionManager::QuicVersionManager(QuicVersionVector supported_versions) - : enable_version_38_(FLAGS_quic_enable_version_38), - enable_version_37_(FLAGS_quic_reloadable_flag_quic_enable_version_37), - enable_version_36_(FLAGS_quic_reloadable_flag_quic_enable_version_36_v3), - disable_version_34_(FLAGS_quic_reloadable_flag_quic_disable_version_34), + : enable_version_40_(GetQuicFlag(FLAGS_quic_enable_version_40)), + enable_version_39_(FLAGS_quic_reloadable_flag_quic_enable_version_39), + enable_version_38_(FLAGS_quic_reloadable_flag_quic_enable_version_38), allowed_supported_versions_(supported_versions), filtered_supported_versions_( FilterSupportedVersions(supported_versions)) {} @@ -26,16 +25,12 @@ const QuicVersionVector& QuicVersionManager::GetSupportedVersions() { } void QuicVersionManager::MaybeRefilterSupportedVersions() { - if (enable_version_38_ != FLAGS_quic_enable_version_38 || - enable_version_37_ != FLAGS_quic_reloadable_flag_quic_enable_version_37 || - enable_version_36_ != - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 || - disable_version_34_ != - FLAGS_quic_reloadable_flag_quic_disable_version_34) { - enable_version_38_ = FLAGS_quic_enable_version_38; - enable_version_37_ = FLAGS_quic_reloadable_flag_quic_enable_version_37; - enable_version_36_ = FLAGS_quic_reloadable_flag_quic_enable_version_36_v3; - disable_version_34_ = FLAGS_quic_reloadable_flag_quic_disable_version_34; + if (enable_version_40_ != GetQuicFlag(FLAGS_quic_enable_version_40) || + enable_version_39_ != FLAGS_quic_reloadable_flag_quic_enable_version_39 || + enable_version_38_ != FLAGS_quic_reloadable_flag_quic_enable_version_38) { + enable_version_40_ = GetQuicFlag(FLAGS_quic_enable_version_40); + enable_version_39_ = FLAGS_quic_reloadable_flag_quic_enable_version_39; + enable_version_38_ = FLAGS_quic_reloadable_flag_quic_enable_version_38; RefilterSupportedVersions(); } } diff --git a/chromium/net/quic/core/quic_version_manager.h b/chromium/net/quic/core/quic_version_manager.h index c1afef5d750..8ef9da10b0d 100644 --- a/chromium/net/quic/core/quic_version_manager.h +++ b/chromium/net/quic/core/quic_version_manager.h @@ -31,14 +31,12 @@ class QUIC_EXPORT_PRIVATE QuicVersionManager { } private: - // FLAGS_quic_enable_version_38 + // FLAGS_quic_enable_version_40 + bool enable_version_40_; + // FLAGS_quic_reloadable_flag_quic_enable_version_39 + bool enable_version_39_; + // FLAGS_quic_reloadable_flag_quic_enable_version_38 bool enable_version_38_; - // FLAGS_quic_reloadable_flag_quic_enable_version_37 - bool enable_version_37_; - // FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 - bool enable_version_36_; - // FLAGS_quic_reloadable_flag_quic_disable_version_34 - bool disable_version_34_; // The list of versions that may be supported. QuicVersionVector allowed_supported_versions_; // This vector contains QUIC versions which are currently supported based on diff --git a/chromium/net/quic/core/quic_version_manager_test.cc b/chromium/net/quic/core/quic_version_manager_test.cc index 22faf092e4c..6a3f9c13b19 100644 --- a/chromium/net/quic/core/quic_version_manager_test.cc +++ b/chromium/net/quic/core/quic_version_manager_test.cc @@ -4,61 +4,62 @@ #include "net/quic/core/quic_version_manager.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_versions.h" +#include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { namespace test { namespace { -TEST(QuicVersionManagerTest, QuicVersionManager) { - QuicFlagSaver flags; - FLAGS_quic_enable_version_38 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_37 = false; - FLAGS_quic_reloadable_flag_quic_disable_version_34 = false; - QuicVersionManager manager(AllSupportedVersions()); - EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), - manager.GetSupportedVersions()); +class QuicVersionManagerTest : public QuicTest {}; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true; +TEST_F(QuicVersionManagerTest, QuicVersionManager) { + SetQuicFlag(&FLAGS_quic_enable_version_40, false); + FLAGS_quic_reloadable_flag_quic_enable_version_39 = false; + FLAGS_quic_reloadable_flag_quic_enable_version_38 = false; + QuicVersionManager manager(AllSupportedVersions()); EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), manager.GetSupportedVersions()); - ASSERT_EQ(3u, manager.GetSupportedVersions().size()); - EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[0]); - EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[1]); - EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[2]); - FLAGS_quic_reloadable_flag_quic_enable_version_37 = true; + FLAGS_quic_reloadable_flag_quic_enable_version_38 = true; EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), manager.GetSupportedVersions()); ASSERT_EQ(4u, manager.GetSupportedVersions().size()); - EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[0]); - EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[1]); - EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[2]); - EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[3]); - - FLAGS_quic_enable_version_38 = true; - EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), - manager.GetSupportedVersions()); - ASSERT_EQ(5u, manager.GetSupportedVersions().size()); EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[0]); EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[1]); EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[2]); EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[3]); - EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[4]); - FLAGS_quic_reloadable_flag_quic_disable_version_34 = true; + FLAGS_quic_reloadable_flag_quic_enable_version_39 = true; EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), manager.GetSupportedVersions()); - ASSERT_EQ(4u, manager.GetSupportedVersions().size()); - EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[0]); - EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[1]); - EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[2]); - EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[3]); + ASSERT_EQ(5u, manager.GetSupportedVersions().size()); + EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[0]); + EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[1]); + EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[2]); + EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[3]); + EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[4]); + + SetQuicFlag(&FLAGS_quic_enable_version_40, true); + ASSERT_EQ(6u, manager.GetSupportedVersions().size()); + EXPECT_EQ(QUIC_VERSION_40, manager.GetSupportedVersions()[0]); + EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[1]); + EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[2]); + EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[3]); + EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[4]); + EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[5]); + + EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), + manager.GetSupportedVersions()); + ASSERT_EQ(6u, manager.GetSupportedVersions().size()); + EXPECT_EQ(QUIC_VERSION_40, manager.GetSupportedVersions()[0]); + EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[1]); + EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[2]); + EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[3]); + EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[4]); + EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[5]); } } // namespace diff --git a/chromium/net/quic/core/quic_versions.cc b/chromium/net/quic/core/quic_versions.cc index a26aa2dddbd..3a92624ac02 100644 --- a/chromium/net/quic/core/quic_versions.cc +++ b/chromium/net/quic/core/quic_versions.cc @@ -5,9 +5,9 @@ #include "net/quic/core/quic_versions.h" #include "net/quic/core/quic_error_codes.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_tag.h" #include "net/quic/core/quic_types.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" using std::string; @@ -30,23 +30,19 @@ QuicVersionVector FilterSupportedVersions(QuicVersionVector versions) { QuicVersionVector filtered_versions(versions.size()); filtered_versions.clear(); // Guaranteed by spec not to change capacity. for (QuicVersion version : versions) { - if (version == QUIC_VERSION_38) { - if (FLAGS_quic_enable_version_38 && - FLAGS_quic_reloadable_flag_quic_enable_version_37 && - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3) { + if (version == QUIC_VERSION_40) { + if (GetQuicFlag(FLAGS_quic_enable_version_40) && + FLAGS_quic_reloadable_flag_quic_enable_version_39 && + FLAGS_quic_reloadable_flag_quic_enable_version_38) { filtered_versions.push_back(version); } - } else if (version == QUIC_VERSION_37) { - if (FLAGS_quic_reloadable_flag_quic_enable_version_37 && - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3) { + } else if (version == QUIC_VERSION_39) { + if (FLAGS_quic_reloadable_flag_quic_enable_version_39 && + FLAGS_quic_reloadable_flag_quic_enable_version_38) { filtered_versions.push_back(version); } - } else if (version == QUIC_VERSION_36) { - if (FLAGS_quic_reloadable_flag_quic_enable_version_36_v3) { - filtered_versions.push_back(version); - } - } else if (version == QUIC_VERSION_34) { - if (!FLAGS_quic_reloadable_flag_quic_disable_version_34) { + } else if (version == QUIC_VERSION_38) { + if (FLAGS_quic_reloadable_flag_quic_enable_version_38) { filtered_versions.push_back(version); } } else { @@ -69,8 +65,6 @@ QuicVersionVector VersionOfIndex(const QuicVersionVector& versions, int index) { QuicTag QuicVersionToQuicTag(const QuicVersion version) { switch (version) { - case QUIC_VERSION_34: - return MakeQuicTag('Q', '0', '3', '4'); case QUIC_VERSION_35: return MakeQuicTag('Q', '0', '3', '5'); case QUIC_VERSION_36: @@ -79,6 +73,10 @@ QuicTag QuicVersionToQuicTag(const QuicVersion version) { return MakeQuicTag('Q', '0', '3', '7'); case QUIC_VERSION_38: return MakeQuicTag('Q', '0', '3', '8'); + case QUIC_VERSION_39: + return MakeQuicTag('Q', '0', '3', '9'); + case QUIC_VERSION_40: + return MakeQuicTag('Q', '0', '4', '0'); default: // This shold be an ERROR because we should never attempt to convert an // invalid QuicVersion to be written to the wire. @@ -105,11 +103,12 @@ QuicVersion QuicTagToQuicVersion(const QuicTag version_tag) { string QuicVersionToString(const QuicVersion version) { switch (version) { - RETURN_STRING_LITERAL(QUIC_VERSION_34); RETURN_STRING_LITERAL(QUIC_VERSION_35); RETURN_STRING_LITERAL(QUIC_VERSION_36); RETURN_STRING_LITERAL(QUIC_VERSION_37); RETURN_STRING_LITERAL(QUIC_VERSION_38); + RETURN_STRING_LITERAL(QUIC_VERSION_39); + RETURN_STRING_LITERAL(QUIC_VERSION_40); default: return "QUIC_VERSION_UNSUPPORTED"; } diff --git a/chromium/net/quic/core/quic_versions.h b/chromium/net/quic/core/quic_versions.h index 546f16b306c..1ddffe1ce55 100644 --- a/chromium/net/quic/core/quic_versions.h +++ b/chromium/net/quic/core/quic_versions.h @@ -24,13 +24,20 @@ enum QuicVersion { // Special case to indicate unknown/unsupported QUIC version. QUIC_VERSION_UNSUPPORTED = 0, - QUIC_VERSION_34 = 34, // Deprecates entropy, removes private flag from packet - // header, uses new ack and stop waiting wire format. QUIC_VERSION_35 = 35, // Allows endpoints to independently set stream limit. QUIC_VERSION_36 = 36, // Add support to force HOL blocking. QUIC_VERSION_37 = 37, // Add perspective into null encryption. - QUIC_VERSION_38 = 38, // Experimental support for HTTP stream pairs - // and HPACK HoL avoidance. + QUIC_VERSION_38 = 38, // PADDING frame is a 1-byte frame with type 0x00. + // Respect NSTP connection option. + QUIC_VERSION_39 = 39, // Integers and floating numbers are written in big + // endian. Dot not ack acks. Send a connection level + // WINDOW_UPDATE every 20 sent packets which do not + // contain retransmittable frames. + QUIC_VERSION_40 = 40, // Initial packet number is randomly chosen from + // [0:2^31], WINDOW_UPDATE for connection flow control + // advertises value in 1024-byte units, WINDOW_UPDATE + // splits into MAX_DATA and MAX_STREAM_DATA, BLOCKED + // frame split into BLOCKED and STREAM_BLOCKED frames // IMPORTANT: if you are adding to this list, follow the instructions at // http://sites/quic/adding-and-removing-versions @@ -44,8 +51,8 @@ enum QuicVersion { // IMPORTANT: if you are adding to this list, follow the instructions at // http://sites/quic/adding-and-removing-versions static const QuicVersion kSupportedQuicVersions[] = { - QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_36, QUIC_VERSION_35, - QUIC_VERSION_34}; + QUIC_VERSION_40, QUIC_VERSION_39, QUIC_VERSION_38, + QUIC_VERSION_37, QUIC_VERSION_36, QUIC_VERSION_35}; typedef std::vector<QuicVersion> QuicVersionVector; diff --git a/chromium/net/quic/core/quic_versions_test.cc b/chromium/net/quic/core/quic_versions_test.cc index cb2df3175cf..fe7134123f3 100644 --- a/chromium/net/quic/core/quic_versions_test.cc +++ b/chromium/net/quic/core/quic_versions_test.cc @@ -4,15 +4,17 @@ #include "net/quic/core/quic_versions.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" namespace net { namespace test { namespace { -TEST(QuicVersionsTest, QuicVersionToQuicTag) { +class QuicVersionsTest : public QuicTest {}; + +TEST_F(QuicVersionsTest, QuicVersionToQuicTag) { // If you add a new version to the QuicVersion enum you will need to add a new // case to QuicVersionToQuicTag, otherwise this test will fail. @@ -25,8 +27,8 @@ TEST(QuicVersionsTest, QuicVersionToQuicTag) { #endif // Explicitly test a specific version. - EXPECT_EQ(MakeQuicTag('Q', '0', '3', '4'), - QuicVersionToQuicTag(QUIC_VERSION_34)); + EXPECT_EQ(MakeQuicTag('Q', '0', '3', '5'), + QuicVersionToQuicTag(QUIC_VERSION_35)); // Loop over all supported versions and make sure that we never hit the // default case (i.e. all supported versions should be successfully converted @@ -37,7 +39,7 @@ TEST(QuicVersionsTest, QuicVersionToQuicTag) { } } -TEST(QuicVersionsTest, QuicVersionToQuicTagUnsupported) { +TEST_F(QuicVersionsTest, QuicVersionToQuicTagUnsupported) { // TODO(rtenneti): Enable checking of Log(ERROR) messages. #if 0 // TODO(rjshade): Change to DFATAL once we actually support multiple versions, @@ -52,7 +54,7 @@ TEST(QuicVersionsTest, QuicVersionToQuicTagUnsupported) { EXPECT_EQ(0u, QuicVersionToQuicTag(QUIC_VERSION_UNSUPPORTED)); } -TEST(QuicVersionsTest, QuicTagToQuicVersion) { +TEST_F(QuicVersionsTest, QuicTagToQuicVersion) { // If you add a new version to the QuicVersion enum you will need to add a new // case to QuicTagToQuicVersion, otherwise this test will fail. @@ -65,8 +67,8 @@ TEST(QuicVersionsTest, QuicTagToQuicVersion) { #endif // Explicitly test specific versions. - EXPECT_EQ(QUIC_VERSION_34, - QuicTagToQuicVersion(MakeQuicTag('Q', '0', '3', '4'))); + EXPECT_EQ(QUIC_VERSION_35, + QuicTagToQuicVersion(MakeQuicTag('Q', '0', '3', '5'))); for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) { QuicVersion version = kSupportedQuicVersions[i]; @@ -82,7 +84,7 @@ TEST(QuicVersionsTest, QuicTagToQuicVersion) { } } -TEST(QuicVersionsTest, QuicTagToQuicVersionUnsupported) { +TEST_F(QuicVersionsTest, QuicTagToQuicVersionUnsupported) { // TODO(rtenneti): Enable checking of Log(ERROR) messages. #if 0 ScopedMockLog log(kDoNotCaptureLogsYet); @@ -98,24 +100,24 @@ TEST(QuicVersionsTest, QuicTagToQuicVersionUnsupported) { QuicTagToQuicVersion(MakeQuicTag('F', 'A', 'K', 'E'))); } -TEST(QuicVersionsTest, QuicVersionToString) { - EXPECT_EQ("QUIC_VERSION_34", QuicVersionToString(QUIC_VERSION_34)); +TEST_F(QuicVersionsTest, QuicVersionToString) { + EXPECT_EQ("QUIC_VERSION_35", QuicVersionToString(QUIC_VERSION_35)); EXPECT_EQ("QUIC_VERSION_UNSUPPORTED", QuicVersionToString(QUIC_VERSION_UNSUPPORTED)); - QuicVersion single_version[] = {QUIC_VERSION_34}; + QuicVersion single_version[] = {QUIC_VERSION_35}; QuicVersionVector versions_vector; for (size_t i = 0; i < arraysize(single_version); ++i) { versions_vector.push_back(single_version[i]); } - EXPECT_EQ("QUIC_VERSION_34", QuicVersionVectorToString(versions_vector)); + EXPECT_EQ("QUIC_VERSION_35", QuicVersionVectorToString(versions_vector)); - QuicVersion multiple_versions[] = {QUIC_VERSION_UNSUPPORTED, QUIC_VERSION_34}; + QuicVersion multiple_versions[] = {QUIC_VERSION_UNSUPPORTED, QUIC_VERSION_35}; versions_vector.clear(); for (size_t i = 0; i < arraysize(multiple_versions); ++i) { versions_vector.push_back(multiple_versions[i]); } - EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_34", + EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_35", QuicVersionVectorToString(versions_vector)); // Make sure that all supported versions are present in QuicVersionToString. @@ -125,67 +127,52 @@ TEST(QuicVersionsTest, QuicVersionToString) { } } -TEST(QuicVersionsTest, FilterSupportedVersionsNo34) { - QuicFlagSaver flags; - QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35, - QUIC_VERSION_36, QUIC_VERSION_37}; +TEST_F(QuicVersionsTest, FilterSupportedVersionsNo38) { + QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_36, + QUIC_VERSION_37, QUIC_VERSION_38, + QUIC_VERSION_39}; - FLAGS_quic_reloadable_flag_quic_disable_version_34 = true; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_37 = false; + FLAGS_quic_reloadable_flag_quic_enable_version_38 = false; QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions); - ASSERT_EQ(1u, filtered_versions.size()); + ASSERT_EQ(3u, filtered_versions.size()); EXPECT_EQ(QUIC_VERSION_35, filtered_versions[0]); + EXPECT_EQ(QUIC_VERSION_36, filtered_versions[1]); + EXPECT_EQ(QUIC_VERSION_37, filtered_versions[2]); } -TEST(QuicVersionsTest, FilterSupportedVersionsNo36) { - QuicFlagSaver flags; - QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35, - QUIC_VERSION_36, QUIC_VERSION_37}; +TEST_F(QuicVersionsTest, FilterSupportedVersionsNo39) { + QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_36, + QUIC_VERSION_37, QUIC_VERSION_38, + QUIC_VERSION_39}; - FLAGS_quic_reloadable_flag_quic_disable_version_34 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_37 = false; + FLAGS_quic_reloadable_flag_quic_enable_version_38 = true; + FLAGS_quic_reloadable_flag_quic_enable_version_39 = false; QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions); - ASSERT_EQ(2u, filtered_versions.size()); - EXPECT_EQ(QUIC_VERSION_34, filtered_versions[0]); - EXPECT_EQ(QUIC_VERSION_35, filtered_versions[1]); -} - -TEST(QuicVersionsTest, FilterSupportedVersionsNo37) { - QuicFlagSaver flags; - QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35, - QUIC_VERSION_36, QUIC_VERSION_37}; - - FLAGS_quic_reloadable_flag_quic_disable_version_34 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true; - FLAGS_quic_reloadable_flag_quic_enable_version_37 = false; - - QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions); - ASSERT_EQ(3u, filtered_versions.size()); - EXPECT_EQ(QUIC_VERSION_34, filtered_versions[0]); - EXPECT_EQ(QUIC_VERSION_35, filtered_versions[1]); - EXPECT_EQ(QUIC_VERSION_36, filtered_versions[2]); + ASSERT_EQ(4u, filtered_versions.size()); + EXPECT_EQ(QUIC_VERSION_35, filtered_versions[0]); + EXPECT_EQ(QUIC_VERSION_36, filtered_versions[1]); + EXPECT_EQ(QUIC_VERSION_37, filtered_versions[2]); + EXPECT_EQ(QUIC_VERSION_38, filtered_versions[3]); } -TEST(QuicVersionsTest, FilterSupportedVersionsAllVersions) { - QuicFlagSaver flags; - QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35, - QUIC_VERSION_36, QUIC_VERSION_37}; +TEST_F(QuicVersionsTest, FilterSupportedVersionsAllVersions) { + QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_36, + QUIC_VERSION_37, QUIC_VERSION_38, + QUIC_VERSION_39}; - FLAGS_quic_reloadable_flag_quic_disable_version_34 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true; - FLAGS_quic_reloadable_flag_quic_enable_version_37 = true; + FLAGS_quic_reloadable_flag_quic_enable_version_38 = true; + FLAGS_quic_reloadable_flag_quic_enable_version_39 = true; QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions); ASSERT_EQ(all_versions, filtered_versions); } -TEST(QuicVersionsTest, LookUpVersionByIndex) { - QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35, - QUIC_VERSION_36, QUIC_VERSION_37}; +TEST_F(QuicVersionsTest, LookUpVersionByIndex) { + QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_36, + QUIC_VERSION_37, QUIC_VERSION_38, + QUIC_VERSION_39}; int version_count = all_versions.size(); for (int i = -5; i <= version_count + 1; ++i) { if (i >= 0 && i < version_count) { diff --git a/chromium/net/quic/core/quic_write_blocked_list.h b/chromium/net/quic/core/quic_write_blocked_list.h index f26491d6cf5..0d3952c0ebd 100644 --- a/chromium/net/quic/core/quic_write_blocked_list.h +++ b/chromium/net/quic/core/quic_write_blocked_list.h @@ -11,7 +11,7 @@ #include "base/macros.h" #include "net/quic/core/quic_packets.h" #include "net/quic/platform/api/quic_export.h" -#include "net/spdy/priority_write_scheduler.h" +#include "net/spdy/core/priority_write_scheduler.h" namespace net { diff --git a/chromium/net/quic/core/quic_write_blocked_list_test.cc b/chromium/net/quic/core/quic_write_blocked_list_test.cc index 8191062cfa3..0589f5573be 100644 --- a/chromium/net/quic/core/quic_write_blocked_list_test.cc +++ b/chromium/net/quic/core/quic_write_blocked_list_test.cc @@ -4,8 +4,8 @@ // #include "net/quic/core/quic_write_blocked_list.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" using net::kV3LowestPriority; using net::kV3HighestPriority; @@ -14,7 +14,9 @@ namespace net { namespace test { namespace { -TEST(QuicWriteBlockedListTest, PriorityOrder) { +class QuicWriteBlockedListTest : public QuicTest {}; + +TEST_F(QuicWriteBlockedListTest, PriorityOrder) { QuicWriteBlockedList write_blocked_list; // Mark streams blocked in roughly reverse priority order, and @@ -49,7 +51,7 @@ TEST(QuicWriteBlockedListTest, PriorityOrder) { EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams()); } -TEST(QuicWriteBlockedListTest, CryptoStream) { +TEST_F(QuicWriteBlockedListTest, CryptoStream) { QuicWriteBlockedList write_blocked_list; write_blocked_list.RegisterStream(kCryptoStreamId, kV3HighestPriority); write_blocked_list.AddStream(kCryptoStreamId); @@ -61,7 +63,7 @@ TEST(QuicWriteBlockedListTest, CryptoStream) { EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); } -TEST(QuicWriteBlockedListTest, HeadersStream) { +TEST_F(QuicWriteBlockedListTest, HeadersStream) { QuicWriteBlockedList write_blocked_list; write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority); write_blocked_list.AddStream(kHeadersStreamId); @@ -73,7 +75,7 @@ TEST(QuicWriteBlockedListTest, HeadersStream) { EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); } -TEST(QuicWriteBlockedListTest, VerifyHeadersStream) { +TEST_F(QuicWriteBlockedListTest, VerifyHeadersStream) { QuicWriteBlockedList write_blocked_list; write_blocked_list.RegisterStream(5, kV3HighestPriority); write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority); @@ -92,13 +94,13 @@ TEST(QuicWriteBlockedListTest, VerifyHeadersStream) { EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams()); } -TEST(QuicWriteBlockedListTest, NoDuplicateEntries) { +TEST_F(QuicWriteBlockedListTest, NoDuplicateEntries) { // Test that QuicWriteBlockedList doesn't allow duplicate entries. QuicWriteBlockedList write_blocked_list; // Try to add a stream to the write blocked list multiple times at the same // priority. - const QuicStreamId kBlockedId = kClientDataStreamId1; + const QuicStreamId kBlockedId = kHeadersStreamId + 2; write_blocked_list.RegisterStream(kBlockedId, kV3HighestPriority); write_blocked_list.AddStream(kBlockedId); write_blocked_list.AddStream(kBlockedId); @@ -114,12 +116,12 @@ TEST(QuicWriteBlockedListTest, NoDuplicateEntries) { EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams()); } -TEST(QuicWriteBlockedListTest, BatchingWrites) { +TEST_F(QuicWriteBlockedListTest, BatchingWrites) { QuicWriteBlockedList write_blocked_list; - const QuicStreamId id1 = kClientDataStreamId1; - const QuicStreamId id2 = kClientDataStreamId2; - const QuicStreamId id3 = kClientDataStreamId2 + 2; + const QuicStreamId id1 = kHeadersStreamId + 2; + const QuicStreamId id2 = id1 + 2; + const QuicStreamId id3 = id2 + 2; write_blocked_list.RegisterStream(id1, kV3LowestPriority); write_blocked_list.RegisterStream(id2, kV3LowestPriority); write_blocked_list.RegisterStream(id3, kV3HighestPriority); @@ -167,7 +169,7 @@ TEST(QuicWriteBlockedListTest, BatchingWrites) { EXPECT_EQ(id1, write_blocked_list.PopFront()); } -TEST(QuicWriteBlockedListTest, Ceding) { +TEST_F(QuicWriteBlockedListTest, Ceding) { QuicWriteBlockedList write_blocked_list; write_blocked_list.RegisterStream(15, kV3HighestPriority); diff --git a/chromium/net/quic/core/spdy_utils.cc b/chromium/net/quic/core/spdy_utils.cc index c86aee10d94..5ad6a43a5cd 100644 --- a/chromium/net/quic/core/spdy_utils.cc +++ b/chromium/net/quic/core/spdy_utils.cc @@ -12,10 +12,10 @@ #include "net/quic/platform/api/quic_string_piece.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/quic/platform/api/quic_url_utils.h" -#include "net/spdy/spdy_flags.h" -#include "net/spdy/spdy_frame_builder.h" -#include "net/spdy/spdy_framer.h" -#include "net/spdy/spdy_protocol.h" +#include "net/spdy/chromium/spdy_flags.h" +#include "net/spdy/core/spdy_frame_builder.h" +#include "net/spdy/core/spdy_framer.h" +#include "net/spdy/core/spdy_protocol.h" using std::string; @@ -32,24 +32,6 @@ string SpdyUtils::SerializeUncompressedHeaders(const SpdyHeaderBlock& headers) { } // static -bool SpdyUtils::ParseHeaders(const char* data, - uint32_t data_len, - int64_t* content_length, - SpdyHeaderBlock* headers) { - SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION); - if (!framer.ParseHeaderBlockInBuffer(data, data_len, headers) || - headers->empty()) { - return false; // Headers were invalid. - } - - if (!QuicContainsKey(*headers, "content-length")) { - return true; - } - - return ExtractContentLengthFromHeaders(content_length, headers); -} - -// static bool SpdyUtils::ExtractContentLengthFromHeaders(int64_t* content_length, SpdyHeaderBlock* headers) { auto it = headers->find("content-length"); @@ -83,47 +65,6 @@ bool SpdyUtils::ExtractContentLengthFromHeaders(int64_t* content_length, } } -// static -bool SpdyUtils::ParseTrailers(const char* data, - uint32_t data_len, - size_t* final_byte_offset, - SpdyHeaderBlock* trailers) { - SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION); - if (!framer.ParseHeaderBlockInBuffer(data, data_len, trailers) || - trailers->empty()) { - QUIC_DVLOG(1) << "Request Trailers are invalid."; - return false; // Trailers were invalid. - } - - // Pull out the final offset pseudo header which indicates the number of - // response body bytes expected. - auto it = trailers->find(kFinalOffsetHeaderKey); - if (it == trailers->end() || - !QuicTextUtils::StringToSizeT(it->second, final_byte_offset)) { - QUIC_DLOG(ERROR) << "Required key '" << kFinalOffsetHeaderKey - << "' not present"; - return false; - } - // The final offset header is no longer needed. - trailers->erase(it->first); - - // Trailers must not have empty keys, and must not contain pseudo headers. - for (const auto& trailer : *trailers) { - QuicStringPiece key = trailer.first; - QuicStringPiece value = trailer.second; - if (QuicTextUtils::StartsWith(key, ":")) { - QUIC_DVLOG(1) << "Trailers must not contain pseudo-header: '" << key - << "','" << value << "'."; - return false; - } - - // TODO(rjshade): Check for other forbidden keys, following the HTTP/2 spec. - } - - QUIC_DVLOG(1) << "Successfully parsed Trailers: " << trailers->DebugString(); - return true; -} - bool SpdyUtils::CopyAndValidateHeaders(const QuicHeaderList& header_list, int64_t* content_length, SpdyHeaderBlock* headers) { diff --git a/chromium/net/quic/core/spdy_utils.h b/chromium/net/quic/core/spdy_utils.h index 752bd77150a..cb11c93a629 100644 --- a/chromium/net/quic/core/spdy_utils.h +++ b/chromium/net/quic/core/spdy_utils.h @@ -13,7 +13,7 @@ #include "net/quic/core/quic_header_list.h" #include "net/quic/core/quic_packets.h" #include "net/quic/platform/api/quic_export.h" -#include "net/spdy/spdy_framer.h" +#include "net/spdy/core/spdy_framer.h" namespace net { @@ -22,40 +22,18 @@ class QUIC_EXPORT_PRIVATE SpdyUtils { static std::string SerializeUncompressedHeaders( const SpdyHeaderBlock& headers); - // Parses |data| as a string containing serialized HTTP/2 HEADERS frame, - // populating |headers| with the key->value pairs found. - // |content_length| will be populated with the value of the content-length - // header if one or more are present. - // Returns true on success, false if parsing fails, or invalid keys are found. - static bool ParseHeaders(const char* data, - uint32_t data_len, - int64_t* content_length, - SpdyHeaderBlock* headers); - // Populate |content length| with the value of the content-length header. // Returns true on success, false if parsing fails or content-length header is // missing. static bool ExtractContentLengthFromHeaders(int64_t* content_length, SpdyHeaderBlock* headers); - // Parses |data| as a string containing serialized HTTP/2 HEADERS frame, - // populating |trailers| with the key->value pairs found. - // The final offset header will be excluded from |trailers|, and instead the - // value will be copied to |final_byte_offset|. - // Returns true on success, false if parsing fails, or invalid keys are found. - static bool ParseTrailers(const char* data, - uint32_t data_len, - size_t* final_byte_offset, - SpdyHeaderBlock* trailers); - - // Copies a list of headers to a SpdyHeaderBlock. Performs similar validation - // to SpdyFramer::ParseHeaderBlockInBuffer and ParseHeaders, above. + // Copies a list of headers to a SpdyHeaderBlock. static bool CopyAndValidateHeaders(const QuicHeaderList& header_list, int64_t* content_length, SpdyHeaderBlock* headers); - // Copies a list of headers to a SpdyHeaderBlock. Performs similar validation - // to SpdyFramer::ParseHeaderBlockInBuffer and ParseTrailers, above. + // Copies a list of headers to a SpdyHeaderBlock. static bool CopyAndValidateTrailers(const QuicHeaderList& header_list, size_t* final_byte_offset, SpdyHeaderBlock* trailers); @@ -76,6 +54,8 @@ class QUIC_EXPORT_PRIVATE SpdyUtils { static bool PopulateHeaderBlockFromUrl(const std::string url, SpdyHeaderBlock* headers); + static bool IsServerPushStream(QuicStreamId id) { return id % 2 == 0; } + private: DISALLOW_COPY_AND_ASSIGN(SpdyUtils); }; diff --git a/chromium/net/quic/core/spdy_utils_test.cc b/chromium/net/quic/core/spdy_utils_test.cc index 42200f2732f..1b19488f4cd 100644 --- a/chromium/net/quic/core/spdy_utils_test.cc +++ b/chromium/net/quic/core/spdy_utils_test.cc @@ -3,11 +3,13 @@ // found in the LICENSE file. #include "net/quic/core/spdy_utils.h" +#include <memory> + #include "base/macros.h" #include "net/quic/platform/api/quic_string_piece.h" +#include "net/quic/platform/api/quic_test.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/test/gtest_util.h" -#include "testing/gtest/include/gtest/gtest.h" using std::string; using testing::UnorderedElementsAre; @@ -16,134 +18,6 @@ using testing::Pair; namespace net { namespace test { -TEST(SpdyUtilsTest, SerializeAndParseHeaders) { - // Creates a SpdyHeaderBlock with some key->value pairs, serializes it, then - // parses the serialized output and verifies that the end result is the same - // as the headers that the test started with. - - SpdyHeaderBlock input_headers; - input_headers[":pseudo1"] = "pseudo value1"; - input_headers[":pseudo2"] = "pseudo value2"; - input_headers["key1"] = "value1"; - const int64_t kContentLength = 1234; - input_headers["content-length"] = - QuicTextUtils::Uint64ToString(kContentLength); - input_headers["key2"] = "value2"; - - // Serialize the header block. - string serialized_headers = - SpdyUtils::SerializeUncompressedHeaders(input_headers); - - // Take the serialized header block, and parse back into SpdyHeaderBlock. - SpdyHeaderBlock output_headers; - int64_t content_length = -1; - ASSERT_TRUE(SpdyUtils::ParseHeaders(serialized_headers.data(), - serialized_headers.size(), - &content_length, &output_headers)); - - // Should be back to the original headers. - EXPECT_EQ(content_length, kContentLength); - EXPECT_EQ(output_headers, input_headers); -} - -TEST(SpdyUtilsTest, SerializeAndParseHeadersLargeContentLength) { - // Creates a SpdyHeaderBlock with some key->value pairs, serializes it, then - // parses the serialized output and verifies that the end result is the same - // as the headers that the test started with. - - SpdyHeaderBlock input_headers; - input_headers[":pseudo1"] = "pseudo value1"; - input_headers[":pseudo2"] = "pseudo value2"; - input_headers["key1"] = "value1"; - const int64_t kContentLength = 12345678900; - input_headers["content-length"] = - QuicTextUtils::Uint64ToString(kContentLength); - input_headers["key2"] = "value2"; - - // Serialize the header block. - string serialized_headers = - SpdyUtils::SerializeUncompressedHeaders(input_headers); - - // Take the serialized header block, and parse back into SpdyHeaderBlock. - SpdyHeaderBlock output_headers; - int64_t content_length = -1; - ASSERT_TRUE(SpdyUtils::ParseHeaders(serialized_headers.data(), - serialized_headers.size(), - &content_length, &output_headers)); - - // Should be back to the original headers. - EXPECT_EQ(content_length, kContentLength); - EXPECT_EQ(output_headers, input_headers); -} - -TEST(SpdyUtilsTest, SerializeAndParseValidTrailers) { - // Creates a SpdyHeaderBlock with some valid Trailers key->value pairs, - // serializes it, then parses the serialized output and verifies that the end - // result is the same as the trailers that the test started with. - SpdyHeaderBlock input_trailers; - const size_t kFinalOffset = 5678; - input_trailers[kFinalOffsetHeaderKey] = - QuicTextUtils::Uint64ToString(kFinalOffset); - input_trailers["key1"] = "value1"; - input_trailers["key2"] = "value2"; - - // Serialize the trailers. - string serialized_trailers = - SpdyUtils::SerializeUncompressedHeaders(input_trailers); - - // Take the serialized trailers, and parse back into a SpdyHeaderBlock. - SpdyHeaderBlock output_trailers; - size_t final_byte_offset = 0; - EXPECT_TRUE(SpdyUtils::ParseTrailers(serialized_trailers.data(), - serialized_trailers.size(), - &final_byte_offset, &output_trailers)); - - // Should be back to the original trailers, without the final offset header. - EXPECT_EQ(final_byte_offset, kFinalOffset); - input_trailers.erase(kFinalOffsetHeaderKey); - EXPECT_EQ(output_trailers, input_trailers); -} - -TEST(SpdyUtilsTest, SerializeAndParseTrailersWithoutFinalOffset) { - // Verifies that parsing fails if Trailers are missing a final offset header. - - SpdyHeaderBlock input_trailers; - input_trailers["key1"] = "value1"; - input_trailers["key2"] = "value2"; - - // Serialize the trailers. - string serialized_trailers = - SpdyUtils::SerializeUncompressedHeaders(input_trailers); - - // Parsing the serialized trailers fails because of the missing final offset. - SpdyHeaderBlock output_trailers; - size_t final_byte_offset = 0; - EXPECT_FALSE(SpdyUtils::ParseTrailers(serialized_trailers.data(), - serialized_trailers.size(), - &final_byte_offset, &output_trailers)); - EXPECT_EQ(final_byte_offset, 0u); -} - -TEST(SpdyUtilsTest, SerializeAndParseTrailersWithPseudoHeaders) { - // Verifies that parsing fails if Trailers include pseudo-headers. - - SpdyHeaderBlock input_trailers; - input_trailers[kFinalOffsetHeaderKey] = "12345"; - input_trailers[":disallowed-pseudo-header"] = "pseudo value"; - input_trailers["key1"] = "value1"; - input_trailers["key2"] = "value2"; - - // Serialize the trailers. - string serialized_trailers = - SpdyUtils::SerializeUncompressedHeaders(input_trailers); - - // Parsing the serialized trailers fails because of the extra pseudo header. - SpdyHeaderBlock output_trailers; - size_t final_byte_offset = 0; - EXPECT_FALSE(SpdyUtils::ParseTrailers(serialized_trailers.data(), - serialized_trailers.size(), - &final_byte_offset, &output_trailers)); -} static std::unique_ptr<QuicHeaderList> FromList( const QuicHeaderList::ListType& src) { std::unique_ptr<QuicHeaderList> headers(new QuicHeaderList); @@ -151,11 +25,13 @@ static std::unique_ptr<QuicHeaderList> FromList( for (const auto& p : src) { headers->OnHeader(p.first, p.second); } - headers->OnHeaderBlockEnd(0); + headers->OnHeaderBlockEnd(0, 0); return headers; } -TEST(SpdyUtilsTest, CopyAndValidateHeaders) { +class SpdyUtilsTest : public QuicTest {}; + +TEST_F(SpdyUtilsTest, CopyAndValidateHeaders) { auto headers = FromList({// All cookie crumbs are joined. {"cookie", " part 1"}, {"cookie", "part 2 "}, @@ -194,7 +70,7 @@ TEST(SpdyUtilsTest, CopyAndValidateHeaders) { EXPECT_EQ(-1, content_length); } -TEST(SpdyUtilsTest, CopyAndValidateHeadersEmptyName) { +TEST_F(SpdyUtilsTest, CopyAndValidateHeadersEmptyName) { auto headers = FromList({{"foo", "foovalue"}, {"", "barvalue"}, {"baz", ""}}); int64_t content_length = -1; SpdyHeaderBlock block; @@ -202,7 +78,7 @@ TEST(SpdyUtilsTest, CopyAndValidateHeadersEmptyName) { SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); } -TEST(SpdyUtilsTest, CopyAndValidateHeadersUpperCaseName) { +TEST_F(SpdyUtilsTest, CopyAndValidateHeadersUpperCaseName) { auto headers = FromList({{"foo", "foovalue"}, {"bar", "barvalue"}, {"bAz", ""}}); int64_t content_length = -1; @@ -211,7 +87,7 @@ TEST(SpdyUtilsTest, CopyAndValidateHeadersUpperCaseName) { SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); } -TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleContentLengths) { +TEST_F(SpdyUtilsTest, CopyAndValidateHeadersMultipleContentLengths) { auto headers = FromList({{"content-length", "9"}, {"foo", "foovalue"}, {"content-length", "9"}, @@ -231,7 +107,7 @@ TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleContentLengths) { EXPECT_EQ(9, content_length); } -TEST(SpdyUtilsTest, CopyAndValidateHeadersInconsistentContentLengths) { +TEST_F(SpdyUtilsTest, CopyAndValidateHeadersInconsistentContentLengths) { auto headers = FromList({{"content-length", "9"}, {"foo", "foovalue"}, {"content-length", "8"}, @@ -243,7 +119,7 @@ TEST(SpdyUtilsTest, CopyAndValidateHeadersInconsistentContentLengths) { SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block)); } -TEST(SpdyUtilsTest, CopyAndValidateHeadersLargeContentLength) { +TEST_F(SpdyUtilsTest, CopyAndValidateHeadersLargeContentLength) { auto headers = FromList({{"content-length", "9000000000"}, {"foo", "foovalue"}, {"bar", "barvalue"}, @@ -259,7 +135,7 @@ TEST(SpdyUtilsTest, CopyAndValidateHeadersLargeContentLength) { EXPECT_EQ(9000000000, content_length); } -TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleValues) { +TEST_F(SpdyUtilsTest, CopyAndValidateHeadersMultipleValues) { auto headers = FromList({{"foo", "foovalue"}, {"bar", "barvalue"}, {"baz", ""}, @@ -276,7 +152,7 @@ TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleValues) { EXPECT_EQ(-1, content_length); } -TEST(SpdyUtilsTest, CopyAndValidateHeadersMoreThanTwoValues) { +TEST_F(SpdyUtilsTest, CopyAndValidateHeadersMoreThanTwoValues) { auto headers = FromList({{"set-cookie", "value1"}, {"set-cookie", "value2"}, {"set-cookie", "value3"}}); @@ -290,7 +166,7 @@ TEST(SpdyUtilsTest, CopyAndValidateHeadersMoreThanTwoValues) { EXPECT_EQ(-1, content_length); } -TEST(SpdyUtilsTest, CopyAndValidateHeadersCookie) { +TEST_F(SpdyUtilsTest, CopyAndValidateHeadersCookie) { auto headers = FromList({{"foo", "foovalue"}, {"bar", "barvalue"}, {"cookie", "value1"}, @@ -305,7 +181,7 @@ TEST(SpdyUtilsTest, CopyAndValidateHeadersCookie) { EXPECT_EQ(-1, content_length); } -TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleCookies) { +TEST_F(SpdyUtilsTest, CopyAndValidateHeadersMultipleCookies) { auto headers = FromList({{"foo", "foovalue"}, {"bar", "barvalue"}, {"cookie", "value1"}, @@ -321,7 +197,7 @@ TEST(SpdyUtilsTest, CopyAndValidateHeadersMultipleCookies) { EXPECT_EQ(-1, content_length); } -TEST(SpdyUtilsTest, GetUrlFromHeaderBlock) { +TEST_F(SpdyUtilsTest, GetUrlFromHeaderBlock) { SpdyHeaderBlock headers; EXPECT_EQ(SpdyUtils::GetUrlFromHeaderBlock(headers), ""); headers[":scheme"] = "https"; @@ -337,7 +213,7 @@ TEST(SpdyUtilsTest, GetUrlFromHeaderBlock) { "https://www.google.com/index.html"); } -TEST(SpdyUtilsTest, GetHostNameFromHeaderBlock) { +TEST_F(SpdyUtilsTest, GetHostNameFromHeaderBlock) { SpdyHeaderBlock headers; EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), ""); headers[":scheme"] = "https"; @@ -357,7 +233,7 @@ TEST(SpdyUtilsTest, GetHostNameFromHeaderBlock) { EXPECT_EQ(SpdyUtils::GetHostNameFromHeaderBlock(headers), "192.168.1.1"); } -TEST(SpdyUtilsTest, PopulateHeaderBlockFromUrl) { +TEST_F(SpdyUtilsTest, PopulateHeaderBlockFromUrl) { string url = "https://www.google.com/index.html"; SpdyHeaderBlock headers; EXPECT_TRUE(SpdyUtils::PopulateHeaderBlockFromUrl(url, &headers)); @@ -366,7 +242,7 @@ TEST(SpdyUtilsTest, PopulateHeaderBlockFromUrl) { EXPECT_EQ("/index.html", headers[":path"].as_string()); } -TEST(SpdyUtilsTest, PopulateHeaderBlockFromUrlWithNoPath) { +TEST_F(SpdyUtilsTest, PopulateHeaderBlockFromUrlWithNoPath) { string url = "https://www.google.com"; SpdyHeaderBlock headers; EXPECT_TRUE(SpdyUtils::PopulateHeaderBlockFromUrl(url, &headers)); @@ -375,7 +251,7 @@ TEST(SpdyUtilsTest, PopulateHeaderBlockFromUrlWithNoPath) { EXPECT_EQ("/", headers[":path"].as_string()); } -TEST(SpdyUtilsTest, PopulateHeaderBlockFromUrlFails) { +TEST_F(SpdyUtilsTest, PopulateHeaderBlockFromUrlFails) { SpdyHeaderBlock headers; EXPECT_FALSE(SpdyUtils::PopulateHeaderBlockFromUrl("/", &headers)); EXPECT_FALSE(SpdyUtils::PopulateHeaderBlockFromUrl("/index.html", &headers)); |