diff options
| author | rjshade <rjshade@chromium.org> | 2016-03-11 12:42:17 -0800 |
|---|---|---|
| committer | Commit bot <commit-bot@chromium.org> | 2016-03-11 20:43:47 +0000 |
| commit | d069aaee0b3affb6004d8cf3a276c32e248a2a3d (patch) | |
| tree | ce0e89ab98a7ca09ac5df43122928a1f5aebf44b | |
| parent | ab26b6681dde41b4141fef09decf9c4e930aee85 (diff) | |
| download | chromium_src-d069aaee0b3affb6004d8cf3a276c32e248a2a3d.zip chromium_src-d069aaee0b3affb6004d8cf3a276c32e248a2a3d.tar.gz chromium_src-d069aaee0b3affb6004d8cf3a276c32e248a2a3d.tar.bz2 | |
Landing Recent QUIC changes until 2016-03-07 19:39 UTC
Up to, and including internal change 116570346
Add a new QUIC Ack Decimation mode that is reordering tolerant. Protected by FLAG_quic_ack_decimation2.
Merge internal change: 115853846
https://codereview.chromium.org/1777293002/
Deprecating FLAG_quic_batch_writes
Merge internal change: 115880164
https://codereview.chromium.org/1780913002/
Deprecate FLAG_quic_validate_stk_without_scid
Merge internal change: 115885351
https://codereview.chromium.org/1780923002/
Deprecate FLAG_quic_use_new_tcp_sender
Merge internal change: 115890504
https://codereview.chromium.org/1785663003/
Deprecate FLAG_quic_use_new_idle_timeout
Merge internal change: 115904466
https://codereview.chromium.org/1785693003/
Deprecate FLAG_quic_block_unencrypted_writes
Merge internal change: 115909446
https://codereview.chromium.org/1784643006/
Clang formatting net/quic.
Merge internal change: 115992556
https://codereview.chromium.org/1780783003/
Optionally defer responding to a QUIC ACK until all ACK processing has completed for an EpollServer iteration. Guarded by FLAG_quic_connection_defer_ack_response
Merge internal change: 114770052
https://codereview.chromium.org/1782053003/
Deprecate FLAG_require_strike_register_or_server_nonce
Merge internal change: 115891009
https://codereview.chromium.org/1785613005/
Add a boolean use_stateless_rejects_if_peer_supported argument to the QuicCryptoServerStream constructor instead of consulting FLAG_enable_quic_stateless_reject_support directly. No behavior change expected.
Merge internal change: 115844136
https://codereview.chromium.org/1783713003/
Remove FEC from send path.
Merge internal change: 115997404
https://codereview.chromium.org/1784903003/
Remove FEC code from receive path.
Drop received FEC packet.
Merge internal change: 116134765
https://codereview.chromium.org/1782143003/
Only cancel QUIC alarms if they have been set. Protected behind FLAG_quic_only_cancel_set_alarms
Merge internal change: 116142833
https://codereview.chromium.org/1781073002/
Call QuicAlarm::IsSet instead of looking at deadline_ directly, rename some variables for readability.
Merge internal change: 116146641
https://codereview.chromium.org/1778243005/
Add whether QUIC's unencrypted stream data was received or about to be sent in the error log. Logging only change.
Merge internal change: 116152506
https://codereview.chromium.org/1782193002/
Temporarily store the raw QUIC packet in QuicConnection.
Merge internal change: 116180343
https://codereview.chromium.org/1779313002/
Deprecate FLAG_quic_no_unencrypted_fec.
Merge internal change: 116244697
https://codereview.chromium.org/1780573006/
Make ShouldCreateOutgoingDynamicStream a virtual method.
Merge internal change: 116249386
https://codereview.chromium.org/1784933003/
Correctly handle EINTR during sendmsg in QuicSocketUtils::WritePacket.
Merge internal change: 116261116
https://codereview.chromium.org/1780323002/
Simplify QUIC's encryption path now that FEC is gone. Protected by FLAG_quic_inplace_encryption.
Merge internal change: 116266391
https://codereview.chromium.org/1785513003/
Remove the force param from QuicPacketGenerator::SetMaxPacketLength because path MTU packets should not be sent if the MTU cannot be changed. Not flag protected.
Merge internal change: 116273065
https://codereview.chromium.org/1781043004/
Remove lastest_revived_packet from QuicAckFrame since FEC is gone. No functional change expected.
Wire format is not changed yet.
Merge internal change: 116411121
https://codereview.chromium.org/1787443002/
Remove is_fec_packet from TransmissionInfo and SerializedPacket. No functional change.
Merge internal change: 116555910
https://codereview.chromium.org/1785853002/
Remove FEC related connection options and update FEC related comment in code base.
Merge internal change: 116566297
https://codereview.chromium.org/1785863002/
Switch "const StringPiece&" to just "StringPiece" in QUIC code. No functional change. Not flag protected.
Merge internal change: 116570346
https://codereview.chromium.org/1787453002/
Add a QuicCompressedCertsCache instance to QuicDispatcher, plumbing to QuicServerSessionBase but not used. No behavior change.
Merge internal change: 116277134
https://codereview.chromium.org/1783783003/
Add more detailed logging to QUIC's ack validation. No functional change.
Merge internal change: 116277228
https://codereview.chromium.org/1784963002/
Remove max_packet_length from QuicPacketGenerator, because it is no longer necessary with FEC gone. Not flag protected.
Merge internal change: 116387934
https://codereview.chromium.org/1777423002/
Add QuicCompressedCertsCache* to QuicCrytoServerStream plumbed from QuicServerSessionBase. No behavior change.
Merge internal change: 116388439
https://codereview.chromium.org/1782743005/
Remove unused return value from QuicAlarm::Delegate::OnAlarm. No behavior change, not protected.
The only place in the codebase that returns something other than
QuicTime::Zero() is the DelayAlarm in PacketDroppingTestWriter. I've the
implementation of OnAlarm in there to set the alarm directly to the new
time, rather than relying on the return value.
Merge internal change: 116389752
https://codereview.chromium.org/1779883005/
Add a QUIC ScopedPacketBundler to send an ack when the ack alarm goes off. No functional change. Not flag protected.
Merge internal change: 116391846
https://codereview.chromium.org/1786493003/
OnStreamEnd is now called instead of the sentinel call of OnStreamFrameData(stream_id, nullptr, 0, true). Protected by the flag FLAGS_spdy_on_stream_end.
Merge internal change: 116272960
https://codereview.chromium.org/1777163003/
R=rch@chromium.org
BUG=
Review URL: https://codereview.chromium.org/1781123002
Cr-Commit-Position: refs/heads/master@{#380718}
125 files changed, 1651 insertions, 8163 deletions
diff --git a/net/net.gypi b/net/net.gypi index fec3bcc..762355d 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -236,10 +236,6 @@ 'quic/congestion_control/rtt_stats.h', 'quic/congestion_control/send_algorithm_interface.cc', 'quic/congestion_control/send_algorithm_interface.h', - 'quic/congestion_control/tcp_cubic_bytes_sender.cc', - 'quic/congestion_control/tcp_cubic_bytes_sender.h', - 'quic/congestion_control/tcp_cubic_sender.cc', - 'quic/congestion_control/tcp_cubic_sender.h', 'quic/congestion_control/tcp_cubic_sender_base.cc', 'quic/congestion_control/tcp_cubic_sender_base.h', 'quic/congestion_control/tcp_cubic_sender_bytes.cc', @@ -1549,8 +1545,6 @@ 'quic/congestion_control/rtt_stats_test.cc', 'quic/congestion_control/send_algorithm_simulator.cc', 'quic/congestion_control/send_algorithm_simulator.h', - 'quic/congestion_control/tcp_cubic_bytes_sender_test.cc', - 'quic/congestion_control/tcp_cubic_sender_test.cc', 'quic/congestion_control/tcp_cubic_sender_bytes_test.cc', 'quic/congestion_control/tcp_cubic_sender_packets_test.cc', 'quic/crypto/aes_128_gcm_12_decrypter_test.cc', diff --git a/net/quic/congestion_control/pacing_sender_test.cc b/net/quic/congestion_control/pacing_sender_test.cc index 4cd5ac6..d5e2fc0 100644 --- a/net/quic/congestion_control/pacing_sender_test.cc +++ b/net/quic/congestion_control/pacing_sender_test.cc @@ -91,8 +91,9 @@ class PacingSenderTest : public ::testing::Test { .WillOnce(Return(zero_time_)); // Verify that the packet is delayed. EXPECT_EQ(delay.ToMicroseconds(), - pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight, - HAS_RETRANSMITTABLE_DATA) + pacing_sender_ + ->TimeUntilSend(clock_.Now(), kBytesInFlight, + HAS_RETRANSMITTABLE_DATA) .ToMicroseconds()); } } diff --git a/net/quic/congestion_control/send_algorithm_interface.cc b/net/quic/congestion_control/send_algorithm_interface.cc index 20821a6..83de14f 100644 --- a/net/quic/congestion_control/send_algorithm_interface.cc +++ b/net/quic/congestion_control/send_algorithm_interface.cc @@ -4,8 +4,6 @@ #include "net/quic/congestion_control/send_algorithm_interface.h" -#include "net/quic/congestion_control/tcp_cubic_bytes_sender.h" -#include "net/quic/congestion_control/tcp_cubic_sender.h" #include "net/quic/congestion_control/tcp_cubic_sender_bytes.h" #include "net/quic/congestion_control/tcp_cubic_sender_packets.h" #include "net/quic/quic_flags.h" @@ -27,39 +25,19 @@ SendAlgorithmInterface* SendAlgorithmInterface::Create( kDefaultTCPMSS; switch (congestion_control_type) { case kCubic: - if (FLAGS_quic_use_new_tcp_sender) { - return new TcpCubicSenderPackets( - clock, rtt_stats, false /* don't use Reno */, - initial_congestion_window, max_congestion_window, stats); - } - return new TcpCubicSender(clock, rtt_stats, false /* don't use Reno */, - initial_congestion_window, - max_congestion_window, stats); + return new TcpCubicSenderPackets( + clock, rtt_stats, false /* don't use Reno */, + initial_congestion_window, max_congestion_window, stats); case kCubicBytes: - if (FLAGS_quic_use_new_tcp_sender) { - return new TcpCubicSenderBytes( - clock, rtt_stats, false /* don't use Reno */, - initial_congestion_window, max_congestion_window, stats); - } - return new TcpCubicBytesSender( + return new TcpCubicSenderBytes( clock, rtt_stats, false /* don't use Reno */, initial_congestion_window, max_congestion_window, stats); case kReno: - if (FLAGS_quic_use_new_tcp_sender) { - return new TcpCubicSenderPackets(clock, rtt_stats, true /* use Reno */, - initial_congestion_window, - max_congestion_window, stats); - } - return new TcpCubicSender(clock, rtt_stats, true /* use Reno */, - initial_congestion_window, - max_congestion_window, stats); - case kRenoBytes: - if (FLAGS_quic_use_new_tcp_sender) { - return new TcpCubicSenderBytes(clock, rtt_stats, true /* use Reno */, + return new TcpCubicSenderPackets(clock, rtt_stats, true /* use Reno */, initial_congestion_window, max_congestion_window, stats); - } - return new TcpCubicBytesSender(clock, rtt_stats, true /* use Reno */, + case kRenoBytes: + return new TcpCubicSenderBytes(clock, rtt_stats, true /* use Reno */, initial_congestion_window, max_congestion_window, stats); case kBBR: diff --git a/net/quic/congestion_control/tcp_cubic_bytes_sender.cc b/net/quic/congestion_control/tcp_cubic_bytes_sender.cc deleted file mode 100644 index 2ceb719..0000000 --- a/net/quic/congestion_control/tcp_cubic_bytes_sender.cc +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright (c) 2015 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/congestion_control/tcp_cubic_bytes_sender.h" - -#include <algorithm> - -#include "net/quic/congestion_control/prr_sender.h" -#include "net/quic/congestion_control/rtt_stats.h" -#include "net/quic/crypto/crypto_protocol.h" -#include "net/quic/proto/cached_network_parameters.pb.h" -#include "net/quic/quic_bug_tracker.h" -#include "net/quic/quic_flags.h" - -using std::max; -using std::min; - -namespace net { - -namespace { -// Constants based on TCP defaults. -// The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a -// fast retransmission. -const QuicByteCount kDefaultMinimumCongestionWindow = 2 * kDefaultTCPMSS; -const QuicByteCount kMaxBurstBytes = 3 * kDefaultTCPMSS; -const float kRenoBeta = 0.7f; // Reno backoff factor. -const uint32_t kDefaultNumConnections = 2; // N-connection emulation. -} // namespace - -TcpCubicBytesSender::TcpCubicBytesSender( - const QuicClock* clock, - const RttStats* rtt_stats, - bool reno, - QuicPacketCount initial_tcp_congestion_window, - QuicPacketCount max_congestion_window, - QuicConnectionStats* stats) - : cubic_(clock), - rtt_stats_(rtt_stats), - stats_(stats), - reno_(reno), - num_connections_(kDefaultNumConnections), - num_acked_packets_(0), - largest_sent_packet_number_(0), - largest_acked_packet_number_(0), - largest_sent_at_last_cutback_(0), - congestion_window_(initial_tcp_congestion_window * kDefaultTCPMSS), - min_congestion_window_(kDefaultMinimumCongestionWindow), - min4_mode_(false), - max_congestion_window_(max_congestion_window * kDefaultTCPMSS), - slowstart_threshold_(max_congestion_window * kDefaultTCPMSS), - last_cutback_exited_slowstart_(false), - initial_tcp_congestion_window_(initial_tcp_congestion_window * - kDefaultTCPMSS), - initial_max_tcp_congestion_window_(max_congestion_window * - kDefaultTCPMSS), - slow_start_large_reduction_(false) {} - -TcpCubicBytesSender::~TcpCubicBytesSender() {} - -void TcpCubicBytesSender::SetFromConfig(const QuicConfig& config, - Perspective perspective) { - if (perspective == Perspective::IS_SERVER) { - if (config.HasReceivedConnectionOptions() && - ContainsQuicTag(config.ReceivedConnectionOptions(), kIW10)) { - // Initial window experiment. - congestion_window_ = 10 * kDefaultTCPMSS; - } - if (config.HasReceivedConnectionOptions() && - ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN1)) { - // Min CWND experiment. - min_congestion_window_ = kDefaultTCPMSS; - } - if (config.HasReceivedConnectionOptions() && - ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN4)) { - // Min CWND of 4 experiment. - min4_mode_ = true; - min_congestion_window_ = kDefaultTCPMSS; - } - if (config.HasReceivedConnectionOptions() && - ContainsQuicTag(config.ReceivedConnectionOptions(), kSSLR)) { - // Slow Start Fast Exit experiment. - slow_start_large_reduction_ = true; - } - } -} - -void TcpCubicBytesSender::ResumeConnectionState( - const CachedNetworkParameters& cached_network_params, - bool max_bandwidth_resumption) { - QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond( - max_bandwidth_resumption - ? cached_network_params.max_bandwidth_estimate_bytes_per_second() - : cached_network_params.bandwidth_estimate_bytes_per_second()); - QuicTime::Delta rtt_ms = - QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms()); - - // Make sure CWND is in appropriate range (in case of bad data). - QuicByteCount new_congestion_window = bandwidth.ToBytesPerPeriod(rtt_ms); - congestion_window_ = - max(min(new_congestion_window, kMaxCongestionWindow * kDefaultTCPMSS), - kMinCongestionWindowForBandwidthResumption * kDefaultTCPMSS); -} - -void TcpCubicBytesSender::SetNumEmulatedConnections(int num_connections) { - num_connections_ = max(1, num_connections); - cubic_.SetNumConnections(num_connections_); -} - -void TcpCubicBytesSender::SetMaxCongestionWindow( - QuicByteCount max_congestion_window) { - max_congestion_window_ = max_congestion_window; -} - -float TcpCubicBytesSender::RenoBeta() const { - // kNConnectionBeta is the backoff factor after loss for our N-connection - // emulation, which emulates the effective backoff of an ensemble of N - // TCP-Reno connections on a single loss event. The effective multiplier is - // computed as: - return (num_connections_ - 1 + kRenoBeta) / num_connections_; -} - -void TcpCubicBytesSender::OnCongestionEvent( - bool rtt_updated, - QuicByteCount bytes_in_flight, - const CongestionVector& acked_packets, - const CongestionVector& lost_packets) { - if (rtt_updated && InSlowStart() && - hybrid_slow_start_.ShouldExitSlowStart( - rtt_stats_->latest_rtt(), rtt_stats_->min_rtt(), - congestion_window_ / kDefaultTCPMSS)) { - slowstart_threshold_ = congestion_window_; - } - for (CongestionVector::const_iterator it = lost_packets.begin(); - it != lost_packets.end(); ++it) { - OnPacketLost(it->first, bytes_in_flight); - } - for (CongestionVector::const_iterator it = acked_packets.begin(); - it != acked_packets.end(); ++it) { - OnPacketAcked(it->first, it->second, bytes_in_flight); - } -} - -void TcpCubicBytesSender::OnPacketAcked(QuicPacketNumber acked_packet_number, - QuicByteCount acked_bytes, - QuicByteCount bytes_in_flight) { - largest_acked_packet_number_ = - max(acked_packet_number, largest_acked_packet_number_); - if (InRecovery()) { - // PRR is used when in recovery. - prr_.OnPacketAcked(acked_bytes); - return; - } - MaybeIncreaseCwnd(acked_packet_number, acked_bytes, bytes_in_flight); - if (InSlowStart()) { - hybrid_slow_start_.OnPacketAcked(acked_packet_number); - } -} - -void TcpCubicBytesSender::OnPacketLost(QuicPacketNumber packet_number, - QuicByteCount bytes_in_flight) { - // TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets - // already sent should be treated as a single loss event, since it's expected. - if (packet_number <= largest_sent_at_last_cutback_) { - if (last_cutback_exited_slowstart_) { - ++stats_->slowstart_packets_lost; - if (slow_start_large_reduction_) { - // Reduce congestion window by 1 MSS for every loss. - congestion_window_ = - max(congestion_window_ - kDefaultTCPMSS, min_congestion_window_); - slowstart_threshold_ = congestion_window_; - } - } - DVLOG(1) << "Ignoring loss for largest_missing:" << packet_number - << " because it was sent prior to the last CWND cutback."; - return; - } - ++stats_->tcp_loss_events; - last_cutback_exited_slowstart_ = InSlowStart(); - if (InSlowStart()) { - ++stats_->slowstart_packets_lost; - } - - prr_.OnPacketLost(bytes_in_flight); - - // TODO(jri): Separate out all of slow start into a separate class. - if (slow_start_large_reduction_ && InSlowStart()) { - DCHECK_LT(kDefaultTCPMSS, congestion_window_); - congestion_window_ = congestion_window_ - kDefaultTCPMSS; - } else if (reno_) { - congestion_window_ = congestion_window_ * RenoBeta(); - } else { - congestion_window_ = - cubic_.CongestionWindowAfterPacketLoss(congestion_window_); - } - // Enforce TCP's minimum congestion window of 2*MSS. - if (congestion_window_ < min_congestion_window_) { - congestion_window_ = min_congestion_window_; - } - slowstart_threshold_ = congestion_window_; - largest_sent_at_last_cutback_ = largest_sent_packet_number_; - // Reset packet count from congestion avoidance mode. We start counting again - // when we're out of recovery. - num_acked_packets_ = 0; - DVLOG(1) << "Incoming loss; congestion window: " << congestion_window_ - << " slowstart threshold: " << slowstart_threshold_; -} - -bool TcpCubicBytesSender::OnPacketSent( - QuicTime /*sent_time*/, - QuicByteCount /*bytes_in_flight*/, - QuicPacketNumber packet_number, - QuicByteCount bytes, - HasRetransmittableData is_retransmittable) { - if (InSlowStart()) { - ++(stats_->slowstart_packets_sent); - } - - // Only update bytes_in_flight_ for data packets. - if (is_retransmittable != HAS_RETRANSMITTABLE_DATA) { - return false; - } - if (InRecovery()) { - // PRR is used when in recovery. - prr_.OnPacketSent(bytes); - } - DCHECK_LT(largest_sent_packet_number_, packet_number); - largest_sent_packet_number_ = packet_number; - hybrid_slow_start_.OnPacketSent(packet_number); - return true; -} - -QuicTime::Delta TcpCubicBytesSender::TimeUntilSend( - QuicTime /* now */, - QuicByteCount bytes_in_flight, - HasRetransmittableData has_retransmittable_data) const { - if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) { - DCHECK(!FLAGS_quic_respect_send_alarm2); - // For TCP we can always send an ACK immediately. - return QuicTime::Delta::Zero(); - } - if (InRecovery()) { - // PRR is used when in recovery. - return prr_.TimeUntilSend(GetCongestionWindow(), bytes_in_flight, - slowstart_threshold_); - } - if (GetCongestionWindow() > bytes_in_flight) { - return QuicTime::Delta::Zero(); - } - if (min4_mode_ && bytes_in_flight < 4 * kDefaultTCPMSS) { - return QuicTime::Delta::Zero(); - } - return QuicTime::Delta::Infinite(); -} - -QuicBandwidth TcpCubicBytesSender::PacingRate() const { - // We pace at twice the rate of the underlying sender's bandwidth estimate - // during slow start and 1.25x during congestion avoidance to ensure pacing - // doesn't prevent us from filling the window. - QuicTime::Delta srtt = rtt_stats_->smoothed_rtt(); - if (srtt.IsZero()) { - srtt = QuicTime::Delta::FromMicroseconds(rtt_stats_->initial_rtt_us()); - } - const QuicBandwidth bandwidth = - QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt); - return bandwidth.Scale(InSlowStart() ? 2 : 1.25); -} - -QuicBandwidth TcpCubicBytesSender::BandwidthEstimate() const { - QuicTime::Delta srtt = rtt_stats_->smoothed_rtt(); - if (srtt.IsZero()) { - // If we haven't measured an rtt, the bandwidth estimate is unknown. - return QuicBandwidth::Zero(); - } - return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt); -} - -QuicTime::Delta TcpCubicBytesSender::RetransmissionDelay() const { - if (rtt_stats_->smoothed_rtt().IsZero()) { - return QuicTime::Delta::Zero(); - } - return rtt_stats_->smoothed_rtt().Add( - rtt_stats_->mean_deviation().Multiply(4)); -} - -QuicByteCount TcpCubicBytesSender::GetCongestionWindow() const { - return congestion_window_; -} - -bool TcpCubicBytesSender::InSlowStart() const { - return congestion_window_ < slowstart_threshold_; -} - -QuicByteCount TcpCubicBytesSender::GetSlowStartThreshold() const { - return slowstart_threshold_; -} - -bool TcpCubicBytesSender::IsCwndLimited(QuicByteCount bytes_in_flight) const { - if (bytes_in_flight >= congestion_window_) { - return true; - } - const QuicByteCount available_bytes = congestion_window_ - bytes_in_flight; - const bool slow_start_limited = - InSlowStart() && bytes_in_flight > congestion_window_ / 2; - return slow_start_limited || available_bytes <= kMaxBurstBytes; -} - -bool TcpCubicBytesSender::InRecovery() const { - return largest_acked_packet_number_ <= largest_sent_at_last_cutback_ && - largest_acked_packet_number_ != 0; -} - -// Called when we receive an ack. Normal TCP tracks how many packets one ack -// represents, but quic has a separate ack for each packet. -void TcpCubicBytesSender::MaybeIncreaseCwnd( - QuicPacketNumber acked_packet_number, - QuicByteCount acked_bytes, - QuicByteCount bytes_in_flight) { - QUIC_BUG_IF(InRecovery()) << "Never increase the CWND during recovery."; - // Do not increase the congestion window unless the sender is close to using - // the current window. - if (!IsCwndLimited(bytes_in_flight)) { - cubic_.OnApplicationLimited(); - return; - } - if (congestion_window_ >= max_congestion_window_) { - return; - } - if (InSlowStart()) { - // TCP slow start, exponential growth, increase by one for each ACK. - congestion_window_ += kDefaultTCPMSS; - DVLOG(1) << "Slow start; congestion window: " << congestion_window_ - << " slowstart threshold: " << slowstart_threshold_; - return; - } - // Congestion avoidance. - if (reno_) { - // Classic Reno congestion avoidance. - ++num_acked_packets_; - // Divide by num_connections to smoothly increase the CWND at a faster rate - // than conventional Reno. - if (num_acked_packets_ * num_connections_ >= - congestion_window_ / kDefaultTCPMSS) { - congestion_window_ += kDefaultTCPMSS; - num_acked_packets_ = 0; - } - - DVLOG(1) << "Reno; congestion window: " << congestion_window_ - << " slowstart threshold: " << slowstart_threshold_ - << " congestion window count: " << num_acked_packets_; - } else { - congestion_window_ = - min(max_congestion_window_, - cubic_.CongestionWindowAfterAck(acked_bytes, congestion_window_, - rtt_stats_->min_rtt())); - DVLOG(1) << "Cubic; congestion window: " << congestion_window_ - << " slowstart threshold: " << slowstart_threshold_; - } -} - -void TcpCubicBytesSender::OnRetransmissionTimeout(bool packets_retransmitted) { - largest_sent_at_last_cutback_ = 0; - if (!packets_retransmitted) { - return; - } - cubic_.Reset(); - hybrid_slow_start_.Restart(); - slowstart_threshold_ = congestion_window_ / 2; - congestion_window_ = min_congestion_window_; -} - -CongestionControlType TcpCubicBytesSender::GetCongestionControlType() const { - return reno_ ? kRenoBytes : kCubicBytes; -} - -void TcpCubicBytesSender::OnConnectionMigration() { - hybrid_slow_start_.Restart(); - cubic_.Reset(); - prr_ = PrrSender(); - num_acked_packets_ = 0; - largest_sent_packet_number_ = 0; - largest_acked_packet_number_ = 0; - largest_sent_at_last_cutback_ = 0; - congestion_window_ = initial_tcp_congestion_window_; - max_congestion_window_ = initial_max_tcp_congestion_window_; - slowstart_threshold_ = initial_max_tcp_congestion_window_; - last_cutback_exited_slowstart_ = false; -} - -} // namespace net diff --git a/net/quic/congestion_control/tcp_cubic_bytes_sender.h b/net/quic/congestion_control/tcp_cubic_bytes_sender.h deleted file mode 100644 index e1b0185..0000000 --- a/net/quic/congestion_control/tcp_cubic_bytes_sender.h +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2015 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. - -// TCP cubic send side congestion algorithm, emulates the behavior of TCP cubic. - -#ifndef NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_BYTES_SENDER_H_ -#define NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_BYTES_SENDER_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "net/base/net_export.h" -#include "net/quic/congestion_control/cubic_bytes.h" -#include "net/quic/congestion_control/hybrid_slow_start.h" -#include "net/quic/congestion_control/prr_sender.h" -#include "net/quic/congestion_control/send_algorithm_interface.h" -#include "net/quic/quic_bandwidth.h" -#include "net/quic/quic_connection_stats.h" -#include "net/quic/quic_protocol.h" -#include "net/quic/quic_time.h" - -namespace net { - -class RttStats; - -namespace test { -class TcpCubicBytesSenderPeer; -} // namespace test - -class NET_EXPORT_PRIVATE TcpCubicBytesSender : public SendAlgorithmInterface { - public: - TcpCubicBytesSender(const QuicClock* clock, - const RttStats* rtt_stats, - bool reno, - QuicPacketCount initial_tcp_congestion_window, - QuicPacketCount max_congestion_window, - QuicConnectionStats* stats); - ~TcpCubicBytesSender() override; - - // Start implementation of SendAlgorithmInterface. - void SetFromConfig(const QuicConfig& config, - Perspective perspective) override; - void ResumeConnectionState( - const CachedNetworkParameters& cached_network_params, - bool max_bandwidth_resumption) override; - void SetNumEmulatedConnections(int num_connections) override; - void SetMaxCongestionWindow(QuicByteCount max_congestion_window) override; - void OnCongestionEvent(bool rtt_updated, - QuicByteCount bytes_in_flight, - const CongestionVector& acked_packets, - const CongestionVector& lost_packets) override; - bool OnPacketSent(QuicTime sent_time, - QuicByteCount bytes_in_flight, - QuicPacketNumber packet_number, - QuicByteCount bytes, - HasRetransmittableData is_retransmittable) override; - void OnRetransmissionTimeout(bool packets_retransmitted) override; - void OnConnectionMigration() override; - QuicTime::Delta TimeUntilSend( - QuicTime now, - QuicByteCount bytes_in_flight, - HasRetransmittableData has_retransmittable_data) const override; - QuicBandwidth PacingRate() const override; - QuicBandwidth BandwidthEstimate() const override; - QuicTime::Delta RetransmissionDelay() const override; - QuicByteCount GetCongestionWindow() const override; - bool InSlowStart() const override; - bool InRecovery() const override; - QuicByteCount GetSlowStartThreshold() const override; - CongestionControlType GetCongestionControlType() const override; - // End implementation of SendAlgorithmInterface. - - private: - friend class test::TcpCubicBytesSenderPeer; - - // Compute the TCP Reno beta based on the current number of connections. - float RenoBeta() const; - - // TODO(ianswett): Remove these and migrate to OnCongestionEvent. - void OnPacketAcked(QuicPacketNumber acked_packet_number, - QuicByteCount acked_bytes, - QuicByteCount bytes_in_flight); - void OnPacketLost(QuicPacketNumber largest_loss, - QuicByteCount bytes_in_flight); - - void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number, - QuicByteCount acked_bytes, - QuicByteCount bytes_in_flight); - bool IsCwndLimited(QuicByteCount bytes_in_flight) const; - - HybridSlowStart hybrid_slow_start_; - CubicBytes cubic_; - PrrSender prr_; - const RttStats* rtt_stats_; - QuicConnectionStats* stats_; - - // If true, Reno congestion control is used instead of Cubic. - const bool reno_; - - // Number of connections to simulate. - uint32_t num_connections_; - - // ACK counter for the Reno implementation. - uint64_t num_acked_packets_; - - // Track the largest packet that has been sent. - QuicPacketNumber largest_sent_packet_number_; - - // Track the largest packet that has been acked. - QuicPacketNumber largest_acked_packet_number_; - - // Track the largest packet number outstanding when a CWND cutback occurs. - QuicPacketNumber largest_sent_at_last_cutback_; - - // Congestion window in bytes. - QuicByteCount congestion_window_; - - // Minimum congestion window in bytes. - QuicByteCount min_congestion_window_; - - // Whether to use 4 packets as the actual min, but pace lower. - bool min4_mode_; - - // Maximum congestion window in bytes. - QuicByteCount max_congestion_window_; - - // Slow start congestion window in bytes, aka ssthresh. - QuicByteCount slowstart_threshold_; - - // Whether the last loss event caused us to exit slowstart. Used for stats - // collection of slowstart_packets_lost. - bool last_cutback_exited_slowstart_; - - // Initial TCP congestion window in bytes. This variable can only be set when - // this algorithm is created. - const QuicByteCount initial_tcp_congestion_window_; - - // Initial maximum TCP congestion window in bytes. This variable can only be - // set when this algorithm is created. - const QuicByteCount initial_max_tcp_congestion_window_; - - // When true, exit slow start with large cutback of congestion window. - bool slow_start_large_reduction_; - - DISALLOW_COPY_AND_ASSIGN(TcpCubicBytesSender); -}; - -} // namespace net - -#endif // NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_BYTES_SENDER_H_ diff --git a/net/quic/congestion_control/tcp_cubic_bytes_sender_test.cc b/net/quic/congestion_control/tcp_cubic_bytes_sender_test.cc deleted file mode 100644 index 3089435..0000000 --- a/net/quic/congestion_control/tcp_cubic_bytes_sender_test.cc +++ /dev/null @@ -1,743 +0,0 @@ -// Copyright (c) 2015 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/congestion_control/tcp_cubic_bytes_sender.h" - -#include <algorithm> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "net/quic/congestion_control/rtt_stats.h" -#include "net/quic/crypto/crypto_protocol.h" -#include "net/quic/proto/cached_network_parameters.pb.h" -#include "net/quic/quic_flags.h" -#include "net/quic/quic_protocol.h" -#include "net/quic/quic_utils.h" -#include "net/quic/test_tools/mock_clock.h" -#include "net/quic/test_tools/quic_config_peer.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { -namespace test { - -// TODO(ianswett): A number of theses tests were written with the assumption of -// an initial CWND of 10. They have carefully calculated values which should be -// updated to be based on kInitialCongestionWindow. -const uint32_t kInitialCongestionWindowPackets = 10; -const uint32_t kDefaultWindowTCP = - kInitialCongestionWindowPackets * kDefaultTCPMSS; -const float kRenoBeta = 0.7f; // Reno backoff factor. - -class TcpCubicBytesSenderPeer : public TcpCubicBytesSender { - public: - TcpCubicBytesSenderPeer(const QuicClock* clock, bool reno) - : TcpCubicBytesSender(clock, - &rtt_stats_, - reno, - kInitialCongestionWindowPackets, - kMaxCongestionWindow, - &stats_) {} - - const HybridSlowStart& hybrid_slow_start() const { - return hybrid_slow_start_; - } - - float GetRenoBeta() const { return RenoBeta(); } - - RttStats rtt_stats_; - QuicConnectionStats stats_; -}; - -class TcpCubicBytesSenderTest : public ::testing::Test { - protected: - TcpCubicBytesSenderTest() - : one_ms_(QuicTime::Delta::FromMilliseconds(1)), - sender_(new TcpCubicBytesSenderPeer(&clock_, true)), - packet_number_(1), - acked_packet_number_(0), - bytes_in_flight_(0) {} - - int SendAvailableSendWindow() { - // Send as long as TimeUntilSend returns Zero. - int packets_sent = 0; - bool can_send = sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_, - HAS_RETRANSMITTABLE_DATA) - .IsZero(); - while (can_send) { - sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, packet_number_++, - kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA); - ++packets_sent; - bytes_in_flight_ += kDefaultTCPMSS; - can_send = sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_, - HAS_RETRANSMITTABLE_DATA) - .IsZero(); - } - return packets_sent; - } - - // Normal is that TCP acks every other segment. - void AckNPackets(int n) { - sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(60), - QuicTime::Delta::Zero(), clock_.Now()); - SendAlgorithmInterface::CongestionVector acked_packets; - SendAlgorithmInterface::CongestionVector lost_packets; - for (int i = 0; i < n; ++i) { - ++acked_packet_number_; - acked_packets.push_back( - std::make_pair(acked_packet_number_, kDefaultTCPMSS)); - } - sender_->OnCongestionEvent(true, bytes_in_flight_, acked_packets, - lost_packets); - bytes_in_flight_ -= n * kDefaultTCPMSS; - clock_.AdvanceTime(one_ms_); - } - - void LoseNPackets(int n) { - SendAlgorithmInterface::CongestionVector acked_packets; - SendAlgorithmInterface::CongestionVector lost_packets; - for (int i = 0; i < n; ++i) { - ++acked_packet_number_; - lost_packets.push_back( - std::make_pair(acked_packet_number_, kDefaultTCPMSS)); - } - sender_->OnCongestionEvent(false, bytes_in_flight_, acked_packets, - lost_packets); - bytes_in_flight_ -= n * kDefaultTCPMSS; - } - - // Does not increment acked_packet_number_. - void LosePacket(QuicPacketNumber packet_number) { - SendAlgorithmInterface::CongestionVector acked_packets; - SendAlgorithmInterface::CongestionVector lost_packets; - lost_packets.push_back(std::make_pair(packet_number, kDefaultTCPMSS)); - sender_->OnCongestionEvent(false, bytes_in_flight_, acked_packets, - lost_packets); - bytes_in_flight_ -= kDefaultTCPMSS; - } - - const QuicTime::Delta one_ms_; - MockClock clock_; - scoped_ptr<TcpCubicBytesSenderPeer> sender_; - QuicPacketNumber packet_number_; - QuicPacketNumber acked_packet_number_; - QuicByteCount bytes_in_flight_; -}; - -TEST_F(TcpCubicBytesSenderTest, SimpleSender) { - // At startup make sure we are at the default. - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); - // At startup make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - // Make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - // And that window is un-affected. - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); - - // Fill the send window with data, then verify that we can't send. - SendAvailableSendWindow(); - EXPECT_FALSE(sender_->TimeUntilSend(clock_.Now(), - sender_->GetCongestionWindow(), - HAS_RETRANSMITTABLE_DATA) - .IsZero()); -} - -TEST_F(TcpCubicBytesSenderTest, ApplicationLimitedSlowStart) { - // Send exactly 10 packets and ensure the CWND ends at 14 packets. - const int kNumberOfAcks = 5; - // At startup make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - // Make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - - SendAvailableSendWindow(); - for (int i = 0; i < kNumberOfAcks; ++i) { - AckNPackets(2); - } - QuicByteCount bytes_to_send = sender_->GetCongestionWindow(); - // It's expected 2 acks will arrive when the bytes_in_flight are greater than - // half the CWND. - EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * 2, bytes_to_send); -} - -TEST_F(TcpCubicBytesSenderTest, ExponentialSlowStart) { - const int kNumberOfAcks = 20; - // At startup make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - EXPECT_EQ(QuicBandwidth::Zero(), sender_->BandwidthEstimate()); - // Make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - const QuicByteCount cwnd = sender_->GetCongestionWindow(); - EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, cwnd); - EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta( - cwnd, sender_->rtt_stats_.smoothed_rtt()), - sender_->BandwidthEstimate()); -} - -TEST_F(TcpCubicBytesSenderTest, SlowStartPacketLoss) { - sender_->SetNumEmulatedConnections(1); - const int kNumberOfAcks = 10; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Lose a packet to exit slow start. - LoseNPackets(1); - size_t packets_in_recovery_window = expected_send_window / kDefaultTCPMSS; - - // We should now have fallen out of slow start with a reduced window. - expected_send_window *= kRenoBeta; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Recovery phase. We need to ack every packet in the recovery window before - // we exit recovery. - size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; - DVLOG(1) << "number_packets: " << number_of_packets_in_window; - AckNPackets(packets_in_recovery_window); - SendAvailableSendWindow(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // We need to ack an entire window before we increase CWND by 1. - AckNPackets(number_of_packets_in_window - 2); - SendAvailableSendWindow(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Next ack should increase cwnd by 1. - AckNPackets(1); - expected_send_window += kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Now RTO and ensure slow start gets reset. - EXPECT_TRUE(sender_->hybrid_slow_start().started()); - sender_->OnRetransmissionTimeout(true); - EXPECT_FALSE(sender_->hybrid_slow_start().started()); -} - -TEST_F(TcpCubicBytesSenderTest, SlowStartPacketLossWithLargeReduction) { - QuicConfig config; - QuicTagVector options; - options.push_back(kSSLR); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - sender_->SetFromConfig(config, Perspective::IS_SERVER); - - sender_->SetNumEmulatedConnections(1); - const int kNumberOfAcks = 10; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Lose a packet to exit slow start. We should now have fallen out of - // slow start with a window reduced by 1. - LoseNPackets(1); - expected_send_window -= kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Lose 5 packets in recovery and verify that congestion window is reduced - // further. - LoseNPackets(5); - expected_send_window -= 5 * kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - size_t packets_in_recovery_window = expected_send_window / kDefaultTCPMSS; - - // Recovery phase. We need to ack every packet in the recovery window before - // we exit recovery. - size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; - DVLOG(1) << "number_packets: " << number_of_packets_in_window; - AckNPackets(packets_in_recovery_window); - SendAvailableSendWindow(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // We need to ack an entire window before we increase CWND by 1. - AckNPackets(number_of_packets_in_window - 1); - SendAvailableSendWindow(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Next ack should increase cwnd by 1. - AckNPackets(1); - expected_send_window += kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Now RTO and ensure slow start gets reset. - EXPECT_TRUE(sender_->hybrid_slow_start().started()); - sender_->OnRetransmissionTimeout(true); - EXPECT_FALSE(sender_->hybrid_slow_start().started()); -} - -TEST_F(TcpCubicBytesSenderTest, NoPRRWhenLessThanOnePacketInFlight) { - SendAvailableSendWindow(); - LoseNPackets(kInitialCongestionWindowPackets - 1); - AckNPackets(1); - // PRR will allow 2 packets for every ack during recovery. - EXPECT_EQ(2, SendAvailableSendWindow()); - // Simulate abandoning all packets by supplying a bytes_in_flight of 0. - // PRR should now allow a packet to be sent, even though prr's state variables - // believe it has sent enough packets. - EXPECT_EQ(QuicTime::Delta::Zero(), - sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)); -} - -TEST_F(TcpCubicBytesSenderTest, SlowStartPacketLossPRR) { - sender_->SetNumEmulatedConnections(1); - // Test based on the first example in RFC6937. - // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example. - const int kNumberOfAcks = 5; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - LoseNPackets(1); - - // We should now have fallen out of slow start with a reduced window. - size_t send_window_before_loss = expected_send_window; - expected_send_window *= kRenoBeta; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Testing TCP proportional rate reduction. - // We should send packets paced over the received acks for the remaining - // outstanding packets. The number of packets before we exit recovery is the - // original CWND minus the packet that has been lost and the one which - // triggered the loss. - size_t remaining_packets_in_recovery = - send_window_before_loss / kDefaultTCPMSS - 2; - - for (size_t i = 0; i < remaining_packets_in_recovery; ++i) { - AckNPackets(1); - SendAvailableSendWindow(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - } - - // We need to ack another window before we increase CWND by 1. - size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; - for (size_t i = 0; i < number_of_packets_in_window; ++i) { - AckNPackets(1); - EXPECT_EQ(1, SendAvailableSendWindow()); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - } - - AckNPackets(1); - expected_send_window += kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicBytesSenderTest, SlowStartBurstPacketLossPRR) { - sender_->SetNumEmulatedConnections(1); - // Test based on the second example in RFC6937, though we also implement - // forward acknowledgements, so the first two incoming acks will trigger - // PRR immediately. - // Ack 20 packets in 10 acks to raise the CWND to 30. - const int kNumberOfAcks = 10; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Lose one more than the congestion window reduction, so that after loss, - // bytes_in_flight is lesser than the congestion window. - size_t send_window_after_loss = kRenoBeta * expected_send_window; - size_t num_packets_to_lose = - (expected_send_window - send_window_after_loss) / kDefaultTCPMSS + 1; - LoseNPackets(num_packets_to_lose); - // Immediately after the loss, ensure at least one packet can be sent. - // Losses without subsequent acks can occur with timer based loss detection. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_, - HAS_RETRANSMITTABLE_DATA) - .IsZero()); - AckNPackets(1); - - // We should now have fallen out of slow start with a reduced window. - expected_send_window *= kRenoBeta; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Only 2 packets should be allowed to be sent, per PRR-SSRB. - EXPECT_EQ(2, SendAvailableSendWindow()); - - // Ack the next packet, which triggers another loss. - LoseNPackets(1); - AckNPackets(1); - - // Send 2 packets to simulate PRR-SSRB. - EXPECT_EQ(2, SendAvailableSendWindow()); - - // Ack the next packet, which triggers another loss. - LoseNPackets(1); - AckNPackets(1); - - // Send 2 packets to simulate PRR-SSRB. - EXPECT_EQ(2, SendAvailableSendWindow()); - - // Exit recovery and return to sending at the new rate. - for (int i = 0; i < kNumberOfAcks; ++i) { - AckNPackets(1); - EXPECT_EQ(1, SendAvailableSendWindow()); - } -} - -TEST_F(TcpCubicBytesSenderTest, RTOCongestionWindow) { - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); - // Expect the window to decrease to the minimum once the RTO fires and slow - // start threshold to be set to 1/2 of the CWND. - sender_->OnRetransmissionTimeout(true); - EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow()); - EXPECT_EQ(5u * kDefaultTCPMSS, sender_->GetSlowStartThreshold()); -} - -TEST_F(TcpCubicBytesSenderTest, RTOCongestionWindowNoRetransmission) { - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); - - // Expect the window to remain unchanged if the RTO fires but no packets are - // retransmitted. - sender_->OnRetransmissionTimeout(false); - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicBytesSenderTest, RetransmissionDelay) { - const int64_t kRttMs = 10; - const int64_t kDeviationMs = 3; - EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay()); - - sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs), - QuicTime::Delta::Zero(), clock_.Now()); - - // Initial value is to set the median deviation to half of the initial rtt, - // the median in then multiplied by a factor of 4 and finally the smoothed rtt - // is added which is the initial rtt. - QuicTime::Delta expected_delay = - QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4); - EXPECT_EQ(expected_delay, sender_->RetransmissionDelay()); - - for (int i = 0; i < 100; ++i) { - // Run to make sure that we converge. - sender_->rtt_stats_.UpdateRtt( - QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs), - QuicTime::Delta::Zero(), clock_.Now()); - sender_->rtt_stats_.UpdateRtt( - QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs), - QuicTime::Delta::Zero(), clock_.Now()); - } - expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4); - - EXPECT_NEAR(kRttMs, sender_->rtt_stats_.smoothed_rtt().ToMilliseconds(), 1); - EXPECT_NEAR(expected_delay.ToMilliseconds(), - sender_->RetransmissionDelay().ToMilliseconds(), 1); - EXPECT_EQ(static_cast<int64_t>( - sender_->GetCongestionWindow() * kNumMicrosPerSecond / - sender_->rtt_stats_.smoothed_rtt().ToMicroseconds()), - sender_->BandwidthEstimate().ToBytesPerSecond()); -} - -TEST_F(TcpCubicBytesSenderTest, TcpCubicResetEpochOnQuiescence) { - const int kMaxCongestionWindow = 50; - const QuicByteCount kMaxCongestionWindowBytes = - kMaxCongestionWindow * kDefaultTCPMSS; - int num_sent = SendAvailableSendWindow(); - - // Make sure we fall out of slow start. - QuicByteCount saved_cwnd = sender_->GetCongestionWindow(); - LoseNPackets(1); - EXPECT_GT(saved_cwnd, sender_->GetCongestionWindow()); - - // Ack the rest of the outstanding packets to get out of recovery. - for (int i = 1; i < num_sent; ++i) { - AckNPackets(1); - } - EXPECT_EQ(0u, bytes_in_flight_); - - // Send a new window of data and ack all; cubic growth should occur. - saved_cwnd = sender_->GetCongestionWindow(); - num_sent = SendAvailableSendWindow(); - for (int i = 0; i < num_sent; ++i) { - AckNPackets(1); - } - EXPECT_LT(saved_cwnd, sender_->GetCongestionWindow()); - EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow()); - EXPECT_EQ(0u, bytes_in_flight_); - - // Quiescent time of 100 seconds - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100000)); - - // Send new window of data and ack one packet. Cubic epoch should have - // been reset; ensure cwnd increase is not dramatic. - saved_cwnd = sender_->GetCongestionWindow(); - SendAvailableSendWindow(); - AckNPackets(1); - EXPECT_NEAR(saved_cwnd, sender_->GetCongestionWindow(), kDefaultTCPMSS); - EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicBytesSenderTest, MultipleLossesInOneWindow) { - SendAvailableSendWindow(); - const QuicByteCount initial_window = sender_->GetCongestionWindow(); - LosePacket(acked_packet_number_ + 1); - const QuicByteCount post_loss_window = sender_->GetCongestionWindow(); - EXPECT_GT(initial_window, post_loss_window); - LosePacket(acked_packet_number_ + 3); - EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); - LosePacket(packet_number_ - 1); - EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); - - // Lose a later packet and ensure the window decreases. - LosePacket(packet_number_); - EXPECT_GT(post_loss_window, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicBytesSenderTest, DontTrackAckPackets) { - // Send a packet with no retransmittable data, and ensure it's not tracked. - EXPECT_FALSE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, - packet_number_++, kDefaultTCPMSS, - NO_RETRANSMITTABLE_DATA)); - - // Send a data packet with retransmittable data, and ensure it is tracked. - EXPECT_TRUE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, - packet_number_++, kDefaultTCPMSS, - HAS_RETRANSMITTABLE_DATA)); -} - -TEST_F(TcpCubicBytesSenderTest, ConfigureMaxInitialWindow) { - QuicConfig config; - - // Verify that kCOPT: kIW10 forces the congestion window to the default of 10. - QuicTagVector options; - options.push_back(kIW10); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - sender_->SetFromConfig(config, Perspective::IS_SERVER); - EXPECT_EQ(10u * kDefaultTCPMSS, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicBytesSenderTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) { - sender_->SetNumEmulatedConnections(2); - // Ack 10 packets in 5 acks to raise the CWND to 20. - const int kNumberOfAcks = 5; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - LoseNPackets(1); - - // We should now have fallen out of slow start with a reduced window. - expected_send_window = expected_send_window * sender_->GetRenoBeta(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // No congestion window growth should occur in recovery phase, i.e., until the - // currently outstanding 20 packets are acked. - for (int i = 0; i < 10; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - EXPECT_TRUE(sender_->InRecovery()); - AckNPackets(2); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - } - EXPECT_FALSE(sender_->InRecovery()); - - // Out of recovery now. Congestion window should not grow for half an RTT. - size_t packets_in_send_window = expected_send_window / kDefaultTCPMSS; - SendAvailableSendWindow(); - AckNPackets(packets_in_send_window / 2 - 2); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Next ack should increase congestion window by 1MSS. - SendAvailableSendWindow(); - AckNPackets(2); - expected_send_window += kDefaultTCPMSS; - packets_in_send_window += 1; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Congestion window should remain steady again for half an RTT. - SendAvailableSendWindow(); - AckNPackets(packets_in_send_window / 2 - 1); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Next ack should cause congestion window to grow by 1MSS. - SendAvailableSendWindow(); - AckNPackets(2); - expected_send_window += kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicBytesSenderTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) { - sender_->SetNumEmulatedConnections(1); - // Ack 10 packets in 5 acks to raise the CWND to 20. - const int kNumberOfAcks = 5; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - LoseNPackets(1); - - // We should now have fallen out of slow start with a reduced window. - expected_send_window *= kRenoBeta; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // No congestion window growth should occur in recovery phase, i.e., until the - // currently outstanding 20 packets are acked. - for (int i = 0; i < 10; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - EXPECT_TRUE(sender_->InRecovery()); - AckNPackets(2); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - } - EXPECT_FALSE(sender_->InRecovery()); - - // Out of recovery now. Congestion window should not grow during RTT. - for (uint64_t i = 0; i < expected_send_window / kDefaultTCPMSS - 2; i += 2) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - } - - // Next ack should cause congestion window to grow by 1MSS. - SendAvailableSendWindow(); - AckNPackets(2); - expected_send_window += kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicBytesSenderTest, BandwidthResumption) { - // Test that when provided with CachedNetworkParameters and opted in to the - // bandwidth resumption experiment, that the TcpCubicSender sets initial CWND - // appropriately. - - // Set some common values. - CachedNetworkParameters cached_network_params; - const QuicPacketCount kNumberOfPackets = 123; - const int kBandwidthEstimateBytesPerSecond = - kNumberOfPackets * kDefaultTCPMSS; - cached_network_params.set_bandwidth_estimate_bytes_per_second( - kBandwidthEstimateBytesPerSecond); - cached_network_params.set_min_rtt_ms(1000); - - // Make sure that a bandwidth estimate results in a changed CWND. - cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() - - (kNumSecondsPerHour - 1)); - sender_->ResumeConnectionState(cached_network_params, false); - EXPECT_EQ(kNumberOfPackets * kDefaultTCPMSS, sender_->GetCongestionWindow()); - - // Resumed CWND is limited to be in a sensible range. - cached_network_params.set_bandwidth_estimate_bytes_per_second( - (kMaxCongestionWindow + 1) * kDefaultTCPMSS); - sender_->ResumeConnectionState(cached_network_params, false); - EXPECT_EQ(kMaxCongestionWindow * kDefaultTCPMSS, - sender_->GetCongestionWindow()); - - cached_network_params.set_bandwidth_estimate_bytes_per_second( - (kMinCongestionWindowForBandwidthResumption - 1) * kDefaultTCPMSS); - sender_->ResumeConnectionState(cached_network_params, false); - EXPECT_EQ(kMinCongestionWindowForBandwidthResumption * kDefaultTCPMSS, - sender_->GetCongestionWindow()); - - // Resume to the max value. - cached_network_params.set_max_bandwidth_estimate_bytes_per_second( - (kMinCongestionWindowForBandwidthResumption + 10) * kDefaultTCPMSS); - sender_->ResumeConnectionState(cached_network_params, true); - EXPECT_EQ((kMinCongestionWindowForBandwidthResumption + 10) * kDefaultTCPMSS, - sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicBytesSenderTest, PaceBelowCWND) { - QuicConfig config; - - // Verify that kCOPT: kMIN4 forces the min CWND to 1 packet, but allows up - // to 4 to be sent. - QuicTagVector options; - options.push_back(kMIN4); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - sender_->SetFromConfig(config, Perspective::IS_SERVER); - sender_->OnRetransmissionTimeout(true); - EXPECT_EQ(kDefaultTCPMSS, sender_->GetCongestionWindow()); - EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS, - HAS_RETRANSMITTABLE_DATA) - .IsZero()); - EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS, - HAS_RETRANSMITTABLE_DATA) - .IsZero()); - EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS, - HAS_RETRANSMITTABLE_DATA) - .IsZero()); - EXPECT_FALSE(sender_->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS, - HAS_RETRANSMITTABLE_DATA) - .IsZero()); -} - -TEST_F(TcpCubicBytesSenderTest, ResetAfterConnectionMigration) { - // Starts from slow start. - sender_->SetNumEmulatedConnections(1); - const int kNumberOfAcks = 10; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Loses a packet to exit slow start. - LoseNPackets(1); - - // We should now have fallen out of slow start with a reduced window. Slow - // start threshold is also updated. - expected_send_window *= kRenoBeta; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - EXPECT_EQ(expected_send_window, sender_->GetSlowStartThreshold()); - - // Resets cwnd and slow start threshold on connection migrations. - sender_->OnConnectionMigration(); - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); - EXPECT_EQ(kMaxCongestionWindow * kDefaultTCPMSS, - sender_->GetSlowStartThreshold()); - EXPECT_FALSE(sender_->hybrid_slow_start().started()); -} - -} // namespace test -} // namespace net diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc deleted file mode 100644 index f78f587..0000000 --- a/net/quic/congestion_control/tcp_cubic_sender.cc +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright (c) 2012 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/congestion_control/tcp_cubic_sender.h" - -#include <algorithm> - -#include "base/metrics/histogram_macros.h" -#include "net/quic/congestion_control/prr_sender.h" -#include "net/quic/congestion_control/rtt_stats.h" -#include "net/quic/crypto/crypto_protocol.h" -#include "net/quic/proto/cached_network_parameters.pb.h" -#include "net/quic/quic_bug_tracker.h" -#include "net/quic/quic_flags.h" - -using std::max; -using std::min; - -namespace net { - -namespace { -// Constants based on TCP defaults. -// The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a -// fast retransmission. The cwnd after a timeout is still 1. -const QuicPacketCount kDefaultMinimumCongestionWindow = 2; -const QuicByteCount kMaxBurstBytes = 3 * kDefaultTCPMSS; -const float kRenoBeta = 0.7f; // Reno backoff factor. -const uint32_t kDefaultNumConnections = 2; // N-connection emulation. -} // namespace - -TcpCubicSender::TcpCubicSender(const QuicClock* clock, - const RttStats* rtt_stats, - bool reno, - QuicPacketCount initial_tcp_congestion_window, - QuicPacketCount max_tcp_congestion_window, - QuicConnectionStats* stats) - : cubic_(clock), - rtt_stats_(rtt_stats), - stats_(stats), - reno_(reno), - num_connections_(kDefaultNumConnections), - congestion_window_count_(0), - largest_sent_packet_number_(0), - largest_acked_packet_number_(0), - largest_sent_at_last_cutback_(0), - congestion_window_(initial_tcp_congestion_window), - min_congestion_window_(kDefaultMinimumCongestionWindow), - min4_mode_(false), - slowstart_threshold_(max_tcp_congestion_window), - last_cutback_exited_slowstart_(false), - max_tcp_congestion_window_(max_tcp_congestion_window), - initial_tcp_congestion_window_(initial_tcp_congestion_window), - initial_max_tcp_congestion_window_(max_tcp_congestion_window), - slow_start_large_reduction_(false) {} - -TcpCubicSender::~TcpCubicSender() { - UMA_HISTOGRAM_COUNTS("Net.QuicSession.FinalTcpCwnd", congestion_window_); -} - -void TcpCubicSender::SetFromConfig(const QuicConfig& config, - Perspective perspective) { - if (perspective == Perspective::IS_SERVER) { - if (config.HasReceivedConnectionOptions() && - ContainsQuicTag(config.ReceivedConnectionOptions(), kIW03)) { - // Initial window experiment. - congestion_window_ = 3; - } - if (config.HasReceivedConnectionOptions() && - ContainsQuicTag(config.ReceivedConnectionOptions(), kIW10)) { - // Initial window experiment. - congestion_window_ = 10; - } - if (config.HasReceivedConnectionOptions() && - ContainsQuicTag(config.ReceivedConnectionOptions(), kIW20)) { - // Initial window experiment. - congestion_window_ = 20; - } - if (config.HasReceivedConnectionOptions() && - ContainsQuicTag(config.ReceivedConnectionOptions(), kIW50)) { - // Initial window experiment. - congestion_window_ = 50; - } - if (config.HasReceivedConnectionOptions() && - ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN1)) { - // Min CWND experiment. - min_congestion_window_ = 1; - } - if (config.HasReceivedConnectionOptions() && - ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN4)) { - // Min CWND of 4 experiment. - min4_mode_ = true; - min_congestion_window_ = 1; - } - if (config.HasReceivedConnectionOptions() && - ContainsQuicTag(config.ReceivedConnectionOptions(), kSSLR)) { - // Slow Start Fast Exit experiment. - slow_start_large_reduction_ = true; - } - } -} - -void TcpCubicSender::ResumeConnectionState( - const CachedNetworkParameters& cached_network_params, - bool max_bandwidth_resumption) { - QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond( - max_bandwidth_resumption - ? cached_network_params.max_bandwidth_estimate_bytes_per_second() - : cached_network_params.bandwidth_estimate_bytes_per_second()); - QuicTime::Delta rtt_ms = - QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms()); - - // Make sure CWND is in appropriate range (in case of bad data). - QuicPacketCount new_congestion_window = - bandwidth.ToBytesPerPeriod(rtt_ms) / kDefaultTCPMSS; - congestion_window_ = max(min(new_congestion_window, kMaxCongestionWindow), - kMinCongestionWindowForBandwidthResumption); -} - -void TcpCubicSender::SetNumEmulatedConnections(int num_connections) { - num_connections_ = max(1, num_connections); - cubic_.SetNumConnections(num_connections_); -} - -void TcpCubicSender::SetMaxCongestionWindow( - QuicByteCount max_congestion_window) { - max_tcp_congestion_window_ = max_congestion_window / kDefaultTCPMSS; -} - -float TcpCubicSender::RenoBeta() const { - // kNConnectionBeta is the backoff factor after loss for our N-connection - // emulation, which emulates the effective backoff of an ensemble of N - // TCP-Reno connections on a single loss event. The effective multiplier is - // computed as: - return (num_connections_ - 1 + kRenoBeta) / num_connections_; -} - -void TcpCubicSender::OnCongestionEvent(bool rtt_updated, - QuicByteCount bytes_in_flight, - const CongestionVector& acked_packets, - const CongestionVector& lost_packets) { - if (rtt_updated && InSlowStart() && - hybrid_slow_start_.ShouldExitSlowStart(rtt_stats_->latest_rtt(), - rtt_stats_->min_rtt(), - congestion_window_)) { - slowstart_threshold_ = congestion_window_; - } - for (CongestionVector::const_iterator it = lost_packets.begin(); - it != lost_packets.end(); ++it) { - OnPacketLost(it->first, bytes_in_flight); - } - for (CongestionVector::const_iterator it = acked_packets.begin(); - it != acked_packets.end(); ++it) { - OnPacketAcked(it->first, it->second, bytes_in_flight); - } -} - -void TcpCubicSender::OnPacketAcked(QuicPacketNumber acked_packet_number, - QuicByteCount acked_bytes, - QuicByteCount bytes_in_flight) { - largest_acked_packet_number_ = - max(acked_packet_number, largest_acked_packet_number_); - if (InRecovery()) { - // PRR is used when in recovery. - prr_.OnPacketAcked(acked_bytes); - return; - } - MaybeIncreaseCwnd(acked_packet_number, bytes_in_flight); - if (InSlowStart()) { - hybrid_slow_start_.OnPacketAcked(acked_packet_number); - } -} - -void TcpCubicSender::OnPacketLost(QuicPacketNumber packet_number, - QuicByteCount bytes_in_flight) { - // TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets - // already sent should be treated as a single loss event, since it's expected. - if (packet_number <= largest_sent_at_last_cutback_) { - if (last_cutback_exited_slowstart_) { - ++stats_->slowstart_packets_lost; - if (slow_start_large_reduction_) { - // Reduce congestion window by 1 for every loss. - congestion_window_ = - max(congestion_window_ - 1, min_congestion_window_); - slowstart_threshold_ = congestion_window_; - } - } - DVLOG(1) << "Ignoring loss for largest_missing:" << packet_number - << " because it was sent prior to the last CWND cutback."; - return; - } - ++stats_->tcp_loss_events; - last_cutback_exited_slowstart_ = InSlowStart(); - if (InSlowStart()) { - ++stats_->slowstart_packets_lost; - } - - prr_.OnPacketLost(bytes_in_flight); - - // TODO(jri): Separate out all of slow start into a separate class. - if (slow_start_large_reduction_ && InSlowStart()) { - DCHECK_LT(1u, congestion_window_); - congestion_window_ = congestion_window_ - 1; - } else if (reno_) { - congestion_window_ = congestion_window_ * RenoBeta(); - } else { - congestion_window_ = - cubic_.CongestionWindowAfterPacketLoss(congestion_window_); - } - // Enforce a minimum congestion window. - if (congestion_window_ < min_congestion_window_) { - congestion_window_ = min_congestion_window_; - } - slowstart_threshold_ = congestion_window_; - largest_sent_at_last_cutback_ = largest_sent_packet_number_; - // reset packet count from congestion avoidance mode. We start - // counting again when we're out of recovery. - congestion_window_count_ = 0; - DVLOG(1) << "Incoming loss; congestion window: " << congestion_window_ - << " slowstart threshold: " << slowstart_threshold_; -} - -bool TcpCubicSender::OnPacketSent(QuicTime /*sent_time*/, - QuicByteCount /*bytes_in_flight*/, - QuicPacketNumber packet_number, - QuicByteCount bytes, - HasRetransmittableData is_retransmittable) { - if (InSlowStart()) { - ++(stats_->slowstart_packets_sent); - } - - // Only update bytes_in_flight_ for data packets. - if (is_retransmittable != HAS_RETRANSMITTABLE_DATA) { - return false; - } - if (InRecovery()) { - // PRR is used when in recovery. - prr_.OnPacketSent(bytes); - } - DCHECK_LT(largest_sent_packet_number_, packet_number); - largest_sent_packet_number_ = packet_number; - hybrid_slow_start_.OnPacketSent(packet_number); - return true; -} - -QuicTime::Delta TcpCubicSender::TimeUntilSend( - QuicTime /* now */, - QuicByteCount bytes_in_flight, - HasRetransmittableData has_retransmittable_data) const { - if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) { - DCHECK(!FLAGS_quic_respect_send_alarm2); - // For TCP we can always send an ACK immediately. - return QuicTime::Delta::Zero(); - } - if (InRecovery()) { - // PRR is used when in recovery. - return prr_.TimeUntilSend(GetCongestionWindow(), bytes_in_flight, - slowstart_threshold_ * kDefaultTCPMSS); - } - if (GetCongestionWindow() > bytes_in_flight) { - return QuicTime::Delta::Zero(); - } - if (min4_mode_ && bytes_in_flight < 4 * kDefaultTCPMSS) { - return QuicTime::Delta::Zero(); - } - return QuicTime::Delta::Infinite(); -} - -QuicBandwidth TcpCubicSender::PacingRate() const { - // We pace at twice the rate of the underlying sender's bandwidth estimate - // during slow start and 1.25x during congestion avoidance to ensure pacing - // doesn't prevent us from filling the window. - QuicTime::Delta srtt = rtt_stats_->smoothed_rtt(); - if (srtt.IsZero()) { - srtt = QuicTime::Delta::FromMicroseconds(rtt_stats_->initial_rtt_us()); - } - const QuicBandwidth bandwidth = - QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt); - return bandwidth.Scale(InSlowStart() ? 2 : 1.25); -} - -QuicBandwidth TcpCubicSender::BandwidthEstimate() const { - QuicTime::Delta srtt = rtt_stats_->smoothed_rtt(); - if (srtt.IsZero()) { - // If we haven't measured an rtt, the bandwidth estimate is unknown. - return QuicBandwidth::Zero(); - } - return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), srtt); -} - -QuicTime::Delta TcpCubicSender::RetransmissionDelay() const { - if (rtt_stats_->smoothed_rtt().IsZero()) { - return QuicTime::Delta::Zero(); - } - return rtt_stats_->smoothed_rtt().Add( - rtt_stats_->mean_deviation().Multiply(4)); -} - -QuicByteCount TcpCubicSender::GetCongestionWindow() const { - return congestion_window_ * kDefaultTCPMSS; -} - -bool TcpCubicSender::InSlowStart() const { - return congestion_window_ < slowstart_threshold_; -} - -QuicByteCount TcpCubicSender::GetSlowStartThreshold() const { - return slowstart_threshold_ * kDefaultTCPMSS; -} - -bool TcpCubicSender::IsCwndLimited(QuicByteCount bytes_in_flight) const { - const QuicByteCount congestion_window_bytes = GetCongestionWindow(); - if (bytes_in_flight >= congestion_window_bytes) { - return true; - } - const QuicByteCount available_bytes = - congestion_window_bytes - bytes_in_flight; - const bool slow_start_limited = - InSlowStart() && bytes_in_flight > congestion_window_bytes / 2; - return slow_start_limited || available_bytes <= kMaxBurstBytes; -} - -bool TcpCubicSender::InRecovery() const { - return largest_acked_packet_number_ <= largest_sent_at_last_cutback_ && - largest_acked_packet_number_ != 0; -} - -// Called when we receive an ack. Normal TCP tracks how many packets one ack -// represents, but quic has a separate ack for each packet. -void TcpCubicSender::MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number, - QuicByteCount bytes_in_flight) { - QUIC_BUG_IF(InRecovery()) << "Never increase the CWND during recovery."; - // Do not increase the congestion window unless the sender is close to using - // the current window. - if (!IsCwndLimited(bytes_in_flight)) { - cubic_.OnApplicationLimited(); - return; - } - if (congestion_window_ >= max_tcp_congestion_window_) { - return; - } - if (InSlowStart()) { - // TCP slow start, exponential growth, increase by one for each ACK. - ++congestion_window_; - DVLOG(1) << "Slow start; congestion window: " << congestion_window_ - << " slowstart threshold: " << slowstart_threshold_; - return; - } - // Congestion avoidance - if (reno_) { - // Classic Reno congestion avoidance. - ++congestion_window_count_; - // Divide by num_connections to smoothly increase the CWND at a faster - // rate than conventional Reno. - if (congestion_window_count_ * num_connections_ >= congestion_window_) { - ++congestion_window_; - congestion_window_count_ = 0; - } - - DVLOG(1) << "Reno; congestion window: " << congestion_window_ - << " slowstart threshold: " << slowstart_threshold_ - << " congestion window count: " << congestion_window_count_; - } else { - congestion_window_ = min(max_tcp_congestion_window_, - cubic_.CongestionWindowAfterAck( - congestion_window_, rtt_stats_->min_rtt())); - DVLOG(1) << "Cubic; congestion window: " << congestion_window_ - << " slowstart threshold: " << slowstart_threshold_; - } -} - -void TcpCubicSender::OnRetransmissionTimeout(bool packets_retransmitted) { - largest_sent_at_last_cutback_ = 0; - if (!packets_retransmitted) { - return; - } - cubic_.Reset(); - hybrid_slow_start_.Restart(); - slowstart_threshold_ = congestion_window_ / 2; - congestion_window_ = min_congestion_window_; -} - -void TcpCubicSender::OnConnectionMigration() { - hybrid_slow_start_.Restart(); - cubic_.Reset(); - prr_ = PrrSender(); - congestion_window_count_ = 0; - largest_sent_packet_number_ = 0; - largest_acked_packet_number_ = 0; - largest_sent_at_last_cutback_ = 0; - congestion_window_ = initial_tcp_congestion_window_; - slowstart_threshold_ = initial_max_tcp_congestion_window_; - last_cutback_exited_slowstart_ = false; - max_tcp_congestion_window_ = initial_max_tcp_congestion_window_; -} - -CongestionControlType TcpCubicSender::GetCongestionControlType() const { - return reno_ ? kReno : kCubic; -} - -} // namespace net diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h deleted file mode 100644 index 9b253a3..0000000 --- a/net/quic/congestion_control/tcp_cubic_sender.h +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2012 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. -// -// TCP cubic send side congestion algorithm, emulates the behavior of TCP cubic. - -#ifndef NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_H_ -#define NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_H_ - -#include <stdint.h> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "net/base/net_export.h" -#include "net/quic/congestion_control/cubic.h" -#include "net/quic/congestion_control/hybrid_slow_start.h" -#include "net/quic/congestion_control/prr_sender.h" -#include "net/quic/congestion_control/send_algorithm_interface.h" -#include "net/quic/quic_bandwidth.h" -#include "net/quic/quic_connection_stats.h" -#include "net/quic/quic_protocol.h" -#include "net/quic/quic_time.h" - -namespace net { - -class RttStats; - -namespace test { -class TcpCubicSenderPeer; -} // namespace test - -class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface { - public: - // Reno option and max_tcp_congestion_window are provided for testing. - TcpCubicSender(const QuicClock* clock, - const RttStats* rtt_stats, - bool reno, - QuicPacketCount initial_tcp_congestion_window, - QuicPacketCount max_tcp_congestion_window, - QuicConnectionStats* stats); - ~TcpCubicSender() override; - - // Start implementation of SendAlgorithmInterface. - void SetFromConfig(const QuicConfig& config, - Perspective perspective) override; - void ResumeConnectionState( - const CachedNetworkParameters& cached_network_params, - bool max_bandwidth_resumption) override; - void SetNumEmulatedConnections(int num_connections) override; - void SetMaxCongestionWindow(QuicByteCount max_congestion_window) override; - void OnCongestionEvent(bool rtt_updated, - QuicByteCount bytes_in_flight, - const CongestionVector& acked_packets, - const CongestionVector& lost_packets) override; - bool OnPacketSent(QuicTime sent_time, - QuicByteCount bytes_in_flight, - QuicPacketNumber packet_number, - QuicByteCount bytes, - HasRetransmittableData is_retransmittable) override; - void OnRetransmissionTimeout(bool packets_retransmitted) override; - void OnConnectionMigration() override; - QuicTime::Delta TimeUntilSend( - QuicTime now, - QuicByteCount bytes_in_flight, - HasRetransmittableData has_retransmittable_data) const override; - QuicBandwidth PacingRate() const override; - QuicBandwidth BandwidthEstimate() const override; - QuicTime::Delta RetransmissionDelay() const override; - QuicByteCount GetCongestionWindow() const override; - bool InSlowStart() const override; - bool InRecovery() const override; - QuicByteCount GetSlowStartThreshold() const override; - CongestionControlType GetCongestionControlType() const override; - // End implementation of SendAlgorithmInterface. - - private: - friend class test::TcpCubicSenderPeer; - - // Compute the TCP Reno beta based on the current number of connections. - float RenoBeta() const; - - // TODO(ianswett): Remove these and migrate to OnCongestionEvent. - void OnPacketAcked(QuicPacketNumber acked_packet_number, - QuicByteCount acked_bytes, - QuicByteCount bytes_in_flight); - void OnPacketLost(QuicPacketNumber largest_loss, - QuicByteCount bytes_in_flight); - - void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number, - QuicByteCount bytes_in_flight); - bool IsCwndLimited(QuicByteCount bytes_in_flight) const; - - HybridSlowStart hybrid_slow_start_; - Cubic cubic_; - PrrSender prr_; - const RttStats* rtt_stats_; - QuicConnectionStats* stats_; - - // If true, Reno congestion control is used instead of Cubic. - const bool reno_; - - // Number of connections to simulate. - uint32_t num_connections_; - - // ACK counter for the Reno implementation. - uint64_t congestion_window_count_; - - // Track the largest packet that has been sent. - QuicPacketNumber largest_sent_packet_number_; - - // Track the largest packet that has been acked. - QuicPacketNumber largest_acked_packet_number_; - - // Track the largest packet number outstanding when a CWND cutback occurs. - QuicPacketNumber largest_sent_at_last_cutback_; - - // Congestion window in packets. - QuicPacketCount congestion_window_; - - // Minimum congestion window in packets. - QuicPacketCount min_congestion_window_; - - // Whether to use 4 packets as the actual min, but pace lower. - bool min4_mode_; - - // Slow start congestion window in packets, aka ssthresh. - QuicPacketCount slowstart_threshold_; - - // Whether the last loss event caused us to exit slowstart. - // Used for stats collection of slowstart_packets_lost - bool last_cutback_exited_slowstart_; - - // Maximum number of outstanding packets for tcp. - QuicPacketCount max_tcp_congestion_window_; - - // Initial TCP congestion window. This variable can only be set when this - // algorithm is created. - const QuicPacketCount initial_tcp_congestion_window_; - - // Initial maximum TCP congestion window. This variable can only be set when - // this algorithm is created. - const QuicPacketCount initial_max_tcp_congestion_window_; - - // When true, exit slow start with large cutback of congestion window. - bool slow_start_large_reduction_; - - DISALLOW_COPY_AND_ASSIGN(TcpCubicSender); -}; - -} // namespace net - -#endif // NET_QUIC_CONGESTION_CONTROL_TCP_CUBIC_SENDER_H_ diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc deleted file mode 100644 index 13ae6c1..0000000 --- a/net/quic/congestion_control/tcp_cubic_sender_test.cc +++ /dev/null @@ -1,887 +0,0 @@ -// Copyright (c) 2012 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/congestion_control/tcp_cubic_sender.h" - -#include <algorithm> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "net/quic/congestion_control/rtt_stats.h" -#include "net/quic/crypto/crypto_protocol.h" -#include "net/quic/proto/cached_network_parameters.pb.h" -#include "net/quic/quic_flags.h" -#include "net/quic/quic_protocol.h" -#include "net/quic/quic_utils.h" -#include "net/quic/test_tools/mock_clock.h" -#include "net/quic/test_tools/quic_config_peer.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -using std::min; - -namespace net { -namespace test { - -// TODO(ianswett): A number of theses tests were written with the assumption of -// an initial CWND of 10. They have carefully calculated values which should be -// updated to be based on kInitialCongestionWindow. -const uint32_t kInitialCongestionWindowPackets = 10; -const uint32_t kDefaultWindowTCP = - kInitialCongestionWindowPackets * kDefaultTCPMSS; -const float kRenoBeta = 0.7f; // Reno backoff factor. - -class TcpCubicSenderPeer : public TcpCubicSender { - public: - TcpCubicSenderPeer(const QuicClock* clock, - bool reno, - QuicPacketCount max_tcp_congestion_window) - : TcpCubicSender(clock, - &rtt_stats_, - reno, - kInitialCongestionWindowPackets, - max_tcp_congestion_window, - &stats_) {} - - QuicPacketCount congestion_window() { return congestion_window_; } - - QuicPacketCount slowstart_threshold() { return slowstart_threshold_; } - - const HybridSlowStart& hybrid_slow_start() const { - return hybrid_slow_start_; - } - - float GetRenoBeta() const { return RenoBeta(); } - - RttStats rtt_stats_; - QuicConnectionStats stats_; -}; - -class TcpCubicSenderTest : public ::testing::Test { - protected: - TcpCubicSenderTest() - : one_ms_(QuicTime::Delta::FromMilliseconds(1)), - sender_(new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindow)), - packet_number_(1), - acked_packet_number_(0), - bytes_in_flight_(0) {} - - int SendAvailableSendWindow() { - // Send as long as TimeUntilSend returns Zero. - int packets_sent = 0; - bool can_send = sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_, - HAS_RETRANSMITTABLE_DATA) - .IsZero(); - while (can_send) { - sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, packet_number_++, - kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA); - ++packets_sent; - bytes_in_flight_ += kDefaultTCPMSS; - can_send = sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_, - HAS_RETRANSMITTABLE_DATA) - .IsZero(); - } - return packets_sent; - } - - // Normal is that TCP acks every other segment. - void AckNPackets(int n) { - sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(60), - QuicTime::Delta::Zero(), clock_.Now()); - SendAlgorithmInterface::CongestionVector acked_packets; - SendAlgorithmInterface::CongestionVector lost_packets; - for (int i = 0; i < n; ++i) { - ++acked_packet_number_; - acked_packets.push_back( - std::make_pair(acked_packet_number_, kDefaultTCPMSS)); - } - sender_->OnCongestionEvent(true, bytes_in_flight_, acked_packets, - lost_packets); - bytes_in_flight_ -= n * kDefaultTCPMSS; - clock_.AdvanceTime(one_ms_); - } - - void LoseNPackets(int n) { - SendAlgorithmInterface::CongestionVector acked_packets; - SendAlgorithmInterface::CongestionVector lost_packets; - for (int i = 0; i < n; ++i) { - ++acked_packet_number_; - lost_packets.push_back( - std::make_pair(acked_packet_number_, kDefaultTCPMSS)); - } - sender_->OnCongestionEvent(false, bytes_in_flight_, acked_packets, - lost_packets); - bytes_in_flight_ -= n * kDefaultTCPMSS; - } - - // Does not increment acked_packet_number_. - void LosePacket(QuicPacketNumber packet_number) { - SendAlgorithmInterface::CongestionVector acked_packets; - SendAlgorithmInterface::CongestionVector lost_packets; - lost_packets.push_back(std::make_pair(packet_number, kDefaultTCPMSS)); - sender_->OnCongestionEvent(false, bytes_in_flight_, acked_packets, - lost_packets); - bytes_in_flight_ -= kDefaultTCPMSS; - } - - const QuicTime::Delta one_ms_; - MockClock clock_; - scoped_ptr<TcpCubicSenderPeer> sender_; - QuicPacketNumber packet_number_; - QuicPacketNumber acked_packet_number_; - QuicByteCount bytes_in_flight_; -}; - -TEST_F(TcpCubicSenderTest, SimpleSender) { - // At startup make sure we are at the default. - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); - // At startup make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - // Make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - // And that window is un-affected. - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); - - // Fill the send window with data, then verify that we can't send. - SendAvailableSendWindow(); - EXPECT_FALSE(sender_->TimeUntilSend(clock_.Now(), - sender_->GetCongestionWindow(), - HAS_RETRANSMITTABLE_DATA) - .IsZero()); -} - -TEST_F(TcpCubicSenderTest, ApplicationLimitedSlowStart) { - // Send exactly 10 packets and ensure the CWND ends at 14 packets. - const int kNumberOfAcks = 5; - // At startup make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - // Make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - - SendAvailableSendWindow(); - for (int i = 0; i < kNumberOfAcks; ++i) { - AckNPackets(2); - } - QuicByteCount bytes_to_send = sender_->GetCongestionWindow(); - // It's expected 2 acks will arrive when the bytes_in_flight are greater than - // half the CWND. - EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * 2, bytes_to_send); -} - -TEST_F(TcpCubicSenderTest, ExponentialSlowStart) { - const int kNumberOfAcks = 20; - // At startup make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - EXPECT_EQ(QuicBandwidth::Zero(), sender_->BandwidthEstimate()); - // Make sure we can send. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA) - .IsZero()); - - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - const QuicByteCount cwnd = sender_->GetCongestionWindow(); - EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks, cwnd); - EXPECT_EQ(QuicBandwidth::FromBytesAndTimeDelta( - cwnd, sender_->rtt_stats_.smoothed_rtt()), - sender_->BandwidthEstimate()); -} - -TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) { - sender_->SetNumEmulatedConnections(1); - const int kNumberOfAcks = 10; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Lose a packet to exit slow start. - LoseNPackets(1); - size_t packets_in_recovery_window = expected_send_window / kDefaultTCPMSS; - - // We should now have fallen out of slow start with a reduced window. - expected_send_window *= kRenoBeta; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Recovery phase. We need to ack every packet in the recovery window before - // we exit recovery. - size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; - DVLOG(1) << "number_packets: " << number_of_packets_in_window; - AckNPackets(packets_in_recovery_window); - SendAvailableSendWindow(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // We need to ack an entire window before we increase CWND by 1. - AckNPackets(number_of_packets_in_window - 2); - SendAvailableSendWindow(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Next ack should increase cwnd by 1. - AckNPackets(1); - expected_send_window += kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Now RTO and ensure slow start gets reset. - EXPECT_TRUE(sender_->hybrid_slow_start().started()); - sender_->OnRetransmissionTimeout(true); - EXPECT_FALSE(sender_->hybrid_slow_start().started()); -} - -TEST_F(TcpCubicSenderTest, SlowStartPacketLossWithLargeReduction) { - QuicConfig config; - QuicTagVector options; - options.push_back(kSSLR); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - sender_->SetFromConfig(config, Perspective::IS_SERVER); - - sender_->SetNumEmulatedConnections(1); - const int kNumberOfAcks = 10; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Lose a packet to exit slow start. We should now have fallen out of - // slow start with a window reduced by 1. - LoseNPackets(1); - expected_send_window -= kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Lose 5 packets in recovery and verify that congestion window is reduced - // further. - LoseNPackets(5); - expected_send_window -= 5 * kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - size_t packets_in_recovery_window = expected_send_window / kDefaultTCPMSS; - - // Recovery phase. We need to ack every packet in the recovery window before - // we exit recovery. - size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; - DVLOG(1) << "number_packets: " << number_of_packets_in_window; - AckNPackets(packets_in_recovery_window); - SendAvailableSendWindow(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // We need to ack the rest of the window before cwnd increases by 1. - AckNPackets(number_of_packets_in_window - 1); - SendAvailableSendWindow(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Next ack should increase cwnd by 1. - AckNPackets(1); - expected_send_window += kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Now RTO and ensure slow start gets reset. - EXPECT_TRUE(sender_->hybrid_slow_start().started()); - sender_->OnRetransmissionTimeout(true); - EXPECT_FALSE(sender_->hybrid_slow_start().started()); -} - -TEST_F(TcpCubicSenderTest, NoPRRWhenLessThanOnePacketInFlight) { - SendAvailableSendWindow(); - LoseNPackets(kInitialCongestionWindowPackets - 1); - AckNPackets(1); - // PRR will allow 2 packets for every ack during recovery. - EXPECT_EQ(2, SendAvailableSendWindow()); - // Simulate abandoning all packets by supplying a bytes_in_flight of 0. - // PRR should now allow a packet to be sent, even though prr's state - // variables believe it has sent enough packets. - EXPECT_EQ(QuicTime::Delta::Zero(), - sender_->TimeUntilSend(clock_.Now(), 0, HAS_RETRANSMITTABLE_DATA)); -} - -TEST_F(TcpCubicSenderTest, SlowStartPacketLossPRR) { - sender_->SetNumEmulatedConnections(1); - // Test based on the first example in RFC6937. - // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example. - const int kNumberOfAcks = 5; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - LoseNPackets(1); - - // We should now have fallen out of slow start with a reduced window. - size_t send_window_before_loss = expected_send_window; - expected_send_window *= kRenoBeta; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Testing TCP proportional rate reduction. - // We should send packets paced over the received acks for the remaining - // outstanding packets. The number of packets before we exit recovery is the - // original CWND minus the packet that has been lost and the one which - // triggered the loss. - size_t remaining_packets_in_recovery = - send_window_before_loss / kDefaultTCPMSS - 2; - - for (size_t i = 0; i < remaining_packets_in_recovery; ++i) { - AckNPackets(1); - SendAvailableSendWindow(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - } - - // We need to ack another window before we increase CWND by 1. - size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS; - for (size_t i = 0; i < number_of_packets_in_window; ++i) { - AckNPackets(1); - EXPECT_EQ(1, SendAvailableSendWindow()); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - } - - AckNPackets(1); - expected_send_window += kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicSenderTest, SlowStartBurstPacketLossPRR) { - sender_->SetNumEmulatedConnections(1); - // Test based on the second example in RFC6937, though we also implement - // forward acknowledgements, so the first two incoming acks will trigger - // PRR immediately. - // Ack 20 packets in 10 acks to raise the CWND to 30. - const int kNumberOfAcks = 10; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Lose one more than the congestion window reduction, so that after loss, - // bytes_in_flight is lesser than the congestion window. - size_t send_window_after_loss = kRenoBeta * expected_send_window; - size_t num_packets_to_lose = - (expected_send_window - send_window_after_loss) / kDefaultTCPMSS + 1; - LoseNPackets(num_packets_to_lose); - // Immediately after the loss, ensure at least one packet can be sent. - // Losses without subsequent acks can occur with timer based loss detection. - EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_, - HAS_RETRANSMITTABLE_DATA) - .IsZero()); - AckNPackets(1); - - // We should now have fallen out of slow start with a reduced window. - expected_send_window *= kRenoBeta; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Only 2 packets should be allowed to be sent, per PRR-SSRB - EXPECT_EQ(2, SendAvailableSendWindow()); - - // Ack the next packet, which triggers another loss. - LoseNPackets(1); - AckNPackets(1); - - // Send 2 packets to simulate PRR-SSRB. - EXPECT_EQ(2, SendAvailableSendWindow()); - - // Ack the next packet, which triggers another loss. - LoseNPackets(1); - AckNPackets(1); - - // Send 2 packets to simulate PRR-SSRB. - EXPECT_EQ(2, SendAvailableSendWindow()); - - // Exit recovery and return to sending at the new rate. - for (int i = 0; i < kNumberOfAcks; ++i) { - AckNPackets(1); - EXPECT_EQ(1, SendAvailableSendWindow()); - } -} - -TEST_F(TcpCubicSenderTest, RTOCongestionWindow) { - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); - EXPECT_EQ(kMaxCongestionWindow, sender_->slowstart_threshold()); - - // Expect the window to decrease to the minimum once the RTO fires - // and slow start threshold to be set to 1/2 of the CWND. - sender_->OnRetransmissionTimeout(true); - EXPECT_EQ(2 * kDefaultTCPMSS, sender_->GetCongestionWindow()); - EXPECT_EQ(5u, sender_->slowstart_threshold()); -} - -TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) { - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); - - // Expect the window to remain unchanged if the RTO fires but no - // packets are retransmitted. - sender_->OnRetransmissionTimeout(false); - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicSenderTest, RetransmissionDelay) { - const int64_t kRttMs = 10; - const int64_t kDeviationMs = 3; - EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay()); - - sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs), - QuicTime::Delta::Zero(), clock_.Now()); - - // Initial value is to set the median deviation to half of the initial - // rtt, the median in then multiplied by a factor of 4 and finally the - // smoothed rtt is added which is the initial rtt. - QuicTime::Delta expected_delay = - QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4); - EXPECT_EQ(expected_delay, sender_->RetransmissionDelay()); - - for (int i = 0; i < 100; ++i) { - // Run to make sure that we converge. - sender_->rtt_stats_.UpdateRtt( - QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs), - QuicTime::Delta::Zero(), clock_.Now()); - sender_->rtt_stats_.UpdateRtt( - QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs), - QuicTime::Delta::Zero(), clock_.Now()); - } - expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4); - - EXPECT_NEAR(kRttMs, sender_->rtt_stats_.smoothed_rtt().ToMilliseconds(), 1); - EXPECT_NEAR(expected_delay.ToMilliseconds(), - sender_->RetransmissionDelay().ToMilliseconds(), 1); - EXPECT_EQ(static_cast<int64_t>( - sender_->GetCongestionWindow() * kNumMicrosPerSecond / - sender_->rtt_stats_.smoothed_rtt().ToMicroseconds()), - sender_->BandwidthEstimate().ToBytesPerSecond()); -} - -TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) { - const QuicPacketCount kMaxCongestionWindowTCP = 50; - const int kNumberOfAcks = 100; - sender_.reset( - new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP)); - - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) { - const QuicPacketCount kMaxCongestionWindowTCP = 50; - const int kNumberOfAcks = 1000; - sender_.reset(new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindowTCP)); - - SendAvailableSendWindow(); - AckNPackets(2); - // Make sure we fall out of slow start. - LoseNPackets(1); - - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - - QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) { - const QuicPacketCount kMaxCongestionWindowTCP = 50; - // Set to 10000 to compensate for small cubic alpha. - const int kNumberOfAcks = 10000; - - sender_.reset( - new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP)); - - SendAvailableSendWindow(); - AckNPackets(2); - // Make sure we fall out of slow start. - LoseNPackets(1); - - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - - QuicByteCount expected_send_window = kMaxCongestionWindowTCP * kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicSenderTest, TcpCubicResetEpochOnQuiescence) { - const int kMaxCongestionWindow = 50; - const QuicByteCount kMaxCongestionWindowBytes = - kMaxCongestionWindow * kDefaultTCPMSS; - sender_.reset(new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindow)); - - int num_sent = SendAvailableSendWindow(); - - // Make sure we fall out of slow start. - QuicByteCount saved_cwnd = sender_->GetCongestionWindow(); - LoseNPackets(1); - EXPECT_GT(saved_cwnd, sender_->GetCongestionWindow()); - - // Ack the rest of the outstanding packets to get out of recovery. - for (int i = 1; i < num_sent; ++i) { - AckNPackets(1); - } - EXPECT_EQ(0u, bytes_in_flight_); - - // Send a new window of data and ack all; cubic growth should occur. - saved_cwnd = sender_->GetCongestionWindow(); - num_sent = SendAvailableSendWindow(); - for (int i = 0; i < num_sent; ++i) { - AckNPackets(1); - } - EXPECT_LT(saved_cwnd, sender_->GetCongestionWindow()); - EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow()); - EXPECT_EQ(0u, bytes_in_flight_); - - // Quiescent time of 100 seconds - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100000)); - - // Send new window of data and ack one packet. Cubic epoch should have - // been reset; ensure cwnd increase is not dramatic. - saved_cwnd = sender_->GetCongestionWindow(); - SendAvailableSendWindow(); - AckNPackets(1); - EXPECT_NEAR(saved_cwnd, sender_->GetCongestionWindow(), kDefaultTCPMSS); - EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicSenderTest, TcpCubicShiftedEpochOnQuiescence) { - ValueRestore<bool> old_flag(&FLAGS_shift_quic_cubic_epoch_when_app_limited, - true); - const int kMaxCongestionWindow = 50; - const QuicByteCount kMaxCongestionWindowBytes = - kMaxCongestionWindow * kDefaultTCPMSS; - sender_.reset(new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindow)); - - int num_sent = SendAvailableSendWindow(); - - // Make sure we fall out of slow start. - QuicByteCount saved_cwnd = sender_->GetCongestionWindow(); - LoseNPackets(1); - EXPECT_GT(saved_cwnd, sender_->GetCongestionWindow()); - - // Ack the rest of the outstanding packets to get out of recovery. - for (int i = 1; i < num_sent; ++i) { - AckNPackets(1); - } - EXPECT_EQ(0u, bytes_in_flight_); - - // Send a new window of data and ack all; cubic growth should occur. - saved_cwnd = sender_->GetCongestionWindow(); - num_sent = SendAvailableSendWindow(); - for (int i = 0; i < num_sent; ++i) { - AckNPackets(1); - } - EXPECT_LT(saved_cwnd, sender_->GetCongestionWindow()); - EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow()); - EXPECT_EQ(0u, bytes_in_flight_); - - // Quiescent time of 100 seconds - clock_.AdvanceTime(QuicTime::Delta::FromSeconds(100)); - - // Send new window of data and ack one packet. Cubic epoch should have - // been reset; ensure cwnd increase is not dramatic. - saved_cwnd = sender_->GetCongestionWindow(); - SendAvailableSendWindow(); - AckNPackets(1); - EXPECT_NEAR(saved_cwnd, sender_->GetCongestionWindow(), kDefaultTCPMSS); - EXPECT_GT(kMaxCongestionWindowBytes, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicSenderTest, MultipleLossesInOneWindow) { - SendAvailableSendWindow(); - const QuicByteCount initial_window = sender_->GetCongestionWindow(); - LosePacket(acked_packet_number_ + 1); - const QuicByteCount post_loss_window = sender_->GetCongestionWindow(); - EXPECT_GT(initial_window, post_loss_window); - LosePacket(acked_packet_number_ + 3); - EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); - LosePacket(packet_number_ - 1); - EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow()); - - // Lose a later packet and ensure the window decreases. - LosePacket(packet_number_); - EXPECT_GT(post_loss_window, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicSenderTest, DontTrackAckPackets) { - // Send a packet with no retransmittable data, and ensure it's not tracked. - EXPECT_FALSE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, - packet_number_++, kDefaultTCPMSS, - NO_RETRANSMITTABLE_DATA)); - - // Send a data packet with retransmittable data, and ensure it is tracked. - EXPECT_TRUE(sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, - packet_number_++, kDefaultTCPMSS, - HAS_RETRANSMITTABLE_DATA)); -} - -TEST_F(TcpCubicSenderTest, ConfigureInitialWindow) { - QuicConfig config; - - QuicTagVector options; - options.push_back(kIW03); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - sender_->SetFromConfig(config, Perspective::IS_SERVER); - EXPECT_EQ(3u, sender_->congestion_window()); - - options.clear(); - options.push_back(kIW10); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - sender_->SetFromConfig(config, Perspective::IS_SERVER); - EXPECT_EQ(10u, sender_->congestion_window()); - - options.clear(); - options.push_back(kIW20); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - sender_->SetFromConfig(config, Perspective::IS_SERVER); - EXPECT_EQ(20u, sender_->congestion_window()); - - options.clear(); - options.push_back(kIW50); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - sender_->SetFromConfig(config, Perspective::IS_SERVER); - EXPECT_EQ(50u, sender_->congestion_window()); -} - -TEST_F(TcpCubicSenderTest, ConfigureMinimumWindow) { - QuicConfig config; - - // Verify that kCOPT: kMIN1 forces the min CWND to 1 packet. - QuicTagVector options; - options.push_back(kMIN1); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - sender_->SetFromConfig(config, Perspective::IS_SERVER); - sender_->OnRetransmissionTimeout(true); - EXPECT_EQ(1u, sender_->congestion_window()); -} - -TEST_F(TcpCubicSenderTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) { - sender_->SetNumEmulatedConnections(2); - // Ack 10 packets in 5 acks to raise the CWND to 20. - const int kNumberOfAcks = 5; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - LoseNPackets(1); - - // We should now have fallen out of slow start with a reduced window. - expected_send_window = expected_send_window * sender_->GetRenoBeta(); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // No congestion window growth should occur in recovery phase, i.e., until the - // currently outstanding 20 packets are acked. - for (int i = 0; i < 10; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - EXPECT_TRUE(sender_->InRecovery()); - AckNPackets(2); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - } - EXPECT_FALSE(sender_->InRecovery()); - - // Out of recovery now. Congestion window should not grow for half an RTT. - size_t packets_in_send_window = expected_send_window / kDefaultTCPMSS; - SendAvailableSendWindow(); - AckNPackets(packets_in_send_window / 2 - 2); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Next ack should increase congestion window by 1MSS. - SendAvailableSendWindow(); - AckNPackets(2); - expected_send_window += kDefaultTCPMSS; - packets_in_send_window += 1; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Congestion window should remain steady again for half an RTT. - SendAvailableSendWindow(); - AckNPackets(packets_in_send_window / 2 - 1); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Next ack should cause congestion window to grow by 1MSS. - SendAvailableSendWindow(); - AckNPackets(2); - expected_send_window += kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicSenderTest, 1ConnectionCongestionAvoidanceAtEndOfRecovery) { - sender_->SetNumEmulatedConnections(1); - // Ack 10 packets in 5 acks to raise the CWND to 20. - const int kNumberOfAcks = 5; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - LoseNPackets(1); - - // We should now have fallen out of slow start with a reduced window. - expected_send_window *= kRenoBeta; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // No congestion window growth should occur in recovery phase, i.e., until the - // currently outstanding 20 packets are acked. - for (int i = 0; i < 10; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - EXPECT_TRUE(sender_->InRecovery()); - AckNPackets(2); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - } - EXPECT_FALSE(sender_->InRecovery()); - - // Out of recovery now. Congestion window should not grow during RTT. - for (uint64_t i = 0; i < expected_send_window / kDefaultTCPMSS - 2; i += 2) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - } - - // Next ack should cause congestion window to grow by 1MSS. - SendAvailableSendWindow(); - AckNPackets(2); - expected_send_window += kDefaultTCPMSS; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicSenderTest, BandwidthResumption) { - // Test that when provided with CachedNetworkParameters and opted in to the - // bandwidth resumption experiment, that the TcpCubicSender sets initial CWND - // appropriately. - - // Set some common values. - CachedNetworkParameters cached_network_params; - const QuicPacketCount kNumberOfPackets = 123; - const int kBandwidthEstimateBytesPerSecond = - kNumberOfPackets * kDefaultTCPMSS; - cached_network_params.set_bandwidth_estimate_bytes_per_second( - kBandwidthEstimateBytesPerSecond); - cached_network_params.set_min_rtt_ms(1000); - - // Make sure that a bandwidth estimate results in a changed CWND. - cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() - - (kNumSecondsPerHour - 1)); - sender_->ResumeConnectionState(cached_network_params, false); - EXPECT_EQ(kNumberOfPackets, sender_->congestion_window()); - - // Resumed CWND is limited to be in a sensible range. - cached_network_params.set_bandwidth_estimate_bytes_per_second( - (kMaxCongestionWindow + 1) * kDefaultTCPMSS); - sender_->ResumeConnectionState(cached_network_params, false); - EXPECT_EQ(kMaxCongestionWindow, sender_->congestion_window()); - - cached_network_params.set_bandwidth_estimate_bytes_per_second( - (kMinCongestionWindowForBandwidthResumption - 1) * kDefaultTCPMSS); - sender_->ResumeConnectionState(cached_network_params, false); - EXPECT_EQ(kMinCongestionWindowForBandwidthResumption, - sender_->congestion_window()); - - // Resume to the max value. - cached_network_params.set_max_bandwidth_estimate_bytes_per_second( - (kMinCongestionWindowForBandwidthResumption + 10) * kDefaultTCPMSS); - sender_->ResumeConnectionState(cached_network_params, true); - EXPECT_EQ((kMinCongestionWindowForBandwidthResumption + 10) * kDefaultTCPMSS, - sender_->GetCongestionWindow()); -} - -TEST_F(TcpCubicSenderTest, PaceBelowCWND) { - QuicConfig config; - - // Verify that kCOPT: kMIN4 forces the min CWND to 1 packet, but allows up - // to 4 to be sent. - QuicTagVector options; - options.push_back(kMIN4); - QuicConfigPeer::SetReceivedConnectionOptions(&config, options); - sender_->SetFromConfig(config, Perspective::IS_SERVER); - sender_->OnRetransmissionTimeout(true); - EXPECT_EQ(1u, sender_->congestion_window()); - EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS, - HAS_RETRANSMITTABLE_DATA) - .IsZero()); - EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS, - HAS_RETRANSMITTABLE_DATA) - .IsZero()); - EXPECT_TRUE(sender_->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS, - HAS_RETRANSMITTABLE_DATA) - .IsZero()); - EXPECT_FALSE(sender_->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS, - HAS_RETRANSMITTABLE_DATA) - .IsZero()); -} - -TEST_F(TcpCubicSenderTest, ResetAfterConnectionMigration) { - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); - EXPECT_EQ(kMaxCongestionWindow, sender_->slowstart_threshold()); - - // Starts with slow start. - sender_->SetNumEmulatedConnections(1); - const int kNumberOfAcks = 10; - for (int i = 0; i < kNumberOfAcks; ++i) { - // Send our full send window. - SendAvailableSendWindow(); - AckNPackets(2); - } - SendAvailableSendWindow(); - QuicByteCount expected_send_window = - kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks); - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - - // Loses a packet to exit slow start. - LoseNPackets(1); - - // We should now have fallen out of slow start with a reduced window. Slow - // start threshold is also updated. - expected_send_window *= kRenoBeta; - EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow()); - EXPECT_EQ(expected_send_window / kDefaultTCPMSS, - sender_->slowstart_threshold()); - - // Resets cwnd and slow start threshold on connection migrations. - sender_->OnConnectionMigration(); - EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow()); - EXPECT_EQ(kMaxCongestionWindow, sender_->slowstart_threshold()); - EXPECT_FALSE(sender_->hybrid_slow_start().started()); -} - -} // namespace test -} // namespace net diff --git a/net/quic/crypto/aead_base_decrypter.h b/net/quic/crypto/aead_base_decrypter.h index edd110b..c76f11f 100644 --- a/net/quic/crypto/aead_base_decrypter.h +++ b/net/quic/crypto/aead_base_decrypter.h @@ -40,8 +40,8 @@ class NET_EXPORT_PRIVATE AeadBaseDecrypter : public QuicDecrypter { bool SetNoncePrefix(base::StringPiece nonce_prefix) override; bool DecryptPacket(QuicPathId path_id, QuicPacketNumber packet_number, - const base::StringPiece& associated_data, - const base::StringPiece& ciphertext, + base::StringPiece associated_data, + base::StringPiece ciphertext, char* output, size_t* output_length, size_t max_output_length) override; @@ -65,7 +65,7 @@ class NET_EXPORT_PRIVATE AeadBaseDecrypter : public QuicDecrypter { }; virtual void FillAeadParams(base::StringPiece nonce, - const base::StringPiece& associated_data, + base::StringPiece associated_data, size_t auth_tag_size, AeadParams* aead_params) const = 0; #endif // !defined(USE_OPENSSL) diff --git a/net/quic/crypto/aead_base_decrypter_nss.cc b/net/quic/crypto/aead_base_decrypter_nss.cc index 26e72ee..46228cc 100644 --- a/net/quic/crypto/aead_base_decrypter_nss.cc +++ b/net/quic/crypto/aead_base_decrypter_nss.cc @@ -49,8 +49,8 @@ bool AeadBaseDecrypter::SetNoncePrefix(StringPiece nonce_prefix) { bool AeadBaseDecrypter::DecryptPacket(QuicPathId path_id, QuicPacketNumber packet_number, - const StringPiece& associated_data, - const StringPiece& ciphertext, + StringPiece associated_data, + StringPiece ciphertext, char* output, size_t* output_length, size_t max_output_length) { diff --git a/net/quic/crypto/aead_base_decrypter_openssl.cc b/net/quic/crypto/aead_base_decrypter_openssl.cc index 512b804..097cb4f 100644 --- a/net/quic/crypto/aead_base_decrypter_openssl.cc +++ b/net/quic/crypto/aead_base_decrypter_openssl.cc @@ -81,8 +81,8 @@ bool AeadBaseDecrypter::SetNoncePrefix(StringPiece nonce_prefix) { bool AeadBaseDecrypter::DecryptPacket(QuicPathId path_id, QuicPacketNumber packet_number, - const StringPiece& associated_data, - const StringPiece& ciphertext, + StringPiece associated_data, + StringPiece ciphertext, char* output, size_t* output_length, size_t max_output_length) { diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter.h b/net/quic/crypto/aes_128_gcm_12_decrypter.h index d0d305a..f8b1196 100644 --- a/net/quic/crypto/aes_128_gcm_12_decrypter.h +++ b/net/quic/crypto/aes_128_gcm_12_decrypter.h @@ -33,7 +33,7 @@ class NET_EXPORT_PRIVATE Aes128Gcm12Decrypter : public AeadBaseDecrypter { protected: // AeadBaseDecrypter methods: void FillAeadParams(base::StringPiece nonce, - const base::StringPiece& associated_data, + base::StringPiece associated_data, size_t auth_tag_size, AeadParams* aead_params) const override; #endif diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc b/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc index abbc565..d4480f4 100644 --- a/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc +++ b/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc @@ -28,7 +28,7 @@ Aes128Gcm12Decrypter::Aes128Gcm12Decrypter() Aes128Gcm12Decrypter::~Aes128Gcm12Decrypter() {} void Aes128Gcm12Decrypter::FillAeadParams(StringPiece nonce, - const StringPiece& associated_data, + StringPiece associated_data, size_t auth_tag_size, AeadParams* aead_params) const { aead_params->len = sizeof(aead_params->data.gcm_params); diff --git a/net/quic/crypto/chacha20_poly1305_decrypter.h b/net/quic/crypto/chacha20_poly1305_decrypter.h index fad9bbb..1e0fd05 100644 --- a/net/quic/crypto/chacha20_poly1305_decrypter.h +++ b/net/quic/crypto/chacha20_poly1305_decrypter.h @@ -34,7 +34,7 @@ class NET_EXPORT_PRIVATE ChaCha20Poly1305Decrypter : public AeadBaseDecrypter { protected: // AeadBaseDecrypter methods: void FillAeadParams(base::StringPiece nonce, - const base::StringPiece& associated_data, + base::StringPiece associated_data, size_t auth_tag_size, AeadParams* aead_params) const override; #endif diff --git a/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc b/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc index 893f8a7..aeff43a 100644 --- a/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc +++ b/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc @@ -29,11 +29,10 @@ ChaCha20Poly1305Decrypter::ChaCha20Poly1305Decrypter() ChaCha20Poly1305Decrypter::~ChaCha20Poly1305Decrypter() {} -void ChaCha20Poly1305Decrypter::FillAeadParams( - StringPiece nonce, - const StringPiece& associated_data, - size_t auth_tag_size, - AeadParams* aead_params) const { +void ChaCha20Poly1305Decrypter::FillAeadParams(StringPiece nonce, + StringPiece associated_data, + size_t auth_tag_size, + AeadParams* aead_params) const { aead_params->len = sizeof(aead_params->data.nss_aead_params); CK_NSS_AEAD_PARAMS* nss_aead_params = &aead_params->data.nss_aead_params; nss_aead_params->pIv = diff --git a/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h b/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h index 3889216..57609d0 100644 --- a/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h +++ b/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter.h @@ -42,7 +42,7 @@ class NET_EXPORT_PRIVATE ChaCha20Poly1305Rfc7539Decrypter protected: // AeadBaseDecrypter methods: void FillAeadParams(base::StringPiece nonce, - const base::StringPiece& associated_data, + base::StringPiece associated_data, size_t auth_tag_size, AeadParams* aead_params) const override; #endif diff --git a/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc b/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc index 8c830e9..799a2c5 100644 --- a/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc +++ b/net/quic/crypto/chacha20_poly1305_rfc7539_decrypter_nss.cc @@ -43,7 +43,7 @@ uint32_t ChaCha20Poly1305Rfc7539Decrypter::cipher_id() const { void ChaCha20Poly1305Rfc7539Decrypter::FillAeadParams( base::StringPiece nonce, - const base::StringPiece& associated_data, + base::StringPiece associated_data, size_t auth_tag_size, AeadParams* aead_params) const {} diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h index 5d2f71f..14d3fab 100644 --- a/net/quic/crypto/crypto_protocol.h +++ b/net/quic/crypto/crypto_protocol.h @@ -89,6 +89,8 @@ const QuicTag kMIN4 = TAG('M', 'I', 'N', '4'); // Min CWND of 4 packets, const QuicTag kTLPR = TAG('T', 'L', 'P', 'R'); // Tail loss probe delay of // 0.5RTT. const QuicTag kACKD = TAG('A', 'C', 'K', 'D'); // Ack decimation style acking. +const QuicTag kAKD2 = TAG('A', 'K', 'D', '2'); // Ack decimation tolerating + // out of order packets. const QuicTag kSSLR = TAG('S', 'S', 'L', 'R'); // Slow Start Large Reduction. // Optional support of truncated Connection IDs. If sent by a peer, the value @@ -99,15 +101,6 @@ const QuicTag kTCID = TAG('T', 'C', 'I', 'D'); // Connection ID truncation. // Multipath option. const QuicTag kMPTH = TAG('M', 'P', 'T', 'H'); // Enable multipath. -// FEC options -const QuicTag kFHDR = TAG('F', 'H', 'D', 'R'); // FEC protect headers -const QuicTag kFSTR = TAG('F', 'S', 'T', 'R'); // FEC protect all streams -// Set FecSendPolicy for sending FEC packet only when FEC alarm goes off. -const QuicTag kFSPA = TAG('F', 'S', 'P', 'A'); -// Run an experiment that sets FecTimeOut alarm to 0.25RTT. -// TODO(rtenneti): Delete it after the experiment. -const QuicTag kFRTT = TAG('F', 'R', 'T', 'T'); - // Enable bandwidth resumption experiment. const QuicTag kBWRE = TAG('B', 'W', 'R', 'E'); // Bandwidth resumption. const QuicTag kBWMX = TAG('B', 'W', 'M', 'X'); // Max bandwidth resumption. diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc index 8c0e3ee..85cf2aa 100644 --- a/net/quic/crypto/crypto_server_test.cc +++ b/net/quic/crypto/crypto_server_test.cc @@ -507,7 +507,6 @@ TEST_P(CryptoServerTest, RejectTooLarge) { } TEST_P(CryptoServerTest, RejectTooLargeButValidSTK) { - ValueRestore<bool> old_flag(&FLAGS_quic_validate_stk_without_scid, true); // Check that the server replies with no certificate when a CHLO is // constructed with a PDMD but no SKT when the REJ would be too large. // clang-format off @@ -540,37 +539,6 @@ TEST_P(CryptoServerTest, RejectTooLargeButValidSTK) { CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); } -TEST_P(CryptoServerTest, RejectTooLargeButValidSTKWithoutFlag) { - ValueRestore<bool> old_flag(&FLAGS_quic_validate_stk_without_scid, false); - // Check that the server replies with no certificate when a CHLO is - // constructed with a PDMD but no SKT when the REJ would be too large. - // clang-format off - CryptoHandshakeMessage msg = CryptoTestUtils::Message( - "CHLO", - "AEAD", "AESG", - "KEXS", "C255", - "PUBS", pub_hex_.c_str(), - "NONC", nonce_hex_.c_str(), - "#004b5453", srct_hex_.c_str(), - "PDMD", "X509", - "VER\0", client_version_string_.c_str(), - "$padding", static_cast<int>(kClientHelloMinimumSize), - nullptr); - // clang-format on - - // The REJ will be larger than the CHLO so no PROF or CRT will be sent. - config_.set_chlo_multiplier(1); - - ShouldSucceed(msg); - StringPiece cert, proof, cert_sct; - EXPECT_FALSE(out_.GetStringPiece(kCertificateTag, &cert)); - EXPECT_FALSE(out_.GetStringPiece(kPROF, &proof)); - EXPECT_FALSE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct)); - const HandshakeFailureReason kRejectReasons[] = { - SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; - CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); -} - TEST_P(CryptoServerTest, TooSmall) { // clang-format off ShouldFailMentioning("too small", CryptoTestUtils::Message( @@ -758,50 +726,7 @@ TEST_P(CryptoServerTest, CorruptMultipleTags) { }; } -TEST_P(CryptoServerTest, ReplayProtection) { - if (client_version_ > QUIC_VERSION_30) { - return; - } - FLAGS_require_strike_register_or_server_nonce = false; - // This tests that disabling replay protection works. - // clang-format off - CryptoHandshakeMessage msg = CryptoTestUtils::Message( - "CHLO", - "AEAD", "AESG", - "KEXS", "C255", - "SCID", scid_hex_.c_str(), - "#004b5453", srct_hex_.c_str(), - "PUBS", pub_hex_.c_str(), - "NONC", nonce_hex_.c_str(), - "XLCT", XlctHexString().c_str(), - "VER\0", client_version_string_.c_str(), - "$padding", static_cast<int>(kClientHelloMinimumSize), - nullptr); - // clang-format on - ShouldSucceed(msg); - // The message should be rejected because the strike-register is still - // quiescent. - CheckRejectTag(); - - const HandshakeFailureReason kRejectReasons[] = { - CLIENT_NONCE_INVALID_TIME_FAILURE}; - CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); - - config_.set_replay_protection(false); - - ShouldSucceed(msg); - // The message should be accepted now. - ASSERT_EQ(kSHLO, out_.tag()); - CheckServerHello(out_); - - ShouldSucceed(msg); - // The message should accepted twice when replay protection is off. - ASSERT_EQ(kSHLO, out_.tag()); - CheckServerHello(out_); -} - TEST_P(CryptoServerTest, NoServerNonce) { - FLAGS_require_strike_register_or_server_nonce = true; // When no server nonce is present and no strike register is configured, // the CHLO should be rejected. // clang-format off diff --git a/net/quic/crypto/curve25519_key_exchange.cc b/net/quic/crypto/curve25519_key_exchange.cc index cf97add..6545d21 100644 --- a/net/quic/crypto/curve25519_key_exchange.cc +++ b/net/quic/crypto/curve25519_key_exchange.cc @@ -18,8 +18,7 @@ Curve25519KeyExchange::Curve25519KeyExchange() {} Curve25519KeyExchange::~Curve25519KeyExchange() {} // static -Curve25519KeyExchange* Curve25519KeyExchange::New( - const StringPiece& private_key) { +Curve25519KeyExchange* Curve25519KeyExchange::New(StringPiece private_key) { Curve25519KeyExchange* ka; // We don't want to #include the NaCl headers in the public header file, so // we use literals for the sizes of private_key_ and public_key_. Here we @@ -58,9 +57,8 @@ KeyExchange* Curve25519KeyExchange::NewKeyPair(QuicRandom* rand) const { return Curve25519KeyExchange::New(private_value); } -bool Curve25519KeyExchange::CalculateSharedKey( - const StringPiece& peer_public_value, - string* out_result) const { +bool Curve25519KeyExchange::CalculateSharedKey(StringPiece peer_public_value, + string* out_result) const { if (peer_public_value.size() != crypto::curve25519::kBytes) { return false; } diff --git a/net/quic/crypto/curve25519_key_exchange.h b/net/quic/crypto/curve25519_key_exchange.h index 1637bbb..a95cf7f 100644 --- a/net/quic/crypto/curve25519_key_exchange.h +++ b/net/quic/crypto/curve25519_key_exchange.h @@ -26,7 +26,7 @@ class NET_EXPORT_PRIVATE Curve25519KeyExchange : public KeyExchange { // New creates a new object from a private key. If the private key is // invalid, nullptr is returned. - static Curve25519KeyExchange* New(const base::StringPiece& private_key); + static Curve25519KeyExchange* New(base::StringPiece private_key); // NewPrivateKey returns a private key, generated from |rand|, suitable for // passing to |New|. @@ -34,7 +34,7 @@ class NET_EXPORT_PRIVATE Curve25519KeyExchange : public KeyExchange { // KeyExchange interface. KeyExchange* NewKeyPair(QuicRandom* rand) const override; - bool CalculateSharedKey(const base::StringPiece& peer_public_value, + bool CalculateSharedKey(base::StringPiece peer_public_value, std::string* shared_key) const override; base::StringPiece public_value() const override; QuicTag tag() const override; diff --git a/net/quic/crypto/key_exchange.h b/net/quic/crypto/key_exchange.h index 8690f0e..a6de1c3 100644 --- a/net/quic/crypto/key_exchange.h +++ b/net/quic/crypto/key_exchange.h @@ -29,7 +29,7 @@ class NET_EXPORT_PRIVATE KeyExchange { // CalculateSharedKey computes the shared key between the local private key // (which is implicitly known by a KeyExchange object) and a public value // from the peer. - virtual bool CalculateSharedKey(const base::StringPiece& peer_public_value, + virtual bool CalculateSharedKey(base::StringPiece peer_public_value, std::string* shared_key) const = 0; // public_value returns the local public key which can be sent to a peer in diff --git a/net/quic/crypto/null_decrypter.cc b/net/quic/crypto/null_decrypter.cc index 52217b5..43adb67 100644 --- a/net/quic/crypto/null_decrypter.cc +++ b/net/quic/crypto/null_decrypter.cc @@ -27,8 +27,8 @@ bool NullDecrypter::SetNoncePrefix(StringPiece nonce_prefix) { bool NullDecrypter::DecryptPacket(QuicPathId /*path_id*/, QuicPacketNumber /*packet_number*/, - const StringPiece& associated_data, - const StringPiece& ciphertext, + StringPiece associated_data, + StringPiece ciphertext, char* output, size_t* output_length, size_t max_output_length) { diff --git a/net/quic/crypto/null_decrypter.h b/net/quic/crypto/null_decrypter.h index 91b5856..e5e15b2 100644 --- a/net/quic/crypto/null_decrypter.h +++ b/net/quic/crypto/null_decrypter.h @@ -30,8 +30,8 @@ class NET_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter { bool SetNoncePrefix(base::StringPiece nonce_prefix) override; bool DecryptPacket(QuicPathId path_id, QuicPacketNumber packet_number, - const base::StringPiece& associated_data, - const base::StringPiece& ciphertext, + base::StringPiece associated_data, + base::StringPiece ciphertext, char* output, size_t* output_length, size_t max_output_length) override; @@ -43,8 +43,7 @@ class NET_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter { private: bool ReadHash(QuicDataReader* reader, uint128* hash); - uint128 ComputeHash(const base::StringPiece data1, - const base::StringPiece data2) const; + uint128 ComputeHash(base::StringPiece data1, base::StringPiece data2) const; DISALLOW_COPY_AND_ASSIGN(NullDecrypter); }; diff --git a/net/quic/crypto/p256_key_exchange.h b/net/quic/crypto/p256_key_exchange.h index e6855aa..197adfe 100644 --- a/net/quic/crypto/p256_key_exchange.h +++ b/net/quic/crypto/p256_key_exchange.h @@ -42,7 +42,7 @@ class NET_EXPORT_PRIVATE P256KeyExchange : public KeyExchange { // KeyExchange interface. KeyExchange* NewKeyPair(QuicRandom* rand) const override; - bool CalculateSharedKey(const base::StringPiece& peer_public_value, + bool CalculateSharedKey(base::StringPiece peer_public_value, std::string* shared_key) const override; base::StringPiece public_value() const override; QuicTag tag() const override; diff --git a/net/quic/crypto/p256_key_exchange_nss.cc b/net/quic/crypto/p256_key_exchange_nss.cc index 576825f..c5529ab 100644 --- a/net/quic/crypto/p256_key_exchange_nss.cc +++ b/net/quic/crypto/p256_key_exchange_nss.cc @@ -153,7 +153,7 @@ KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* /*rand*/) const { return P256KeyExchange::New(private_value); } -bool P256KeyExchange::CalculateSharedKey(const StringPiece& peer_public_value, +bool P256KeyExchange::CalculateSharedKey(StringPiece peer_public_value, string* out_result) const { if (peer_public_value.size() != kUncompressedP256PointBytes || peer_public_value[0] != kUncompressedECPointForm) { diff --git a/net/quic/crypto/p256_key_exchange_openssl.cc b/net/quic/crypto/p256_key_exchange_openssl.cc index 7a9707e..9703a2e 100644 --- a/net/quic/crypto/p256_key_exchange_openssl.cc +++ b/net/quic/crypto/p256_key_exchange_openssl.cc @@ -77,7 +77,7 @@ KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* /*rand*/) const { return P256KeyExchange::New(private_value); } -bool P256KeyExchange::CalculateSharedKey(const StringPiece& peer_public_value, +bool P256KeyExchange::CalculateSharedKey(StringPiece peer_public_value, string* out_result) const { if (peer_public_value.size() != kUncompressedP256PointBytes) { DVLOG(1) << "Peer public value is invalid"; diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc index cd14bc1..25d344b 100644 --- a/net/quic/crypto/quic_crypto_server_config.cc +++ b/net/quic/crypto/quic_crypto_server_config.cc @@ -997,23 +997,21 @@ void QuicCryptoServerConfig::EvaluateClientHello( HandshakeFailureReason source_address_token_error = MAX_FAILURE_REASON; StringPiece srct; - if (FLAGS_quic_validate_stk_without_scid) { - if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) { - Config& config = - requested_config != nullptr ? *requested_config : *primary_config; - source_address_token_error = - ParseSourceAddressToken(config, srct, &info->source_address_tokens); - - if (source_address_token_error == HANDSHAKE_OK) { - source_address_token_error = ValidateSourceAddressTokens( - info->source_address_tokens, info->client_ip, info->now, - &client_hello_state->cached_network_params); - } - info->valid_source_address_token = - (source_address_token_error == HANDSHAKE_OK); - } else { - source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE; + if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) { + Config& config = + requested_config != nullptr ? *requested_config : *primary_config; + source_address_token_error = + ParseSourceAddressToken(config, srct, &info->source_address_tokens); + + if (source_address_token_error == HANDSHAKE_OK) { + source_address_token_error = ValidateSourceAddressTokens( + info->source_address_tokens, info->client_ip, info->now, + &client_hello_state->cached_network_params); } + info->valid_source_address_token = + (source_address_token_error == HANDSHAKE_OK); + } else { + source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE; } if (!requested_config.get()) { @@ -1028,23 +1026,6 @@ void QuicCryptoServerConfig::EvaluateClientHello( return; } - if (!FLAGS_quic_validate_stk_without_scid) { - if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) { - source_address_token_error = ParseSourceAddressToken( - *requested_config, srct, &info->source_address_tokens); - - if (source_address_token_error == HANDSHAKE_OK) { - source_address_token_error = ValidateSourceAddressTokens( - info->source_address_tokens, info->client_ip, info->now, - &client_hello_state->cached_network_params); - } - info->valid_source_address_token = - (source_address_token_error == HANDSHAKE_OK); - } else { - source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE; - } - } - bool found_error = false; if (source_address_token_error != HANDSHAKE_OK) { info->reject_reasons.push_back(source_address_token_error); @@ -1140,18 +1121,6 @@ void QuicCryptoServerConfig::EvaluateClientHello( StrikeRegisterClient* strike_register_client; { base::AutoLock locked(strike_register_client_lock_); - - if (strike_register_client_.get() == nullptr) { - if (!FLAGS_require_strike_register_or_server_nonce) { - strike_register_client_.reset(new LocalStrikeRegisterClient( - strike_register_max_entries_, - static_cast<uint32_t>(info->now.ToUNIXSeconds()), - strike_register_window_secs_, primary_orbit, - strike_register_no_startup_period_ - ? StrikeRegister::NO_STARTUP_PERIOD_NEEDED - : StrikeRegister::DENY_REQUESTS_AT_STARTUP)); - } - } strike_register_client = strike_register_client_.get(); } diff --git a/net/quic/crypto/quic_crypto_server_config_test.cc b/net/quic/crypto/quic_crypto_server_config_test.cc index f3f9de7..0585a19 100644 --- a/net/quic/crypto/quic_crypto_server_config_test.cc +++ b/net/quic/crypto/quic_crypto_server_config_test.cc @@ -145,7 +145,8 @@ class QuicCryptoServerConfigPeer { } ASSERT_TRUE(found) << "Failed to find match for " << i.first - << " in configs:\n" << ConfigsDebug(); + << " in configs:\n" + << ConfigsDebug(); } } diff --git a/net/quic/crypto/quic_decrypter.h b/net/quic/crypto/quic_decrypter.h index 3e55170..4f2be96 100644 --- a/net/quic/crypto/quic_decrypter.h +++ b/net/quic/crypto/quic_decrypter.h @@ -52,8 +52,8 @@ class NET_EXPORT_PRIVATE QuicDecrypter { // to non-authentic inputs, as opposed to other reasons for failure. virtual bool DecryptPacket(QuicPathId path_id, QuicPacketNumber packet_number, - const base::StringPiece& associated_data, - const base::StringPiece& ciphertext, + base::StringPiece associated_data, + base::StringPiece ciphertext, char* output, size_t* output_length, size_t max_output_length) = 0; diff --git a/net/quic/quic_alarm.cc b/net/quic/quic_alarm.cc index b978a14..ca407b5 100644 --- a/net/quic/quic_alarm.cc +++ b/net/quic/quic_alarm.cc @@ -5,6 +5,7 @@ #include "net/quic/quic_alarm.h" #include "base/logging.h" +#include "net/quic/quic_flags.h" namespace net { @@ -13,29 +14,33 @@ QuicAlarm::QuicAlarm(QuicArenaScopedPtr<Delegate> delegate) QuicAlarm::~QuicAlarm() {} -void QuicAlarm::Set(QuicTime deadline) { +void QuicAlarm::Set(QuicTime new_deadline) { DCHECK(!IsSet()); - DCHECK(deadline.IsInitialized()); - deadline_ = deadline; + DCHECK(new_deadline.IsInitialized()); + deadline_ = new_deadline; SetImpl(); } void QuicAlarm::Cancel() { + if (FLAGS_quic_only_cancel_set_alarms && !IsSet()) { + // Don't try to cancel an alarm that hasn't been set. + return; + } deadline_ = QuicTime::Zero(); CancelImpl(); } -void QuicAlarm::Update(QuicTime deadline, QuicTime::Delta granularity) { - if (!deadline.IsInitialized()) { +void QuicAlarm::Update(QuicTime new_deadline, QuicTime::Delta granularity) { + if (!new_deadline.IsInitialized()) { Cancel(); return; } - if (std::abs(deadline.Subtract(deadline_).ToMicroseconds()) < + if (std::abs(new_deadline.Subtract(deadline_).ToMicroseconds()) < granularity.ToMicroseconds()) { return; } Cancel(); - Set(deadline); + Set(new_deadline); } bool QuicAlarm::IsSet() const { @@ -43,19 +48,12 @@ bool QuicAlarm::IsSet() const { } void QuicAlarm::Fire() { - if (!deadline_.IsInitialized()) { + if (!IsSet()) { return; } deadline_ = QuicTime::Zero(); - QuicTime deadline = delegate_->OnAlarm(); - // delegate_->OnAlarm() might call Set(), in which case deadline_ - // will already contain the new value, so don't overwrite it. Also, - // OnAlarm() might delete |this| so check |deadline| before - // |deadline_|. - if (deadline.IsInitialized() && !deadline_.IsInitialized()) { - Set(deadline); - } + delegate_->OnAlarm(); } } // namespace net diff --git a/net/quic/quic_alarm.h b/net/quic/quic_alarm.h index a775cfb5..53a823f 100644 --- a/net/quic/quic_alarm.h +++ b/net/quic/quic_alarm.h @@ -24,10 +24,8 @@ class NET_EXPORT_PRIVATE QuicAlarm { public: virtual ~Delegate() {} - // Invoked when the alarm fires. If the return value is not - // infinite, then the alarm will be rescheduled at the - // specified time. - virtual QuicTime OnAlarm() = 0; + // Invoked when the alarm fires. + virtual void OnAlarm() = 0; }; explicit QuicAlarm(QuicArenaScopedPtr<Delegate> delegate); @@ -36,7 +34,7 @@ class NET_EXPORT_PRIVATE QuicAlarm { // Sets the alarm to fire at |deadline|. Must not be called while // the alarm is set. To reschedule an alarm, call Cancel() first, // then Set(). - void Set(QuicTime deadline); + void Set(QuicTime new_deadline); // Cancels the alarm. May be called repeatedly. Does not // guarantee that the underlying scheduling system will remove @@ -47,8 +45,9 @@ class NET_EXPORT_PRIVATE QuicAlarm { // Cancels and sets the alarm if the |deadline| is farther from the current // deadline than |granularity|, and otherwise does nothing. If |deadline| is // not initialized, the alarm is cancelled. - void Update(QuicTime deadline, QuicTime::Delta granularity); + void Update(QuicTime new_deadline, QuicTime::Delta granularity); + // Returns true if |deadline_| has been set to a non-zero time. bool IsSet() const; QuicTime deadline() const { return deadline_; } diff --git a/net/quic/quic_alarm_test.cc b/net/quic/quic_alarm_test.cc index 0ae6459..0509090 100644 --- a/net/quic/quic_alarm_test.cc +++ b/net/quic/quic_alarm_test.cc @@ -17,7 +17,7 @@ namespace { class MockDelegate : public QuicAlarm::Delegate { public: - MOCK_METHOD0(OnAlarm, QuicTime()); + MOCK_METHOD0(OnAlarm, void()); }; class DestructiveDelegate : public QuicAlarm::Delegate { @@ -26,10 +26,9 @@ class DestructiveDelegate : public QuicAlarm::Delegate { void set_alarm(QuicAlarm* alarm) { alarm_ = alarm; } - QuicTime OnAlarm() override { + void OnAlarm() override { DCHECK(alarm_); delete alarm_; - return QuicTime::Zero(); } private: @@ -137,28 +136,17 @@ TEST_F(QuicAlarmTest, UpdateWithZero) { TEST_F(QuicAlarmTest, Fire) { QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7)); alarm_.Set(deadline); - EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Return(QuicTime::Zero())); alarm_.FireAlarm(); EXPECT_FALSE(alarm_.IsSet()); EXPECT_FALSE(alarm_.scheduled()); EXPECT_EQ(QuicTime::Zero(), alarm_.deadline()); } -TEST_F(QuicAlarmTest, FireAndResetViaReturn) { - alarm_.Set(deadline_); - EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Return(deadline2_)); - alarm_.FireAlarm(); - EXPECT_TRUE(alarm_.IsSet()); - EXPECT_TRUE(alarm_.scheduled()); - EXPECT_EQ(deadline2_, alarm_.deadline()); -} - TEST_F(QuicAlarmTest, FireAndResetViaSet) { alarm_.Set(deadline_); new_deadline_ = deadline2_; EXPECT_CALL(*delegate_, OnAlarm()) - .WillOnce(DoAll(Invoke(this, &QuicAlarmTest::ResetAlarm), - Return(QuicTime::Zero()))); + .WillOnce(Invoke(this, &QuicAlarmTest::ResetAlarm)); alarm_.FireAlarm(); EXPECT_TRUE(alarm_.IsSet()); EXPECT_TRUE(alarm_.scheduled()); diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc index bb1a57a..2de5d3c 100644 --- a/net/quic/quic_chromium_client_session_test.cc +++ b/net/quic/quic_chromium_client_session_test.cc @@ -368,7 +368,7 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) { iov[0].iov_base = data; iov[0].iov_len = 4; session_->WritevData(5, QuicIOVector(iov, arraysize(iov), 4), 0, false, - MAY_FEC_PROTECT, nullptr); + nullptr); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); diff --git a/net/quic/quic_chromium_client_stream_test.cc b/net/quic/quic_chromium_client_stream_test.cc index f384304..19c427c 100644 --- a/net/quic/quic_chromium_client_stream_test.cc +++ b/net/quic/quic_chromium_client_stream_test.cc @@ -60,12 +60,11 @@ class MockQuicClientSessionBase : public QuicClientSessionBase { MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id)); MOCK_METHOD1(CreateOutgoingDynamicStream, QuicChromiumClientStream*(SpdyPriority priority)); - MOCK_METHOD6(WritevData, + MOCK_METHOD5(WritevData, QuicConsumedData(QuicStreamId id, QuicIOVector data, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface*)); MOCK_METHOD3(SendRstStream, void(QuicStreamId stream_id, @@ -102,7 +101,6 @@ class MockQuicClientSessionBase : public QuicClientSessionBase { const QuicIOVector& data, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface* ack_notifier_delegate); void OnProofValid( @@ -125,7 +123,7 @@ MockQuicClientSessionBase::MockQuicClientSessionBase( DefaultQuicConfig()) { crypto_stream_.reset(new QuicCryptoStream(this)); Initialize(); - ON_CALL(*this, WritevData(_, _, _, _, _, _)) + ON_CALL(*this, WritevData(_, _, _, _, _)) .WillByDefault(testing::Return(QuicConsumedData(0, false))); } @@ -335,7 +333,7 @@ TEST_P(QuicChromiumClientStreamTest, WriteStreamData) { const size_t kDataLen = arraysize(kData1); // All data written. - EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _)) .WillOnce(Return(QuicConsumedData(kDataLen, true))); TestCompletionCallback callback; EXPECT_EQ(OK, stream_->WriteStreamData(base::StringPiece(kData1, kDataLen), @@ -350,7 +348,7 @@ TEST_P(QuicChromiumClientStreamTest, WriteStreamDataAsync) { const size_t kDataLen = arraysize(kData1); // No data written. - EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _)) .WillOnce(Return(QuicConsumedData(0, false))); TestCompletionCallback callback; EXPECT_EQ(ERR_IO_PENDING, @@ -359,7 +357,7 @@ TEST_P(QuicChromiumClientStreamTest, WriteStreamDataAsync) { ASSERT_FALSE(callback.have_result()); // All data written. - EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _)) .WillOnce(Return(QuicConsumedData(kDataLen, true))); stream_->OnCanWrite(); ASSERT_TRUE(callback.have_result()); diff --git a/net/quic/quic_chromium_connection_helper_test.cc b/net/quic/quic_chromium_connection_helper_test.cc index aefa22a..9fab8fb 100644 --- a/net/quic/quic_chromium_connection_helper_test.cc +++ b/net/quic/quic_chromium_connection_helper_test.cc @@ -17,10 +17,7 @@ class TestDelegate : public QuicAlarm::Delegate { public: TestDelegate() : fired_(false) {} - QuicTime OnAlarm() override { - fired_ = true; - return QuicTime::Zero(); - } + void OnAlarm() override { fired_ = true; } bool fired() const { return fired_; } void Clear() { fired_ = false; } diff --git a/net/quic/quic_client_promised_info.cc b/net/quic/quic_client_promised_info.cc index 3b8740c4..d3816bf 100644 --- a/net/quic/quic_client_promised_info.cc +++ b/net/quic/quic_client_promised_info.cc @@ -23,10 +23,9 @@ QuicClientPromisedInfo::QuicClientPromisedInfo(QuicClientSessionBase* session, QuicClientPromisedInfo::~QuicClientPromisedInfo() {} -QuicTime QuicClientPromisedInfo::CleanupAlarm::OnAlarm() { +void QuicClientPromisedInfo::CleanupAlarm::OnAlarm() { DVLOG(1) << "self GC alarm for stream " << promised_->id_; promised_->Reset(QUIC_STREAM_CANCELLED); - return QuicTime::Zero(); } void QuicClientPromisedInfo::Init() { diff --git a/net/quic/quic_client_promised_info.h b/net/quic/quic_client_promised_info.h index 300c41f..f4bb50f 100644 --- a/net/quic/quic_client_promised_info.h +++ b/net/quic/quic_client_promised_info.h @@ -83,7 +83,7 @@ class NET_EXPORT_PRIVATE QuicClientPromisedInfo explicit CleanupAlarm(QuicClientPromisedInfo* promised) : promised_(promised) {} - QuicTime OnAlarm() override; + void OnAlarm() override; QuicClientPromisedInfo* promised_; }; diff --git a/net/quic/quic_config_test.cc b/net/quic/quic_config_test.cc index ec1c6aa..b18673e 100644 --- a/net/quic/quic_config_test.cc +++ b/net/quic/quic_config_test.cc @@ -77,7 +77,6 @@ TEST_F(QuicConfigTest, ProcessClientHello) { client_config.SetSocketReceiveBufferToSend(kDefaultSocketReceiveBuffer); QuicTagVector copt; copt.push_back(kTBBR); - copt.push_back(kFHDR); client_config.SetConnectionOptionsToSend(copt); CryptoHandshakeMessage msg; client_config.ToHandshakeMessage(&msg); @@ -102,10 +101,9 @@ TEST_F(QuicConfigTest, ProcessClientHello) { EXPECT_EQ(kDefaultMaxStreamsPerConnection, config_.MaxStreamsPerConnection()); EXPECT_EQ(10 * kNumMicrosPerMilli, config_.ReceivedInitialRoundTripTimeUs()); EXPECT_TRUE(config_.HasReceivedConnectionOptions()); - EXPECT_EQ(3u, config_.ReceivedConnectionOptions().size()); + EXPECT_EQ(2u, config_.ReceivedConnectionOptions().size()); EXPECT_EQ(config_.ReceivedConnectionOptions()[0], kIW50); EXPECT_EQ(config_.ReceivedConnectionOptions()[1], kTBBR); - EXPECT_EQ(config_.ReceivedConnectionOptions()[2], kFHDR); EXPECT_EQ(config_.ReceivedInitialStreamFlowControlWindowBytes(), 2 * kInitialStreamFlowControlWindowForTest); EXPECT_EQ(config_.ReceivedInitialSessionFlowControlWindowBytes(), @@ -228,12 +226,9 @@ TEST_F(QuicConfigTest, HasClientSentConnectionOption) { QuicConfig client_config; QuicTagVector copt; copt.push_back(kTBBR); - copt.push_back(kFHDR); client_config.SetConnectionOptionsToSend(copt); EXPECT_TRUE(client_config.HasClientSentConnectionOption( kTBBR, Perspective::IS_CLIENT)); - EXPECT_TRUE(client_config.HasClientSentConnectionOption( - kFHDR, Perspective::IS_CLIENT)); CryptoHandshakeMessage msg; client_config.ToHandshakeMessage(&msg); @@ -245,11 +240,9 @@ TEST_F(QuicConfigTest, HasClientSentConnectionOption) { EXPECT_TRUE(config_.negotiated()); EXPECT_TRUE(config_.HasReceivedConnectionOptions()); - EXPECT_EQ(2u, config_.ReceivedConnectionOptions().size()); + EXPECT_EQ(1u, config_.ReceivedConnectionOptions().size()); EXPECT_TRUE( config_.HasClientSentConnectionOption(kTBBR, Perspective::IS_SERVER)); - EXPECT_TRUE( - config_.HasClientSentConnectionOption(kFHDR, Perspective::IS_SERVER)); } } // namespace diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc index a210022..74bc9e3 100644 --- a/net/quic/quic_connection.cc +++ b/net/quic/quic_connection.cc @@ -31,7 +31,6 @@ #include "net/quic/quic_bandwidth.h" #include "net/quic/quic_bug_tracker.h" #include "net/quic/quic_config.h" -#include "net/quic/quic_fec_group.h" #include "net/quic/quic_flags.h" #include "net/quic/quic_packet_generator.h" #include "net/quic/quic_utils.h" @@ -60,10 +59,6 @@ namespace { // This will likely have to be tuned. const QuicPacketNumber kMaxPacketGap = 5000; -// Limit the number of FEC groups to two. If we get enough out of order packets -// that this becomes limiting, we can revisit. -const size_t kMaxFecGroups = 2; - // Maximum number of acks received before sending an ack in response. const QuicPacketCount kMaxPacketsReceivedBeforeAckSend = 20; @@ -91,10 +86,10 @@ class AckAlarm : public QuicAlarm::Delegate { public: explicit AckAlarm(QuicConnection* connection) : connection_(connection) {} - QuicTime OnAlarm() override { + void OnAlarm() override { DCHECK(connection_->ack_frame_updated()); - connection_->SendAck(); - return QuicTime::Zero(); + QuicConnection::ScopedPacketBundler bundler(connection_, + QuicConnection::SEND_ACK); } private: @@ -111,10 +106,7 @@ class RetransmissionAlarm : public QuicAlarm::Delegate { explicit RetransmissionAlarm(QuicConnection* connection) : connection_(connection) {} - QuicTime OnAlarm() override { - connection_->OnRetransmissionTimeout(); - return QuicTime::Zero(); - } + void OnAlarm() override { connection_->OnRetransmissionTimeout(); } private: QuicConnection* connection_; @@ -128,11 +120,7 @@ class SendAlarm : public QuicAlarm::Delegate { public: explicit SendAlarm(QuicConnection* connection) : connection_(connection) {} - QuicTime OnAlarm() override { - connection_->WriteIfNotBlocked(); - // Never reschedule the alarm, since CanWrite does that. - return QuicTime::Zero(); - } + void OnAlarm() override { connection_->WriteAndBundleAcksIfNotBlocked(); } private: QuicConnection* connection_; @@ -144,11 +132,7 @@ class TimeoutAlarm : public QuicAlarm::Delegate { public: explicit TimeoutAlarm(QuicConnection* connection) : connection_(connection) {} - QuicTime OnAlarm() override { - connection_->CheckForTimeout(); - // Never reschedule the alarm, since CheckForTimeout does that. - return QuicTime::Zero(); - } + void OnAlarm() override { connection_->CheckForTimeout(); } private: QuicConnection* connection_; @@ -160,10 +144,7 @@ class PingAlarm : public QuicAlarm::Delegate { public: explicit PingAlarm(QuicConnection* connection) : connection_(connection) {} - QuicTime OnAlarm() override { - connection_->OnPingTimeout(); - return QuicTime::Zero(); - } + void OnAlarm() override { connection_->OnPingTimeout(); } private: QuicConnection* connection_; @@ -176,11 +157,7 @@ class MtuDiscoveryAlarm : public QuicAlarm::Delegate { explicit MtuDiscoveryAlarm(QuicConnection* connection) : connection_(connection) {} - QuicTime OnAlarm() override { - connection_->DiscoverMtu(); - // DiscoverMtu() handles rescheduling the alarm by itself. - return QuicTime::Zero(); - } + void OnAlarm() override { connection_->DiscoverMtu(); } private: QuicConnection* connection_; @@ -188,23 +165,6 @@ class MtuDiscoveryAlarm : public QuicAlarm::Delegate { DISALLOW_COPY_AND_ASSIGN(MtuDiscoveryAlarm); }; -// This alarm may be scheduled when an FEC protected packet is sent out. -class FecAlarm : public QuicAlarm::Delegate { - public: - explicit FecAlarm(QuicPacketGenerator* packet_generator) - : packet_generator_(packet_generator) {} - - QuicTime OnAlarm() override { - packet_generator_->OnFecTimeout(); - return QuicTime::Zero(); - } - - private: - QuicPacketGenerator* packet_generator_; - - DISALLOW_COPY_AND_ASSIGN(FecAlarm); -}; - // Listens for acks of MTU discovery packets and raises the maximum packet size // of the connection if the probe succeeds. class MtuDiscoveryAckListener : public QuicAckListenerInterface { @@ -265,8 +225,8 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id, peer_address_(address), migrating_peer_port_(0), last_packet_decrypted_(false), - last_packet_revived_(false), last_size_(0), + current_packet_data_(nullptr), last_decrypted_packet_level_(ENCRYPTION_NONE), should_last_packet_instigate_acks_(false), largest_seen_packet_with_ack_(0), @@ -278,11 +238,13 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id, received_packet_manager_(&stats_), ack_queued_(false), num_retransmittable_packets_received_since_last_ack_sent_(0), + last_ack_had_missing_packets_(false), num_packets_received_since_last_ack_sent_(0), stop_waiting_count_(0), - ack_decimation_enabled_(false), + ack_mode_(TCP_ACKING), delay_setting_retransmission_alarm_(false), pending_retransmission_alarm_(false), + defer_send_in_response_to_packets_(false), arena_(), ack_alarm_(helper->CreateAlarm(arena_.New<AckAlarm>(this), &arena_)), retransmission_alarm_( @@ -302,8 +264,6 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id, random_generator_, helper->GetBufferAllocator(), this), - fec_alarm_(helper->CreateAlarm(arena_.New<FecAlarm>(&packet_generator_), - &arena_)), idle_network_timeout_(QuicTime::Delta::Infinite()), handshake_timeout_(QuicTime::Delta::Infinite()), time_of_last_received_packet_(clock_->ApproximateNow()), @@ -356,7 +316,6 @@ QuicConnection::~QuicConnection() { if (termination_packets_.get() != nullptr) { STLDeleteElements(termination_packets_.get()); } - STLDeleteValues(&group_map_); ClearQueuedPackets(); } @@ -395,16 +354,6 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) { } max_undecryptable_packets_ = config.max_undecryptable_packets(); - if (config.HasClientSentConnectionOption(kFSPA, perspective_)) { - packet_generator_.set_fec_send_policy(FecSendPolicy::FEC_ALARM_TRIGGER); - } - if (config.HasClientSentConnectionOption(kFRTT, perspective_)) { - // TODO(rtenneti): Delete this code after the 0.25 RTT FEC experiment. - const float kFecTimeoutRttMultiplier = 0.25; - packet_generator_.set_rtt_multiplier_for_fec_timeout( - kFecTimeoutRttMultiplier); - } - if (config.HasClientSentConnectionOption(kMTUH, perspective_)) { SetMtuDiscoveryTarget(kMtuDiscoveryTargetPacketSizeHigh); } @@ -415,7 +364,11 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) { debug_visitor_->OnSetFromConfig(config); } if (config.HasClientSentConnectionOption(kACKD, perspective_)) { - ack_decimation_enabled_ = true; + ack_mode_ = ACK_DECIMATION; + } + if (FLAGS_quic_ack_decimation2 && + config.HasClientSentConnectionOption(kAKD2, perspective_)) { + ack_mode_ = ACK_DECIMATION_WITH_REORDERING; } } @@ -470,20 +423,8 @@ void QuicConnection::OnError(QuicFramer* framer) { SendConnectionCloseWithDetails(framer->error(), framer->detailed_error()); } -void QuicConnection::MaybeSetFecAlarm(QuicPacketNumber packet_number) { - if (fec_alarm_->IsSet()) { - return; - } - QuicTime::Delta timeout = packet_generator_.GetFecTimeout(packet_number); - if (!timeout.IsInfinite()) { - fec_alarm_->Update(clock_->ApproximateNow().Add(timeout), - QuicTime::Delta::FromMilliseconds(1)); - } -} - void QuicConnection::OnPacket() { last_packet_decrypted_ = false; - last_packet_revived_ = false; } void QuicConnection::OnPublicResetPacket(const QuicPublicResetPacket& packet) { @@ -601,8 +542,6 @@ void QuicConnection::OnVersionNegotiationPacket( RetransmitUnackedPackets(ALL_UNACKED_RETRANSMISSION); } -void QuicConnection::OnRevivedPacket() {} - bool QuicConnection::OnUnauthenticatedPublicHeader( const QuicPacketPublicHeader& header) { if (header.connection_id == connection_id_) { @@ -689,15 +628,6 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) { return true; } -void QuicConnection::OnFecProtectedPayload(StringPiece payload) { - DCHECK_EQ(IN_FEC_GROUP, last_header_.is_in_fec_group); - DCHECK_NE(0u, last_header_.fec_group); - QuicFecGroup* group = GetFecGroup(); - if (group != nullptr) { - group->Update(last_decrypted_packet_level_, last_header_, payload); - } -} - bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) { DCHECK(connected_); if (debug_visitor_ != nullptr) { @@ -708,6 +638,7 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) { QUIC_BUG << ENDPOINT << "Received an unencrypted data frame: closing connection" << " packet_number:" << last_header_.packet_number + << " stream_id:" << frame.stream_id << " received_packets:" << received_packet_manager_.ack_frame(); SendConnectionCloseWithDetails(QUIC_UNENCRYPTED_STREAM_DATA, "Unencrypted stream data seen"); @@ -773,8 +704,6 @@ void QuicConnection::ProcessStopWaitingFrame( const QuicStopWaitingFrame& stop_waiting) { largest_seen_packet_with_stop_waiting_ = last_header_.packet_number; received_packet_manager_.UpdatePacketInformationSentByPeer(stop_waiting); - // Possibly close any FecGroups which are now irrelevant. - CloseFecGroupsBefore(stop_waiting.least_unacked + 1); } bool QuicConnection::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) { @@ -820,7 +749,10 @@ const char* QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) { if (incoming_ack.largest_observed < sent_packet_manager_.largest_observed()) { LOG(WARNING) << ENDPOINT << "Peer's largest_observed packet decreased:" << incoming_ack.largest_observed << " vs " - << sent_packet_manager_.largest_observed(); + << sent_packet_manager_.largest_observed() + << " packet_number:" << last_header_.packet_number + << " largest seen with ack:" << largest_seen_packet_with_ack_ + << " connection_id: " << connection_id_; // A new ack has a diminished largest_observed value. Error out. // If this was an old packet, we wouldn't even have checked. return "Largest observed too low"; @@ -854,14 +786,6 @@ const char* QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) { return "Invalid entropy"; } - if (incoming_ack.latest_revived_packet != 0 && - !incoming_ack.missing_packets.Contains( - incoming_ack.latest_revived_packet)) { - LOG(WARNING) << ENDPOINT - << "Peer specified revived packet which was not missing." - << " revived_packet:" << incoming_ack.latest_revived_packet; - return "Invalid revived packet"; - } return nullptr; } @@ -887,15 +811,6 @@ const char* QuicConnection::ValidateStopWaitingFrame( return nullptr; } -void QuicConnection::OnFecData(StringPiece redundancy) { - DCHECK_EQ(IN_FEC_GROUP, last_header_.is_in_fec_group); - DCHECK_NE(0u, last_header_.fec_group); - QuicFecGroup* group = GetFecGroup(); - if (group != nullptr) { - group->UpdateFec(last_decrypted_packet_level_, last_header_, redundancy); - } -} - bool QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) { DCHECK(connected_); if (debug_visitor_ != nullptr) { @@ -987,8 +902,7 @@ void QuicConnection::OnPacketComplete() { return; } - DVLOG(1) << ENDPOINT << (last_packet_revived_ ? "Revived" : "Got") - << " packet " << last_header_.packet_number << " for " + DVLOG(1) << ENDPOINT << "Got packet " << last_header_.packet_number << " for " << last_header_.public_header.connection_id; // An ack will be sent if a missing retransmittable packet was received; @@ -996,15 +910,11 @@ void QuicConnection::OnPacketComplete() { should_last_packet_instigate_acks_ && received_packet_manager_.IsMissing(last_header_.packet_number); - // Record received or revived packet to populate ack info correctly before - // processing stream frames, since the processing may result in a response - // packet with a bundled ack. - if (last_packet_revived_) { - received_packet_manager_.RecordPacketRevived(last_header_.packet_number); - } else { - received_packet_manager_.RecordPacketReceived( - last_size_, last_header_, time_of_last_received_packet_); - } + // Record received to populate ack info correctly before processing stream + // frames, since the processing may result in a response packet with a bundled + // ack. + received_packet_manager_.RecordPacketReceived(last_size_, last_header_, + time_of_last_received_packet_); // Process stop waiting frames here, instead of inline, because the packet // needs to be considered 'received' before the entropy can be updated. @@ -1019,7 +929,6 @@ void QuicConnection::OnPacketComplete() { ClearLastFrames(); MaybeCloseIfTooManyOutstandingPackets(); - MaybeProcessRevivedPacket(); } void QuicConnection::MaybeQueueAck(bool was_missing) { @@ -1033,13 +942,16 @@ void QuicConnection::MaybeQueueAck(bool was_missing) { // Determine whether the newly received packet was missing before recording // the received packet. - if (was_missing) { + // Ack decimation with reordering relies on the timer to send an ack, but if + // missing packets we reported in the previous ack, send an ack immediately. + if (was_missing && (ack_mode_ != ACK_DECIMATION_WITH_REORDERING || + last_ack_had_missing_packets_)) { ack_queued_ = true; } if (should_last_packet_instigate_acks_ && !ack_queued_) { ++num_retransmittable_packets_received_since_last_ack_sent_; - if (ack_decimation_enabled_ && + if (ack_mode_ != TCP_ACKING && last_header_.packet_number > kMinReceivedBeforeAckDecimation) { // Ack up to 10 packets at once. if (num_retransmittable_packets_received_since_last_ack_sent_ >= @@ -1064,10 +976,18 @@ void QuicConnection::MaybeQueueAck(bool was_missing) { } // If there are new missing packets to report, send an ack immediately. - // TODO(ianswett): Consider allowing 1ms of reordering for the - // ack decimation experiment. if (received_packet_manager_.HasNewMissingPackets()) { - ack_queued_ = true; + if (ack_mode_ == ACK_DECIMATION_WITH_REORDERING) { + // Wait the minimum of an eighth min_rtt and the existing ack time. + QuicTime ack_time = clock_->ApproximateNow().Add( + sent_packet_manager_.GetRttStats()->min_rtt().Multiply(0.125)); + if (!ack_alarm_->IsSet() || ack_alarm_->deadline() > ack_time) { + ack_alarm_->Cancel(); + ack_alarm_->Set(ack_time); + } + } else { + ack_queued_ = true; + } } } @@ -1119,11 +1039,14 @@ void QuicConnection::MaybeSendInResponseToPacket() { if (!connected_) { return; } - ScopedPacketBundler bundler(this, ack_queued_ ? SEND_ACK : NO_ACK); - // Now that we have received an ack, we might be able to send packets which // are queued locally, or drain streams which are blocked. - WriteIfNotBlocked(); + if (defer_send_in_response_to_packets_) { + send_alarm_->Cancel(); + send_alarm_->Set(clock_->ApproximateNow()); + } else { + WriteAndBundleAcksIfNotBlocked(); + } } void QuicConnection::SendVersionNegotiationPacket() { @@ -1162,7 +1085,6 @@ QuicConsumedData QuicConnection::SendStreamData( QuicIOVector iov, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface* listener) { if (!fin && iov.total_length == 0) { QUIC_BUG << "Attempt to send empty stream frame"; @@ -1184,8 +1106,7 @@ QuicConsumedData QuicConnection::SendStreamData( // processing left that may cause received_info_ to change. ScopedRetransmissionScheduler alarm_delayer(this); ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK); - return packet_generator_.ConsumeData(id, iov, offset, fin, fec_protection, - listener); + return packet_generator_.ConsumeData(id, iov, offset, fin, listener); } void QuicConnection::SendRstStream(QuicStreamId id, @@ -1263,7 +1184,7 @@ const QuicConnectionStats& QuicConnection::GetStats() { stats_.srtt_us = srtt.ToMicroseconds(); stats_.estimated_bandwidth = sent_packet_manager_.BandwidthEstimate(); - stats_.max_packet_size = packet_generator_.GetMaxPacketLength(); + stats_.max_packet_size = packet_generator_.GetCurrentMaxPacketLength(); stats_.max_received_packet_size = largest_received_packet_size_; return stats_; } @@ -1278,6 +1199,7 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address, debug_visitor_->OnPacketReceived(self_address, peer_address, packet); } last_size_ = packet.length(); + current_packet_data_ = packet.data(); if (FLAGS_check_peer_address_change_after_decryption) { last_packet_destination_address_ = self_address; @@ -1309,6 +1231,7 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address, } DVLOG(1) << ENDPOINT << "Unable to process packet. Last packet processed: " << last_header_.packet_number; + current_packet_data_ = nullptr; return; } @@ -1316,6 +1239,7 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address, MaybeProcessUndecryptablePackets(); MaybeSendInResponseToPacket(); SetPingAlarm(); + current_packet_data_ = nullptr; } void QuicConnection::CheckForAddressMigration(const IPEndPoint& self_address, @@ -1384,7 +1308,19 @@ void QuicConnection::WriteIfNotBlocked() { } } +void QuicConnection::WriteAndBundleAcksIfNotBlocked() { + if (!writer_->IsWriteBlocked()) { + ScopedPacketBundler bundler(this, ack_queued_ ? SEND_ACK : NO_ACK); + OnCanWrite(); + } +} + bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) { + if (header.fec_flag) { + // Drop any FEC packet. + return false; + } + if (FLAGS_check_peer_address_change_after_decryption) { if (perspective_ == Perspective::IS_SERVER && IsInitializedIPEndPoint(self_address_) && @@ -1459,7 +1395,7 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) { if (perspective_ == Perspective::IS_SERVER && encryption_level_ == ENCRYPTION_NONE && - last_size_ > packet_generator_.GetMaxPacketLength()) { + last_size_ > packet_generator_.GetCurrentMaxPacketLength()) { SetMaxPacketLength(last_size_); } return true; @@ -1492,7 +1428,6 @@ void QuicConnection::WritePendingRetransmissions() { } // Re-packetize the frames with a new packet number for retransmission. - // Retransmitted data packets do not use FEC, even when it's enabled. // Retransmitted packets use the same packet number length as the // original. // Flush the packet generator before making a new packet. @@ -1615,13 +1550,11 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) { } DCHECK_LE(encrypted_length, kMaxPacketSize); - DCHECK_LE(encrypted_length, packet_generator_.GetMaxPacketLength()); + DCHECK_LE(encrypted_length, packet_generator_.GetCurrentMaxPacketLength()); DVLOG(1) << ENDPOINT << "Sending packet " << packet_number << " : " - << (packet->is_fec_packet - ? "FEC " - : (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA - ? "data bearing " - : " ack only ")) + << (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA + ? "data bearing " + : " ack only ") << ", encryption level: " << QuicUtils::EncryptionLevelToString(packet->encryption_level) << ", encrypted length:" << encrypted_length; @@ -1663,7 +1596,6 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) { } } SetPingAlarm(); - MaybeSetFecAlarm(packet_number); MaybeSetMtuAlarm(); DVLOG(1) << ENDPOINT << "time we began writing last sent packet: " << packet_send_time.ToDebuggingValue(); @@ -1751,10 +1683,6 @@ void QuicConnection::OnSerializedPacket(SerializedPacket* serialized_packet) { CloseConnection(QUIC_ENCRYPTION_FAILURE, ConnectionCloseSource::FROM_SELF); return; } - if (serialized_packet->is_fec_packet && fec_alarm_->IsSet()) { - // If an FEC packet is serialized with the FEC alarm set, cancel the alarm. - fec_alarm_->Cancel(); - } SendOrQueuePacket(serialized_packet); } @@ -1765,17 +1693,7 @@ void QuicConnection::OnUnrecoverableError(QuicErrorCode error, CloseConnection(error, source); } -void QuicConnection::OnResetFecGroup() { - if (!fec_alarm_->IsSet()) { - return; - } - // If an FEC Group is closed with the FEC alarm set, cancel the alarm. - fec_alarm_->Cancel(); -} - void QuicConnection::OnCongestionWindowChange() { - packet_generator_.OnCongestionWindowChange( - sent_packet_manager_.EstimateMaxPacketsInFlight(max_packet_length())); visitor_->OnCongestionWindowChange(clock_->ApproximateNow()); } @@ -1786,9 +1704,9 @@ void QuicConnection::OnRttChange() { rtt = QuicTime::Delta::FromMicroseconds( sent_packet_manager_.GetRttStats()->initial_rtt_us()); } + if (debug_visitor_) debug_visitor_->OnRttChanged(rtt); - packet_generator_.OnRttChange(rtt); } void QuicConnection::OnPathDegrading() { @@ -1853,6 +1771,7 @@ void QuicConnection::SendAck() { ack_queued_ = false; stop_waiting_count_ = 0; num_retransmittable_packets_received_since_last_ack_sent_ = 0; + last_ack_had_missing_packets_ = received_packet_manager_.HasMissingPackets(); num_packets_received_since_last_ack_sent_ = 0; packet_generator_.SetShouldSendAck(true); @@ -1969,75 +1888,6 @@ void QuicConnection::MaybeProcessUndecryptablePackets() { } } -void QuicConnection::MaybeProcessRevivedPacket() { - QuicFecGroup* group = GetFecGroup(); - if (!connected_ || group == nullptr || !group->CanRevive()) { - return; - } - QuicPacketHeader revived_header; - char revived_payload[kMaxPacketSize]; - size_t len = group->Revive(&revived_header, revived_payload, kMaxPacketSize); - if (!received_packet_manager_.IsAwaitingPacket( - revived_header.packet_number)) { - // Close this FEC group because all packets in the group has been received. - group_map_.erase(last_header_.fec_group); - delete group; - return; - } - revived_header.public_header.connection_id = connection_id_; - revived_header.public_header.connection_id_length = - last_header_.public_header.connection_id_length; - revived_header.public_header.version_flag = false; - revived_header.public_header.reset_flag = false; - revived_header.public_header.packet_number_length = - last_header_.public_header.packet_number_length; - revived_header.fec_flag = false; - revived_header.is_in_fec_group = NOT_IN_FEC_GROUP; - revived_header.fec_group = 0; - group_map_.erase(last_header_.fec_group); - last_decrypted_packet_level_ = group->EffectiveEncryptionLevel(); - DCHECK_LT(last_decrypted_packet_level_, NUM_ENCRYPTION_LEVELS); - delete group; - - last_packet_revived_ = true; - if (debug_visitor_ != nullptr) { - debug_visitor_->OnRevivedPacket(revived_header, - StringPiece(revived_payload, len)); - } - - ++stats_.packets_revived; - framer_.ProcessRevivedPacket(&revived_header, - StringPiece(revived_payload, len)); -} - -QuicFecGroup* QuicConnection::GetFecGroup() { - QuicFecGroupNumber fec_group_num = last_header_.fec_group; - if (fec_group_num == 0 || - (fec_group_num < - received_packet_manager_.peer_least_packet_awaiting_ack() && - !ContainsKey(group_map_, fec_group_num))) { - // If the group number is below peer_least_packet_awaiting_ack and this - // group does not exist, which means this group has missing packets below - // |peer_least_packet_awaiting_ack| which we would never receive, so return - // nullptr. - return nullptr; - } - if (!ContainsKey(group_map_, fec_group_num)) { - if (group_map_.size() >= kMaxFecGroups) { // Too many groups - if (fec_group_num < group_map_.begin()->first) { - // The group being requested is a group we've seen before and deleted. - // Don't recreate it. - return nullptr; - } - // Clear the lowest group number. - delete group_map_.begin()->second; - group_map_.erase(group_map_.begin()); - } - group_map_[fec_group_num] = new QuicFecGroup(fec_group_num); - } - return group_map_[fec_group_num]; -} - void QuicConnection::SendConnectionCloseWithDetails(QuicErrorCode error, const string& details) { if (!connected_) { @@ -2087,7 +1937,6 @@ void QuicConnection::CloseConnection(QuicErrorCode error, // connection is closed. ack_alarm_->Cancel(); ping_alarm_->Cancel(); - fec_alarm_->Cancel(); resume_writes_alarm_->Cancel(); retransmission_alarm_->Cancel(); send_alarm_->Cancel(); @@ -2112,31 +1961,12 @@ void QuicConnection::SendGoAway(QuicErrorCode error, QuicFrame(new QuicGoAwayFrame(error, last_good_stream_id, reason))); } -void QuicConnection::CloseFecGroupsBefore(QuicPacketNumber packet_number) { - FecGroupMap::iterator it = group_map_.begin(); - while (it != group_map_.end()) { - // If the group doesn't protect this packet we can ignore it. - if (!it->second->IsWaitingForPacketBefore(packet_number)) { - ++it; - continue; - } - QuicFecGroup* fec_group = it->second; - DCHECK(!fec_group->CanRevive()); - FecGroupMap::iterator next = it; - ++next; - group_map_.erase(it); - delete fec_group; - it = next; - } -} - QuicByteCount QuicConnection::max_packet_length() const { - return packet_generator_.GetMaxPacketLength(); + return packet_generator_.GetCurrentMaxPacketLength(); } void QuicConnection::SetMaxPacketLength(QuicByteCount length) { - return packet_generator_.SetMaxPacketLength(LimitMaxPacketSize(length), - /*force=*/false); + return packet_generator_.SetMaxPacketLength(LimitMaxPacketSize(length)); } bool QuicConnection::HasQueuedData() const { @@ -2184,14 +2014,8 @@ void QuicConnection::SetNetworkTimeouts(QuicTime::Delta handshake_timeout, void QuicConnection::CheckForTimeout() { QuicTime now = clock_->ApproximateNow(); - QuicTime time_of_last_packet = QuicTime::Zero(); - if (!FLAGS_quic_use_new_idle_timeout) { - time_of_last_packet = - max(time_of_last_received_packet_, time_of_last_sent_new_packet_); - } else { - time_of_last_packet = - max(time_of_last_received_packet_, last_send_for_timeout_); - } + QuicTime time_of_last_packet = + max(time_of_last_received_packet_, last_send_for_timeout_); // |delta| can be < 0 as |now| is approximate time but |time_of_last_packet| // is accurate time. However, this should not change the behavior of @@ -2502,4 +2326,11 @@ bool QuicConnection::ack_frame_updated() const { return received_packet_manager_.ack_frame_updated(); } +StringPiece QuicConnection::GetCurrentPacket() { + if (current_packet_data_ == nullptr) { + return StringPiece(); + } + return StringPiece(current_packet_data_, last_size_); +} + } // namespace net diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h index b9e9ef7..bf4e85c 100644 --- a/net/quic/quic_connection.h +++ b/net/quic/quic_connection.h @@ -54,7 +54,6 @@ class QuicClock; class QuicConfig; class QuicConnection; class QuicEncrypter; -class QuicFecGroup; class QuicRandom; namespace test { @@ -234,11 +233,6 @@ class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor virtual void OnVersionNegotiationPacket( const QuicVersionNegotiationPacket& packet) {} - // Called after a packet has been successfully parsed which results - // in the revival of a packet via FEC. - virtual void OnRevivedPacket(const QuicPacketHeader& revived_header, - base::StringPiece payload) {} - // Called when the connection is closed. virtual void OnConnectionClosed(QuicErrorCode error, ConnectionCloseSource source) {} @@ -307,6 +301,8 @@ class NET_EXPORT_PRIVATE QuicConnection BUNDLE_PENDING_ACK = 2, }; + enum AckMode { TCP_ACKING, ACK_DECIMATION, ACK_DECIMATION_WITH_REORDERING }; + // Constructs a new QuicConnection for |connection_id| and |address| using // |writer| to write packets. |owns_writer| specifies whether the connection // takes ownership of |writer|. |helper| must outlive this connection. @@ -342,10 +338,7 @@ class NET_EXPORT_PRIVATE QuicConnection // Returns a pair with the number of bytes consumed from data, and a boolean // indicating if the fin bit was consumed. This does not indicate the data // has been sent on the wire: it may have been turned into a packet and queued - // if the socket was unexpectedly blocked. |fec_protection| indicates if - // data is to be FEC protected. Note that data that is sent immediately - // following MUST_FEC_PROTECT data may get protected by falling within the - // same FEC group. + // if the socket was unexpectedly blocked. // If |listener| is provided, then it will be informed once ACKs have been // received for all the packets written in this call. // The |listener| is not owned by the QuicConnection and must outlive it. @@ -353,7 +346,6 @@ class NET_EXPORT_PRIVATE QuicConnection QuicIOVector iov, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface* listener); // Send a RST_STREAM frame to the peer. @@ -392,8 +384,7 @@ class NET_EXPORT_PRIVATE QuicConnection const QuicConnectionStats& GetStats(); // Processes an incoming UDP packet (consisting of a QuicEncryptedPacket) from - // the peer. If processing this packet permits a packet to be revived from - // its FEC group that packet will be revived and processed. + // the peer. // In a client, the packet may be "stray" and have a different connection ID // than that of this connection. virtual void ProcessUdpPacket(const IPEndPoint& self_address, @@ -412,6 +403,10 @@ class NET_EXPORT_PRIVATE QuicConnection // If the socket is not blocked, writes queued packets. void WriteIfNotBlocked(); + // If the socket is not blocked, writes queued packets and bundles any pending + // ACKs. + void WriteAndBundleAcksIfNotBlocked(); + // Set the packet writer. void SetQuicPacketWriter(QuicPacketWriter* writer, bool owns_writer) { DCHECK(writer != nullptr); @@ -440,13 +435,11 @@ class NET_EXPORT_PRIVATE QuicConnection void OnPublicResetPacket(const QuicPublicResetPacket& packet) override; void OnVersionNegotiationPacket( const QuicVersionNegotiationPacket& packet) override; - void OnRevivedPacket() override; bool OnUnauthenticatedPublicHeader( const QuicPacketPublicHeader& header) override; bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override; void OnDecryptedPacket(EncryptionLevel level) override; bool OnPacketHeader(const QuicPacketHeader& header) override; - void OnFecProtectedPayload(base::StringPiece payload) override; bool OnStreamFrame(const QuicStreamFrame& frame) override; bool OnAckFrame(const QuicAckFrame& frame) override; bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override; @@ -457,7 +450,6 @@ class NET_EXPORT_PRIVATE QuicConnection bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override; bool OnBlockedFrame(const QuicBlockedFrame& frame) override; bool OnPathCloseFrame(const QuicPathCloseFrame& frame) override; - void OnFecData(base::StringPiece redundnancy) override; void OnPacketComplete() override; // QuicPacketGenerator::DelegateInterface @@ -470,7 +462,6 @@ class NET_EXPORT_PRIVATE QuicConnection void OnSerializedPacket(SerializedPacket* packet) override; void OnUnrecoverableError(QuicErrorCode error, ConnectionCloseSource source) override; - void OnResetFecGroup() override; // QuicSentPacketManager::NetworkChangeVisitor void OnCongestionWindowChange() override; @@ -516,8 +507,6 @@ class NET_EXPORT_PRIVATE QuicConnection return server_supported_versions_; } - size_t NumFecGroups() const { return group_map_.size(); } - // Testing only. size_t NumQueuedPackets() const { return queued_packets_.size(); } @@ -555,10 +544,6 @@ class NET_EXPORT_PRIVATE QuicConnection // remaining unacked packets. void OnRetransmissionTimeout(); - // Called when a data packet is sent. Starts an alarm if the data sent in - // |packet_number| was FEC protected. - void MaybeSetFecAlarm(QuicPacketNumber packet_number); - // Retransmits all unacked packets with retransmittable frames if // |retransmission_type| is ALL_UNACKED_PACKETS, otherwise retransmits only // initially encrypted packets. Used when the negotiated protocol version is @@ -676,6 +661,8 @@ class NET_EXPORT_PRIVATE QuicConnection QuicConnectionHelperInterface* helper() { return helper_; } + base::StringPiece GetCurrentPacket(); + protected: // Send a packet to the peer, and takes ownership of the packet if the packet // cannot be written immediately. @@ -711,12 +698,18 @@ class NET_EXPORT_PRIVATE QuicConnection per_packet_options_ = options; } + // If |defer| is true, configures the connection to defer sending packets in + // response to an ACK to the SendAlarm. If |defer| is false, packets may be + // sent immediately after receiving an ACK. + void set_defer_send_in_response_to_packets(bool defer) { + defer_send_in_response_to_packets_ = defer; + } + private: friend class test::QuicConnectionPeer; friend class test::PacketSavingConnection; typedef std::list<SerializedPacket> QueuedPacketList; - typedef std::map<QuicFecGroupNumber, QuicFecGroup*> FecGroupMap; // Writes the given packet to socket, encrypted with packet's // encryption_level. Returns true on successful write, and false if the writer @@ -767,10 +760,6 @@ class NET_EXPORT_PRIVATE QuicConnection // Attempts to process any queued undecryptable packets. void MaybeProcessUndecryptablePackets(); - // If a packet can be revived from the current FEC group, then - // revive and process the packet. - void MaybeProcessRevivedPacket(); - void ProcessAckFrame(const QuicAckFrame& incoming_ack); void ProcessStopWaitingFrame(const QuicStopWaitingFrame& stop_waiting); @@ -787,13 +776,6 @@ class NET_EXPORT_PRIVATE QuicConnection // to be sent if there are no outstanding packets. QuicPacketNumber GetLeastUnacked() const; - // Get the FEC group associate with the last processed packet or nullptr, if - // the group has already been deleted. - QuicFecGroup* GetFecGroup(); - - // Closes any FEC groups protecting packets before |packet_number|. - void CloseFecGroupsBefore(QuicPacketNumber packet_number); - // Sets the timeout alarm to the appropriate value, if any. void SetTimeoutAlarm(); @@ -865,8 +847,10 @@ class NET_EXPORT_PRIVATE QuicConnection // True if the last packet has gotten far enough in the framer to be // decrypted. bool last_packet_decrypted_; - bool last_packet_revived_; // True if the last packet was revived from FEC. QuicByteCount last_size_; // Size of the last received packet. + // TODO(rch): remove this when b/27221014 is fixed. + const char* current_packet_data_; // UDP payload of packet currently being + // parsed or nullptr. EncryptionLevel last_decrypted_packet_level_; QuicPacketHeader last_header_; QuicStopWaitingFrame last_stop_waiting_frame_; @@ -910,8 +894,6 @@ class NET_EXPORT_PRIVATE QuicConnection // This is particularly important on mobile, where connections are short. bool silent_close_enabled_; - FecGroupMap group_map_; - QuicReceivedPacketManager received_packet_manager_; QuicSentEntropyManager sent_entropy_manager_; @@ -919,13 +901,15 @@ class NET_EXPORT_PRIVATE QuicConnection bool ack_queued_; // How many retransmittable packets have arrived without sending an ack. QuicPacketCount num_retransmittable_packets_received_since_last_ack_sent_; + // Whether there were missing packets in the last sent ack. + bool last_ack_had_missing_packets_; // How many consecutive packets have arrived without sending an ack. QuicPacketCount num_packets_received_since_last_ack_sent_; // Indicates how many consecutive times an ack has arrived which indicates // the peer needs to stop waiting for some packets. int stop_waiting_count_; - // When true, ack only every 10 packets as long as they arrive close together. - bool ack_decimation_enabled_; + // Indicates the current ack mode, defaults to acking every 2 packets. + AckMode ack_mode_; // Indicates the retransmit alarm is going to be set by the // ScopedRetransmitAlarmDelayer @@ -933,6 +917,10 @@ class NET_EXPORT_PRIVATE QuicConnection // Indicates the retransmission alarm needs to be set. bool pending_retransmission_alarm_; + // If true, defer sending data in response to received packets to the + // SendAlarm. + bool defer_send_in_response_to_packets_; + // Arena to store class implementations within the QuicConnection. QuicConnectionArena arena_; @@ -959,9 +947,6 @@ class NET_EXPORT_PRIVATE QuicConnection QuicPacketGenerator packet_generator_; - // An alarm that fires when an FEC packet should be sent. - QuicArenaScopedPtr<QuicAlarm> fec_alarm_; - // Network idle time before this connection is closed. QuicTime::Delta idle_network_timeout_; // The connection will wait this long for the handshake to complete. diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc index 6b82396..ad4775d 100644 --- a/net/quic/quic_connection_logger.cc +++ b/net/quic/quic_connection_logger.cc @@ -124,9 +124,6 @@ scoped_ptr<base::Value> NetLogQuicAckFrameCallback( for (QuicPacketNumber packet : frame->missing_packets) missing->AppendString(base::Uint64ToString(packet)); - dict->SetString("latest_revived_packet", - base::Int64ToString(frame->latest_revived_packet)); - base::ListValue* received = new base::ListValue(); dict->Set("received_packet_times", received); const PacketTimeVector& received_times = frame->received_packet_times; @@ -640,14 +637,6 @@ void QuicConnectionLogger::OnVersionNegotiationPacket( base::Bind(&NetLogQuicVersionNegotiationPacketCallback, &packet)); } -void QuicConnectionLogger::OnRevivedPacket( - const QuicPacketHeader& revived_header, - base::StringPiece payload) { - net_log_.AddEvent( - NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_REVIVED, - base::Bind(&NetLogQuicPacketHeaderCallback, &revived_header)); -} - void QuicConnectionLogger::OnCryptoHandshakeMessageReceived( const CryptoHandshakeMessage& message) { net_log_.AddEvent( diff --git a/net/quic/quic_connection_logger.h b/net/quic/quic_connection_logger.h index f059ef9..4aba233 100644 --- a/net/quic/quic_connection_logger.h +++ b/net/quic/quic_connection_logger.h @@ -69,8 +69,6 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger void OnPublicResetPacket(const QuicPublicResetPacket& packet) override; void OnVersionNegotiationPacket( const QuicVersionNegotiationPacket& packet) override; - void OnRevivedPacket(const QuicPacketHeader& revived_header, - base::StringPiece payload) override; void OnConnectionClosed(QuicErrorCode error, ConnectionCloseSource source) override; void OnSuccessfulVersionNegotiation(const QuicVersion& version) override; diff --git a/net/quic/quic_connection_stats.cc b/net/quic/quic_connection_stats.cc index f314452..bb3130f 100644 --- a/net/quic/quic_connection_stats.cc +++ b/net/quic/quic_connection_stats.cc @@ -24,7 +24,6 @@ QuicConnectionStats::QuicConnectionStats() packets_lost(0), slowstart_packets_sent(0), slowstart_packets_lost(0), - packets_revived(0), packets_dropped(0), crypto_retransmit_count(0), loss_timeout_count(0), diff --git a/net/quic/quic_connection_stats.h b/net/quic/quic_connection_stats.h index 2787612..b955b66 100644 --- a/net/quic/quic_connection_stats.h +++ b/net/quic/quic_connection_stats.h @@ -26,7 +26,7 @@ struct NET_EXPORT_PRIVATE QuicConnectionStats { std::ostream& os, const QuicConnectionStats& s); - QuicByteCount bytes_sent; // Includes retransmissions, fec. + QuicByteCount bytes_sent; // Includes retransmissions. QuicPacketCount packets_sent; // Non-retransmitted bytes sent in a stream frame. QuicByteCount stream_bytes_sent; @@ -35,7 +35,7 @@ struct NET_EXPORT_PRIVATE QuicConnectionStats { // These include version negotiation and public reset packets, which do not // have packet numbers or frame data. - QuicByteCount bytes_received; // Includes duplicate data for a stream, fec. + QuicByteCount bytes_received; // Includes duplicate data for a stream. // Includes packets which were not processable. QuicPacketCount packets_received; // Excludes packets which were not processable. @@ -55,7 +55,6 @@ struct NET_EXPORT_PRIVATE QuicConnectionStats { // Number of packets lost exiting slow start. QuicPacketCount slowstart_packets_lost; - QuicPacketCount packets_revived; QuicPacketCount packets_dropped; // Duplicate or less than least unacked. size_t crypto_retransmit_count; // Count of times the loss detection alarm fired. At least one packet should diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc index c30ac0a..969fcf2 100644 --- a/net/quic/quic_connection_test.cc +++ b/net/quic/quic_connection_test.cc @@ -141,8 +141,8 @@ class TaggingDecrypter : public QuicDecrypter { bool DecryptPacket(QuicPathId path_id, QuicPacketNumber packet_number, - const StringPiece& associated_data, - const StringPiece& ciphertext, + StringPiece associated_data, + StringPiece ciphertext, char* output, size_t* output_length, size_t max_output_length) override { @@ -482,31 +482,9 @@ class TestConnection : public QuicConnection { QuicStreamOffset offset, bool fin, QuicAckListenerInterface* listener) { - return SendStreamDataWithStringHelper(id, data, offset, fin, - MAY_FEC_PROTECT, listener); - } - - QuicConsumedData SendStreamDataWithStringWithFec( - QuicStreamId id, - StringPiece data, - QuicStreamOffset offset, - bool fin, - QuicAckListenerInterface* listener) { - return SendStreamDataWithStringHelper(id, data, offset, fin, - MUST_FEC_PROTECT, listener); - } - - QuicConsumedData SendStreamDataWithStringHelper( - QuicStreamId id, - StringPiece data, - QuicStreamOffset offset, - bool fin, - FecProtection fec_protection, - QuicAckListenerInterface* listener) { struct iovec iov; QuicIOVector data_iov(MakeIOVector(data, &iov)); - return QuicConnection::SendStreamData(id, data_iov, offset, fin, - fec_protection, listener); + return QuicConnection::SendStreamData(id, data_iov, offset, fin, listener); } QuicConsumedData SendStreamData3() { @@ -514,20 +492,11 @@ class TestConnection : public QuicConnection { nullptr); } - QuicConsumedData SendStreamData3WithFec() { - return SendStreamDataWithStringWithFec(kClientDataStreamId1, "food", 0, - !kFin, nullptr); - } - QuicConsumedData SendStreamData5() { return SendStreamDataWithString(kClientDataStreamId2, "food2", 0, !kFin, nullptr); } - QuicConsumedData SendStreamData5WithFec() { - return SendStreamDataWithStringWithFec(kClientDataStreamId2, "food2", 0, - !kFin, nullptr); - } // Ensures the connection can write stream data before writing. QuicConsumedData EnsureWritableAndSendStreamData5() { EXPECT_TRUE(CanWriteStreamData()); @@ -586,11 +555,6 @@ class TestConnection : public QuicConnection { QuicConnectionPeer::GetPingAlarm(this)); } - TestConnectionHelper::TestAlarm* GetFecAlarm() { - return reinterpret_cast<TestConnectionHelper::TestAlarm*>( - QuicConnectionPeer::GetFecAlarm(this)); - } - TestConnectionHelper::TestAlarm* GetResumeWritesAlarm() { return reinterpret_cast<TestConnectionHelper::TestAlarm*>( QuicConnectionPeer::GetResumeWritesAlarm(this)); @@ -617,6 +581,7 @@ class TestConnection : public QuicConnection { } using QuicConnection::SelectMutualVersion; + using QuicConnection::set_defer_send_in_response_to_packets; private: TestPacketWriter* writer() { @@ -626,34 +591,23 @@ class TestConnection : public QuicConnection { DISALLOW_COPY_AND_ASSIGN(TestConnection); }; -// Used for testing packets revived from FEC packets. -class FecQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor { - public: - void OnRevivedPacket(const QuicPacketHeader& header, - StringPiece data) override { - revived_header_ = header; - } - - // Public accessor method. - QuicPacketHeader revived_header() const { return revived_header_; } +enum class AckResponse { kDefer, kImmediate }; - private: - QuicPacketHeader revived_header_; -}; - -// Run tests with combinations of {QuicVersion, fec_send_policy}. +// Run tests with combinations of {QuicVersion, AckResponse}. struct TestParams { - TestParams(QuicVersion version, FecSendPolicy fec_send_policy) - : version(version), fec_send_policy(fec_send_policy) {} + TestParams(QuicVersion version, AckResponse ack_response) + : version(version), ack_response(ack_response) {} friend ostream& operator<<(ostream& os, const TestParams& p) { os << "{ client_version: " << QuicVersionToString(p.version) - << " fec_send_policy: " << p.fec_send_policy << " }"; + << " ack_response: " + << (p.ack_response == AckResponse::kDefer ? "defer" : "immediate") + << " }"; return os; } QuicVersion version; - FecSendPolicy fec_send_policy; + AckResponse ack_response; }; // Constructs various test permutations. @@ -661,8 +615,10 @@ vector<TestParams> GetTestParams() { vector<TestParams> params; QuicVersionVector all_supported_versions = QuicSupportedVersions(); for (size_t i = 0; i < all_supported_versions.size(); ++i) { - params.push_back(TestParams(all_supported_versions[i], FEC_ANY_TRIGGER)); - params.push_back(TestParams(all_supported_versions[i], FEC_ALARM_TRIGGER)); + for (AckResponse ack_response : + {AckResponse::kDefer, AckResponse::kImmediate}) { + params.push_back(TestParams(all_supported_versions[i], ack_response)); + } } return params; } @@ -696,12 +652,13 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { frame2_(1, false, 3, StringPiece(data2)), packet_number_length_(PACKET_6BYTE_PACKET_NUMBER), connection_id_length_(PACKET_8BYTE_CONNECTION_ID) { + connection_.set_defer_send_in_response_to_packets(GetParam().ack_response == + AckResponse::kDefer); FLAGS_quic_always_log_bugs_for_tests = true; connection_.set_visitor(&visitor_); connection_.SetSendAlgorithm(send_algorithm_); connection_.SetLossAlgorithm(loss_algorithm_); framer_.set_received_entropy_calculator(&entropy_calculator_); - generator_->set_fec_send_policy(GetParam().fec_send_policy); EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)) .WillRepeatedly(Return(QuicTime::Delta::Zero())); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) @@ -735,7 +692,6 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { // TODO(ianswett): Fix QuicConnectionTests so they don't attempt to write // non-crypto stream data at ENCRYPTION_NONE. FLAGS_quic_never_write_unencrypted_data = false; - FLAGS_quic_no_unencrypted_fec = false; } QuicVersion version() { return GetParam().version; } @@ -761,7 +717,10 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { void ProcessPacket(QuicPathId path_id, QuicPacketNumber number) { EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - ProcessDataPacket(path_id, number, 0, !kEntropyFlag); + ProcessDataPacket(path_id, number, !kEntropyFlag); + if (connection_.GetSendAlarm()->IsSet()) { + connection_.GetSendAlarm()->Fire(); + } } QuicPacketEntropyHash ProcessFramePacket(QuicFrame frame) { @@ -785,6 +744,9 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { self_address, peer_address, QuicEncryptedPacket(serialized_packet.encrypted_buffer, serialized_packet.encrypted_length)); + if (connection_.GetSendAlarm()->IsSet()) { + connection_.GetSendAlarm()->Fire(); + } return serialized_packet.entropy_hash; } @@ -814,33 +776,32 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { size_t ProcessDataPacket(QuicPathId path_id, QuicPacketNumber number, - QuicFecGroupNumber fec_group, bool entropy_flag) { - return ProcessDataPacketAtLevel(path_id, number, fec_group, entropy_flag, - false, ENCRYPTION_NONE); + return ProcessDataPacketAtLevel(path_id, number, entropy_flag, false, + ENCRYPTION_NONE); } size_t ProcessDataPacketAtLevel(QuicPathId path_id, QuicPacketNumber number, - QuicFecGroupNumber fec_group, bool entropy_flag, bool has_stop_waiting, EncryptionLevel level) { - scoped_ptr<QuicPacket> packet(ConstructDataPacket( - path_id, number, fec_group, entropy_flag, has_stop_waiting)); + scoped_ptr<QuicPacket> packet( + ConstructDataPacket(path_id, number, entropy_flag, has_stop_waiting)); char buffer[kMaxPacketSize]; size_t encrypted_length = framer_.EncryptPayload( level, path_id, number, *packet, buffer, kMaxPacketSize); connection_.ProcessUdpPacket( kSelfAddress, kPeerAddress, QuicEncryptedPacket(buffer, encrypted_length, false)); + if (connection_.GetSendAlarm()->IsSet()) { + connection_.GetSendAlarm()->Fire(); + } return encrypted_length; } - void ProcessClosePacket(QuicPathId path_id, - QuicPacketNumber number, - QuicFecGroupNumber fec_group) { - scoped_ptr<QuicPacket> packet(ConstructClosePacket(number, fec_group)); + void ProcessClosePacket(QuicPathId path_id, QuicPacketNumber number) { + scoped_ptr<QuicPacket> packet(ConstructClosePacket(number)); char buffer[kMaxPacketSize]; size_t encrypted_length = framer_.EncryptPayload( ENCRYPTION_NONE, path_id, number, *packet, buffer, kMaxPacketSize); @@ -849,106 +810,6 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { QuicEncryptedPacket(buffer, encrypted_length, false)); } - size_t ProcessFecProtectedPacket(QuicPathId path_id, - QuicPacketNumber number, - bool expect_revival, - bool entropy_flag, - bool has_stop_waiting) { - return ProcessFecProtectedPacketAtLevel(path_id, number, 1, expect_revival, - entropy_flag, has_stop_waiting, - ENCRYPTION_NONE); - } - - size_t ProcessFecProtectedPacketAtLevel(QuicPathId path_id, - QuicPacketNumber number, - QuicFecGroupNumber fec_group, - bool expect_revival, - bool entropy_flag, - bool has_stop_waiting, - EncryptionLevel level) { - if (expect_revival) { - EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - } - EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1).RetiresOnSaturation(); - return ProcessDataPacketAtLevel(path_id, number, fec_group, entropy_flag, - has_stop_waiting, level); - } - - // Processes an FEC packet that covers the packets that would have been - // received. - size_t ProcessFecPacket(QuicPathId path_id, - QuicPacketNumber number, - QuicPacketNumber min_protected_packet, - bool expect_revival, - bool entropy_flag, - QuicPacket* packet) { - return ProcessFecPacketAtLevel(path_id, number, min_protected_packet, - expect_revival, entropy_flag, packet, - ENCRYPTION_NONE); - } - - // Processes an FEC packet that covers the packets that would have been - // received. - size_t ProcessFecPacketAtLevel(QuicPathId path_id, - QuicPacketNumber number, - QuicPacketNumber min_protected_packet, - bool expect_revival, - bool entropy_flag, - QuicPacket* packet, - EncryptionLevel level) { - if (expect_revival) { - EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - } - - // Construct the decrypted data packet so we can compute the correct - // redundancy. If |packet| has been provided then use that, otherwise - // construct a default data packet. - scoped_ptr<QuicPacket> data_packet; - if (packet) { - data_packet.reset(packet); - } else { - data_packet.reset(ConstructDataPacket(path_id, number, 1, !kEntropyFlag, - !kHasStopWaiting)); - } - - QuicPacketHeader header; - header.public_header.connection_id = 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 = path_id != kDefaultPathId; - header.path_id = path_id; - header.packet_number = number; - header.entropy_flag = entropy_flag; - header.fec_flag = true; - header.is_in_fec_group = IN_FEC_GROUP; - header.fec_group = min_protected_packet; - - // Since all data packets in this test have the same payload, the - // redundancy is either equal to that payload or the xor of that payload - // with itself, depending on the number of packets. - if (((number - min_protected_packet) % 2) == 0) { - for (size_t i = GetStartOfFecProtectedData( - header.public_header.connection_id_length, - header.public_header.version_flag, - header.public_header.multipath_flag, - header.public_header.packet_number_length); - i < data_packet->length(); ++i) { - data_packet->mutable_data()[i] ^= data_packet->data()[i]; - } - } - - scoped_ptr<QuicPacket> fec_packet( - framer_.BuildFecPacket(header, data_packet->FecProtectedData())); - char buffer[kMaxPacketSize]; - size_t encrypted_length = framer_.EncryptPayload( - level, path_id, number, *fec_packet, buffer, kMaxPacketSize); - - connection_.ProcessUdpPacket( - kSelfAddress, kPeerAddress, - QuicEncryptedPacket(buffer, encrypted_length, false)); - return encrypted_length; - } - QuicByteCount SendStreamDataToPeer(QuicStreamId id, StringPiece data, QuicStreamOffset offset, @@ -1015,7 +876,6 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { QuicPacket* ConstructDataPacket(QuicPathId path_id, QuicPacketNumber number, - QuicFecGroupNumber fec_group, bool entropy_flag, bool has_stop_waiting) { QuicPacketHeader header; @@ -1026,8 +886,8 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { header.entropy_flag = entropy_flag; header.path_id = path_id; header.packet_number = number; - header.is_in_fec_group = fec_group == 0u ? NOT_IN_FEC_GROUP : IN_FEC_GROUP; - header.fec_group = fec_group; + header.is_in_fec_group = NOT_IN_FEC_GROUP; + header.fec_group = 0; QuicFrames frames; frames.push_back(QuicFrame(&frame1_)); @@ -1037,13 +897,12 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { return ConstructPacket(header, frames); } - QuicPacket* ConstructClosePacket(QuicPacketNumber number, - QuicFecGroupNumber fec_group) { + QuicPacket* ConstructClosePacket(QuicPacketNumber number) { QuicPacketHeader header; header.public_header.connection_id = connection_id_; header.packet_number = number; - header.is_in_fec_group = fec_group == 0u ? NOT_IN_FEC_GROUP : IN_FEC_GROUP; - header.fec_group = fec_group; + header.is_in_fec_group = NOT_IN_FEC_GROUP; + header.fec_group = 0; QuicConnectionCloseFrame qccf; qccf.error_code = QUIC_PEER_GOING_AWAY; @@ -1099,7 +958,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> { ConnectionCloseSource::FROM_SELF)); // Call ProcessDataPacket rather than ProcessPacket, as we should not get a // packet call to the visitor. - ProcessDataPacket(kDefaultPathId, 6000, 0, !kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 6000, !kEntropyFlag); EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) == nullptr); } @@ -1346,7 +1205,7 @@ TEST_P(QuicConnectionTest, DuplicatePacket) { // Send packet 3 again, but do not set the expectation that // the visitor OnStreamFrame() will be called. - ProcessDataPacket(kDefaultPathId, 3, 0, !kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 3, !kEntropyFlag); EXPECT_EQ(3u, outgoing_ack()->largest_observed); EXPECT_TRUE(IsMissing(2)); EXPECT_TRUE(IsMissing(1)); @@ -1387,7 +1246,7 @@ TEST_P(QuicConnectionTest, RejectPacketTooFarOut) { ConnectionCloseSource::FROM_SELF)); // Call ProcessDataPacket rather than ProcessPacket, as we should not get a // packet call to the visitor. - ProcessDataPacket(kDefaultPathId, 6000, 0, !kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 6000, !kEntropyFlag); EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) == nullptr); } @@ -1398,7 +1257,7 @@ TEST_P(QuicConnectionTest, RejectUnencryptedStreamData) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_UNENCRYPTED_STREAM_DATA, ConnectionCloseSource::FROM_SELF)); - EXPECT_DFATAL(ProcessDataPacket(kDefaultPathId, 1, 0, !kEntropyFlag), ""); + EXPECT_DFATAL(ProcessDataPacket(kDefaultPathId, 1, !kEntropyFlag), ""); EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) == nullptr); const vector<QuicConnectionCloseFrame>& connection_close_frames = @@ -1867,412 +1726,6 @@ TEST_P(QuicConnectionTest, RecordSentTimeBeforePacketSent) { << ". Actual time = " << actual_recorded_send_time.ToDebuggingValue(); } -TEST_P(QuicConnectionTest, FECSending) { - // All packets carry version info till version is negotiated. - size_t payload_length; - // GetPacketLengthForOneStream() assumes a stream offset of 0 in determining - // packet length. The size of the offset field in a stream frame is 0 for - // offset 0, and 2 for non-zero offsets up through 64K. Increase - // max_packet_length by 2 so that subsequent packets containing subsequent - // stream frames with non-zero offets will fit within the packet length. - size_t length = - 2 + GetPacketLengthForOneStream( - connection_.version(), kIncludeVersion, !kIncludePathId, - PACKET_8BYTE_CONNECTION_ID, PACKET_1BYTE_PACKET_NUMBER, - IN_FEC_GROUP, &payload_length); - connection_.SetMaxPacketLength(length); - - if (generator_->fec_send_policy() == FEC_ALARM_TRIGGER) { - // Send 4 protected data packets. FEC packet is not sent. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)) - .Times(4); - } else { - // Send 4 protected data packets, which should also trigger 1 FEC packet. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)) - .Times(5); - } - // The first stream frame will have 2 fewer overhead bytes than the other 3. - const string payload(payload_length * 4 + 2, 'a'); - connection_.SendStreamDataWithStringWithFec(1, payload, 0, !kFin, nullptr); - // Expect the FEC group to be closed after SendStreamDataWithString. - EXPECT_FALSE(creator_->IsFecGroupOpen()); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); -} - -TEST_P(QuicConnectionTest, FECQueueing) { - // All packets carry version info till version is negotiated. - size_t payload_length; - size_t length = GetPacketLengthForOneStream( - connection_.version(), kIncludeVersion, !kIncludePathId, - PACKET_8BYTE_CONNECTION_ID, PACKET_1BYTE_PACKET_NUMBER, IN_FEC_GROUP, - &payload_length); - connection_.SetMaxPacketLength(length); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_)); - - EXPECT_EQ(0u, connection_.NumQueuedPackets()); - BlockOnNextWrite(); - const string payload(payload_length, 'a'); - connection_.SendStreamDataWithStringWithFec(1, payload, 0, !kFin, nullptr); - EXPECT_FALSE(creator_->IsFecGroupOpen()); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - if (generator_->fec_send_policy() == FEC_ALARM_TRIGGER) { - // Expect the first data packet to be queued and not the FEC packet. - EXPECT_EQ(1u, connection_.NumQueuedPackets()); - } else { - // Expect the first data packet and the fec packet to be queued. - EXPECT_EQ(2u, connection_.NumQueuedPackets()); - } -} - -TEST_P(QuicConnectionTest, FECAlarmStoppedWhenFECPacketSent) { - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_)); - EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); - - creator_->set_max_packets_per_fec_group(2); - - // 1 Data packet. FEC alarm should be set. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.SendStreamDataWithStringWithFec(3, "foo", 0, true, nullptr); - EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); - - if (generator_->fec_send_policy() == FEC_ALARM_TRIGGER) { - // If FEC send policy is FEC_ALARM_TRIGGER, FEC packet is not sent. - // FEC alarm should not be set. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - } else { - // Second data packet triggers FEC packet out. FEC alarm should not be set. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)) - .Times(2); - } - connection_.SendStreamDataWithStringWithFec(5, "foo", 0, true, nullptr); - if (generator_->fec_send_policy() == FEC_ANY_TRIGGER) { - EXPECT_TRUE(writer_->header().fec_flag); - } - EXPECT_FALSE(creator_->IsFecGroupOpen()); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); -} - -TEST_P(QuicConnectionTest, FECAlarmStoppedOnConnectionClose) { - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_)); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); - creator_->set_max_packets_per_fec_group(100); - - // 1 Data packet. FEC alarm should be set. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr); - EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); - - EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NO_ERROR, - ConnectionCloseSource::FROM_SELF)); - // Closing connection should stop the FEC alarm. - connection_.CloseConnection(QUIC_NO_ERROR, ConnectionCloseSource::FROM_SELF); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); -} - -TEST_P(QuicConnectionTest, RemoveFECFromInflightOnRetransmissionTimeout) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_)); - EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); - - // 1 Data packet. FEC alarm should be set. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr); - EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); - size_t protected_packet = - QuicSentPacketManagerPeer::GetBytesInFlight(manager_); - - // Force FEC timeout to send FEC packet out. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, 2u, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.GetFecAlarm()->Fire(); - EXPECT_TRUE(writer_->header().fec_flag); - - size_t fec_packet = protected_packet; - EXPECT_EQ(protected_packet + fec_packet, - QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - clock_.AdvanceTime(DefaultRetransmissionTime()); - - // On RTO, both data and FEC packets are removed from inflight, only the data - // packet is retransmitted, and this retransmission (but not FEC) gets added - // back into the inflight. - EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - connection_.GetRetransmissionAlarm()->Fire(); - - // The retransmission of packet 1 will be 3 bytes smaller than packet 1, since - // the first transmission will have 1 byte for FEC group number and 2 bytes of - // stream frame size, which are absent in the retransmission. - size_t retransmitted_packet = protected_packet - 3; - EXPECT_EQ(protected_packet + retransmitted_packet, - QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); - - // Receive ack for the retransmission. No data should be outstanding. - QuicAckFrame ack = InitAckFrame(3); - NackPacket(1, &ack); - NackPacket(2, &ack); - SendAlgorithmInterface::CongestionVector lost_packets; - lost_packets.push_back(std::make_pair(1, kMaxPacketSize)); - EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _)) - .WillOnce(SetArgPointee<3>(lost_packets)); - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); - ProcessAckPacket(&ack); - - // Ensure the alarm is not set since all packets have been acked or abandoned. - EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); - EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); -} - -TEST_P(QuicConnectionTest, RemoveFECFromInflightOnLossRetransmission) { - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_)); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); - - // 1 FEC-protected data packet. FEC alarm should be set. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr); - EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); - size_t protected_packet = - QuicSentPacketManagerPeer::GetBytesInFlight(manager_); - - // Force FEC timeout to send FEC packet out. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.GetFecAlarm()->Fire(); - EXPECT_TRUE(writer_->header().fec_flag); - size_t fec_packet = protected_packet; - EXPECT_EQ(protected_packet + fec_packet, - QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - - // Send more data to trigger NACKs. Note that all data starts at stream offset - // 0 to ensure the same packet size, for ease of testing. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)) - .Times(4); - connection_.SendStreamDataWithString(5, "foo", 0, kFin, nullptr); - connection_.SendStreamDataWithString(7, "foo", 0, kFin, nullptr); - connection_.SendStreamDataWithString(9, "foo", 0, kFin, nullptr); - connection_.SendStreamDataWithString(11, "foo", 0, kFin, nullptr); - - // An unprotected packet will be 3 bytes smaller than an FEC-protected packet, - // since the protected packet will have 1 byte for FEC group number and - // 2 bytes of stream frame size, which are absent in the unprotected packet. - size_t unprotected_packet = protected_packet - 3; - EXPECT_EQ(protected_packet + fec_packet + 4 * unprotected_packet, - QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); - - // Ack data packets, and NACK FEC packet and one data packet. Triggers - // NACK-based loss detection of both packets, but only data packet is - // retransmitted and considered outstanding. - QuicAckFrame ack = InitAckFrame(6); - NackPacket(2, &ack); - NackPacket(3, &ack); - SendAlgorithmInterface::CongestionVector lost_packets; - lost_packets.push_back(std::make_pair(2, kMaxPacketSize)); - lost_packets.push_back(std::make_pair(3, kMaxPacketSize)); - EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _)) - .WillOnce(SetArgPointee<3>(lost_packets)); - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - ProcessAckPacket(&ack); - // On receiving this ack from the server, the client will no longer send - // version number in subsequent packets, including in this retransmission. - size_t unprotected_packet_no_version = unprotected_packet - 4; - EXPECT_EQ(unprotected_packet_no_version, - QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - - // Receive ack for the retransmission. No data should be outstanding. - QuicAckFrame ack2 = InitAckFrame(7); - NackPacket(2, &ack2); - NackPacket(3, &ack2); - EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _)); - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); - ProcessAckPacket(&ack2); - EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); -} - -TEST_P(QuicConnectionTest, FECRemainsInflightOnTLPOfEarlierData) { - // This test checks if TLP is sent correctly when a data and an FEC packet - // are outstanding. TLP should be sent for the data packet when the - // retransmission alarm fires. - // Turn on TLP for this test. - QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_)); - EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); - - // 1 Data packet. FEC alarm should be set. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr); - EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); - size_t protected_packet = - QuicSentPacketManagerPeer::GetBytesInFlight(manager_); - EXPECT_LT(0u, protected_packet); - - // Force FEC timeout to send FEC packet out. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, 2u, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.GetFecAlarm()->Fire(); - EXPECT_TRUE(writer_->header().fec_flag); - size_t fec_packet = protected_packet; - EXPECT_EQ(protected_packet + fec_packet, - QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - - // TLP alarm should be set. - QuicTime retransmission_time = - connection_.GetRetransmissionAlarm()->deadline(); - EXPECT_NE(QuicTime::Zero(), retransmission_time); - // Simulate the retransmission alarm firing and sending a TLP, so send - // algorithm's OnRetransmissionTimeout is not called. - clock_.AdvanceTime(retransmission_time.Subtract(clock_.Now())); - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, 3u, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.GetRetransmissionAlarm()->Fire(); - // The TLP retransmission of packet 1 will be 3 bytes smaller than packet 1, - // since packet 1 will have 1 byte for FEC group number and 2 bytes of stream - // frame size, which are absent in the the TLP retransmission. - size_t tlp_packet = protected_packet - 3; - EXPECT_EQ(protected_packet + fec_packet + tlp_packet, - QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); -} - -TEST_P(QuicConnectionTest, FECRemainsInflightOnTLPOfLaterData) { - // Tests if TLP is sent correctly when data packet 1 and an FEC packet are - // sent followed by data packet 2, and data packet 1 is acked. TLP should be - // sent for data packet 2 when the retransmission alarm fires. Turn on TLP for - // this test. - QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_)); - EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); - - // 1 Data packet. FEC alarm should be set. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, 1u, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.SendStreamDataWithStringWithFec(3, "foo", 0, kFin, nullptr); - EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); - size_t protected_packet = - QuicSentPacketManagerPeer::GetBytesInFlight(manager_); - EXPECT_LT(0u, protected_packet); - - // Force FEC timeout to send FEC packet out. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, 2u, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.GetFecAlarm()->Fire(); - EXPECT_TRUE(writer_->header().fec_flag); - // Protected data packet and FEC packet oustanding. - size_t fec_packet = protected_packet; - EXPECT_EQ(protected_packet + fec_packet, - QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - - // Send 1 unprotected data packet. No FEC alarm should be set. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, 3u, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.SendStreamDataWithString(5, "foo", 0, kFin, nullptr); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); - // Protected data packet, FEC packet, and unprotected data packet oustanding. - // An unprotected packet will be 3 bytes smaller than an FEC-protected packet, - // since the protected packet will have 1 byte for FEC group number and - // 2 bytes of stream frame size, which are absent in the unprotected packet. - size_t unprotected_packet = protected_packet - 3; - EXPECT_EQ(protected_packet + fec_packet + unprotected_packet, - QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - - // Receive ack for first data packet. FEC and second data packet are still - // outstanding. - QuicAckFrame ack = InitAckFrame(1); - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - ProcessAckPacket(&ack); - // FEC packet and unprotected data packet oustanding. - EXPECT_EQ(fec_packet + unprotected_packet, - QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - - // TLP alarm should be set. - QuicTime retransmission_time = - connection_.GetRetransmissionAlarm()->deadline(); - EXPECT_NE(QuicTime::Zero(), retransmission_time); - // Simulate the retransmission alarm firing and sending a TLP, so send - // algorithm's OnRetransmissionTimeout is not called. - clock_.AdvanceTime(retransmission_time.Subtract(clock_.Now())); - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, 4u, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.GetRetransmissionAlarm()->Fire(); - - // Having received an ack from the server, the client will no longer send - // version number in subsequent packets, including in this retransmission. - size_t tlp_packet_no_version = unprotected_packet - 4; - EXPECT_EQ(fec_packet + unprotected_packet + tlp_packet_no_version, - QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); -} - -TEST_P(QuicConnectionTest, NoTLPForFECPacket) { - // Turn on TLP for this test. - QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_)); - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - - // Send 1 FEC-protected data packet. FEC alarm should be set. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr); - EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); - // Force FEC timeout to send FEC packet out. - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)) - .Times(1); - connection_.GetFecAlarm()->Fire(); - EXPECT_TRUE(writer_->header().fec_flag); - - // Ack data packet, but not FEC packet. - QuicAckFrame ack = InitAckFrame(1); - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); - ProcessAckPacket(&ack); - - // No TLP alarm for FEC, but retransmission alarm should be set for an RTO. - EXPECT_LT(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); - EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); - QuicTime rto_time = connection_.GetRetransmissionAlarm()->deadline(); - EXPECT_NE(QuicTime::Zero(), rto_time); - - // Simulate the retransmission alarm firing. FEC packet is no longer - // outstanding. - clock_.AdvanceTime(rto_time.Subtract(clock_.Now())); - connection_.GetRetransmissionAlarm()->Fire(); - - EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); - EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_)); -} - TEST_P(QuicConnectionTest, FramePacking) { // Send an ack and two stream frames in 1 packet by queueing them. { @@ -2333,34 +1786,11 @@ TEST_P(QuicConnectionTest, FramePackingCryptoThenNonCrypto) { EXPECT_EQ(kClientDataStreamId1, writer_->stream_frames()[0]->stream_id); } -TEST_P(QuicConnectionTest, FramePackingFEC) { - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(creator_)); - - // Queue an ack and two stream frames. Ack gets flushed when FEC is turned on - // for sending protected data; two stream frames are packed in 1 packet. - { - QuicConnection::ScopedPacketBundler bundler(&connection_, - QuicConnection::SEND_ACK); - connection_.SendStreamData3WithFec(); - connection_.SendStreamData5WithFec(); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - } - EXPECT_EQ(0u, connection_.NumQueuedPackets()); - EXPECT_FALSE(connection_.HasQueuedData()); - - // Parse the last packet and ensure it's in an fec group. - EXPECT_EQ(2u, writer_->header().fec_group); - EXPECT_EQ(2u, writer_->frame_count()); - - // FEC alarm should be set. - EXPECT_TRUE(connection_.GetFecAlarm()->IsSet()); -} - TEST_P(QuicConnectionTest, FramePackingAckResponse) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); // Process a data packet to queue up a pending ack. EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - ProcessDataPacket(kDefaultPathId, 1, 1, kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 1, kEntropyFlag); EXPECT_CALL(visitor_, OnCanWrite()) .WillOnce(DoAll(IgnoreResult(InvokeWithoutArgs( @@ -2398,8 +1828,7 @@ 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, - MAY_FEC_PROTECT, nullptr); + connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, !kFin, nullptr); EXPECT_EQ(0u, connection_.NumQueuedPackets()); EXPECT_FALSE(connection_.HasQueuedData()); @@ -2424,8 +1853,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, - MAY_FEC_PROTECT, nullptr); + connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, !kFin, nullptr); EXPECT_EQ(1u, connection_.NumQueuedPackets()); EXPECT_TRUE(connection_.HasQueuedData()); @@ -2445,7 +1873,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(1, empty_iov, 0, kFin, MAY_FEC_PROTECT, nullptr); + connection_.SendStreamData(1, empty_iov, 0, kFin, nullptr); EXPECT_EQ(0u, connection_.NumQueuedPackets()); EXPECT_FALSE(connection_.HasQueuedData()); @@ -2985,128 +2413,6 @@ TEST_P(QuicConnectionTest, DontLatchUnackedPacket) { EXPECT_EQ(6u, stop_waiting()->least_unacked); } -TEST_P(QuicConnectionTest, ReviveMissingPacketAfterFecPacket) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - - // Don't send missing packet 1. - ProcessFecPacket(kDefaultPathId, 2, 1, true, !kEntropyFlag, nullptr); - // Entropy flag should be false, so entropy should be 0. - EXPECT_EQ(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2)); -} - -TEST_P(QuicConnectionTest, ReviveMissingPacketWithVaryingSeqNumLengths) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - - // Set up a debug visitor to the connection. - scoped_ptr<FecQuicConnectionDebugVisitor> fec_visitor( - new FecQuicConnectionDebugVisitor()); - connection_.set_debug_visitor(fec_visitor.get()); - - QuicPacketNumber fec_packet = 0; - // clang-format off - QuicPacketNumberLength lengths[] = { - PACKET_6BYTE_PACKET_NUMBER, PACKET_4BYTE_PACKET_NUMBER, - PACKET_2BYTE_PACKET_NUMBER, PACKET_1BYTE_PACKET_NUMBER}; - // clang-format on - // For each packet number length size, revive a packet and check sequence - // number length in the revived packet. - for (size_t i = 0; i < arraysize(lengths); ++i) { - // Set packet_number_length_ (for data and FEC packets). - packet_number_length_ = lengths[i]; - fec_packet += 2; - // Don't send missing packet, but send fec packet right after it. - ProcessFecPacket(kDefaultPathId, fec_packet, fec_packet - 1, true, - !kEntropyFlag, nullptr); - // packet number length in the revived header should be the same as - // in the original data/fec packet headers. - EXPECT_EQ(packet_number_length_, - fec_visitor->revived_header().public_header.packet_number_length); - } -} - -TEST_P(QuicConnectionTest, ReviveMissingPacketWithVaryingConnectionIdLengths) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - - // Set up a debug visitor to the connection. - scoped_ptr<FecQuicConnectionDebugVisitor> fec_visitor( - new FecQuicConnectionDebugVisitor()); - connection_.set_debug_visitor(fec_visitor.get()); - - QuicPacketNumber fec_packet = 0; - QuicConnectionIdLength lengths[] = { - PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_CONNECTION_ID, - PACKET_1BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID}; - // For each connection id length size, revive a packet and check connection - // id length in the revived packet. - for (size_t i = 0; i < arraysize(lengths); ++i) { - // Set connection id length (for data and FEC packets). - connection_id_length_ = lengths[i]; - fec_packet += 2; - // Don't send missing packet, but send fec packet right after it. - ProcessFecPacket(kDefaultPathId, fec_packet, fec_packet - 1, true, - !kEntropyFlag, nullptr); - // Connection id length in the revived header should be the same as - // in the original data/fec packet headers. - EXPECT_EQ(connection_id_length_, - fec_visitor->revived_header().public_header.connection_id_length); - } -} - -TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacketThenFecPacket) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - - ProcessFecProtectedPacket(kDefaultPathId, 1, false, kEntropyFlag, - !kHasStopWaiting); - // Don't send missing packet 2. - ProcessFecPacket(kDefaultPathId, 3, 1, true, !kEntropyFlag, nullptr); - // Entropy flag should be true, so entropy should not be 0. - EXPECT_NE(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2)); -} - -TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacketsThenFecPacket) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - - ProcessFecProtectedPacket(kDefaultPathId, 1, false, !kEntropyFlag, - !kHasStopWaiting); - // Don't send missing packet 2. - ProcessFecProtectedPacket(kDefaultPathId, 3, false, !kEntropyFlag, - !kHasStopWaiting); - ProcessFecPacket(kDefaultPathId, 4, 1, true, kEntropyFlag, nullptr); - // Ensure QUIC no longer revives entropy for lost packets. - EXPECT_EQ(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2)); - EXPECT_NE(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 4)); -} - -TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacket) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - - // Don't send missing packet 1. - ProcessFecPacket(kDefaultPathId, 3, 1, false, !kEntropyFlag, nullptr); - // Out of order. - ProcessFecProtectedPacket(kDefaultPathId, 2, true, !kEntropyFlag, - !kHasStopWaiting); - // Entropy flag should be false, so entropy should be 0. - EXPECT_EQ(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2)); -} - -TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPackets) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - - ProcessFecProtectedPacket(kDefaultPathId, 1, false, !kEntropyFlag, - !kHasStopWaiting); - // Don't send missing packet 2. - ProcessFecPacket(kDefaultPathId, 6, 1, false, kEntropyFlag, nullptr); - ProcessFecProtectedPacket(kDefaultPathId, 3, false, kEntropyFlag, - !kHasStopWaiting); - ProcessFecProtectedPacket(kDefaultPathId, 4, false, kEntropyFlag, - !kHasStopWaiting); - ProcessFecProtectedPacket(kDefaultPathId, 5, true, !kEntropyFlag, - !kHasStopWaiting); - // Ensure entropy is not revived for the missing packet. - EXPECT_EQ(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2)); - EXPECT_NE(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 3)); -} - TEST_P(QuicConnectionTest, TLP) { QuicSentPacketManagerPeer::SetMaxTailLossProbes(manager_, 1); @@ -3315,7 +2621,7 @@ TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) { // Process an encrypted packet which can not yet be decrypted which should // result in the packet being buffered. - ProcessDataPacketAtLevel(kDefaultPathId, 1, 0, kEntropyFlag, !kHasStopWaiting, + ProcessDataPacketAtLevel(kDefaultPathId, 1, kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); // Transition to the new encryption state and process another encrypted packet @@ -3324,55 +2630,16 @@ TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) { connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag)); EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(2); - ProcessDataPacketAtLevel(kDefaultPathId, 2, 0, kEntropyFlag, !kHasStopWaiting, + ProcessDataPacketAtLevel(kDefaultPathId, 2, kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); // Finally, process a third packet and note that we do not reprocess the // buffered packet. EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - ProcessDataPacketAtLevel(kDefaultPathId, 3, 0, kEntropyFlag, !kHasStopWaiting, + ProcessDataPacketAtLevel(kDefaultPathId, 3, kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); } -TEST_P(QuicConnectionTest, ProcessBufferedFECGroup) { - // SetFromConfig is always called after construction from InitializeSession. - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - QuicConfig config; - config.set_max_undecryptable_packets(100); - connection_.SetFromConfig(config); - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - use_tagging_decrypter(); - - const uint8_t tag = 0x07; - framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag)); - - // Don't send packet 1 and buffer initially encrypted packets. - ProcessFecProtectedPacketAtLevel(kDefaultPathId, 2, 1, false, !kEntropyFlag, - !kHasStopWaiting, ENCRYPTION_INITIAL); - ProcessFecPacketAtLevel(kDefaultPathId, 3, 1, false, kEntropyFlag, nullptr, - ENCRYPTION_INITIAL); - // Since the packets were buffered, no FEC group should be open. - ASSERT_EQ(0u, connection_.NumFecGroups()); - - // Now send non-fec protected ack packet and close the group. - QuicStopWaitingFrame frame = InitStopWaitingFrame(4); - ProcessStopWaitingPacketAtLevel(kDefaultPathId, 4, &frame, - ENCRYPTION_INITIAL); - - // Transition to the new encryption state and process another encrypted packet - // which should result in the original packets being processed. The missing - // packet should be revived before the STOP_WAITING packet is processed. - connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag)); - connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); - connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag)); - - EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(2).RetiresOnSaturation(); - ProcessDataPacketAtLevel(kDefaultPathId, 5, 0, kEntropyFlag, !kHasStopWaiting, - ENCRYPTION_INITIAL); - const QuicConnectionStats& stats = connection_.GetStats(); - EXPECT_EQ(1u, stats.packets_revived); -} - TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) { // SetFromConfig is always called after construction from InitializeSession. EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); @@ -3388,8 +2655,8 @@ TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) { // Process an encrypted packet which can not yet be decrypted which should // result in the packet being buffered. for (QuicPacketNumber i = 1; i <= 100; ++i) { - ProcessDataPacketAtLevel(kDefaultPathId, i, 0, kEntropyFlag, - !kHasStopWaiting, ENCRYPTION_INITIAL); + ProcessDataPacketAtLevel(kDefaultPathId, i, kEntropyFlag, !kHasStopWaiting, + ENCRYPTION_INITIAL); } // Transition to the new encryption state and process another encrypted packet @@ -3398,14 +2665,14 @@ TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) { connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag)); EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(101); - ProcessDataPacketAtLevel(kDefaultPathId, 101, 0, kEntropyFlag, - !kHasStopWaiting, ENCRYPTION_INITIAL); + ProcessDataPacketAtLevel(kDefaultPathId, 101, kEntropyFlag, !kHasStopWaiting, + ENCRYPTION_INITIAL); // Finally, process a third packet and note that we do not reprocess the // buffered packet. EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - ProcessDataPacketAtLevel(kDefaultPathId, 102, 0, kEntropyFlag, - !kHasStopWaiting, ENCRYPTION_INITIAL); + ProcessDataPacketAtLevel(kDefaultPathId, 102, kEntropyFlag, !kHasStopWaiting, + ENCRYPTION_INITIAL); } TEST_P(QuicConnectionTest, TestRetransmitOrder) { @@ -3501,53 +2768,6 @@ TEST_P(QuicConnectionTest, TestQueued) { EXPECT_EQ(0u, connection_.NumQueuedPackets()); } -TEST_P(QuicConnectionTest, CloseFecGroup) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - // Don't send missing packet 1. - // Don't send missing packet 2. - ProcessFecProtectedPacket(kDefaultPathId, 3, false, !kEntropyFlag, - !kHasStopWaiting); - // Don't send missing FEC packet 3. - ASSERT_EQ(1u, connection_.NumFecGroups()); - - // Now send non-fec protected ack packet and close the group. - QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 4); - QuicStopWaitingFrame frame = InitStopWaitingFrame(5); - ProcessStopWaitingPacket(&frame); - ASSERT_EQ(0u, connection_.NumFecGroups()); -} - -TEST_P(QuicConnectionTest, - CloseFecGroupUnderStopWaitingAndWaitingForPacketsBelowStopWaiting) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - // Don't send missing packet 1. - ProcessFecProtectedPacket(kDefaultPathId, 2, false, !kEntropyFlag, - !kHasStopWaiting); - EXPECT_EQ(1u, connection_.NumFecGroups()); - stop_waiting_ = InitStopWaitingFrame(2); - ProcessFecProtectedPacket(kDefaultPathId, 3, false, !kEntropyFlag, - kHasStopWaiting); - // This Fec group would be closed. - EXPECT_EQ(0u, connection_.NumFecGroups()); -} - -TEST_P(QuicConnectionTest, - DoNotCloseFecGroupUnderStopWaitingButNotWaitingForPacketsBelow) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - ProcessFecProtectedPacket(kDefaultPathId, 1, false, !kEntropyFlag, - !kHasStopWaiting); - ProcessFecProtectedPacket(kDefaultPathId, 2, false, !kEntropyFlag, - !kHasStopWaiting); - // Don't send missing packet 3. - EXPECT_EQ(1u, connection_.NumFecGroups()); - stop_waiting_ = InitStopWaitingFrame(2); - ProcessFecProtectedPacket(kDefaultPathId, 3, false, !kEntropyFlag, - kHasStopWaiting); - // This group will not be closed because this group is not waiting for packets - // below stop waiting. - EXPECT_EQ(1u, connection_.NumFecGroups()); -} - TEST_P(QuicConnectionTest, InitialTimeout) { EXPECT_TRUE(connection_.connected()); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber()); @@ -3573,7 +2793,6 @@ TEST_P(QuicConnectionTest, InitialTimeout) { EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); EXPECT_FALSE(connection_.GetPingAlarm()->IsSet()); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); EXPECT_FALSE(connection_.GetResumeWritesAlarm()->IsSet()); EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); EXPECT_FALSE(connection_.GetSendAlarm()->IsSet()); @@ -3617,7 +2836,6 @@ TEST_P(QuicConnectionTest, HandshakeTimeout) { EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); EXPECT_FALSE(connection_.GetPingAlarm()->IsSet()); - EXPECT_FALSE(connection_.GetFecAlarm()->IsSet()); EXPECT_FALSE(connection_.GetResumeWritesAlarm()->IsSet()); EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); EXPECT_FALSE(connection_.GetSendAlarm()->IsSet()); @@ -3898,110 +3116,7 @@ TEST_P(QuicConnectionTest, NoMtuDiscoveryAfterConnectionClosed) { EXPECT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } -TEST_P(QuicConnectionTest, OldTimeoutAfterSend) { - ValueRestore<bool> old_flags(&FLAGS_quic_use_new_idle_timeout, false); - EXPECT_TRUE(connection_.connected()); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - QuicConfig config; - connection_.SetFromConfig(config); - EXPECT_FALSE(QuicConnectionPeer::IsSilentCloseEnabled(&connection_)); - - const QuicTime::Delta initial_idle_timeout = - QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1); - const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5); - QuicTime default_timeout = clock_.ApproximateNow().Add(initial_idle_timeout); - - // When we send a packet, the timeout will change to 5ms + - // kInitialIdleTimeoutSecs. - clock_.AdvanceTime(five_ms); - - // Send an ack so we don't set the retransmission alarm. - SendAckPacketToPeer(); - EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); - - // The original alarm will fire. We should not time out because we had a - // network event at t=5ms. The alarm will reregister. - clock_.AdvanceTime(initial_idle_timeout.Subtract(five_ms)); - EXPECT_EQ(default_timeout, clock_.ApproximateNow()); - connection_.GetTimeoutAlarm()->Fire(); - EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); - EXPECT_TRUE(connection_.connected()); - EXPECT_EQ(default_timeout.Add(five_ms), - connection_.GetTimeoutAlarm()->deadline()); - - // This time, we should time out. - EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NETWORK_IDLE_TIMEOUT, - ConnectionCloseSource::FROM_SELF)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - clock_.AdvanceTime(five_ms); - EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow()); - connection_.GetTimeoutAlarm()->Fire(); - EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet()); - EXPECT_FALSE(connection_.connected()); -} - -TEST_P(QuicConnectionTest, OldTimeoutAfterSendSilentClose) { - ValueRestore<bool> old_flags(&FLAGS_quic_use_new_idle_timeout, false); - // 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_, SetFromConfig(_, _)); - QuicConfig config; - - // Create a handshake message that also enables silent close. - CryptoHandshakeMessage msg; - string error_details; - QuicConfig client_config; - client_config.SetInitialStreamFlowControlWindowToSend( - kInitialStreamFlowControlWindowForTest); - client_config.SetInitialSessionFlowControlWindowToSend( - kInitialSessionFlowControlWindowForTest); - client_config.SetIdleConnectionStateLifetime( - QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs), - QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs)); - client_config.ToHandshakeMessage(&msg); - const QuicErrorCode error = - config.ProcessPeerHello(msg, CLIENT, &error_details); - EXPECT_EQ(QUIC_NO_ERROR, error); - - connection_.SetFromConfig(config); - EXPECT_TRUE(QuicConnectionPeer::IsSilentCloseEnabled(&connection_)); - - const QuicTime::Delta default_idle_timeout = - QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs - 1); - const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5); - QuicTime default_timeout = clock_.ApproximateNow().Add(default_idle_timeout); - - // When we send a packet, the timeout will change to 5ms + - // kInitialIdleTimeoutSecs. - clock_.AdvanceTime(five_ms); - - // Send an ack so we don't set the retransmission alarm. - SendAckPacketToPeer(); - EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); - - // The original alarm will fire. We should not time out because we had a - // network event at t=5ms. The alarm will reregister. - clock_.AdvanceTime(default_idle_timeout.Subtract(five_ms)); - EXPECT_EQ(default_timeout, clock_.ApproximateNow()); - connection_.GetTimeoutAlarm()->Fire(); - EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); - EXPECT_TRUE(connection_.connected()); - EXPECT_EQ(default_timeout.Add(five_ms), - connection_.GetTimeoutAlarm()->deadline()); - - // This time, we should time out. - EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NETWORK_IDLE_TIMEOUT, - ConnectionCloseSource::FROM_SELF)); - clock_.AdvanceTime(five_ms); - EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow()); - connection_.GetTimeoutAlarm()->Fire(); - EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet()); - EXPECT_FALSE(connection_.connected()); -} - TEST_P(QuicConnectionTest, TimeoutAfterSend) { - ValueRestore<bool> old_flags(&FLAGS_quic_use_new_idle_timeout, true); EXPECT_TRUE(connection_.connected()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; @@ -4047,7 +3162,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterSend) { } TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) { - ValueRestore<bool> old_flags(&FLAGS_quic_use_new_idle_timeout, true); // Same test as above, but complete a handshake which enables silent close, // causing no connection close packet to be sent. EXPECT_TRUE(connection_.connected()); @@ -4159,7 +3273,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceive) { } TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) { - ValueRestore<bool> old_flags(&FLAGS_quic_use_new_idle_timeout, true); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_TRUE(connection_.connected()); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); @@ -4220,8 +3333,8 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) { TEST_P(QuicConnectionTest, SendScheduler) { // Test that if we send a packet without delay, it is not queued. - QuicPacket* packet = ConstructDataPacket(kDefaultPathId, 1, 0, !kEntropyFlag, - !kHasStopWaiting); + QuicPacket* packet = + ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA, false, @@ -4233,8 +3346,8 @@ TEST_P(QuicConnectionTest, FailToSendFirstPacket) { // Test that the connection does not crash when it fails to send the first // packet at which point self_address_ might be uninitialized. EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(1); - QuicPacket* packet = ConstructDataPacket(kDefaultPathId, 1, 0, !kEntropyFlag, - !kHasStopWaiting); + QuicPacket* packet = + ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting); writer_->SetShouldWriteFail(); connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA, false, @@ -4242,8 +3355,8 @@ TEST_P(QuicConnectionTest, FailToSendFirstPacket) { } TEST_P(QuicConnectionTest, SendSchedulerEAGAIN) { - QuicPacket* packet = ConstructDataPacket(kDefaultPathId, 1, 0, !kEntropyFlag, - !kHasStopWaiting); + QuicPacket* packet = + ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting); BlockOnNextWrite(); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0); connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet, @@ -4257,8 +3370,7 @@ TEST_P(QuicConnectionTest, TestQueueLimitsOnSendStreamData) { size_t payload_length; size_t length = GetPacketLengthForOneStream( connection_.version(), kIncludeVersion, !kIncludePathId, - PACKET_8BYTE_CONNECTION_ID, PACKET_1BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP, - &payload_length); + PACKET_8BYTE_CONNECTION_ID, PACKET_1BYTE_PACKET_NUMBER, &payload_length); connection_.SetMaxPacketLength(length); // Queue the first packet. @@ -4279,11 +3391,10 @@ TEST_P(QuicConnectionTest, LoopThroughSendingPackets) { // offset 0, and 2 for non-zero offsets up through 16K. Increase // max_packet_length by 2 so that subsequent packets containing subsequent // stream frames with non-zero offets will fit within the packet length. - size_t length = - 2 + GetPacketLengthForOneStream( - connection_.version(), kIncludeVersion, !kIncludePathId, - PACKET_8BYTE_CONNECTION_ID, PACKET_1BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP, &payload_length); + size_t length = 2 + GetPacketLengthForOneStream( + connection_.version(), kIncludeVersion, + !kIncludePathId, PACKET_8BYTE_CONNECTION_ID, + PACKET_1BYTE_PACKET_NUMBER, &payload_length); connection_.SetMaxPacketLength(length); // Queue the first packet. @@ -4356,8 +3467,8 @@ TEST_P(QuicConnectionTest, SendDelayedAck) { // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used // instead of ENCRYPTION_NONE. EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - ProcessDataPacketAtLevel(kDefaultPathId, 1, 0, !kEntropyFlag, - !kHasStopWaiting, ENCRYPTION_INITIAL); + ProcessDataPacketAtLevel(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting, + ENCRYPTION_INITIAL); // Check if delayed ack timer is running for the expected interval. EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); @@ -4372,7 +3483,7 @@ TEST_P(QuicConnectionTest, SendDelayedAck) { } TEST_P(QuicConnectionTest, SendDelayedAckDecimation) { - QuicConnectionPeer::EnableAckDecimation(&connection_); + QuicConnectionPeer::SetAckMode(&connection_, QuicConnection::ACK_DECIMATION); const size_t kMinRttMs = 40; RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager_); @@ -4394,15 +3505,15 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) { QuicPacketNumber kFirstDecimatedPacket = 101; for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) { EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, 0, !kEntropyFlag, + ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); } EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used // instead of ENCRYPTION_NONE. EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket, 0, - !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); + ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket, !kEntropyFlag, + !kHasStopWaiting, ENCRYPTION_INITIAL); // Check if delayed ack timer is running for the expected interval. EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); @@ -4412,7 +3523,131 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) { for (int i = 0; i < 9; ++i) { EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); - ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i, 0, + ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i, + !kEntropyFlag, !kHasStopWaiting, + ENCRYPTION_INITIAL); + } + // Check that ack is sent and that delayed ack alarm is reset. + EXPECT_EQ(2u, writer_->frame_count()); + EXPECT_FALSE(writer_->stop_waiting_frames().empty()); + EXPECT_FALSE(writer_->ack_frames().empty()); + EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); +} + +TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) { + FLAGS_quic_ack_decimation2 = true; + QuicConnectionPeer::SetAckMode( + &connection_, QuicConnection::ACK_DECIMATION_WITH_REORDERING); + + const size_t kMinRttMs = 40; + RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager_); + rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kMinRttMs), + QuicTime::Delta::Zero(), QuicTime::Zero()); + // The ack time should be based on min_rtt/4, since it's less than the + // default delayed ack time. + QuicTime ack_time = clock_.ApproximateNow().Add( + QuicTime::Delta::FromMilliseconds(kMinRttMs / 4)); + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); + const uint8_t tag = 0x07; + connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag)); + framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag)); + // Process a packet from the non-crypto stream. + frame1_.stream_id = 3; + + // Process all the initial packets in order so there aren't missing packets. + QuicPacketNumber kFirstDecimatedPacket = 101; + for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) { + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kEntropyFlag, + !kHasStopWaiting, ENCRYPTION_INITIAL); + } + EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); + // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used + // instead of ENCRYPTION_NONE. + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket, !kEntropyFlag, + !kHasStopWaiting, ENCRYPTION_INITIAL); + + // Check if delayed ack timer is running for the expected interval. + EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); + EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline()); + + // Process packet 10 first and ensure the alarm is one eighth min_rtt. + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 9, + !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); + ack_time = clock_.ApproximateNow().Add(QuicTime::Delta::FromMilliseconds(5)); + EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); + EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline()); + + // The 10th received packet causes an ack to be sent. + for (int i = 0; i < 8; ++i) { + EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i, + !kEntropyFlag, !kHasStopWaiting, + ENCRYPTION_INITIAL); + } + // Check that ack is sent and that delayed ack alarm is reset. + EXPECT_EQ(2u, writer_->frame_count()); + EXPECT_FALSE(writer_->stop_waiting_frames().empty()); + EXPECT_FALSE(writer_->ack_frames().empty()); + EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); +} + +TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) { + FLAGS_quic_ack_decimation2 = true; + QuicConnectionPeer::SetAckMode( + &connection_, QuicConnection::ACK_DECIMATION_WITH_REORDERING); + + const size_t kMinRttMs = 40; + RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager_); + rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kMinRttMs), + QuicTime::Delta::Zero(), QuicTime::Zero()); + // The ack time should be based on min_rtt/4, since it's less than the + // default delayed ack time. + QuicTime ack_time = clock_.ApproximateNow().Add( + QuicTime::Delta::FromMilliseconds(kMinRttMs / 4)); + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); + const uint8_t tag = 0x07; + connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag)); + framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag)); + // Process a packet from the non-crypto stream. + frame1_.stream_id = 3; + + // Process all the initial packets in order so there aren't missing packets. + QuicPacketNumber kFirstDecimatedPacket = 101; + for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) { + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(kDefaultPathId, 1 + i, !kEntropyFlag, + !kHasStopWaiting, ENCRYPTION_INITIAL); + } + EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); + // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used + // instead of ENCRYPTION_NONE. + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket, !kEntropyFlag, + !kHasStopWaiting, ENCRYPTION_INITIAL); + + // Check if delayed ack timer is running for the expected interval. + EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); + EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline()); + + // Process packet 10 first and ensure the alarm is one eighth min_rtt. + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 19, + !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); + ack_time = clock_.ApproximateNow().Add(QuicTime::Delta::FromMilliseconds(5)); + EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); + EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline()); + + // The 10th received packet causes an ack to be sent. + for (int i = 0; i < 8; ++i) { + EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 1 + i, !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); } @@ -4421,6 +3656,18 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) { EXPECT_FALSE(writer_->stop_waiting_frames().empty()); EXPECT_FALSE(writer_->ack_frames().empty()); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); + + // The next packet received in order will cause an immediate ack, + // because it fills a hole. + EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 10, + !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); + // Check that ack is sent and that delayed ack alarm is reset. + EXPECT_EQ(2u, writer_->frame_count()); + EXPECT_FALSE(writer_->stop_waiting_frames().empty()); + EXPECT_FALSE(writer_->ack_frames().empty()); + EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); } TEST_P(QuicConnectionTest, SendDelayedAckOnHandshakeConfirmed) { @@ -4594,7 +3841,7 @@ TEST_P(QuicConnectionTest, NoAckSentForClose) { EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, ConnectionCloseSource::FROM_PEER)); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0); - ProcessClosePacket(kDefaultPathId, 2, 0); + ProcessClosePacket(kDefaultPathId, 2); } TEST_P(QuicConnectionTest, SendWhenDisconnected) { @@ -4605,8 +3852,8 @@ TEST_P(QuicConnectionTest, SendWhenDisconnected) { ConnectionCloseSource::FROM_SELF); EXPECT_FALSE(connection_.connected()); EXPECT_FALSE(connection_.CanWriteStreamData()); - QuicPacket* packet = ConstructDataPacket(kDefaultPathId, 1, 0, !kEntropyFlag, - !kHasStopWaiting); + QuicPacket* packet = + ConstructDataPacket(kDefaultPathId, 1, !kEntropyFlag, !kHasStopWaiting); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0); connection_.SendPacket(ENCRYPTION_NONE, kDefaultPathId, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA, false, @@ -4684,30 +3931,19 @@ TEST_P(QuicConnectionTest, MissingPacketsBeforeLeastUnacked) { TEST_P(QuicConnectionTest, ReceivedEntropyHashCalculation) { EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1)); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - ProcessDataPacket(kDefaultPathId, 1, 1, kEntropyFlag); - ProcessDataPacket(kDefaultPathId, 4, 1, kEntropyFlag); - ProcessDataPacket(kDefaultPathId, 3, 1, !kEntropyFlag); - ProcessDataPacket(kDefaultPathId, 7, 1, kEntropyFlag); - EXPECT_EQ(146u, outgoing_ack()->entropy_hash); -} - -TEST_P(QuicConnectionTest, ReceivedEntropyHashCalculationHalfFEC) { - // FEC packets should not change the entropy hash calculation. - EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1)); - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - ProcessDataPacket(kDefaultPathId, 1, 1, kEntropyFlag); - ProcessFecPacket(kDefaultPathId, 4, 1, false, kEntropyFlag, nullptr); - ProcessDataPacket(kDefaultPathId, 3, 3, !kEntropyFlag); - ProcessFecPacket(kDefaultPathId, 7, 3, false, kEntropyFlag, nullptr); + ProcessDataPacket(kDefaultPathId, 1, kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 4, kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 3, !kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 7, kEntropyFlag); EXPECT_EQ(146u, outgoing_ack()->entropy_hash); } TEST_P(QuicConnectionTest, UpdateEntropyForReceivedPackets) { EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1)); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - ProcessDataPacket(kDefaultPathId, 1, 1, kEntropyFlag); - ProcessDataPacket(kDefaultPathId, 5, 1, kEntropyFlag); - ProcessDataPacket(kDefaultPathId, 4, 1, !kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 1, kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 5, kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 4, !kEntropyFlag); EXPECT_EQ(34u, outgoing_ack()->entropy_hash); // Make 4th packet my least unacked, and update entropy for 2, 3 packets. QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5); @@ -4726,9 +3962,9 @@ TEST_P(QuicConnectionTest, UpdateEntropyForReceivedPackets) { TEST_P(QuicConnectionTest, UpdateEntropyHashUptoCurrentPacket) { EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AtLeast(1)); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - ProcessDataPacket(kDefaultPathId, 1, 1, kEntropyFlag); - ProcessDataPacket(kDefaultPathId, 5, 1, !kEntropyFlag); - ProcessDataPacket(kDefaultPathId, 22, 1, kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 1, kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 5, !kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 22, kEntropyFlag); EXPECT_EQ(66u, outgoing_ack()->entropy_hash); QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 22); QuicPacketEntropyHash random_entropy_hash = 85u; @@ -4739,7 +3975,7 @@ TEST_P(QuicConnectionTest, UpdateEntropyHashUptoCurrentPacket) { ack_entropy_hash = ProcessStopWaitingPacket(&frame); EXPECT_EQ((random_entropy_hash + ack_entropy_hash), outgoing_ack()->entropy_hash); - ProcessDataPacket(kDefaultPathId, 25, 1, kEntropyFlag); + ProcessDataPacket(kDefaultPathId, 25, kEntropyFlag); EXPECT_EQ((random_entropy_hash + ack_entropy_hash + (1 << (25 % 8))), outgoing_ack()->entropy_hash); } @@ -4761,7 +3997,7 @@ TEST_P(QuicConnectionTest, EntropyCalculationForTruncatedAck) { } else { entropy[i] = entropy[i - 1]; } - ProcessDataPacket(kDefaultPathId, i, 1, entropy_flag); + ProcessDataPacket(kDefaultPathId, i, entropy_flag); } for (int i = 1; i < 50; ++i) { EXPECT_EQ(entropy[i], @@ -4965,52 +4201,6 @@ TEST_P(QuicConnectionTest, CheckSendStats) { EXPECT_EQ(kDefaultMaxPacketSize, stats.max_packet_size); } -TEST_P(QuicConnectionTest, CheckReceiveStats) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - - size_t received_bytes = 0; - received_bytes += ProcessFecProtectedPacket(kDefaultPathId, 1, false, - !kEntropyFlag, !kHasStopWaiting); - received_bytes += ProcessFecProtectedPacket(kDefaultPathId, 3, false, - !kEntropyFlag, !kHasStopWaiting); - // Should be counted against dropped packets. - received_bytes += ProcessDataPacket(kDefaultPathId, 3, 1, !kEntropyFlag); - received_bytes += - ProcessFecPacket(kDefaultPathId, 4, 1, true, !kEntropyFlag, nullptr); - - EXPECT_CALL(*send_algorithm_, BandwidthEstimate()) - .WillOnce(Return(QuicBandwidth::Zero())); - - const QuicConnectionStats& stats = connection_.GetStats(); - EXPECT_EQ(received_bytes, stats.bytes_received); - EXPECT_EQ(4u, stats.packets_received); - - EXPECT_EQ(1u, stats.packets_revived); - EXPECT_EQ(1u, stats.packets_dropped); -} - -TEST_P(QuicConnectionTest, TestFecGroupLimits) { - // Create and return a group for 1. - ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 1) != nullptr); - - // Create and return a group for 2. - ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 2) != nullptr); - - // Create and return a group for 4. This should remove 1 but not 2. - ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 4) != nullptr); - ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 1) == nullptr); - ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 2) != nullptr); - - // Create and return a group for 3. This will kill off 2. - ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 3) != nullptr); - ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 2) == nullptr); - - // Verify that adding 5 kills off 3, despite 4 being created before 3. - ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 5) != nullptr); - ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 4) != nullptr); - ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 3) == nullptr); -} - TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) { // Construct a packet with stream frame and connection close frame. QuicPacketHeader header; @@ -5252,116 +4442,6 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackForAckOfNackedPacket) { ProcessAckPacket(&third_ack_frame); } -TEST_P(QuicConnectionTest, AckNotifierFECTriggerCallback) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - - // Create a listener which we expect to be called. - scoped_refptr<MockAckListener> listener(new MockAckListener); - EXPECT_CALL(*listener, OnPacketAcked(_, _)).Times(1); - // Send some data, which will register the listener to be notified. - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener.get()); - connection_.SendStreamDataWithString(2, "bar", 0, !kFin, nullptr); - - // Process an ACK from the server with a revived packet, which should trigger - // the callback. - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); - QuicAckFrame frame = InitAckFrame(2); - NackPacket(1, &frame); - frame.latest_revived_packet = 1; - ProcessAckPacket(&frame); - // If the ack is processed again, the notifier should not be called again. - ProcessAckPacket(&frame); -} - -TEST_P(QuicConnectionTest, AckNotifierCallbackAfterFECRecovery) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - EXPECT_CALL(visitor_, OnCanWrite()); - - // Create a listener which we expect to be called. - scoped_refptr<MockAckListener> listener(new MockAckListener); - EXPECT_CALL(*listener, OnPacketAcked(_, _)).Times(1); - - // Expect ACKs for 1 packet. - EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); - - // Send one packet, and register to be notified on ACK. - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener.get()); - - // Ack packet gets dropped, but we receive an FEC packet that covers it. - // Should recover the Ack packet and trigger the notification callback. - QuicFrames frames; - - QuicAckFrame ack_frame = InitAckFrame(1); - frames.push_back(QuicFrame(&ack_frame)); - - // Dummy stream frame to satisfy expectations set elsewhere. - frames.push_back(QuicFrame(&frame1_)); - - QuicPacketHeader ack_header; - ack_header.public_header.connection_id = connection_id_; - ack_header.public_header.reset_flag = false; - ack_header.public_header.version_flag = false; - ack_header.entropy_flag = !kEntropyFlag; - ack_header.fec_flag = true; - ack_header.packet_number = 1; - ack_header.is_in_fec_group = IN_FEC_GROUP; - ack_header.fec_group = 1; - - QuicPacket* packet = BuildUnsizedDataPacket(&framer_, ack_header, frames); - - // Take the packet which contains the ACK frame, and construct and deliver an - // FEC packet which allows the ACK packet to be recovered. - ProcessFecPacket(kDefaultPathId, 2, 1, true, !kEntropyFlag, packet); -} - -TEST_P(QuicConnectionTest, NetworkChangeVisitorCwndCallbackChangesFecState) { - size_t max_packets_per_fec_group = creator_->max_packets_per_fec_group(); - - QuicSentPacketManager::NetworkChangeVisitor* visitor = - QuicSentPacketManagerPeer::GetNetworkChangeVisitor(manager_); - EXPECT_TRUE(visitor); - - // Increase FEC group size by increasing congestion window to a large number. - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillRepeatedly(Return(1000 * kDefaultTCPMSS)); - visitor->OnCongestionWindowChange(); - EXPECT_LT(max_packets_per_fec_group, creator_->max_packets_per_fec_group()); -} - -TEST_P(QuicConnectionTest, NetworkChangeVisitorConfigCallbackChangesFecState) { - QuicSentPacketManager::NetworkChangeVisitor* visitor = - QuicSentPacketManagerPeer::GetNetworkChangeVisitor(manager_); - EXPECT_TRUE(visitor); - EXPECT_EQ(QuicTime::Delta::Zero(), - QuicPacketCreatorPeer::GetFecTimeout(creator_)); - - // Verify that sending a config with a new initial rtt changes fec timeout. - // Create and process a config with a non-zero initial RTT. - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - QuicConfig config; - config.SetInitialRoundTripTimeUsToSend(300000); - connection_.SetFromConfig(config); - EXPECT_LT(QuicTime::Delta::Zero(), - QuicPacketCreatorPeer::GetFecTimeout(creator_)); -} - -TEST_P(QuicConnectionTest, NetworkChangeVisitorRttCallbackChangesFecState) { - // Verify that sending a config with a new initial rtt changes fec timeout. - QuicSentPacketManager::NetworkChangeVisitor* visitor = - QuicSentPacketManagerPeer::GetNetworkChangeVisitor(manager_); - EXPECT_TRUE(visitor); - EXPECT_EQ(QuicTime::Delta::Zero(), - QuicPacketCreatorPeer::GetFecTimeout(creator_)); - - // Increase FEC timeout by increasing RTT. - RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager_); - rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(300), - QuicTime::Delta::Zero(), QuicTime::Zero()); - visitor->OnRttChange(); - EXPECT_LT(QuicTime::Delta::Zero(), - QuicPacketCreatorPeer::GetFecTimeout(creator_)); -} - TEST_P(QuicConnectionTest, OnPacketHeaderDebugVisitor) { QuicPacketHeader header; @@ -5422,43 +4502,6 @@ TEST_P(QuicConnectionTest, NoDataNoFin) { "Attempt to send empty stream frame"); } -TEST_P(QuicConnectionTest, FecSendPolicyReceivedConnectionOption) { - // Test sending SetReceivedConnectionOptions when FEC send policy is - // FEC_ANY_TRIGGER. - if (GetParam().fec_send_policy == FEC_ALARM_TRIGGER) { - return; - } - connection_.set_perspective(Perspective::IS_SERVER); - - // Test ReceivedConnectionOptions. - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - QuicConfig config; - QuicTagVector copt; - copt.push_back(kFSPA); - QuicConfigPeer::SetReceivedConnectionOptions(&config, copt); - EXPECT_EQ(FEC_ANY_TRIGGER, generator_->fec_send_policy()); - connection_.SetFromConfig(config); - EXPECT_EQ(FEC_ALARM_TRIGGER, generator_->fec_send_policy()); -} - -// TODO(rtenneti): Delete this code after the 0.25 RTT FEC experiment. -TEST_P(QuicConnectionTest, FecRTTMultiplierReceivedConnectionOption) { - connection_.set_perspective(Perspective::IS_SERVER); - - // Test ReceivedConnectionOptions. - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - QuicConfig config; - QuicTagVector copt; - copt.push_back(kFRTT); - QuicConfigPeer::SetReceivedConnectionOptions(&config, copt); - float rtt_multiplier_for_fec_timeout = - QuicPacketCreatorPeer::GetRttMultiplierForFecTimeout(creator_); - connection_.SetFromConfig(config); - // New RTT multiplier is half of the old RTT multiplier. - EXPECT_EQ(rtt_multiplier_for_fec_timeout, - QuicPacketCreatorPeer::GetRttMultiplierForFecTimeout(creator_) * 2); -} - TEST_P(QuicConnectionTest, DoNotSendGoAwayTwice) { EXPECT_FALSE(connection_.goaway_sent()); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc index e95582c..01ea2d4 100644 --- a/net/quic/quic_crypto_client_stream_test.cc +++ b/net/quic/quic_crypto_client_stream_test.cc @@ -263,6 +263,8 @@ class QuicCryptoClientStreamStatelessTest : public ::testing::Test { server_crypto_config_(QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), CryptoTestUtils::ProofSourceForTesting()), + server_compressed_certs_cache_( + QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), server_id_(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED) { TestQuicSpdyClientSession* client_session = nullptr; CreateClientSessionForTest( @@ -288,10 +290,10 @@ class QuicCryptoClientStreamStatelessTest : public ::testing::Test { // Initializes the server_stream_ for stateless rejects. void InitializeFakeStatelessRejectServer() { TestQuicSpdyServerSession* server_session = nullptr; - CreateServerSessionForTest(server_id_, QuicTime::Delta::FromSeconds(100000), - QuicSupportedVersions(), &helper_, - &server_crypto_config_, &server_connection_, - &server_session); + CreateServerSessionForTest( + server_id_, QuicTime::Delta::FromSeconds(100000), + QuicSupportedVersions(), &helper_, &server_crypto_config_, + &server_compressed_certs_cache_, &server_connection_, &server_session); CHECK(server_session); server_session_.reset(server_session); CryptoTestUtils::FakeServerOptions options; @@ -312,6 +314,7 @@ class QuicCryptoClientStreamStatelessTest : public ::testing::Test { PacketSavingConnection* server_connection_; scoped_ptr<TestQuicSpdyServerSession> server_session_; QuicCryptoServerConfig server_crypto_config_; + QuicCompressedCertsCache server_compressed_certs_cache_; QuicServerId server_id_; }; diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc index f53602e..41a701e 100644 --- a/net/quic/quic_crypto_server_stream.cc +++ b/net/quic/quic_crypto_server_stream.cc @@ -48,15 +48,18 @@ void ServerHelloNotifier::OnPacketRetransmitted(int /*retransmitted_bytes*/) {} QuicCryptoServerStream::QuicCryptoServerStream( const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache, + bool use_stateless_rejects_if_peer_supported, QuicSession* session) : QuicCryptoServerStreamBase(session), crypto_config_(crypto_config), + compressed_certs_cache_(compressed_certs_cache), validate_client_hello_cb_(nullptr), num_handshake_messages_(0), num_handshake_messages_with_server_nonces_(0), num_server_config_update_messages_sent_(0), use_stateless_rejects_if_peer_supported_( - FLAGS_enable_quic_stateless_reject_support), + use_stateless_rejects_if_peer_supported), peer_supports_stateless_rejects_(false) { DCHECK_EQ(Perspective::IS_SERVER, session->connection()->perspective()); } diff --git a/net/quic/quic_crypto_server_stream.h b/net/quic/quic_crypto_server_stream.h index fc9a7f3..b78e888 100644 --- a/net/quic/quic_crypto_server_stream.h +++ b/net/quic/quic_crypto_server_stream.h @@ -11,6 +11,7 @@ #include "base/macros.h" #include "net/quic/crypto/crypto_handshake.h" +#include "net/quic/crypto/quic_compressed_certs_cache.h" #include "net/quic/crypto/quic_crypto_server_config.h" #include "net/quic/proto/source_address_token.pb.h" #include "net/quic/quic_config.h" @@ -52,7 +53,6 @@ class NET_EXPORT_PRIVATE ServerHelloNotifier : public QuicAckListenerInterface { // various code and test refactoring. class NET_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream { public: - // |crypto_config| must outlive the stream. explicit QuicCryptoServerStreamBase(QuicSession* session) : QuicCryptoStream(session) {} ~QuicCryptoServerStreamBase() override {} @@ -93,6 +93,8 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream public: // |crypto_config| must outlive the stream. QuicCryptoServerStream(const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache, + bool use_stateless_rejects_if_peer_supported, QuicSession* session); ~QuicCryptoServerStream() override; @@ -165,6 +167,10 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream // crypto_config_ contains crypto parameters for the handshake. const QuicCryptoServerConfig* crypto_config_; + // compressed_certs_cache_ contains a set of most recently compressed certs. + // Owned by QuicDispatcher. + QuicCompressedCertsCache* compressed_certs_cache_; + // Server's certificate chain and signature of the server config, as provided // by ProofSource::GetProof. QuicCryptoProof crypto_proof_; diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc index 4b32c18..d4eea18 100644 --- a/net/quic/quic_crypto_server_stream_test.cc +++ b/net/quic/quic_crypto_server_stream_test.cc @@ -70,6 +70,8 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> { : server_crypto_config_(QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), CryptoTestUtils::ProofSourceForTesting()), + server_compressed_certs_cache_( + QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), server_id_(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED), client_crypto_config_(CryptoTestUtils::ProofVerifierForTesting()) { FLAGS_enable_quic_stateless_reject_support = false; @@ -107,11 +109,10 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> { void InitializeServer() { TestQuicSpdyServerSession* server_session = nullptr; helpers_.push_back(new MockConnectionHelper); - - CreateServerSessionForTest(server_id_, QuicTime::Delta::FromSeconds(100000), - supported_versions_, helpers_.back(), - &server_crypto_config_, &server_connection_, - &server_session); + CreateServerSessionForTest( + server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_, + helpers_.back(), &server_crypto_config_, + &server_compressed_certs_cache_, &server_connection_, &server_session); CHECK(server_session); server_session_.reset(server_session); CryptoTestUtils::FakeServerOptions options; @@ -186,6 +187,7 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> { PacketSavingConnection* server_connection_; scoped_ptr<TestQuicSpdyServerSession> server_session_; QuicCryptoServerConfig server_crypto_config_; + QuicCompressedCertsCache server_compressed_certs_cache_; QuicServerId server_id_; // Client state @@ -375,11 +377,10 @@ TEST_P(QuicCryptoServerStreamTest, ZeroRTT) { server_stream()); } - if (FLAGS_require_strike_register_or_server_nonce && - !AsyncStrikeRegisterVerification()) { - EXPECT_EQ(2, client_stream()->num_sent_client_hellos()); - } else { + if (AsyncStrikeRegisterVerification()) { EXPECT_EQ(1, client_stream()->num_sent_client_hellos()); + } else { + EXPECT_EQ(2, client_stream()->num_sent_client_hellos()); } } diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc index 9878561..7dea7ec 100644 --- a/net/quic/quic_flags.cc +++ b/net/quic/quic_flags.cc @@ -62,46 +62,21 @@ bool FLAGS_quic_measure_headers_hol_blocking_time = true; // Disable QUIC's userspace pacing. bool FLAGS_quic_disable_pacing = false; -// If true, QUIC connections will timeout when packets are not being recieved, -// even if they are being sent. -bool FLAGS_quic_use_new_idle_timeout = true; - // If true, don't send QUIC packets if the send alarm is set. bool FLAGS_quic_respect_send_alarm2 = true; -// If true, allow each quic stream to write 16k blocks rather than doing a round -// robin of one packet per session when ack clocked or paced. -bool FLAGS_quic_batch_writes = true; - -// If true, QUIC sessions will write block streams that attempt to write -// unencrypted data. -bool FLAGS_quic_block_unencrypted_writes = true; - // If true, Close the connection instead of writing unencrypted stream data. bool FLAGS_quic_never_write_unencrypted_data = true; -// If true, clear the FEC group instead of sending it with ENCRYPTION_NONE. -// Close the connection if we ever try to serialized unencrypted FEC. -bool FLAGS_quic_no_unencrypted_fec = true; - // If true, reject any incoming QUIC which does not have the FIXD tag. bool FLAGS_quic_require_fix = true; // If true, headers stream will support receiving PUSH_PROMISE frames. bool FLAGS_quic_supports_push_promise = false; -// If true, QUIC servers will attempt to validate a client's source -// address token using the primary config, even if no server config id -// is present in the client hello. -bool FLAGS_quic_validate_stk_without_scid = true; - // If true, QUIC will support RFC 7539 variants of ChaCha20 Poly1305. bool FLAGS_quic_use_rfc7539 = true; -// If true, require QUIC connections to use a valid server nonce or a non-local -// strike register. -bool FLAGS_require_strike_register_or_server_nonce = true; - // When turn on, log packet loss into transport connection stats LossEvent. bool FLAGS_quic_log_loss_event = true; @@ -141,3 +116,20 @@ bool FLAGS_quic_save_initial_subkey_secret = true; // If true, the QUIC dispatcher will directly send version negotiation packets // without needing to create a QUIC session first. bool FLAGS_quic_stateless_version_negotiation = false; + +// QUIC Ack Decimation with tolerance for packet reordering. +bool FLAGS_quic_ack_decimation2 = true; + +// If true, QUIC connections will defer responding to ACKs to their send alarms. +bool FLAGS_quic_connection_defer_ack_response = true; + +// If true, calls to QuicAlarm::Cancel don't do anything if the alarm is not +// set. +bool FLAGS_quic_only_cancel_set_alarms = true; + +// Simplify QUIC's write path for inplace encryption now that FEC is gone. +bool FLAGS_quic_inplace_encryption2 = true; + +// If true, SpdyFramer will call OnStreamEnd from SpdyFramerVisitorInterface +// instead of empty-data sentinel calls when the stream is to be ended. +bool FLAGS_spdy_on_stream_end = true; diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h index a110e57..c50d527 100644 --- a/net/quic/quic_flags.h +++ b/net/quic/quic_flags.h @@ -23,19 +23,13 @@ NET_EXPORT_PRIVATE extern bool FLAGS_quic_require_handshake_confirmation; NET_EXPORT_PRIVATE extern bool FLAGS_shift_quic_cubic_epoch_when_app_limited; NET_EXPORT_PRIVATE extern bool FLAGS_quic_measure_headers_hol_blocking_time; NET_EXPORT_PRIVATE extern bool FLAGS_quic_disable_pacing; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_new_idle_timeout; NET_EXPORT_PRIVATE extern bool FLAGS_quic_respect_send_alarm2; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_batch_writes; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_block_unencrypted_writes; NET_EXPORT_PRIVATE extern bool FLAGS_quic_never_write_unencrypted_data; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_no_unencrypted_fec; NET_EXPORT_PRIVATE extern bool FLAGS_quic_require_fix; NET_EXPORT_PRIVATE extern bool FLAGS_quic_stateless_version_negotiation; NET_EXPORT_PRIVATE extern bool FLAGS_quic_supports_push_promise; NET_EXPORT_PRIVATE extern bool FLAGS_quic_supports_push_promise; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_validate_stk_without_scid; NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_rfc7539; -NET_EXPORT_PRIVATE extern bool FLAGS_require_strike_register_or_server_nonce; NET_EXPORT_PRIVATE extern bool FLAGS_quic_log_loss_event; NET_EXPORT_PRIVATE extern bool FLAGS_quic_include_path_id_in_iv; NET_EXPORT_PRIVATE extern bool FLAGS_quic_cede_correctly; @@ -46,5 +40,10 @@ NET_EXPORT_PRIVATE extern bool FLAGS_check_peer_address_change_after_decryption; NET_EXPORT_PRIVATE extern bool FLAGS_quic_log_received_parameters; NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_new_tcp_sender; NET_EXPORT_PRIVATE extern bool FLAGS_quic_save_initial_subkey_secret; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_ack_decimation2; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_connection_defer_ack_response; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_only_cancel_set_alarms; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_inplace_encryption2; +NET_EXPORT_PRIVATE extern bool FLAGS_spdy_on_stream_end; #endif // NET_QUIC_QUIC_FLAGS_H_ diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc index ac58d57..fa667f2 100644 --- a/net/quic/quic_framer.cc +++ b/net/quic/quic_framer.cc @@ -159,13 +159,10 @@ QuicFramer::~QuicFramer() {} // static size_t QuicFramer::GetMinStreamFrameSize(QuicStreamId stream_id, QuicStreamOffset offset, - bool last_frame_in_packet, - InFecGroup is_in_fec_group) { - bool no_stream_frame_length = - last_frame_in_packet && is_in_fec_group == NOT_IN_FEC_GROUP; + bool last_frame_in_packet) { return kQuicFrameTypeSize + GetStreamIdSize(stream_id) + GetStreamOffsetSize(offset) + - (no_stream_frame_length ? 0 : kQuicStreamPayloadLengthSize); + (last_frame_in_packet ? 0 : kQuicStreamPayloadLengthSize); } // static @@ -270,7 +267,6 @@ size_t QuicFramer::GetSerializedFrameLength( size_t free_bytes, bool first_frame, bool last_frame, - InFecGroup is_in_fec_group, QuicPacketNumberLength packet_number_length) { // Prevent a rare crash reported in b/19458523. if ((frame.type == STREAM_FRAME || frame.type == ACK_FRAME) && @@ -278,7 +274,6 @@ size_t QuicFramer::GetSerializedFrameLength( QUIC_BUG << "Cannot compute the length of a null frame. " << "type:" << frame.type << "free_bytes:" << free_bytes << " first_frame:" << first_frame << " last_frame:" << last_frame - << " is_in_fec:" << is_in_fec_group << " seq num length:" << packet_number_length; set_error(QUIC_INTERNAL_ERROR); visitor_->OnError(this); @@ -288,8 +283,8 @@ size_t QuicFramer::GetSerializedFrameLength( // PADDING implies end of packet. return free_bytes; } - size_t frame_len = ComputeFrameLength(frame, last_frame, is_in_fec_group, - packet_number_length); + size_t frame_len = + ComputeFrameLength(frame, last_frame, packet_number_length); if (frame_len <= free_bytes) { // Frame fits within packet. Note that acks may be truncated. return frame_len; @@ -336,9 +331,7 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header, size_t i = 0; for (const QuicFrame& frame : frames) { // Determine if we should write stream frame length in header. - const bool no_stream_frame_length = - (header.is_in_fec_group == NOT_IN_FEC_GROUP) && - (i == frames.size() - 1); + const bool no_stream_frame_length = i == frames.size() - 1; if (!AppendTypeByte(frame, no_stream_frame_length, &writer)) { QUIC_BUG << "AppendTypeByte failed"; return 0; @@ -421,31 +414,6 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header, return writer.length(); } -QuicPacket* QuicFramer::BuildFecPacket(const QuicPacketHeader& header, - StringPiece redundancy) { - DCHECK_EQ(IN_FEC_GROUP, header.is_in_fec_group); - DCHECK_NE(0u, header.fec_group); - size_t len = GetPacketHeaderSize(header); - len += redundancy.length(); - - scoped_ptr<char[]> buffer(new char[len]); - QuicDataWriter writer(len, buffer.get()); - if (!AppendPacketHeader(header, &writer)) { - QUIC_BUG << "AppendPacketHeader failed"; - return nullptr; - } - - if (!writer.WriteBytes(redundancy.data(), redundancy.length())) { - QUIC_BUG << "Failed to add FEC"; - return nullptr; - } - - return new QuicPacket( - buffer.release(), len, true, header.public_header.connection_id_length, - header.public_header.version_flag, header.public_header.multipath_flag, - header.public_header.packet_number_length); -} - // static QuicEncryptedPacket* QuicFramer::BuildPublicResetPacket( const QuicPublicResetPacket& packet) { @@ -619,19 +587,12 @@ bool QuicFramer::ProcessDataPacket(QuicDataReader* encrypted_reader, return RaiseError(QUIC_PACKET_TOO_LARGE); } + DCHECK(!header.fec_flag); // Handle the payload. - if (!header.fec_flag) { - if (header.is_in_fec_group == IN_FEC_GROUP) { - StringPiece payload = reader.PeekRemainingPayload(); - visitor_->OnFecProtectedPayload(payload); - } - if (!ProcessFrameData(&reader, header)) { - DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error. - DLOG(WARNING) << "Unable to process frame data."; - return false; - } - } else { - visitor_->OnFecData(reader.ReadRemainingPayload()); + if (!ProcessFrameData(&reader, header)) { + DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error. + DLOG(WARNING) << "Unable to process frame data."; + return false; } visitor_->OnPacketComplete(); @@ -679,36 +640,9 @@ bool QuicFramer::ProcessPublicResetPacket( return true; } -bool QuicFramer::ProcessRevivedPacket(QuicPacketHeader* header, - StringPiece payload) { - visitor_->OnRevivedPacket(); - - header->entropy_hash = GetPacketEntropyHash(*header); - - if (!visitor_->OnPacketHeader(*header)) { - return true; - } - - if (payload.length() > kMaxPacketSize) { - set_detailed_error("Revived packet too large."); - return RaiseError(QUIC_PACKET_TOO_LARGE); - } - - QuicDataReader reader(payload.data(), payload.length()); - if (!ProcessFrameData(&reader, *header)) { - DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error. - DLOG(WARNING) << "Unable to process frame data."; - return false; - } - - visitor_->OnPacketComplete(); - return true; -} - bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header, QuicDataWriter* writer) { DVLOG(1) << "Appending header: " << header; - DCHECK(header.fec_group > 0 || header.is_in_fec_group == NOT_IN_FEC_GROUP); uint8_t public_flags = 0; if (header.public_header.reset_flag) { public_flags |= PACKET_PUBLIC_FLAGS_RST; @@ -785,30 +719,10 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header, if (header.entropy_flag) { private_flags |= PACKET_PRIVATE_FLAGS_ENTROPY; } - if (header.is_in_fec_group == IN_FEC_GROUP) { - private_flags |= PACKET_PRIVATE_FLAGS_FEC_GROUP; - } - if (header.fec_flag) { - private_flags |= PACKET_PRIVATE_FLAGS_FEC; - } if (!writer->WriteUInt8(private_flags)) { return false; } - // The FEC group number is the packet number of the first fec - // protected packet, or 0 if this packet is not protected. - if (header.is_in_fec_group == IN_FEC_GROUP) { - DCHECK_LE(header.fec_group, header.packet_number); - DCHECK_LT(header.packet_number - header.fec_group, 255u); - // Offset from the current packet number to the first fec - // protected packet. - uint8_t first_fec_protected_packet_offset = - static_cast<uint8_t>(header.packet_number - header.fec_group); - if (!writer->WriteBytes(&first_fec_protected_packet_offset, 1)) { - return false; - } - } - return true; } @@ -1470,7 +1384,6 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, set_detailed_error("Unable to read revived packet."); return false; } - ack_frame->latest_revived_packet = revived_packet; } return true; @@ -1718,6 +1631,27 @@ void QuicFramer::SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter) { encrypter_[level].reset(encrypter); } +size_t QuicFramer::EncryptInPlace(EncryptionLevel level, + QuicPathId path_id, + QuicPacketNumber packet_number, + size_t ad_len, + size_t total_len, + size_t buffer_len, + char* buffer) { + size_t output_length = 0; + if (!encrypter_[level]->EncryptPacket( + path_id, packet_number, + StringPiece(buffer, ad_len), // Associated data + StringPiece(buffer + ad_len, total_len - ad_len), // Plaintext + buffer + ad_len, // Destination buffer + &output_length, buffer_len - ad_len)) { + RaiseError(QUIC_ENCRYPTION_FAILURE); + return 0; + } + + return ad_len + output_length; +} + size_t QuicFramer::EncryptPayload(EncryptionLevel level, QuicPathId path_id, QuicPacketNumber packet_number, @@ -1768,7 +1702,7 @@ bool QuicFramer::DecryptPayload(QuicDataReader* encrypted_reader, size_t* decrypted_length) { StringPiece encrypted = encrypted_reader->ReadRemainingPayload(); DCHECK(decrypter_.get() != nullptr); - const StringPiece& associated_data = GetAssociatedDataFromEncryptedPacket( + StringPiece associated_data = GetAssociatedDataFromEncryptedPacket( packet, header.public_header.connection_id_length, header.public_header.version_flag, header.public_header.multipath_flag, header.public_header.packet_number_length); @@ -1822,9 +1756,6 @@ size_t QuicFramer::GetAckFrameSize( ack_size += kNumberOfNackRangesSize + kNumberOfRevivedPacketsSize; ack_size += min(ack_info.nack_ranges.size(), kMaxNackRanges) * (missing_packet_number_length + PACKET_1BYTE_PACKET_NUMBER); - if (ack.latest_revived_packet != 0) { - ack_size += largest_observed_length; - } } // In version 23, if the ack will be truncated due to too many nack ranges, @@ -1849,13 +1780,12 @@ size_t QuicFramer::GetAckFrameSize( size_t QuicFramer::ComputeFrameLength( const QuicFrame& frame, bool last_frame_in_packet, - InFecGroup is_in_fec_group, QuicPacketNumberLength packet_number_length) { switch (frame.type) { case STREAM_FRAME: return GetMinStreamFrameSize(frame.stream_frame->stream_id, frame.stream_frame->offset, - last_frame_in_packet, is_in_fec_group) + + last_frame_in_packet) + frame.stream_frame->frame_length; case ACK_FRAME: { return GetAckFrameSize(*frame.ack_frame, packet_number_length); @@ -2114,24 +2044,12 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicPacketHeader& header, DCHECK_EQ(num_missing_ranges, num_ranges_written); // Append revived packets. - // If not all the revived packets fit, only mention the ones that do. - uint8_t num_revived_packets = frame.latest_revived_packet == 0 ? 0 : 1; - if (((writer->capacity() - writer->length()) / largest_observed_length) == - 0) { - num_revived_packets = 0; - } + // FEC is not supported. + uint8_t num_revived_packets = 0; if (!writer->WriteBytes(&num_revived_packets, 1)) { return false; } - if (num_revived_packets > 0) { - QUIC_BUG_IF(!frame.missing_packets.Contains(frame.latest_revived_packet)); - if (!AppendPacketSequenceNumber(largest_observed_length, - frame.latest_revived_packet, writer)) { - return false; - } - } - return true; } diff --git a/net/quic/quic_framer.h b/net/quic/quic_framer.h index 3cc2426..a0a0db1 100644 --- a/net/quic/quic_framer.h +++ b/net/quic/quic_framer.h @@ -91,10 +91,6 @@ class NET_EXPORT_PRIVATE QuicFramerVisitorInterface { virtual void OnVersionNegotiationPacket( const QuicVersionNegotiationPacket& packet) = 0; - // Called when a lost packet has been recovered via FEC, - // before it has been processed. - virtual void OnRevivedPacket() = 0; - // Called when the public header has been parsed, but has not been // authenticated. If it returns false, framing for this packet will cease. virtual bool OnUnauthenticatedPublicHeader( @@ -113,10 +109,6 @@ class NET_EXPORT_PRIVATE QuicFramerVisitorInterface { // If OnPacketHeader returns false, framing for this packet will cease. virtual bool OnPacketHeader(const QuicPacketHeader& header) = 0; - // Called when a data packet is parsed that is part of an FEC group. - // |payload| is the non-encrypted FEC protected payload of the packet. - virtual void OnFecProtectedPayload(base::StringPiece payload) = 0; - // Called when a StreamFrame has been parsed. virtual bool OnStreamFrame(const QuicStreamFrame& frame) = 0; @@ -149,9 +141,6 @@ class NET_EXPORT_PRIVATE QuicFramerVisitorInterface { // Called when a PathCloseFrame has been parsed. virtual bool OnPathCloseFrame(const QuicPathCloseFrame& frame) = 0; - // Called when FEC data has been parsed. - virtual void OnFecData(base::StringPiece redundancy) = 0; - // Called when a packet has been completely processed. virtual void OnPacketComplete() = 0; }; @@ -173,8 +162,6 @@ class NET_EXPORT_PRIVATE QuicReceivedEntropyHashCalculatorInterface { // Class for parsing and constructing QUIC packets. It has a // QuicFramerVisitorInterface that is called when packets are parsed. -// It also has a QuicFecBuilder that is called when packets are constructed -// in order to generate FEC data for subsequently building FEC packets. class NET_EXPORT_PRIVATE QuicFramer { public: // Constructs a new framer that installs a kNULL QuicEncrypter and @@ -228,18 +215,10 @@ class NET_EXPORT_PRIVATE QuicFramer { // ignored. bool ProcessPacket(const QuicEncryptedPacket& packet); - // Pass a data packet that was revived from FEC data into the framer - // for parsing. - // Return true if the packet was processed succesfully. |payload| must be - // the complete DECRYPTED payload of the revived packet. - bool ProcessRevivedPacket(QuicPacketHeader* header, - base::StringPiece payload); - // Largest size in bytes of all stream frame fields without the payload. static size_t GetMinStreamFrameSize(QuicStreamId stream_id, QuicStreamOffset offset, - bool last_frame_in_packet, - InFecGroup is_in_fec_group); + bool last_frame_in_packet); // Size in bytes of all ack frame fields without the missing packets. static size_t GetMinAckFrameSize( QuicPacketNumberLength largest_observed_length); @@ -276,7 +255,6 @@ class NET_EXPORT_PRIVATE QuicFramer { size_t free_bytes, bool first_frame_in_packet, bool last_frame_in_packet, - InFecGroup is_in_fec_group, QuicPacketNumberLength packet_number_length); // Returns the associated data from the encrypted packet |encrypted| as a @@ -296,12 +274,6 @@ class NET_EXPORT_PRIVATE QuicFramer { char* buffer, size_t packet_length); - // Returns a QuicPacket* that is owned by the caller, and is populated with - // the fields in |header| and |fec|. Returns nullptr if the packet could - // not be created. - QuicPacket* BuildFecPacket(const QuicPacketHeader& header, - base::StringPiece redundancy); - // Returns a new public reset packet, owned by the caller. static QuicEncryptedPacket* BuildPublicResetPacket( const QuicPublicResetPacket& packet); @@ -335,6 +307,17 @@ class NET_EXPORT_PRIVATE QuicFramer { // takes ownership of |encrypter|. void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter); + // Encrypts a payload in |buffer|. |ad_len| is the length of the associated + // data. |total_len| is the length of the associated data plus plaintext. + // |buffer_len| is the full length of the allocated buffer. + size_t EncryptInPlace(EncryptionLevel level, + QuicPathId path_id, + QuicPacketNumber packet_number, + size_t ad_len, + size_t total_len, + size_t buffer_len, + char* buffer); + // Returns the length of the data encrypted into |buffer| if |buffer_len| is // long enough, and otherwise 0. size_t EncryptPayload(EncryptionLevel level, @@ -467,7 +450,6 @@ class NET_EXPORT_PRIVATE QuicFramer { // Computes the wire size in bytes of the payload of |frame|. size_t ComputeFrameLength(const QuicFrame& frame, bool last_frame_in_packet, - InFecGroup is_in_fec_group, QuicPacketNumberLength packet_number_length); static bool AppendPacketSequenceNumber( @@ -529,12 +511,12 @@ class NET_EXPORT_PRIVATE QuicFramer { // TODO(fayang): this set is never cleaned up. A possible improvement is to // use intervals. std::unordered_set<QuicPathId> closed_paths_; - // Map mapping path id to packet number of last successfully decrypted/revived + // Map mapping path id to packet number of last successfully decrypted // received packet. std::unordered_map<QuicPathId, QuicPacketNumber> last_packet_numbers_; // Updated by ProcessPacketHeader when it succeeds. QuicPacketNumber last_packet_number_; - // The path on which last successfully decrypted/revived packet was received. + // The path on which last successfully decrypted packet was received. QuicPathId last_path_id_; // Updated by WritePacketHeader. QuicConnectionId last_serialized_connection_id_; diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc index 025fb83..d770db9 100644 --- a/net/quic/quic_framer_test.cc +++ b/net/quic/quic_framer_test.cc @@ -106,29 +106,6 @@ size_t GetPrivateFlagsOffset(bool include_version, packet_number_length; } -// Index into the fec group offset in the header. -size_t GetFecGroupOffset(QuicConnectionIdLength connection_id_length, - bool include_version, - bool include_path_id) { - return GetPrivateFlagsOffset(connection_id_length, include_version, - include_path_id) + - kPrivateFlagsSize; -} - -size_t GetFecGroupOffset(bool include_version, bool include_path_id) { - return GetPrivateFlagsOffset(PACKET_8BYTE_CONNECTION_ID, include_version, - include_path_id) + - kPrivateFlagsSize; -} - -size_t GetFecGroupOffset(bool include_version, - bool include_path_id, - QuicPacketNumberLength packet_number_length) { - return GetPrivateFlagsOffset(include_version, include_path_id, - packet_number_length) + - kPrivateFlagsSize; -} - // Index into the message tag of the public reset packet. // Public resets always have full connection_ids. const size_t kPublicResetPacketMessageTagOffset = @@ -177,8 +154,8 @@ class TestDecrypter : public QuicDecrypter { bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; } bool DecryptPacket(QuicPathId path_id, QuicPacketNumber packet_number, - const StringPiece& associated_data, - const StringPiece& ciphertext, + StringPiece associated_data, + StringPiece ciphertext, char* output, size_t* output_length, size_t max_output_length) override { @@ -208,9 +185,7 @@ class TestQuicVisitor : public QuicFramerVisitorInterface { version_mismatch_(0), packet_count_(0), frame_count_(0), - fec_count_(0), complete_packets_(0), - revived_packets_(0), accept_packet_(true), accept_public_header_(true) {} @@ -239,8 +214,6 @@ class TestQuicVisitor : public QuicFramerVisitorInterface { version_negotiation_packet_.reset(new QuicVersionNegotiationPacket(packet)); } - void OnRevivedPacket() override { ++revived_packets_; } - bool OnProtocolVersionMismatch(QuicVersion version) override { DVLOG(1) << "QuicFramer Version Mismatch, version: " << version; ++version_mismatch_; @@ -260,6 +233,10 @@ class TestQuicVisitor : public QuicFramerVisitorInterface { void OnDecryptedPacket(EncryptionLevel level) override {} bool OnPacketHeader(const QuicPacketHeader& header) override { + if (header.fec_flag) { + // Drop any FEC packet. + return false; + } ++packet_count_; header_.reset(new QuicPacketHeader(header)); return accept_packet_; @@ -277,10 +254,6 @@ class TestQuicVisitor : public QuicFramerVisitorInterface { return true; } - void OnFecProtectedPayload(StringPiece payload) override { - fec_protected_payload_ = payload.as_string(); - } - bool OnAckFrame(const QuicAckFrame& frame) override { ++frame_count_; ack_frames_.push_back(new QuicAckFrame(frame)); @@ -299,11 +272,6 @@ class TestQuicVisitor : public QuicFramerVisitorInterface { return true; } - void OnFecData(StringPiece redundancy) override { - ++fec_count_; - fec_data_redundancy_.push_back(redundancy.as_string()); - } - void OnPacketComplete() override { ++complete_packets_; } bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override { @@ -341,9 +309,7 @@ class TestQuicVisitor : public QuicFramerVisitorInterface { int version_mismatch_; int packet_count_; int frame_count_; - int fec_count_; int complete_packets_; - int revived_packets_; bool accept_packet_; bool accept_public_header_; @@ -355,7 +321,6 @@ class TestQuicVisitor : public QuicFramerVisitorInterface { vector<QuicAckFrame*> ack_frames_; vector<QuicStopWaitingFrame*> stop_waiting_frames_; vector<QuicPingFrame*> ping_frames_; - string fec_protected_payload_; QuicRstStreamFrame rst_stream_frame_; QuicConnectionCloseFrame connection_close_frame_; QuicGoAwayFrame goaway_frame_; @@ -363,7 +328,6 @@ class TestQuicVisitor : public QuicFramerVisitorInterface { QuicBlockedFrame blocked_frame_; QuicPathCloseFrame path_close_frame_; vector<string*> stream_data_; - vector<string> fec_data_redundancy_; }; class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> { @@ -481,8 +445,7 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, include_version, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_STREAM_DATA); } } @@ -648,10 +611,10 @@ TEST_P(QuicFramerTest, LargePacket) { memset(packet + GetPacketHeaderSize( PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId, - PACKET_6BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP), 0, + PACKET_6BYTE_PACKET_NUMBER), 0, kMaxPacketSize - GetPacketHeaderSize( PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId, - PACKET_6BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP) + 1); + PACKET_6BYTE_PACKET_NUMBER) + 1); // clang-format on QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); @@ -696,8 +659,7 @@ TEST_P(QuicFramerTest, PacketHeader) { // Now test framing boundaries. for (size_t i = 0; i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP); + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER); ++i) { string expected_error; if (i < kConnectionIdOffset) { @@ -706,10 +668,8 @@ TEST_P(QuicFramerTest, PacketHeader) { expected_error = "Unable to read ConnectionId."; } else if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId)) { expected_error = "Unable to read packet number."; - } else if (i < GetFecGroupOffset(!kIncludeVersion, !kIncludePathId)) { - expected_error = "Unable to read private flags."; } else { - expected_error = "Unable to read first fec protected packet offset."; + expected_error = "Unable to read private flags."; } CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); } @@ -749,8 +709,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteConnectionId) { // Now test framing boundaries. for (size_t i = 0; i < GetPacketHeaderSize(PACKET_4BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP); + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER); ++i) { string expected_error; if (i < kConnectionIdOffset) { @@ -761,11 +720,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteConnectionId) { } else if (i < GetPrivateFlagsOffset(PACKET_4BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId)) { expected_error = "Unable to read packet number."; - } else if (i < GetFecGroupOffset(PACKET_4BYTE_CONNECTION_ID, - !kIncludeVersion, !kIncludePathId)) { - expected_error = "Unable to read private flags."; } else { - expected_error = "Unable to read first fec protected packet offset."; + expected_error = "Unable to read private flags."; } CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); } @@ -805,8 +761,7 @@ TEST_P(QuicFramerTest, PacketHeader1ByteConnectionId) { // Now test framing boundaries. for (size_t i = 0; i < GetPacketHeaderSize(PACKET_1BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP); + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER); ++i) { string expected_error; if (i < kConnectionIdOffset) { @@ -817,11 +772,8 @@ TEST_P(QuicFramerTest, PacketHeader1ByteConnectionId) { } else if (i < GetPrivateFlagsOffset(PACKET_1BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId)) { expected_error = "Unable to read packet number."; - } else if (i < GetFecGroupOffset(PACKET_1BYTE_CONNECTION_ID, - !kIncludeVersion, !kIncludePathId)) { - expected_error = "Unable to read private flags."; } else { - expected_error = "Unable to read first fec protected packet offset."; + expected_error = "Unable to read private flags."; } CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); } @@ -861,8 +813,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) { // Now test framing boundaries. for (size_t i = 0; i < GetPacketHeaderSize(PACKET_0BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP); + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER); ++i) { string expected_error; if (i < kConnectionIdOffset) { @@ -873,11 +824,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) { } else if (i < GetPrivateFlagsOffset(PACKET_0BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId)) { expected_error = "Unable to read packet number."; - } else if (i < GetFecGroupOffset(PACKET_0BYTE_CONNECTION_ID, - !kIncludeVersion, !kIncludePathId)) { - expected_error = "Unable to read private flags."; } else { - expected_error = "Unable to read first fec protected packet offset."; + expected_error = "Unable to read private flags."; } CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); } @@ -918,8 +866,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) { // Now test framing boundaries. for (size_t i = 0; i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP); + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER); ++i) { string expected_error; if (i < kConnectionIdOffset) { @@ -930,10 +877,8 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) { expected_error = "Unable to read protocol version."; } else if (i < GetPrivateFlagsOffset(kIncludeVersion, !kIncludePathId)) { expected_error = "Unable to read packet number."; - } else if (i < GetFecGroupOffset(kIncludeVersion, !kIncludePathId)) { - expected_error = "Unable to read private flags."; } else { - expected_error = "Unable to read first fec protected packet offset."; + expected_error = "Unable to read private flags."; } CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); } @@ -975,8 +920,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithMultipathFlag) { // Now test framing boundaries. for (size_t i = 0; i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP); + kIncludePathId, PACKET_6BYTE_PACKET_NUMBER); ++i) { string expected_error; if (i < kConnectionIdOffset) { @@ -988,10 +932,8 @@ TEST_P(QuicFramerTest, PacketHeaderWithMultipathFlag) { expected_error = "Unable to read path id."; } else if (i < GetPrivateFlagsOffset(!kIncludeVersion, kIncludePathId)) { expected_error = "Unable to read packet number."; - } else if (i < GetFecGroupOffset(!kIncludeVersion, kIncludePathId)) { - expected_error = "Unable to read private flags."; } else { - expected_error = "Unable to read first fec protected packet offset."; + expected_error = "Unable to read private flags."; } CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); } @@ -1036,8 +978,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithBothVersionFlagAndMultipathFlag) { // Now test framing boundaries. for (size_t i = 0; i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP); + kIncludePathId, PACKET_6BYTE_PACKET_NUMBER); ++i) { string expected_error; if (i < kConnectionIdOffset) { @@ -1051,10 +992,8 @@ TEST_P(QuicFramerTest, PacketHeaderWithBothVersionFlagAndMultipathFlag) { expected_error = "Unable to read path id."; } else if (i < GetPrivateFlagsOffset(kIncludeVersion, kIncludePathId)) { expected_error = "Unable to read packet number."; - } else if (i < GetFecGroupOffset(kIncludeVersion, kIncludePathId)) { - expected_error = "Unable to read private flags."; } else { - expected_error = "Unable to read first fec protected packet offset."; + expected_error = "Unable to read private flags."; } CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); } @@ -1201,8 +1140,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) { // Now test framing boundaries. for (size_t i = 0; i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_4BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP); + !kIncludePathId, PACKET_4BYTE_PACKET_NUMBER); ++i) { string expected_error; if (i < kConnectionIdOffset) { @@ -1212,11 +1150,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) { } else if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId, PACKET_4BYTE_PACKET_NUMBER)) { expected_error = "Unable to read packet number."; - } else if (i < GetFecGroupOffset(!kIncludeVersion, !kIncludePathId, - PACKET_4BYTE_PACKET_NUMBER)) { - expected_error = "Unable to read private flags."; } else { - expected_error = "Unable to read first fec protected packet offset."; + expected_error = "Unable to read private flags."; } CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); } @@ -1256,8 +1191,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) { // Now test framing boundaries. for (size_t i = 0; i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_2BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP); + !kIncludePathId, PACKET_2BYTE_PACKET_NUMBER); ++i) { string expected_error; if (i < kConnectionIdOffset) { @@ -1267,11 +1201,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) { } else if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId, PACKET_2BYTE_PACKET_NUMBER)) { expected_error = "Unable to read packet number."; - } else if (i < GetFecGroupOffset(!kIncludeVersion, !kIncludePathId, - PACKET_2BYTE_PACKET_NUMBER)) { - expected_error = "Unable to read private flags."; } else { - expected_error = "Unable to read first fec protected packet offset."; + expected_error = "Unable to read private flags."; } CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); } @@ -1311,8 +1242,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) { // Now test framing boundaries. for (size_t i = 0; i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_1BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP); + !kIncludePathId, PACKET_1BYTE_PACKET_NUMBER); ++i) { string expected_error; if (i < kConnectionIdOffset) { @@ -1322,11 +1252,8 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) { } else if (i < GetPrivateFlagsOffset(!kIncludeVersion, !kIncludePathId, PACKET_1BYTE_PACKET_NUMBER)) { expected_error = "Unable to read packet number."; - } else if (i < GetFecGroupOffset(!kIncludeVersion, !kIncludePathId, - PACKET_1BYTE_PACKET_NUMBER)) { - expected_error = "Unable to read private flags."; } else { - expected_error = "Unable to read first fec protected packet offset."; + expected_error = "Unable to read private flags."; } CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); } @@ -1504,8 +1431,7 @@ TEST_P(QuicFramerTest, PaddingFrame) { // A packet with no frames is not acceptable. CheckProcessingFails( packet, GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), "Packet has no frames.", QUIC_MISSING_PAYLOAD); } @@ -1823,114 +1749,6 @@ TEST_P(QuicFramerTest, RejectPublicHeader) { ASSERT_FALSE(visitor_.header_.get()); } -TEST_P(QuicFramerTest, RevivedStreamFrame) { - // clang-format off - unsigned char payload[] = { - // 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', '!', - }; - // clang-format on - - QuicPacketHeader header; - header.public_header.connection_id = kConnectionId; - header.public_header.reset_flag = false; - header.public_header.version_flag = false; - header.fec_flag = true; - header.entropy_flag = true; - header.packet_number = kPacketNumber; - header.fec_group = 0; - - // Do not encrypt the payload because the revived payload is post-encryption. - EXPECT_TRUE(framer_.ProcessRevivedPacket( - &header, StringPiece(AsChars(payload), arraysize(payload)))); - - EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); - ASSERT_EQ(1, visitor_.revived_packets_); - ASSERT_TRUE(visitor_.header_.get()); - EXPECT_EQ(kConnectionId, visitor_.header_->public_header.connection_id); - EXPECT_FALSE(visitor_.header_->public_header.reset_flag); - EXPECT_FALSE(visitor_.header_->public_header.version_flag); - EXPECT_TRUE(visitor_.header_->fec_flag); - EXPECT_TRUE(visitor_.header_->entropy_flag); - EXPECT_EQ(1 << (header.packet_number % 8), visitor_.header_->entropy_hash); - EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number); - EXPECT_EQ(NOT_IN_FEC_GROUP, visitor_.header_->is_in_fec_group); - EXPECT_EQ(0u, visitor_.header_->fec_group); - - ASSERT_EQ(1u, visitor_.stream_frames_.size()); - EXPECT_EQ(0u, visitor_.ack_frames_.size()); - 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]); -} - -TEST_P(QuicFramerTest, StreamFrameInFecGroup) { - // clang-format off - unsigned char packet[] = { - // public flags (8 byte connection_id) - 0x3C, - // connection_id - 0x10, 0x32, 0x54, 0x76, - 0x98, 0xBA, 0xDC, 0xFE, - // packet number - 0xBC, 0x9A, 0x78, 0x56, - 0x34, 0x12, - // private flags (fec group) - 0x02, - // first fec protected packet offset - 0x02, - - // 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', '!', - }; - // clang-format on - - QuicEncryptedPacket encrypted(AsChars(packet), 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, !kIncludePathId)); - EXPECT_EQ(IN_FEC_GROUP, visitor_.header_->is_in_fec_group); - EXPECT_EQ(kPacketNumber - 2, visitor_.header_->fec_group); - const size_t fec_offset = - GetStartOfFecProtectedData(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER); - EXPECT_EQ( - string(AsChars(packet) + fec_offset, arraysize(packet) - fec_offset), - visitor_.fec_protected_payload_); - - ASSERT_EQ(1u, visitor_.stream_frames_.size()); - EXPECT_EQ(0u, visitor_.ack_frames_.size()); - 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]); -} - TEST_P(QuicFramerTest, AckFrameTwoTimestamp) { // clang-format off unsigned char packet[] = { @@ -2046,8 +1864,7 @@ TEST_P(QuicFramerTest, AckFrameTwoTimestamp) { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_ACK_DATA); } } @@ -2153,8 +1970,7 @@ TEST_P(QuicFramerTest, AckFrameOneTimestamp) { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_ACK_DATA); } } @@ -2248,8 +2064,7 @@ TEST_P(QuicFramerTest, AckFrame) { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_ACK_DATA); } } @@ -2353,8 +2168,7 @@ TEST_P(QuicFramerTest, AckFrameRevivedPackets) { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_ACK_DATA); } } @@ -2462,7 +2276,6 @@ TEST_P(QuicFramerTest, AckFrame500Nacks) { QuicAckFrame* frame = visitor_.ack_frames_[0]; EXPECT_EQ(0xBA, frame->entropy_hash); EXPECT_EQ(kLargestObserved, frame->largest_observed); - EXPECT_EQ(0u, frame->latest_revived_packet); ASSERT_EQ(500u, frame->missing_packets.NumPacketsSlow()); EXPECT_EQ(kMissingPacket - 499, frame->missing_packets.Min()); EXPECT_EQ(kMissingPacket, frame->missing_packets.Max()); @@ -2529,8 +2342,7 @@ TEST_P(QuicFramerTest, StopWaitingFrame) { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_STOP_WAITING_DATA); } } @@ -2590,8 +2402,7 @@ TEST_P(QuicFramerTest, RstStreamFrameQuic) { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_RST_STREAM_DATA); } } @@ -2651,8 +2462,7 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_CONNECTION_CLOSE_DATA); } } @@ -2714,8 +2524,7 @@ TEST_P(QuicFramerTest, GoAwayFrame) { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_GOAWAY_DATA); } } @@ -2767,8 +2576,7 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_WINDOW_UPDATE_DATA); } } @@ -2811,8 +2619,7 @@ TEST_P(QuicFramerTest, BlockedFrame) { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_BLOCKED_DATA); } } @@ -2887,8 +2694,7 @@ TEST_P(QuicFramerTest, PathCloseFrame) { CheckProcessingFails( packet, i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, - kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + kIncludePathId, PACKET_6BYTE_PACKET_NUMBER), expected_error, QUIC_INVALID_PATH_CLOSE_DATA); } } @@ -3102,7 +2908,7 @@ TEST_P(QuicFramerTest, VersionNegotiationPacket) { } } -TEST_P(QuicFramerTest, FecPacket) { +TEST_P(QuicFramerTest, DropFecPacket) { // clang-format off unsigned char packet[] = { // public flags (8 byte connection_id) @@ -3130,13 +2936,7 @@ TEST_P(QuicFramerTest, FecPacket) { EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); - ASSERT_TRUE(visitor_.header_.get()); - EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId)); - - EXPECT_EQ(0u, visitor_.stream_frames_.size()); - EXPECT_EQ(0u, visitor_.ack_frames_.size()); - ASSERT_EQ(1, visitor_.fec_count_); - EXPECT_EQ("abcdefghijklmnop", visitor_.fec_data_redundancy_[0]); + EXPECT_FALSE(visitor_.header_.get()); } TEST_P(QuicFramerTest, BuildPaddingFramePacket) { @@ -3173,9 +2973,9 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) { }; // clang-format on - uint64_t header_size = GetPacketHeaderSize( - PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId, - PACKET_6BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP); + uint64_t header_size = + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER); memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1); scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); @@ -3220,9 +3020,9 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) { }; // clang-format on - uint64_t header_size = GetPacketHeaderSize( - PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId, - PACKET_4BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP); + uint64_t header_size = + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, + !kIncludePathId, PACKET_4BYTE_PACKET_NUMBER); memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1); scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); @@ -3267,9 +3067,9 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) { }; // clang-format on - uint64_t header_size = GetPacketHeaderSize( - PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId, - PACKET_2BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP); + uint64_t header_size = + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, + !kIncludePathId, PACKET_2BYTE_PACKET_NUMBER); memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1); scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); @@ -3314,9 +3114,9 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) { }; // clang-format on - uint64_t header_size = GetPacketHeaderSize( - PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId, - PACKET_1BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP); + uint64_t header_size = + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, + !kIncludePathId, PACKET_1BYTE_PACKET_NUMBER); memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1); scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); @@ -3378,55 +3178,6 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) { arraysize(packet)); } -TEST_P(QuicFramerTest, BuildStreamFramePacketInFecGroup) { - QuicPacketHeader header; - header.public_header.connection_id = kConnectionId; - header.public_header.reset_flag = false; - header.public_header.version_flag = false; - header.fec_flag = false; - header.entropy_flag = true; - header.packet_number = kPacketNumber; - header.is_in_fec_group = IN_FEC_GROUP; - header.fec_group = kPacketNumber; - - QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset, - StringPiece("hello world!")); - - QuicFrames frames; - frames.push_back(QuicFrame(&stream_frame)); - // clang-format off - unsigned char packet[] = { - // public flags (8 byte connection_id) - 0x3C, - // connection_id - 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, - // packet number - 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, - // private flags (entropy, is_in_fec_group) - 0x03, - // FEC group - 0x00, - // frame type (stream frame with fin and data length field) - 0xFF, - // stream id - 0x04, 0x03, 0x02, 0x01, - // offset - 0x54, 0x76, 0x10, 0x32, 0xDC, 0xFE, 0x98, 0xBA, - // data length (since packet is in an FEC group) - 0x0C, 0x00, - // data - 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', - }; - // clang-format on - - scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); - ASSERT_TRUE(data != nullptr); - - test::CompareCharArraysWithHexError("constructed packet", data->data(), - data->length(), AsChars(packet), - arraysize(packet)); -} - TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) { QuicPacketHeader header; header.public_header.connection_id = kConnectionId; @@ -4372,50 +4123,6 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) { arraysize(packet)); } -TEST_P(QuicFramerTest, BuildFecPacket) { - QuicPacketHeader header; - header.public_header.connection_id = kConnectionId; - header.public_header.reset_flag = false; - header.public_header.version_flag = false; - header.fec_flag = true; - header.entropy_flag = true; - header.packet_number = kPacketNumber; - header.is_in_fec_group = IN_FEC_GROUP; - header.fec_group = kPacketNumber - 1; - - string redundancy = "abcdefghijklmnop"; - - // clang-format off - unsigned char packet[] = { - // public flags (8 byte connection_id) - 0x3C, - // connection_id - 0x10, 0x32, 0x54, 0x76, - 0x98, 0xBA, 0xDC, 0xFE, - // packet number - 0xBC, 0x9A, 0x78, 0x56, - 0x34, 0x12, - // private flags (entropy & fec group & fec packet) - 0x07, - // first fec protected packet offset - 0x01, - - // redundancy - 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', - 'i', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', - }; - // clang-format on - - scoped_ptr<QuicPacket> data(framer_.BuildFecPacket(header, redundancy)); - ASSERT_TRUE(data != nullptr); - - test::CompareCharArraysWithHexError("constructed packet", data->data(), - data->length(), AsChars(packet), - arraysize(packet)); -} - TEST_P(QuicFramerTest, EncryptPacket) { QuicPacketNumber packet_number = kPacketNumber; // clang-format off @@ -4428,10 +4135,8 @@ TEST_P(QuicFramerTest, EncryptPacket) { // packet number 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, - // private flags (fec group & fec packet) - 0x06, - // first fec protected packet offset - 0x01, + // private flags + 0x00, // redundancy 'a', 'b', 'c', 'd', @@ -4467,10 +4172,8 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) { // packet number 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, - // private flags (fec group & fec flags) - 0x06, - // first fec protected packet offset - 0x01, + // private flags + 0x00, // redundancy 'a', 'b', 'c', 'd', @@ -4506,10 +4209,8 @@ TEST_P(QuicFramerTest, EncryptPacketWithMultipathFlag) { // packet number 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, - // private flags (fec group & fec flags) - 0x06, - // first fec protected packet offset - 0x01, + // private flags + 0x00, // redundancy 'a', 'b', 'c', 'd', @@ -4546,10 +4247,8 @@ TEST_P(QuicFramerTest, EncryptPacketWithBothVersionFlagAndMultipathFlag) { // packet number 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, - // private flags (fec group & fec flags) - 0x06, - // first fec protected packet offset - 0x01, + // private flags + 0x00, // redundancy 'a', 'b', 'c', 'd', @@ -4731,45 +4430,6 @@ TEST_P(QuicFramerTest, EntropyFlagTest) { EXPECT_FALSE(visitor_.header_->fec_flag); }; -TEST_P(QuicFramerTest, FecEntropyTest) { - // clang-format off - unsigned char packet[] = { - // public flags (8 byte connection_id) - 0x3C, - // connection_id - 0x10, 0x32, 0x54, 0x76, - 0x98, 0xBA, 0xDC, 0xFE, - // packet number - 0xBC, 0x9A, 0x78, 0x56, - 0x34, 0x12, - // private flags (Entropy & fec group & FEC) - 0x07, - // first fec protected packet offset - 0xFF, - - // frame type (stream frame with fin and no length) - 0xDF, - // stream id - 0x04, 0x03, 0x02, 0x01, - // offset - 0x54, 0x76, 0x10, 0x32, - 0xDC, 0xFE, 0x98, 0xBA, - // data - 'h', 'e', 'l', 'l', - 'o', ' ', 'w', 'o', - 'r', 'l', 'd', '!', - }; - // clang-format on - - QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); - EXPECT_TRUE(framer_.ProcessPacket(encrypted)); - EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); - ASSERT_TRUE(visitor_.header_.get()); - EXPECT_TRUE(visitor_.header_->fec_flag); - EXPECT_TRUE(visitor_.header_->entropy_flag); - EXPECT_EQ(1 << 4, visitor_.header_->entropy_hash); -}; - TEST_P(QuicFramerTest, StopPacketProcessing) { // clang-format off unsigned char packet[] = { diff --git a/net/quic/quic_headers_stream.cc b/net/quic/quic_headers_stream.cc index b62717c..88a6186 100644 --- a/net/quic/quic_headers_stream.cc +++ b/net/quic/quic_headers_stream.cc @@ -66,7 +66,8 @@ class QuicHeadersStream::SpdyFramerVisitor } void OnStreamEnd(SpdyStreamId stream_id) override { - LOG(DFATAL) << "Unimplemented."; + // The framer invokes OnStreamEnd after processing a SYN_STREAM + // or SYN_REPLY frame that had the fin bit set. } void OnStreamPadding(SpdyStreamId stream_id, size_t len) override { diff --git a/net/quic/quic_headers_stream_test.cc b/net/quic/quic_headers_stream_test.cc index a821fb2..2f51bab 100644 --- a/net/quic/quic_headers_stream_test.cc +++ b/net/quic/quic_headers_stream_test.cc @@ -93,19 +93,26 @@ class MockVisitor : public SpdyFramerVisitorInterface { MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type)); }; -// Run all tests with each version, and client or server +// Run all tests with each version, perspective (client or server), +// and relevant flag options (false or true) struct TestParams { - TestParams(QuicVersion version, Perspective perspective) - : version(version), perspective(perspective) {} + TestParams(QuicVersion version, + Perspective perspective, + bool spdy_on_stream_end) + : version(version), + perspective(perspective), + spdy_on_stream_end(spdy_on_stream_end) {} friend ostream& operator<<(ostream& os, const TestParams& p) { os << "{ version: " << QuicVersionToString(p.version); - os << ", perspective: " << p.perspective << " }"; + os << ", perspective: " << p.perspective; + os << ", spdy_on_stream_end: " << p.spdy_on_stream_end << " }"; return os; } QuicVersion version; Perspective perspective; + bool spdy_on_stream_end; }; // Constructs various test permutations. @@ -113,8 +120,10 @@ vector<TestParams> GetTestParams() { vector<TestParams> params; QuicVersionVector all_supported_versions = QuicSupportedVersions(); for (const QuicVersion version : all_supported_versions) { - params.push_back(TestParams(version, Perspective::IS_CLIENT)); - params.push_back(TestParams(version, Perspective::IS_SERVER)); + params.push_back(TestParams(version, Perspective::IS_CLIENT, true)); + params.push_back(TestParams(version, Perspective::IS_SERVER, true)); + params.push_back(TestParams(version, Perspective::IS_CLIENT, false)); + params.push_back(TestParams(version, Perspective::IS_SERVER, false)); } FLAGS_quic_supports_push_promise = true; return params; @@ -129,14 +138,15 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> { session_(connection_), headers_stream_(QuicSpdySessionPeer::GetHeadersStream(&session_)), body_("hello world"), - framer_(HTTP2), stream_frame_(kHeadersStreamId, /*fin=*/false, /*offset=*/0, ""), next_promised_stream_id_(2) { FLAGS_quic_always_log_bugs_for_tests = true; headers_[":version"] = "HTTP/1.1"; headers_[":status"] = "200 Ok"; headers_["content-length"] = "11"; - framer_.set_visitor(&visitor_); + FLAGS_spdy_on_stream_end = GetParam().spdy_on_stream_end; + framer_ = std::unique_ptr<SpdyFramer>(new SpdyFramer(HTTP2)); + framer_->set_visitor(&visitor_); EXPECT_EQ(version(), session_.connection()->version()); EXPECT_TRUE(headers_stream_ != nullptr); VLOG(1) << GetParam(); @@ -176,7 +186,7 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> { SpdyPriority priority, SpdyFrameType type) { // Write the headers and capture the outgoing data - EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, _, nullptr)) + EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, nullptr)) .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov))); headers_stream_->WriteHeaders(stream_id, headers_, fin, priority, nullptr); @@ -197,11 +207,15 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> { .WillRepeatedly(WithArgs<1, 2>( Invoke(this, &QuicHeadersStreamTest::SaveHeaderData))); if (fin) { - EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, nullptr, 0, true)); + if (FLAGS_spdy_on_stream_end) { + EXPECT_CALL(visitor_, OnStreamEnd(stream_id)); + } else { + EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, nullptr, 0, true)); + } } - framer_.ProcessInput(saved_data_.data(), saved_data_.length()); - EXPECT_FALSE(framer_.HasError()) - << SpdyFramer::ErrorCodeToString(framer_.error_code()); + framer_->ProcessInput(saved_data_.data(), saved_data_.length()); + EXPECT_FALSE(framer_->HasError()) + << SpdyFramer::ErrorCodeToString(framer_->error_code()); CheckHeaders(); saved_data_.clear(); @@ -209,7 +223,7 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> { void CheckHeaders() { SpdyHeaderBlock headers; - EXPECT_TRUE(framer_.ParseHeaderBlockInBuffer( + EXPECT_TRUE(framer_->ParseHeaderBlockInBuffer( saved_header_data_.data(), saved_header_data_.length(), &headers)); EXPECT_EQ(headers_, headers); saved_header_data_.clear(); @@ -240,7 +254,7 @@ class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> { string body_; string saved_data_; string saved_header_data_; - SpdyFramer framer_; + std::unique_ptr<SpdyFramer> framer_; StrictMock<MockVisitor> visitor_; QuicStreamFrame stream_frame_; QuicStreamId next_promised_stream_id_; @@ -276,8 +290,7 @@ TEST_P(QuicHeadersStreamTest, WritePushPromises) { QuicStreamId promised_stream_id = NextPromisedStreamId(); if (perspective() == Perspective::IS_SERVER) { // Write the headers and capture the outgoing data - EXPECT_CALL(session_, - WritevData(kHeadersStreamId, _, _, false, _, nullptr)) + EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, nullptr)) .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov))); headers_stream_->WritePushPromise(stream_id, promised_stream_id, headers_, nullptr); @@ -288,9 +301,9 @@ TEST_P(QuicHeadersStreamTest, WritePushPromises) { EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _)) .WillRepeatedly(WithArgs<1, 2>( Invoke(this, &QuicHeadersStreamTest::SaveHeaderData))); - framer_.ProcessInput(saved_data_.data(), saved_data_.length()); - EXPECT_FALSE(framer_.HasError()) - << SpdyFramer::ErrorCodeToString(framer_.error_code()); + framer_->ProcessInput(saved_data_.data(), saved_data_.length()); + EXPECT_FALSE(framer_->HasError()) + << SpdyFramer::ErrorCodeToString(framer_->error_code()); CheckHeaders(); saved_data_.clear(); } else { @@ -313,13 +326,13 @@ TEST_P(QuicHeadersStreamTest, ProcessRawData) { headers_frame.set_header_block(headers_); headers_frame.set_fin(fin); headers_frame.set_has_priority(true); - frame.reset(framer_.SerializeFrame(headers_frame)); + frame.reset(framer_->SerializeFrame(headers_frame)); EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)); } else { SpdyHeadersIR headers_frame(stream_id); headers_frame.set_header_block(headers_); headers_frame.set_fin(fin); - frame.reset(framer_.SerializeFrame(headers_frame)); + frame.reset(framer_->SerializeFrame(headers_frame)); } EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)) .WillRepeatedly(WithArgs<1>(Invoke( @@ -345,7 +358,7 @@ TEST_P(QuicHeadersStreamTest, ProcessPushPromise) { scoped_ptr<SpdySerializedFrame> frame; SpdyPushPromiseIR push_promise(stream_id, promised_stream_id); push_promise.set_header_block(headers_); - frame.reset(framer_.SerializeFrame(push_promise)); + frame.reset(framer_->SerializeFrame(push_promise)); if (perspective() == Perspective::IS_SERVER) { EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( QUIC_INVALID_HEADERS_STREAM_DATA, @@ -382,13 +395,13 @@ TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) { headers_frame.set_header_block(headers_); headers_frame.set_fin(fin); headers_frame.set_has_priority(true); - frame.reset(framer_.SerializeFrame(headers_frame)); + frame.reset(framer_->SerializeFrame(headers_frame)); EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)); } else { SpdyHeadersIR headers_frame(stream_id); headers_frame.set_header_block(headers_); headers_frame.set_fin(fin); - frame.reset(framer_.SerializeFrame(headers_frame)); + frame.reset(framer_->SerializeFrame(headers_frame)); } EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)); EXPECT_CALL(session_, @@ -416,13 +429,13 @@ TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) { headers_frame.set_header_block(headers_); headers_frame.set_fin(fin); headers_frame.set_has_priority(true); - frames[stream_num].reset(framer_.SerializeFrame(headers_frame)); + frames[stream_num].reset(framer_->SerializeFrame(headers_frame)); EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)).Times(1); } else { SpdyHeadersIR headers_frame(stream_id); headers_frame.set_header_block(headers_); headers_frame.set_fin(fin); - frames[stream_num].reset(framer_.SerializeFrame(headers_frame)); + frames[stream_num].reset(framer_->SerializeFrame(headers_frame)); } stream_frames[stream_num].stream_id = stream_frame_.stream_id; stream_frames[stream_num].offset = stream_frame_.offset; @@ -466,13 +479,13 @@ TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) { headers_frame.set_header_block(headers_); headers_frame.set_fin(fin); headers_frame.set_has_priority(true); - frame.reset(framer_.SerializeFrame(headers_frame)); + frame.reset(framer_->SerializeFrame(headers_frame)); EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)); } else { SpdyHeadersIR headers_frame(stream_id); headers_frame.set_header_block(headers_); headers_frame.set_fin(fin); - frame.reset(framer_.SerializeFrame(headers_frame)); + frame.reset(framer_->SerializeFrame(headers_frame)); } EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)) .WillRepeatedly(WithArgs<1>(Invoke( @@ -501,7 +514,7 @@ TEST_P(QuicHeadersStreamTest, ProcessBadData) { TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) { SpdyDataIR data(2, ""); - scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); + scoped_ptr<SpdySerializedFrame> frame(framer_->SerializeFrame(data)); EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, "SPDY DATA frame received.")) @@ -514,7 +527,7 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) { TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) { SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR); - scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); + scoped_ptr<SpdySerializedFrame> frame(framer_->SerializeFrame(data)); EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, "SPDY RST_STREAM frame received.")) @@ -528,7 +541,7 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) { TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) { SpdySettingsIR data; data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, 0); - scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); + scoped_ptr<SpdySerializedFrame> frame(framer_->SerializeFrame(data)); EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, "SPDY SETTINGS frame received.")) @@ -541,7 +554,7 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) { TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) { SpdyPingIR data(1); - scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); + scoped_ptr<SpdySerializedFrame> frame(framer_->SerializeFrame(data)); EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, "SPDY PING frame received.")) @@ -554,7 +567,7 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) { TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) { SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away"); - scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); + scoped_ptr<SpdySerializedFrame> frame(framer_->SerializeFrame(data)); EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, "SPDY GOAWAY frame received.")) @@ -567,7 +580,7 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) { TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) { SpdyWindowUpdateIR data(1, 1); - scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); + scoped_ptr<SpdySerializedFrame> frame(framer_->SerializeFrame(data)); EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( QUIC_INVALID_HEADERS_STREAM_DATA, "SPDY WINDOW_UPDATE frame received.")) diff --git a/net/quic/quic_multipath_received_packet_manager.cc b/net/quic/quic_multipath_received_packet_manager.cc index 6494137..26d7fa0 100644 --- a/net/quic/quic_multipath_received_packet_manager.cc +++ b/net/quic/quic_multipath_received_packet_manager.cc @@ -57,18 +57,6 @@ void QuicMultipathReceivedPacketManager::RecordPacketReceived( manager->RecordPacketReceived(bytes, header, receipt_time); } -void QuicMultipathReceivedPacketManager::RecordPacketRevived( - QuicPathId path_id, - QuicPacketNumber packet_number) { - QuicReceivedPacketManager* manager = path_managers_[path_id]; - if (manager == nullptr) { - QUIC_BUG << "Revived a packet on a non-existent path."; - return; - } - - manager->RecordPacketRevived(packet_number); -} - bool QuicMultipathReceivedPacketManager::IsMissing( QuicPathId path_id, QuicPacketNumber packet_number) { diff --git a/net/quic/quic_multipath_received_packet_manager.h b/net/quic/quic_multipath_received_packet_manager.h index dba9244..5f1f3a3 100644 --- a/net/quic/quic_multipath_received_packet_manager.h +++ b/net/quic/quic_multipath_received_packet_manager.h @@ -40,9 +40,6 @@ class NET_EXPORT_PRIVATE QuicMultipathReceivedPacketManager { const QuicPacketHeader& header, QuicTime receipt_time); - // Called when packet with |packet_number| is revived on path with |path_id|. - void RecordPacketRevived(QuicPathId path_id, QuicPacketNumber packet_number); - // Checks whether |packet_number| is missing on path with |path_id|. bool IsMissing(QuicPathId path_id, QuicPacketNumber packet_number); diff --git a/net/quic/quic_multipath_received_packet_manager_test.cc b/net/quic/quic_multipath_received_packet_manager_test.cc index e342ae8..8a54a68 100644 --- a/net/quic/quic_multipath_received_packet_manager_test.cc +++ b/net/quic/quic_multipath_received_packet_manager_test.cc @@ -100,14 +100,6 @@ TEST_F(QuicMultipathReceivedPacketManagerTest, RecordPacketReceived) { "Received a packet on a non-existent path"); } -TEST_F(QuicMultipathReceivedPacketManagerTest, RecordPacketRevived) { - EXPECT_CALL(*manager_0_, RecordPacketRevived(_)).Times(1); - multipath_manager_.RecordPacketRevived(kDefaultPathId, header_.packet_number); - EXPECT_DFATAL( - multipath_manager_.RecordPacketRevived(kPathId2, header_.packet_number), - "Revived a packet on a non-existent path"); -} - TEST_F(QuicMultipathReceivedPacketManagerTest, IsMissing) { EXPECT_CALL(*manager_0_, IsMissing(header_.packet_number)) .WillOnce(Return(true)); diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc index f4e0cf7..a0a38a5 100644 --- a/net/quic/quic_packet_creator.cc +++ b/net/quic/quic_packet_creator.cc @@ -11,7 +11,6 @@ #include "net/quic/crypto/quic_random.h" #include "net/quic/quic_bug_tracker.h" #include "net/quic/quic_data_writer.h" -#include "net/quic/quic_fec_group.h" #include "net/quic/quic_flags.h" #include "net/quic/quic_utils.h" @@ -24,29 +23,6 @@ using std::vector; namespace net { -namespace { - -// Default max packets in an FEC group. -static const size_t kDefaultMaxPacketsPerFecGroup = 10; -// Lowest max packets in an FEC group. -static const size_t kLowestMaxPacketsPerFecGroup = 2; - -// We want to put some space between a protected packet and the FEC packet to -// avoid losing them both within the same loss episode. On the other hand, we -// expect to be able to recover from any loss in about an RTT. We resolve this -// tradeoff by sending an FEC packet atmost half an RTT, or equivalently, half -// the max number of in-flight packets, the first protected packet. Since we -// don't want to delay an FEC packet past half an RTT, we set the max FEC group -// size to be half the current congestion window. -const float kMaxPacketsInFlightMultiplierForFecGroupSize = 0.5; -const float kRttMultiplierForFecTimeout = 0.5; - -// Minimum timeout for FEC alarm, set to half the minimum Tail Loss Probe -// timeout of 10ms. -const int64_t kMinFecTimeoutMs = 5u; - -} // namespace - // A QuicRandom wrapper that gets a bucket of entropy and distributes it // bit-by-bit. Replenishes the bucket as needed. Not thread-safe. Expose this // class if single bit randomness is needed elsewhere. @@ -104,13 +80,7 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id, 0, 0, false, - false), - should_fec_protect_next_packet_(false), - fec_protect_(false), - max_packets_per_fec_group_(kDefaultMaxPacketsPerFecGroup), - fec_send_policy_(FEC_ANY_TRIGGER), - fec_timeout_(QuicTime::Delta::Zero()), - rtt_multiplier_for_fec_timeout_(kRttMultiplierForFecTimeout) { + false) { SetMaxPacketLength(kDefaultMaxPacketSize); } @@ -118,15 +88,6 @@ QuicPacketCreator::~QuicPacketCreator() { QuicUtils::DeleteFrames(&packet_.retransmittable_frames); } -void QuicPacketCreator::OnBuiltFecProtectedPayload( - const QuicPacketHeader& header, - StringPiece payload) { - if (fec_group_.get() != nullptr) { - DCHECK_NE(0u, header.fec_group); - fec_group_->Update(packet_.encryption_level, header, payload); - } -} - void QuicPacketCreator::SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter) { framer_->SetEncrypter(level, encrypter); @@ -134,8 +95,8 @@ void QuicPacketCreator::SetEncrypter(EncryptionLevel level, } bool QuicPacketCreator::CanSetMaxPacketLength() const { - // |max_packet_length_| should not be changed mid-packet or mid-FEC group. - return fec_group_.get() == nullptr && queued_frames_.empty(); + // |max_packet_length_| should not be changed mid-packet. + return queued_frames_.empty(); } void QuicPacketCreator::SetMaxPacketLength(QuicByteCount length) { @@ -151,81 +112,14 @@ void QuicPacketCreator::SetMaxPacketLength(QuicByteCount length) { max_plaintext_size_ = framer_->GetMaxPlaintextSize(max_packet_length_); } -void QuicPacketCreator::set_max_packets_per_fec_group( - size_t max_packets_per_fec_group) { - max_packets_per_fec_group_ = - max(kLowestMaxPacketsPerFecGroup, max_packets_per_fec_group); - DCHECK_LT(0u, max_packets_per_fec_group_); -} - -bool QuicPacketCreator::ShouldSendFec(bool force_close) const { - return !HasPendingFrames() && fec_group_.get() != nullptr && - fec_group_->NumReceivedPackets() > 0 && - (force_close || - fec_group_->NumReceivedPackets() >= max_packets_per_fec_group_); -} - -void QuicPacketCreator::ResetFecGroup() { - if (HasPendingFrames()) { - QUIC_BUG_IF(packet_size_ != 0) - << "Cannot reset FEC group with pending frames."; - return; - } - fec_group_.reset(nullptr); -} - -bool QuicPacketCreator::IsFecGroupOpen() const { - return fec_group_.get() != nullptr; -} - -void QuicPacketCreator::StartFecProtectingPackets() { - if (max_packets_per_fec_group_ == 0) { - QUIC_BUG << "Cannot start FEC protection when FEC is not enabled."; - return; - } - // TODO(jri): This currently requires that the generator flush out any - // pending frames when FEC protection is turned on. If current packet can be - // converted to an FEC protected packet, do it. This will require the - // generator to check if the resulting expansion still allows the incoming - // frame to be added to the packet. - if (HasPendingFrames()) { - QUIC_BUG << "Cannot start FEC protection with pending frames."; - return; - } - DCHECK(!fec_protect_); - fec_protect_ = true; -} - -void QuicPacketCreator::StopFecProtectingPackets() { - if (fec_group_.get() != nullptr) { - QUIC_BUG << "Cannot stop FEC protection with open FEC group."; - return; - } - DCHECK(fec_protect_); - fec_protect_ = false; -} - -InFecGroup QuicPacketCreator::MaybeUpdateLengthsAndStartFec() { - if (fec_group_.get() != nullptr) { - // Don't update any lengths when an FEC group is open, to ensure same - // packet header size in all packets within a group. - return IN_FEC_GROUP; - } +void QuicPacketCreator::MaybeUpdatePacketNumberLength() { if (!queued_frames_.empty()) { // Don't change creator state if there are frames queued. - return NOT_IN_FEC_GROUP; + return; } - // Update packet number length only on packet and FEC group boundaries. + // Update packet number length only on packet boundary. packet_.packet_number_length = next_packet_number_length_; - - if (!fec_protect_) { - return NOT_IN_FEC_GROUP; - } - // Start a new FEC group since protection is on. Set the fec group number to - // the packet number of the next packet. - fec_group_.reset(new QuicFecGroup(packet_.packet_number + 1)); - return IN_FEC_GROUP; } // Stops serializing version of the protocol in packets sent after this call. @@ -244,11 +138,8 @@ void QuicPacketCreator::UpdatePacketNumberLength( QuicPacketNumber least_packet_awaited_by_peer, QuicPacketCount max_packets_in_flight) { DCHECK_LE(least_packet_awaited_by_peer, packet_.packet_number + 1); - // Since the packet creator will not change packet number length mid FEC - // group, include the size of an FEC group to be safe. - const QuicPacketNumber current_delta = max_packets_per_fec_group_ + - packet_.packet_number + 1 - - least_packet_awaited_by_peer; + const QuicPacketNumber current_delta = + packet_.packet_number + 1 - least_packet_awaited_by_peer; const uint64_t delta = max(current_delta, max_packets_in_flight); next_packet_number_length_ = QuicFramer::GetMinSequenceNumberLength(delta * 4); @@ -260,15 +151,10 @@ bool QuicPacketCreator::ConsumeData(QuicStreamId id, QuicStreamOffset offset, bool fin, bool needs_padding, - QuicFrame* frame, - FecProtection fec_protection) { + QuicFrame* frame) { if (!HasRoomForStreamFrame(id, offset)) { return false; } - if (fec_protection == MUST_FEC_PROTECT) { - should_fec_protect_next_packet_ = true; - MaybeStartFecProtection(); - } CreateStreamFrame(id, iov, iov_offset, offset, fin, frame); if (!AddFrame(*frame, /*save_retransmittable_frames=*/true)) { // Fails if we try to write unencrypted stream data. @@ -278,23 +164,12 @@ bool QuicPacketCreator::ConsumeData(QuicStreamId id, if (needs_padding) { packet_.needs_padding = true; } - if (fec_protection == MUST_FEC_PROTECT && - iov_offset + frame->stream_frame->frame_length == iov.total_length) { - // Turn off FEC protection when we're done writing protected data. - DVLOG(1) << "Turning FEC protection OFF"; - should_fec_protect_next_packet_ = false; - } return true; } bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id, QuicStreamOffset offset) { - // TODO(jri): This is a simple safe decision for now, but make - // is_in_fec_group a parameter. Same as with all public methods in - // QuicPacketCreator. - return BytesFree() > - QuicFramer::GetMinStreamFrameSize( - id, offset, true, fec_protect_ ? IN_FEC_GROUP : NOT_IN_FEC_GROUP); + return BytesFree() > QuicFramer::GetMinStreamFrameSize(id, offset, true); } // static @@ -303,13 +178,11 @@ size_t QuicPacketCreator::StreamFramePacketOverhead( bool include_version, bool include_path_id, QuicPacketNumberLength packet_number_length, - QuicStreamOffset offset, - InFecGroup is_in_fec_group) { + QuicStreamOffset offset) { return GetPacketHeaderSize(connection_id_length, include_version, - include_path_id, packet_number_length, - is_in_fec_group) + + include_path_id, packet_number_length) + // Assumes this is a stream with a single lone packet. - QuicFramer::GetMinStreamFrameSize(1u, offset, true, is_in_fec_group); + QuicFramer::GetMinStreamFrameSize(1u, offset, true); } size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id, @@ -319,16 +192,16 @@ size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id, bool fin, QuicFrame* frame) { DCHECK_GT(max_packet_length_, - StreamFramePacketOverhead( - connection_id_length_, kIncludeVersion, kIncludePathId, - PACKET_6BYTE_PACKET_NUMBER, offset, IN_FEC_GROUP)); + StreamFramePacketOverhead(connection_id_length_, kIncludeVersion, + kIncludePathId, + PACKET_6BYTE_PACKET_NUMBER, offset)); - InFecGroup is_in_fec_group = MaybeUpdateLengthsAndStartFec(); + MaybeUpdatePacketNumberLength(); LOG_IF(DFATAL, !HasRoomForStreamFrame(id, offset)) << "No room for Stream frame, BytesFree: " << BytesFree() << " MinStreamFrameSize: " - << QuicFramer::GetMinStreamFrameSize(id, offset, true, is_in_fec_group); + << QuicFramer::GetMinStreamFrameSize(id, offset, true); if (iov_offset == iov.total_length) { QUIC_BUG_IF(!fin) << "Creating a stream frame with no data or fin."; @@ -339,7 +212,7 @@ size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id, const size_t data_size = iov.total_length - iov_offset; size_t min_frame_size = QuicFramer::GetMinStreamFrameSize( - id, offset, /* last_frame_in_packet= */ true, is_in_fec_group); + id, offset, /* last_frame_in_packet= */ true); size_t bytes_consumed = min<size_t>(BytesFree() - min_frame_size, data_size); bool set_fin = fin && bytes_consumed == data_size; // Last frame. @@ -409,20 +282,16 @@ void QuicPacketCreator::ReserializeAllFrames( char* buffer, size_t buffer_len) { DCHECK(queued_frames_.empty()); - DCHECK(fec_group_.get() == nullptr); DCHECK(!packet_.needs_padding); QUIC_BUG_IF(retransmission.retransmittable_frames.empty()) << "Attempt to serialize empty packet"; const QuicPacketNumberLength saved_length = packet_.packet_number_length; const QuicPacketNumberLength saved_next_length = next_packet_number_length_; - const bool saved_should_fec_protect = fec_protect_; const EncryptionLevel default_encryption_level = packet_.encryption_level; - // Temporarily set the packet number length, stop FEC protection, - // and change the encryption level. + // Temporarily set the packet number length and change the encryption level. packet_.packet_number_length = retransmission.packet_number_length; next_packet_number_length_ = retransmission.packet_number_length; - fec_protect_ = false; packet_.needs_padding = retransmission.needs_padding; // Only preserve the original encryption level if it's a handshake packet or // if we haven't gone forward secure. @@ -431,7 +300,7 @@ void QuicPacketCreator::ReserializeAllFrames( packet_.encryption_level = retransmission.encryption_level; } - // Serialize the packet and restore the FEC and packet number length state. + // Serialize the packet and restore packet number length state. for (const QuicFrame& frame : retransmission.retransmittable_frames) { bool success = AddFrame(frame, false); DCHECK(success); @@ -443,7 +312,6 @@ void QuicPacketCreator::ReserializeAllFrames( // Restore old values. packet_.packet_number_length = saved_length; next_packet_number_length_ = saved_next_length; - fec_protect_ = saved_should_fec_protect; packet_.encryption_level = default_encryption_level; } @@ -461,8 +329,7 @@ void QuicPacketCreator::Flush() { void QuicPacketCreator::OnSerializedPacket() { if (packet_.encrypted_buffer == nullptr) { - QUIC_BUG << "Failed to SerializePacket. fec_policy:" << fec_send_policy() - << " should_fec_protect_:" << should_fec_protect_next_packet_; + QUIC_BUG << "Failed to SerializePacket."; delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET, ConnectionCloseSource::FROM_SELF); return; @@ -470,8 +337,6 @@ void QuicPacketCreator::OnSerializedPacket() { delegate_->OnSerializedPacket(&packet_); ClearPacket(); - MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/false, - /*is_fec_timeout=*/false); // Maximum packet size may be only enacted while no packet is currently being // constructed, so here we have a good opportunity to actually change it. if (CanSetMaxPacketLength()) { @@ -484,7 +349,6 @@ void QuicPacketCreator::ClearPacket() { packet_.has_stop_waiting = false; packet_.has_crypto_handshake = NOT_HANDSHAKE; packet_.needs_padding = false; - packet_.is_fec_packet = false; packet_.original_packet_number = 0; packet_.transmission_type = NOT_RETRANSMISSION; packet_.encrypted_buffer = nullptr; @@ -502,10 +366,6 @@ bool QuicPacketCreator::HasPendingRetransmittableFrames() const { } size_t QuicPacketCreator::ExpansionOnNewFrame() const { - // If packet is FEC protected, there's no expansion. - if (fec_protect_) { - return 0; - } // If the last frame in the packet is a stream frame, then it will expand to // include the stream_length field when a new frame is added. bool has_trailing_stream_frame = @@ -523,14 +383,11 @@ size_t QuicPacketCreator::PacketSize() { if (!queued_frames_.empty()) { return packet_size_; } - if (fec_group_.get() == nullptr) { - // Update packet number length on packet and FEC boundary. - packet_.packet_number_length = next_packet_number_length_; - } - packet_size_ = - GetPacketHeaderSize(connection_id_length_, send_version_in_packet_, - send_path_id_in_packet_, packet_.packet_number_length, - fec_protect_ ? IN_FEC_GROUP : NOT_IN_FEC_GROUP); + // Update packet number length on packet boundary. + packet_.packet_number_length = next_packet_number_length_; + packet_size_ = GetPacketHeaderSize( + connection_id_length_, send_version_in_packet_, send_path_id_in_packet_, + packet_.packet_number_length); return packet_size_; } @@ -556,24 +413,13 @@ 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"; - if (fec_group_.get() != nullptr) { - DCHECK_GE(packet_.packet_number + 1, fec_group_->FecGroupNumber()); - } QuicPacketHeader header; // FillPacketHeader increments packet_number_. - FillPacketHeader(fec_group_ != nullptr ? fec_group_->FecGroupNumber() : 0, - false, &header); + FillPacketHeader(&header); MaybeAddPadding(); DCHECK_GE(max_plaintext_size_, packet_size_); - // ACK Frames will be truncated due to length only if they're the only frame - // in the packet, and if packet_size_ was set to max_plaintext_size_. If - // truncation due to length occurred, then GetSerializedFrameLength will have - // returned all bytes free. - bool possibly_truncated_by_length = packet_size_ == max_plaintext_size_ && - queued_frames_.size() == 1 && - queued_frames_.back().type == ACK_FRAME; // Use the packet_size_ instead of the buffer size to ensure smaller // packet sizes are properly used. size_t length = framer_->BuildDataPacket(header, queued_frames_, @@ -583,25 +429,36 @@ void QuicPacketCreator::SerializePacket(char* encrypted_buffer, return; } - // TODO(ianswett) Consider replacing QuicPacket with something else, since - // it's only used to provide convenience methods to FEC and encryption. - QuicPacket packet( - encrypted_buffer, length, - /* owns_buffer */ false, header.public_header.connection_id_length, - header.public_header.version_flag, header.public_header.multipath_flag, - header.public_header.packet_number_length); - OnBuiltFecProtectedPayload(header, packet.FecProtectedData()); - + // ACK Frames will be truncated due to length only if they're the only frame + // in the packet, and if packet_size_ was set to max_plaintext_size_. If + // truncation due to length occurred, then GetSerializedFrameLength will have + // returned all bytes free. + bool possibly_truncated_by_length = packet_size_ == max_plaintext_size_ && + queued_frames_.size() == 1 && + queued_frames_.back().type == ACK_FRAME; // Because of possible truncation, we can't be confident that our // packet size calculation worked correctly. if (!possibly_truncated_by_length) { DCHECK_EQ(packet_size_, length); } - // Immediately encrypt the packet, to ensure we don't encrypt the same - // packet number multiple times. - size_t encrypted_length = framer_->EncryptPayload( - packet_.encryption_level, packet_.path_id, packet_.packet_number, packet, - encrypted_buffer, encrypted_buffer_len); + size_t encrypted_length = 0; + if (FLAGS_quic_inplace_encryption2) { + const size_t ad_len = GetStartOfEncryptedData(header); + encrypted_length = framer_->EncryptInPlace( + packet_.encryption_level, packet_.path_id, packet_.packet_number, + ad_len, length, encrypted_buffer_len, encrypted_buffer); + } else { + QuicPacket packet( + encrypted_buffer, length, + /* owns_buffer */ false, header.public_header.connection_id_length, + header.public_header.version_flag, header.public_header.multipath_flag, + header.public_header.packet_number_length); + // Immediately encrypt the packet, to ensure we don't encrypt the same + // packet number multiple times. + encrypted_length = framer_->EncryptPayload( + packet_.encryption_level, packet_.path_id, packet_.packet_number, + packet, encrypted_buffer, encrypted_buffer_len); + } if (encrypted_length == 0) { QUIC_BUG << "Failed to encrypt packet number " << packet_.packet_number; return; @@ -614,44 +471,6 @@ void QuicPacketCreator::SerializePacket(char* encrypted_buffer, packet_.encrypted_length = encrypted_length; } -void QuicPacketCreator::SerializeFec(char* buffer, size_t buffer_len) { - DCHECK_LT(0u, buffer_len); - if (fec_group_.get() == nullptr || fec_group_->NumReceivedPackets() <= 0) { - QUIC_BUG << "SerializeFEC called but no group or zero packets in group."; - return; - } - if (FLAGS_quic_no_unencrypted_fec && - packet_.encryption_level == ENCRYPTION_NONE) { - QUIC_BUG << "SerializeFEC must be called with encryption."; - delegate_->OnUnrecoverableError(QUIC_UNENCRYPTED_FEC_DATA, - ConnectionCloseSource::FROM_SELF); - return; - } - DCHECK_EQ(0u, queued_frames_.size()); - QuicPacketHeader header; - FillPacketHeader(fec_group_->FecGroupNumber(), true, &header); - scoped_ptr<QuicPacket> packet( - framer_->BuildFecPacket(header, fec_group_->PayloadParity())); - fec_group_.reset(nullptr); - packet_size_ = 0; - QUIC_BUG_IF(packet == nullptr) << "Failed to serialize fec packet for group:" - << fec_group_->FecGroupNumber(); - DCHECK_GE(max_packet_length_, packet->length()); - // Immediately encrypt the packet, to ensure we don't encrypt the same packet - // packet number multiple times. - size_t encrypted_length = framer_->EncryptPayload( - packet_.encryption_level, packet_.path_id, packet_.packet_number, *packet, - buffer, buffer_len); - if (encrypted_length == 0) { - QUIC_BUG << "Failed to encrypt packet number " << packet_.packet_number; - return; - } - packet_.entropy_hash = QuicFramer::GetPacketEntropyHash(header); - packet_.encrypted_buffer = buffer; - packet_.encrypted_length = encrypted_length; - packet_.is_fec_packet = true; -} - QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket( const QuicVersionVector& supported_versions) { DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective()); @@ -668,21 +487,19 @@ SerializedPacket QuicPacketCreator::NoPacket() { nullptr, 0, 0, false, false); } -void QuicPacketCreator::FillPacketHeader(QuicFecGroupNumber fec_group, - bool fec_flag, - QuicPacketHeader* header) { +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 = send_path_id_in_packet_; header->public_header.reset_flag = false; header->public_header.version_flag = send_version_in_packet_; - header->fec_flag = fec_flag; + header->fec_flag = false; header->path_id = packet_.path_id; header->packet_number = ++packet_.packet_number; header->public_header.packet_number_length = packet_.packet_number_length; header->entropy_flag = random_bool_source_->RandBool(); - header->is_in_fec_group = fec_group == 0 ? NOT_IN_FEC_GROUP : IN_FEC_GROUP; - header->fec_group = fec_group; + header->is_in_fec_group = NOT_IN_FEC_GROUP; + header->fec_group = 0; } bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) { @@ -708,10 +525,10 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame, ConnectionCloseSource::FROM_SELF); return false; } - InFecGroup is_in_fec_group = MaybeUpdateLengthsAndStartFec(); + MaybeUpdatePacketNumberLength(); size_t frame_len = framer_->GetSerializedFrameLength( - frame, BytesFree(), queued_frames_.empty(), true, is_in_fec_group, + frame, BytesFree(), queued_frames_.empty(), true, packet_.packet_number_length); if (frame_len == 0) { // Current open packet is full. @@ -762,64 +579,6 @@ void QuicPacketCreator::MaybeAddPadding() { DCHECK(success); } -void QuicPacketCreator::MaybeStartFecProtection() { - if (max_packets_per_fec_group_ == 0 || fec_protect_) { - // Do not start FEC protection when FEC protection is not enabled or FEC - // protection is already on. - return; - } - DVLOG(1) << "Turning FEC protection ON"; - // Flush current open packet. - Flush(); - - StartFecProtectingPackets(); - DCHECK(fec_protect_); -} - -void QuicPacketCreator::MaybeSendFecPacketAndCloseGroup(bool force_send_fec, - bool is_fec_timeout) { - if (ShouldSendFec(force_send_fec)) { - if ((FLAGS_quic_no_unencrypted_fec && - packet_.encryption_level == ENCRYPTION_NONE) || - (fec_send_policy_ == FEC_ALARM_TRIGGER && !is_fec_timeout)) { - ResetFecGroup(); - delegate_->OnResetFecGroup(); - } else { - // TODO(zhongyi): Change the default 64 alignas value (used the default - // value from CACHELINE_SIZE). - ALIGNAS(64) char seralized_fec_buffer[kMaxPacketSize]; - SerializeFec(seralized_fec_buffer, kMaxPacketSize); - OnSerializedPacket(); - } - } - - if (!should_fec_protect_next_packet_ && fec_protect_ && !IsFecGroupOpen()) { - StopFecProtectingPackets(); - } -} - -QuicTime::Delta QuicPacketCreator::GetFecTimeout( - QuicPacketNumber packet_number) { - // Do not set up FEC alarm for |packet_number| it is not the first packet in - // the current group. - if (fec_group_.get() != nullptr && - (packet_number == fec_group_->FecGroupNumber())) { - return QuicTime::Delta::Max( - fec_timeout_, QuicTime::Delta::FromMilliseconds(kMinFecTimeoutMs)); - } - return QuicTime::Delta::Infinite(); -} - -void QuicPacketCreator::OnCongestionWindowChange( - QuicPacketCount max_packets_in_flight) { - set_max_packets_per_fec_group(static_cast<size_t>( - kMaxPacketsInFlightMultiplierForFecGroupSize * max_packets_in_flight)); -} - -void QuicPacketCreator::OnRttChange(QuicTime::Delta rtt) { - fec_timeout_ = rtt.Multiply(rtt_multiplier_for_fec_timeout_); -} - void QuicPacketCreator::SetCurrentPath( QuicPathId path_id, QuicPacketNumber least_packet_awaited_by_peer, @@ -832,10 +591,6 @@ void QuicPacketCreator::SetCurrentPath( QUIC_BUG << "Unable to change paths when a packet is under construction."; return; } - - // Send FEC packet and close FEC group. - MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, - /*is_fec_timeout=*/false); // Save current packet number and load switching path's packet number. multipath_packet_number_[packet_.path_id] = packet_.packet_number; std::unordered_map<QuicPathId, QuicPacketNumber>::iterator it = diff --git a/net/quic/quic_packet_creator.h b/net/quic/quic_packet_creator.h index fcb4b50..870de4a 100644 --- a/net/quic/quic_packet_creator.h +++ b/net/quic/quic_packet_creator.h @@ -3,10 +3,9 @@ // found in the LICENSE file. // // Accumulates frames for the next packet until more frames no longer fit or -// it's time to create a packet from them. Also provides packet creation of -// FEC packets based on previously created packets. If multipath enabled, only -// creates packets on one path at the same time. Currently, next packet number -// is tracked per-path. +// it's time to create a packet from them. If multipath enabled, only creates +// packets on one path at the same time. Currently, next packet number is +// tracked per-path. #ifndef NET_QUIC_QUIC_PACKET_CREATOR_H_ #define NET_QUIC_QUIC_PACKET_CREATOR_H_ @@ -21,7 +20,6 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_piece.h" -#include "net/quic/quic_fec_group.h" #include "net/quic/quic_framer.h" #include "net/quic/quic_protocol.h" @@ -50,9 +48,6 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { // Called when an unrecoverable error is encountered. virtual void OnUnrecoverableError(QuicErrorCode error, ConnectionCloseSource source) = 0; - - // Called when current FEC group is reset (closed). - virtual void OnResetFecGroup() = 0; }; // Interface which gets callbacks from the QuicPacketCreator at interesting @@ -75,27 +70,6 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { ~QuicPacketCreator(); - // Checks if it's time to send an FEC packet. |force_close| forces this to - // return true if an FEC group is open. - bool ShouldSendFec(bool force_close) const; - - // If ShouldSendFec returns true, serializes currently constructed FEC packet - // and calls the delegate on the packet. Resets current FEC group if FEC - // protection policy is FEC_ALARM_TRIGGER but |is_fec_timeout| is false. - // Also tries to turn off FEC protection if should_fec_protect_next_packet is - // false. - void MaybeSendFecPacketAndCloseGroup(bool force_send_fec, - bool is_fec_timeout); - - // Returns true if an FEC packet is under construction. - bool IsFecGroupOpen() const; - - // Called after sending |packet_number| to determine whether an FEC alarm - // should be set for sending out an FEC packet. Returns a positive and finite - // timeout if an FEC alarm should be set, and infinite if no alarm should be - // set. - QuicTime::Delta GetFecTimeout(QuicPacketNumber packet_number); - // Makes the framer not serialize the protocol version in sent packets. void StopSendingVersion(); @@ -112,23 +86,20 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { bool include_version, bool include_path_id, QuicPacketNumberLength packet_number_length, - QuicStreamOffset offset, - InFecGroup is_in_fec_group); + QuicStreamOffset offset); // Returns false and flushes all pending frames if current open packet is // full. // If current packet is not full, converts a raw payload into a stream frame // that fits into the open packet and adds it to the packet. // The payload begins at |iov_offset| into the |iov|. - // Also tries to start FEC protection depends on |fec_protection|. bool ConsumeData(QuicStreamId id, QuicIOVector iov, size_t iov_offset, QuicStreamOffset offset, bool fin, bool needs_padding, - QuicFrame* frame, - FecProtection fec_protection); + QuicFrame* frame); // Returns true if current open packet can accommodate more stream frames of // stream |id| at |offset|, false otherwise. @@ -136,8 +107,6 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { // Re-serializes frames with the original packet's packet number length. // Used for retransmitting packets to ensure they aren't too long. - // Caller must ensure that any open FEC group is closed before calling this - // method. void ReserializeAllFrames(const PendingRetransmission& retransmission, char* buffer, size_t buffer_len); @@ -161,8 +130,7 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { // Returns the number of bytes that the packet will expand by if a new frame // is added to the packet. If the last frame was a stream frame, it will // expand slightly when a new frame is added, and this method returns the - // amount of expected expansion. If the packet is in an FEC group, no - // expansion happens and this method always returns zero. + // amount of expected expansion. size_t ExpansionOnNewFrame() const; // Returns the number of bytes in the current packet, including the header, @@ -194,12 +162,6 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { // Returns a dummy packet that is valid but contains no useful information. static SerializedPacket NoPacket(); - // Called when the congestion window has changed. - void OnCongestionWindowChange(QuicPacketCount max_packets_in_flight); - - // Called when the RTT may have changed. - void OnRttChange(QuicTime::Delta rtt); - // Sets the encryption level that will be applied to new packets. void set_encryption_level(EncryptionLevel level) { packet_.encryption_level = level; @@ -236,35 +198,12 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { // Sets the path on which subsequent packets will be created. It is the // caller's responsibility to guarantee no packet is under construction before - // calling this function. If |path_id| is different from current_path_, the - // FEC packet (if exists) will be sent and next_packet_number_length_ is - // recalculated. + // calling this function. If |path_id| is different from current_path_, + // next_packet_number_length_ is recalculated. void SetCurrentPath(QuicPathId path_id, QuicPacketNumber least_packet_awaited_by_peer, QuicPacketCount max_packets_in_flight); - // Returns current max number of packets covered by an FEC group. - size_t max_packets_per_fec_group() const { - return max_packets_per_fec_group_; - } - - // Sets creator's max number of packets covered by an FEC group. - // Note: While there are no constraints on |max_packets_per_fec_group|, - // this setter enforces a min value of kLowestMaxPacketsPerFecGroup. - // To turn off FEC protection, use StopFecProtectingPackets(). - void set_max_packets_per_fec_group(size_t max_packets_per_fec_group); - - FecSendPolicy fec_send_policy() { return fec_send_policy_; } - - void set_fec_send_policy(FecSendPolicy fec_send_policy) { - fec_send_policy_ = fec_send_policy; - } - - void set_rtt_multiplier_for_fec_timeout( - float rtt_multiplier_for_fec_timeout) { - rtt_multiplier_for_fec_timeout_ = rtt_multiplier_for_fec_timeout; - } - void set_debug_delegate(DebugDelegate* debug_delegate) { debug_delegate_ = debug_delegate; } @@ -295,18 +234,10 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { size_t length, char* buffer); - // Updates lengths and also starts an FEC group if FEC protection is on and - // there is not already an FEC group open. - InFecGroup MaybeUpdateLengthsAndStartFec(); + // Updates packet number length on packet boundary. + void MaybeUpdatePacketNumberLength(); - // Called when a data packet is constructed that is part of an FEC group. - // |payload| is the non-encrypted FEC protected payload of the packet. - void OnBuiltFecProtectedPayload(const QuicPacketHeader& header, - base::StringPiece payload); - - void FillPacketHeader(QuicFecGroupNumber fec_group, - bool fec_flag, - QuicPacketHeader* header); + void FillPacketHeader(QuicPacketHeader* header); // Adds a |frame| if there is space and returns false and flushes all pending // frames if there isn't room. If |save_retransmittable_frames| is true, @@ -326,36 +257,12 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { void SerializePacket(char* encrypted_buffer, size_t buffer_len); // Called after a new SerialiedPacket is created to call the delegate's - // OnSerializedPacket, reset state, and potentially flush FEC groups. + // OnSerializedPacket and reset state. void OnSerializedPacket(); // Clears all fields of packet_ that should be cleared between serializations. void ClearPacket(); - // Turn on FEC protection for subsequent packets. If no FEC group is currently - // open, this method flushes current open packet and then turns FEC on. - void MaybeStartFecProtection(); - - // Turn on FEC protection for subsequently created packets. FEC should be - // enabled first (max_packets_per_fec_group should be non-zero) for FEC - // protection to start. - void StartFecProtectingPackets(); - - // Turn off FEC protection for subsequently created packets. If the creator - // has any open FEC group, call will fail. It is the caller's responsibility - // to flush out FEC packets in generation, and to verify with ShouldSendFec() - // that there is no open FEC group. - void StopFecProtectingPackets(); - - // Resets (closes) the FEC group. This method should only be called on a - // packet boundary. - void ResetFecGroup(); - - // Packetize FEC data. Sets the entropy hash of the serialized packet to a - // random bool. - // Fails if |buffer_len| isn't long enough for the encrypted packet. - void SerializeFec(char* buffer, size_t buffer_len); - // Does not own these delegates or the framer. DelegateInterface* delegate_; DebugDelegate* debug_delegate_; @@ -370,8 +277,8 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { bool send_path_id_in_packet_; // Staging variable to hold next packet number length. When sequence // number length is to be changed, this variable holds the new length until - // a packet or FEC group boundary, when the creator's packet_number_length_ - // can be changed to this new value. + // a packet boundary, when the creator's packet_number_length_ can be changed + // to this new value. QuicPacketNumberLength next_packet_number_length_; // Maximum length including headers and encryption (UDP payload length.) QuicByteCount max_packet_length_; @@ -394,28 +301,6 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { // Map mapping path_id to last sent packet number on the path. std::unordered_map<QuicPathId, QuicPacketNumber> multipath_packet_number_; - // FEC related fields. - // True when creator is requested to turn on FEC protection. False otherwise. - // There is a time difference between should_fec_protect_next_packet_ is - // true/false and FEC is actually turned on/off (e.g., The creator may have an - // open FEC group even if this variable is false). - bool should_fec_protect_next_packet_; - // If true, any created packets will be FEC protected. - // TODO(fayang): Combine should_fec_protect_next_packet and fec_protect_ to - // one variable. - bool fec_protect_; - scoped_ptr<QuicFecGroup> fec_group_; - // 0 indicates FEC is disabled. - size_t max_packets_per_fec_group_; - // FEC policy that specifies when to send FEC packet. - FecSendPolicy fec_send_policy_; - // Timeout used for FEC alarm. Can be set to zero initially or if the SRTT has - // not yet been set. - QuicTime::Delta fec_timeout_; - // The multiplication factor for FEC timeout based on RTT. - // TODO(rtenneti): Delete this code after the 0.25 RTT FEC experiment. - float rtt_multiplier_for_fec_timeout_; - DISALLOW_COPY_AND_ASSIGN(QuicPacketCreator); }; diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc index b5dddcf..98e1ef2 100644 --- a/net/quic/quic_packet_creator_test.cc +++ b/net/quic/quic_packet_creator_test.cc @@ -82,7 +82,6 @@ class MockDelegate : public QuicPacketCreator::DelegateInterface { ~MockDelegate() override {} MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet)); - MOCK_METHOD0(OnResetFecGroup, void()); MOCK_METHOD2(OnUnrecoverableError, void(QuicErrorCode, ConnectionCloseSource source)); @@ -142,7 +141,6 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> { server_framer_.set_visitor(&framer_visitor_); // TODO(ianswett): Fix this test so it uses a non-null encrypter. FLAGS_quic_never_write_unencrypted_data = false; - FLAGS_quic_no_unencrypted_fec = false; } ~QuicPacketCreatorTest() override { @@ -180,11 +178,10 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> { // Returns the number of bytes consumed by the header of packet, including // the version. - size_t GetPacketHeaderOverhead(InFecGroup is_in_fec_group) { + size_t GetPacketHeaderOverhead() { return GetPacketHeaderSize( creator_.connection_id_length(), kIncludeVersion, !kIncludePathId, - QuicPacketCreatorPeer::NextPacketNumberLength(&creator_), - is_in_fec_group); + QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); } // Returns the number of bytes of overhead that will be added to a packet @@ -196,9 +193,9 @@ 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(InFecGroup is_in_fec_group) { + size_t GetStreamFrameOverhead() { return QuicFramer::GetMinStreamFrameSize(kClientDataStreamId1, kOffset, - true, is_in_fec_group); + true); } QuicIOVector MakeIOVector(StringPiece s) { @@ -274,62 +271,6 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) { } } -TEST_P(QuicPacketCreatorTest, SerializeWithFEC) { - // Send FEC packet every 6 packets. - creator_.set_max_packets_per_fec_group(6); - // Should return false since we do not have enough packets in the FEC group to - // trigger an FEC packet. - ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); - // Turn on FEC protection. - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - // Serialize the packet. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - 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_, OnFecProtectedPayload(_)); - EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); - EXPECT_CALL(framer_visitor_, OnPacketComplete()); - } - ProcessPacket(serialized_packet_); - DeleteSerializedPacket(); - - // Should return false since we do not have enough packets in the FEC group to - // trigger an FEC packet. - ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); - // Should return true since there are packets in the FEC group. - ASSERT_TRUE(creator_.ShouldSendFec(/*force_close=*/true)); - - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, - /*is_fec_timeout=*/false); - ASSERT_EQ(2u, serialized_packet_.packet_number); - { - 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_, OnFecData(_)); - EXPECT_CALL(framer_visitor_, OnPacketComplete()); - } - ProcessPacket(serialized_packet_); - DeleteSerializedPacket(); -} - TEST_P(QuicPacketCreatorTest, SerializeChangingSequenceNumberLength) { frames_.push_back(QuicFrame(new QuicAckFrame(MakeAckFrame(0u)))); creator_.AddSavedFrame(frames_[0]); @@ -460,109 +401,6 @@ TEST_P(QuicPacketCreatorTest, ChangeSequenceNumberLengthMidPacket) { delete ack_frame.ack_frame; } -TEST_P(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) { - // Test goal is to test the following sequence (P1 => generate Packet 1): - // P1 <change seq num length> P2 FEC, - // and we expect that packet number length should not change until the end - // of the open FEC group. - - // Send FEC packet every 6 packets. - creator_.set_max_packets_per_fec_group(6); - // Should return false since we do not have enough packets in the FEC group to - // trigger an FEC packet. - ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); - - // Generate Packet 1. - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - // Change the packet number length mid-FEC group and it should not change. - QuicPacketCreatorPeer::SetNextPacketNumberLength(&creator_, - PACKET_4BYTE_PACKET_NUMBER); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillRepeatedly( - Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - creator_.Flush(); - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, - serialized_packet_.packet_number_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_, OnFecProtectedPayload(_)); - EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); - EXPECT_CALL(framer_visitor_, OnPacketComplete()); - } - ProcessPacket(serialized_packet_); - DeleteSerializedPacket(); - - // Generate Packet 2. - ASSERT_TRUE(creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - creator_.Flush(); - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, - serialized_packet_.packet_number_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_, OnFecProtectedPayload(_)); - EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); - EXPECT_CALL(framer_visitor_, OnPacketComplete()); - } - ProcessPacket(serialized_packet_); - DeleteSerializedPacket(); - - // Should return false since we do not have enough packets in the FEC group to - // trigger an FEC packet. - ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); - // Should return true since there are packets in the FEC group. - ASSERT_TRUE(creator_.ShouldSendFec(/*force_close=*/true)); - - // Force generation of FEC packet. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - // Turn off FEC protection. - creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, - /*is_fec_timeout=*/false); - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, - serialized_packet_.packet_number_length); - ASSERT_EQ(3u, serialized_packet_.packet_number); - - { - 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_, OnFecData(_)); - EXPECT_CALL(framer_visitor_, OnPacketComplete()); - } - ProcessPacket(serialized_packet_); - DeleteSerializedPacket(); - - // Ensure the next FEC group starts using the new packet number length. - ASSERT_TRUE(creator_.ConsumeData(3u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - creator_.Flush(); - EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, - serialized_packet_.packet_number_length); - DeleteSerializedPacket(); -} - TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) { // If the original packet number length, the current packet number // length, and the configured send packet number length are different, the @@ -659,9 +497,8 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithPadding) { } TEST_P(QuicPacketCreatorTest, ReserializeFramesWithFullPacketAndPadding) { - const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) + - GetEncryptionOverhead() + - GetStreamFrameOverhead(NOT_IN_FEC_GROUP); + const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead() + + GetStreamFrameOverhead(); size_t capacity = kDefaultMaxPacketSize - overhead; for (int delta = -5; delta <= 0; ++delta) { string data(capacity + delta, 'A'); @@ -722,75 +559,11 @@ TEST_P(QuicPacketCreatorTest, SerializeConnectionClose) { ProcessPacket(serialized); } -TEST_P(QuicPacketCreatorTest, SwitchFecOnOffWithGroupInProgress) { - // Send FEC packet every 6 packets. - creator_.set_max_packets_per_fec_group(6); - // Turn on FEC protection. - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - creator_.Flush(); - // We do not have enough packets in the FEC group to trigger an FEC packet. - EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); - // Should return true since there are packets in the FEC group. - EXPECT_TRUE(creator_.ShouldSendFec(/*force_close=*/true)); - - // Switching FEC off should not change creator state, since there is an - // FEC packet under construction. - EXPECT_DFATAL(QuicPacketCreatorPeer::StopFecProtectingPackets(&creator_), - "Cannot stop FEC protection with open FEC group."); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - // Confirm that FEC packet is still under construction. - EXPECT_TRUE(creator_.ShouldSendFec(/*force_close=*/true)); - - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - // Turn off FEC protection. - creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, - /*is_fec_timeout=*/false); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); -} - -TEST_P(QuicPacketCreatorTest, SwitchFecOnWithStreamFrameQueued) { - // Add a stream frame to the creator. - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MAY_FEC_PROTECT)); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->frame_length; - EXPECT_EQ(4u, consumed); - EXPECT_TRUE(creator_.HasPendingFrames()); - - // Enable FEC protection, and send FEC packet every 6 packets. - creator_.set_max_packets_per_fec_group(6); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(&creator_)); - EXPECT_DFATAL(QuicPacketCreatorPeer::StartFecProtectingPackets(&creator_), - "Cannot start FEC protection with pending frames."); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - - // Start FEC protection after current open packet is flushed. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - ASSERT_TRUE(creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - ASSERT_TRUE(frame.stream_frame); - consumed = frame.stream_frame->frame_length; - EXPECT_EQ(4u, consumed); - EXPECT_TRUE(creator_.HasPendingFrames()); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); -} - TEST_P(QuicPacketCreatorTest, ConsumeData) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MAY_FEC_PROTECT)); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); @@ -801,8 +574,8 @@ TEST_P(QuicPacketCreatorTest, ConsumeData) { TEST_P(QuicPacketCreatorTest, ConsumeDataFin) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 10u, true, false, &frame, - MAY_FEC_PROTECT)); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 10u, true, false, &frame)); ASSERT_TRUE(frame.stream_frame); size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); @@ -813,8 +586,7 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataFin) { TEST_P(QuicPacketCreatorTest, ConsumeDataFinOnly) { QuicFrame frame; QuicIOVector io_vector(nullptr, 0, 0); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame, - MAY_FEC_PROTECT)); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame)); ASSERT_TRUE(frame.stream_frame); size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(0u, consumed); @@ -822,28 +594,11 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataFinOnly) { EXPECT_TRUE(creator_.HasPendingFrames()); } -TEST_P(QuicPacketCreatorTest, ConsumeDataWithFecProtect) { - creator_.set_max_packets_per_fec_group(6); - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector("test")); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->frame_length; - EXPECT_EQ(4u, consumed); - CheckStreamFrame(frame, 1u, "test", 0u, false); - EXPECT_TRUE(creator_.HasPendingFrames()); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); -} - TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) { - const size_t overhead = - GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) + GetEncryptionOverhead(); + const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead(); for (size_t i = overhead; i < overhead + 100; ++i) { creator_.SetMaxPacketLength(i); - const bool should_have_room = - i > overhead + GetStreamFrameOverhead(NOT_IN_FEC_GROUP); + const bool should_have_room = i > overhead + GetStreamFrameOverhead(); ASSERT_EQ(should_have_room, creator_.HasRoomForStreamFrame(kClientDataStreamId1, kOffset)); if (should_have_room) { @@ -853,8 +608,7 @@ TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) { .WillRepeatedly( Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u, - kOffset, false, false, &frame, - MAY_FEC_PROTECT)); + kOffset, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); size_t bytes_consumed = frame.stream_frame->frame_length; EXPECT_LT(0u, bytes_consumed); @@ -865,9 +619,8 @@ TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) { TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) { // Compute the total overhead for a single frame in packet. - const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) + - GetEncryptionOverhead() + - GetStreamFrameOverhead(NOT_IN_FEC_GROUP); + const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead() + + GetStreamFrameOverhead(); size_t capacity = kDefaultMaxPacketSize - overhead; // Now, test various sizes around this size. for (int delta = -5; delta <= 5; ++delta) { @@ -876,8 +629,7 @@ TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector(data)); ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u, - kOffset, false, false, &frame, - MAY_FEC_PROTECT)); + kOffset, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); // BytesFree() returns bytes available for the next frame, which will @@ -893,63 +645,10 @@ TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) { } } -TEST_P(QuicPacketCreatorTest, StreamFrameConsumptionWithFec) { - // Send FEC packet every 6 packets. - creator_.set_max_packets_per_fec_group(6); - // Turn on FEC protection. - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - - // Serialize the packet. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - creator_.Flush(); - // Compute the total overhead for a single frame in packet. - const size_t overhead = GetPacketHeaderOverhead(IN_FEC_GROUP) + - GetEncryptionOverhead() + - GetStreamFrameOverhead(IN_FEC_GROUP); - size_t capacity = kDefaultMaxPacketSize - overhead; - // Now, test various sizes around this size. - for (int delta = -5; delta <= 5; ++delta) { - string data(capacity + delta, 'A'); - size_t bytes_free = delta > 0 ? 0 : 0 - delta; - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector(data)); - ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u, - kOffset, false, false, &frame, - MUST_FEC_PROTECT)); - ASSERT_TRUE(frame.stream_frame); - // BytesFree() returns bytes available for the next frame. Since stream - // frame does not grow for FEC protected packets, this should be the same - // as bytes_free (bound by 0). - EXPECT_EQ(0u, creator_.ExpansionOnNewFrame()); - size_t expected_bytes_free = bytes_free > 0 ? bytes_free : 0; - EXPECT_EQ(expected_bytes_free, creator_.BytesFree()) << "delta: " << delta; - { - InSequence s; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - // Every 6th packet will generate an extra FEC packet. - if (delta == -1 || delta == 5) { - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce( - Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - } - } - creator_.Flush(); - ASSERT_TRUE(serialized_packet_.encrypted_buffer); - DeleteSerializedPacket(); - } -} - TEST_P(QuicPacketCreatorTest, CryptoStreamFramePacketPadding) { // Compute the total overhead for a single frame in packet. - const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) + - GetEncryptionOverhead() + - GetStreamFrameOverhead(NOT_IN_FEC_GROUP); + const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead() + + GetStreamFrameOverhead(); ASSERT_GT(kMaxPacketSize, overhead); size_t capacity = kDefaultMaxPacketSize - overhead; // Now, test various sizes around this size. @@ -963,7 +662,7 @@ TEST_P(QuicPacketCreatorTest, CryptoStreamFramePacketPadding) { .WillRepeatedly( Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, kOffset, - false, true, &frame, MAY_FEC_PROTECT)); + false, true, &frame)); ASSERT_TRUE(frame.stream_frame); size_t bytes_consumed = frame.stream_frame->frame_length; EXPECT_LT(0u, bytes_consumed); @@ -984,9 +683,8 @@ TEST_P(QuicPacketCreatorTest, CryptoStreamFramePacketPadding) { TEST_P(QuicPacketCreatorTest, NonCryptoStreamFramePacketNonPadding) { // Compute the total overhead for a single frame in packet. - const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) + - GetEncryptionOverhead() + - GetStreamFrameOverhead(NOT_IN_FEC_GROUP); + const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead() + + GetStreamFrameOverhead(); ASSERT_GT(kDefaultMaxPacketSize, overhead); size_t capacity = kDefaultMaxPacketSize - overhead; // Now, test various sizes around this size. @@ -999,8 +697,7 @@ TEST_P(QuicPacketCreatorTest, NonCryptoStreamFramePacketNonPadding) { EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u, - kOffset, false, false, &frame, - MAY_FEC_PROTECT)); + kOffset, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); size_t bytes_consumed = frame.stream_frame->frame_length; EXPECT_LT(0u, bytes_consumed); @@ -1037,29 +734,23 @@ TEST_P(QuicPacketCreatorTest, UpdatePacketSequenceNumberLengthLeastAwaiting) { EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); - size_t max_packets_per_fec_group = 10; - creator_.set_max_packets_per_fec_group(max_packets_per_fec_group); - QuicPacketCreatorPeer::SetPacketNumber(&creator_, - 64 - max_packets_per_fec_group); + QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64); creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); - QuicPacketCreatorPeer::SetPacketNumber(&creator_, - 64 * 256 - max_packets_per_fec_group); + QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64 * 256); creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); - QuicPacketCreatorPeer::SetPacketNumber( - &creator_, 64 * 256 * 256 - max_packets_per_fec_group); + QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64 * 256 * 256); creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); - QuicPacketCreatorPeer::SetPacketNumber( - &creator_, - UINT64_C(64) * 256 * 256 * 256 * 256 - max_packets_per_fec_group); + QuicPacketCreatorPeer::SetPacketNumber(&creator_, + UINT64_C(64) * 256 * 256 * 256 * 256); creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_6BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); @@ -1125,14 +816,13 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataLargerThanOneStreamFrame) { QuicPacketCreatorPeer::SendVersionInPacket(&creator_), QuicPacketCreatorPeer::SendPathIdInPacket(&creator_), creator_.connection_id_length(), PACKET_1BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP, &payload_length)); + &payload_length)); QuicFrame frame; const string too_long_payload(payload_length * 2, 'a'); QuicIOVector io_vector(MakeIOVector(too_long_payload)); EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame, - MAY_FEC_PROTECT)); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame)); ASSERT_TRUE(frame.stream_frame); size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(payload_length, consumed); @@ -1154,7 +844,7 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) { creator_.connection_id_length(), QuicPacketCreatorPeer::SendVersionInPacket(&creator_), QuicPacketCreatorPeer::SendPathIdInPacket(&creator_), - PACKET_1BYTE_PACKET_NUMBER, NOT_IN_FEC_GROUP), + PACKET_1BYTE_PACKET_NUMBER), creator_.BytesFree()); // Add a variety of frame types and then a padding frame. @@ -1164,8 +854,8 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MAY_FEC_PROTECT)); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); @@ -1195,8 +885,7 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) { GetPacketHeaderSize( creator_.connection_id_length(), QuicPacketCreatorPeer::SendVersionInPacket(&creator_), - /*include_path_id=*/false, PACKET_1BYTE_PACKET_NUMBER, - NOT_IN_FEC_GROUP), + /*include_path_id=*/false, PACKET_1BYTE_PACKET_NUMBER), creator_.BytesFree()); } @@ -1210,7 +899,7 @@ TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithLargePacketSize) { // the number of nack ranges that can be fit in an ack frame. QuicAckFrame ack_frame = MakeAckFrameWithNackRanges(2000u, 0u); size_t frame_len = client_framer_.GetSerializedFrameLength( - QuicFrame(&ack_frame), creator_.BytesFree(), true, true, NOT_IN_FEC_GROUP, + QuicFrame(&ack_frame), creator_.BytesFree(), true, true, PACKET_1BYTE_PACKET_NUMBER); EXPECT_GT(creator_.BytesFree(), frame_len); EXPECT_GT(creator_.max_packet_length(), creator_.PacketSize()); @@ -1224,8 +913,8 @@ TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithLargePacketSize) { // Make sure that an additional stream frame can be added to the packet. QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame, - MAY_FEC_PROTECT)); + ASSERT_TRUE( + creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); @@ -1258,7 +947,7 @@ TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithSmallPacketSize) { // the packet size. QuicAckFrame ack_frame = MakeAckFrameWithNackRanges(2000u, 0u); size_t frame_len = client_framer_.GetSerializedFrameLength( - QuicFrame(&ack_frame), creator_.BytesFree(), true, true, NOT_IN_FEC_GROUP, + QuicFrame(&ack_frame), creator_.BytesFree(), true, true, PACKET_1BYTE_PACKET_NUMBER); EXPECT_EQ(creator_.BytesFree(), frame_len); @@ -1305,103 +994,6 @@ TEST_P(QuicPacketCreatorTest, EntropyFlag) { delete frames_[0].stream_frame; } -TEST_P(QuicPacketCreatorTest, ResetFecGroup) { - // Send FEC packet every 6 packets. - creator_.set_max_packets_per_fec_group(6); - // Add a stream frame and turn on FEC protection. - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - // Serialize the packet. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - creator_.Flush(); - - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - EXPECT_TRUE(creator_.IsFecGroupOpen()); - // We do not have enough packets in the FEC group to trigger an FEC packet. - EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); - // Should return true since there are packets in the FEC group. - EXPECT_TRUE(creator_.ShouldSendFec(/*force_close=*/true)); - - // FEC group will be reset if FEC police is alarm trigger but FEC alarm does - // not fire. - EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); - creator_.set_fec_send_policy(FEC_ALARM_TRIGGER); - creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, - /*is_fec_timeout=*/false); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - EXPECT_FALSE(creator_.IsFecGroupOpen()); - // We do not have enough packets in the FEC group to trigger an FEC packet. - EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); - // Confirm that there is no FEC packet under construction. - EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/true)); - - char buffer[kMaxPacketSize]; - EXPECT_DFATAL( - QuicPacketCreatorPeer::SerializeFec(&creator_, buffer, kMaxPacketSize), - "SerializeFEC called but no group or zero packets in group."); - - // Create and send a new FEC protected packet. - ASSERT_TRUE(creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - creator_.Flush(); - - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - EXPECT_TRUE(creator_.IsFecGroupOpen()); - // We do not have enough packets in the FEC group to trigger an FEC packet. - EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); - // Should return true since there are packets in the FEC group. - EXPECT_TRUE(creator_.ShouldSendFec(/*force_close=*/true)); - - // Should return false since we do not have enough packets in the FEC group to - // trigger an FEC packet. - ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); - // Should return true since there are packets in the FEC group. - ASSERT_TRUE(creator_.ShouldSendFec(/*force_close=*/true)); - - // Change FEC policy, send FEC packet and close FEC group. - creator_.set_fec_send_policy(FEC_ANY_TRIGGER); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, - /*is_fec_timeout=*/false); - ASSERT_EQ(3u, serialized_packet_.packet_number); - DeleteSerializedPacket(); -} - -TEST_P(QuicPacketCreatorTest, ResetFecGroupWithQueuedFrames) { - // Send FEC packet every 6 packets. - creator_.set_max_packets_per_fec_group(6); - // Add a stream frame to the creator and turn on FEC protection. - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->frame_length; - EXPECT_EQ(4u, consumed); - EXPECT_TRUE(creator_.HasPendingFrames()); - EXPECT_DFATAL(QuicPacketCreatorPeer::ResetFecGroup(&creator_), - "Cannot reset FEC group with pending frames."); - - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - creator_.Flush(); - EXPECT_FALSE(creator_.HasPendingFrames()); - - // FEC group will be reset if FEC police is alarm trigger but FEC alarm does - // not fire. - EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); - creator_.set_fec_send_policy(FEC_ALARM_TRIGGER); - creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, - /*is_fec_timeout=*/false); - EXPECT_FALSE(creator_.IsFecGroupOpen()); -} - TEST_P(QuicPacketCreatorTest, SetCurrentPath) { // Current path is the default path. EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(&creator_)); @@ -1411,8 +1003,8 @@ TEST_P(QuicPacketCreatorTest, SetCurrentPath) { // Add a stream frame to the creator. QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MAY_FEC_PROTECT)); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); @@ -1443,8 +1035,8 @@ TEST_P(QuicPacketCreatorTest, SetCurrentPath) { EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); // Add a stream frame to the creator. - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MAY_FEC_PROTECT)); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); @@ -1459,95 +1051,24 @@ TEST_P(QuicPacketCreatorTest, SetCurrentPath) { QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); } -TEST_P(QuicPacketCreatorTest, SetCurrentPathWithFec) { - // Send FEC packet every 6 packets. - creator_.set_max_packets_per_fec_group(6); - // Current path is the default path. - EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(&creator_)); - EXPECT_EQ(0u, creator_.packet_number()); - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, - QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - // Add a stream frame to the creator. - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->frame_length; - EXPECT_EQ(4u, consumed); - EXPECT_TRUE(creator_.HasPendingFrames()); - EXPECT_EQ(0u, creator_.packet_number()); - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, - QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - - // Change current path. - QuicPathId kPathId1 = 1; - EXPECT_DFATAL(creator_.SetCurrentPath(kPathId1, 1, 0), - "Unable to change paths when a packet is under construction"); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .Times(2) - .WillRepeatedly( - Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - creator_.Flush(); - EXPECT_FALSE(creator_.HasPendingFrames()); - creator_.SetCurrentPath(kPathId1, 1, 0); - EXPECT_EQ(kPathId1, QuicPacketCreatorPeer::GetCurrentPath(&creator_)); - EXPECT_FALSE(creator_.HasPendingFrames()); - EXPECT_EQ(0u, creator_.packet_number()); - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, - QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - - // Change current path back. - creator_.SetCurrentPath(kDefaultPathId, 3, 2); - EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(&creator_)); - // FEC packet consumes a packet number. - EXPECT_EQ(2u, creator_.packet_number()); - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, - QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); - // Add a stream frame to the creator. - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); - ASSERT_TRUE(frame.stream_frame); - consumed = frame.stream_frame->frame_length; - EXPECT_EQ(4u, consumed); - EXPECT_TRUE(creator_.HasPendingFrames()); - - // Does not change current path. - creator_.SetCurrentPath(kDefaultPathId, 3, 0); - EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(&creator_)); - EXPECT_TRUE(creator_.HasPendingFrames()); - // FEC packet consumes a packet number. - EXPECT_EQ(2u, creator_.packet_number()); - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, - QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); -} - TEST_P(QuicPacketCreatorTest, - SetCurrentPathWithFecAndUpdatePacketSequenceNumberLength) { - // Send FEC packet every 10 packets. - size_t max_packets_per_fec_group = 10; - creator_.set_max_packets_per_fec_group(max_packets_per_fec_group); + SetCurrentPathAndUpdatePacketSequenceNumberLength) { // Current path is the default path. EXPECT_EQ(kDefaultPathId, QuicPacketCreatorPeer::GetCurrentPath(&creator_)); EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); - QuicPacketCreatorPeer::SetPacketNumber( - &creator_, 64 * 256 - max_packets_per_fec_group - 2); + QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64 * 256 - 2); // Add a stream frame to the creator and send the packet. QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MUST_FEC_PROTECT)); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .Times(2) + .Times(1) .WillRepeatedly( Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); creator_.Flush(); - EXPECT_EQ(64 * 256 - max_packets_per_fec_group - 1, creator_.packet_number()); + EXPECT_EQ(UINT64_C(64 * 256 - 1), creator_.packet_number()); creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); @@ -1561,8 +1082,7 @@ TEST_P(QuicPacketCreatorTest, // Change current path back. creator_.SetCurrentPath(kDefaultPathId, 2, 10000 / kDefaultMaxPacketSize); - // FEC packet consumes a packet number. - EXPECT_EQ(64 * 256 - max_packets_per_fec_group, creator_.packet_number()); + EXPECT_EQ(UINT64_C(64 * 256 - 1), creator_.packet_number()); EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); } @@ -1574,8 +1094,8 @@ TEST_P(QuicPacketCreatorTest, SerializePacketOnDifferentPath) { // Add a stream frame to the creator and flush the packet. QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MAY_FEC_PROTECT)); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); @@ -1601,8 +1121,8 @@ TEST_P(QuicPacketCreatorTest, SerializePacketOnDifferentPath) { QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); // Add a stream frame to the creator and flush the packet. - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, - MAY_FEC_PROTECT)); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); @@ -1622,56 +1142,6 @@ TEST_P(QuicPacketCreatorTest, AddUnencryptedStreamDataClosesConnection) { "Cannot send stream data without encryption."); } -TEST_P(QuicPacketCreatorTest, DontSendUnencryptedFec) { - ValueRestore<bool> old_flag(&FLAGS_quic_no_unencrypted_fec, true); - // Send FEC packet every 6 packets. - creator_.set_max_packets_per_fec_group(6); - // Send stream data encrypted with FEC protection. - creator_.set_encryption_level(ENCRYPTION_INITIAL); - // Turn on FEC protection. - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(kHeadersStreamId, io_vector, 0u, 0u, false, - false, &frame, MUST_FEC_PROTECT)); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - // Serialize the packet. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - creator_.Flush(); - - // The creator will clear the FEC group rather than try to send without - // encryption. - creator_.set_encryption_level(ENCRYPTION_NONE); - EXPECT_CALL(delegate_, OnResetFecGroup()); - creator_.MaybeSendFecPacketAndCloseGroup(true, false); -} - -TEST_P(QuicPacketCreatorTest, SerializeUnencryptedFecClosesConnection) { - ValueRestore<bool> old_flag(&FLAGS_quic_no_unencrypted_fec, true); - // Send FEC packet every 6 packets. - creator_.set_max_packets_per_fec_group(6); - // Send stream data encrypted with FEC protection. - creator_.set_encryption_level(ENCRYPTION_INITIAL); - // Turn on FEC protection. - QuicFrame frame; - QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE(creator_.ConsumeData(kHeadersStreamId, io_vector, 0u, 0u, false, - false, &frame, MUST_FEC_PROTECT)); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - // Serialize the packet. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - creator_.Flush(); - - // Try to send an FEC packet unencrypted. - creator_.set_encryption_level(ENCRYPTION_NONE); - EXPECT_CALL(delegate_, OnUnrecoverableError(QUIC_UNENCRYPTED_FEC_DATA, _)); - char seralized_fec_buffer[kMaxPacketSize]; - EXPECT_DFATAL(QuicPacketCreatorPeer::SerializeFec( - &creator_, seralized_fec_buffer, kMaxPacketSize), - "SerializeFEC must be called with encryption."); -} - } // namespace } // namespace test } // namespace net diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc index 75e1c59..908872e 100644 --- a/net/quic/quic_packet_generator.cc +++ b/net/quic/quic_packet_generator.cc @@ -6,7 +6,6 @@ #include "base/logging.h" #include "net/quic/quic_bug_tracker.h" -#include "net/quic/quic_fec_group.h" #include "net/quic/quic_flags.h" #include "net/quic/quic_utils.h" @@ -27,22 +26,12 @@ QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id, delegate), batch_mode_(false), should_send_ack_(false), - should_send_stop_waiting_(false), - max_packet_length_(kDefaultMaxPacketSize) {} + should_send_stop_waiting_(false) {} QuicPacketGenerator::~QuicPacketGenerator() { QuicUtils::DeleteFrames(&queued_control_frames_); } -void QuicPacketGenerator::OnCongestionWindowChange( - QuicPacketCount max_packets_in_flight) { - packet_creator_.OnCongestionWindowChange(max_packets_in_flight); -} - -void QuicPacketGenerator::OnRttChange(QuicTime::Delta rtt) { - packet_creator_.OnRttChange(rtt); -} - void QuicPacketGenerator::SetShouldSendAck(bool also_send_stop_waiting) { if (packet_creator_.has_ack()) { // Ack already queued, nothing to do. @@ -56,12 +45,12 @@ void QuicPacketGenerator::SetShouldSendAck(bool also_send_stop_waiting) { should_send_ack_ = true; should_send_stop_waiting_ = also_send_stop_waiting; - SendQueuedFrames(/*flush=*/false, /*is_fec_timeout=*/false); + SendQueuedFrames(/*flush=*/false); } void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) { queued_control_frames_.push_back(frame); - SendQueuedFrames(/*flush=*/false, /*is_fec_timeout=*/false); + SendQueuedFrames(/*flush=*/false); } QuicConsumedData QuicPacketGenerator::ConsumeData( @@ -69,14 +58,13 @@ QuicConsumedData QuicPacketGenerator::ConsumeData( QuicIOVector iov, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface* listener) { bool has_handshake = id == kCryptoStreamId; // To make reasoning about crypto frames easier, we don't combine them with // other retransmittable frames in a single packet. const bool flush = has_handshake && packet_creator_.HasPendingRetransmittableFrames(); - SendQueuedFrames(flush, /*is_fec_timeout=*/false); + SendQueuedFrames(flush); size_t total_bytes_consumed = 0; bool fin_consumed = false; @@ -95,7 +83,7 @@ QuicConsumedData QuicPacketGenerator::ConsumeData( QuicFrame frame; if (!packet_creator_.ConsumeData(id, iov, total_bytes_consumed, offset + total_bytes_consumed, fin, - has_handshake, &frame, fec_protection)) { + has_handshake, &frame)) { // The creator is always flushed if there's not enough room for a new // stream frame before ConsumeData, so ConsumeData should always succeed. QUIC_BUG << "Failed to ConsumeData, stream:" << id; @@ -113,9 +101,6 @@ QuicConsumedData QuicPacketGenerator::ConsumeData( (bytes_consumed > 0 && packet_creator_.HasPendingFrames())); if (!InBatchMode()) { - // TODO(rtenneti): remove MaybeSendFecPacketAndCloseGroup() from inside - // SerializeAndSendPacket() and make it an explicit call here (and - // elsewhere where we call SerializeAndSendPacket?). packet_creator_.Flush(); } @@ -131,14 +116,9 @@ QuicConsumedData QuicPacketGenerator::ConsumeData( // Don't allow the handshake to be bundled with other retransmittable frames. if (has_handshake) { - SendQueuedFrames(/*flush=*/true, /*is_fec_timeout=*/false); + SendQueuedFrames(/*flush=*/true); } - // Try to close FEC group since we've either run out of data to send or we're - // blocked. - packet_creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/false, - /*is_fec_timeout=*/false); - DCHECK(InBatchMode() || !packet_creator_.HasPendingFrames()); return QuicConsumedData(total_bytes_consumed, fin_consumed); } @@ -147,8 +127,12 @@ void QuicPacketGenerator::GenerateMtuDiscoveryPacket( QuicByteCount target_mtu, QuicAckListenerInterface* listener) { // MTU discovery frames must be sent by themselves. - DCHECK(!InBatchMode() && !packet_creator_.HasPendingFrames()); - const QuicByteCount current_mtu = GetMaxPacketLength(); + if (!packet_creator_.CanSetMaxPacketLength()) { + QUIC_BUG << "MTU discovery packets should only be sent when no other " + << "frames needs to be sent."; + return; + } + const QuicByteCount current_mtu = GetCurrentMaxPacketLength(); // The MTU discovery frame is allocated on the stack, since it is going to be // serialized within this function. @@ -156,7 +140,7 @@ void QuicPacketGenerator::GenerateMtuDiscoveryPacket( QuicFrame frame(mtu_discovery_frame); // Send the probe packet with the new length. - SetMaxPacketLength(target_mtu, /*force=*/true); + SetMaxPacketLength(target_mtu); const bool success = packet_creator_.AddPaddedSavedFrame(frame); if (listener != nullptr) { packet_creator_.AddAckListener(listener, 0); @@ -167,7 +151,7 @@ void QuicPacketGenerator::GenerateMtuDiscoveryPacket( DCHECK(success); // Reset the packet length back. - SetMaxPacketLength(current_mtu, /*force=*/true); + SetMaxPacketLength(current_mtu); } bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const { @@ -182,7 +166,7 @@ bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const { return delegate_->ShouldGeneratePacket(retransmittable, NOT_HANDSHAKE); } -void QuicPacketGenerator::SendQueuedFrames(bool flush, bool is_fec_timeout) { +void QuicPacketGenerator::SendQueuedFrames(bool flush) { // Only add pending frames if we are SURE we can then send the whole packet. while (HasPendingFrames() && (flush || CanSendWithNextPendingFrameAddition())) { @@ -191,23 +175,6 @@ void QuicPacketGenerator::SendQueuedFrames(bool flush, bool is_fec_timeout) { if (flush || !InBatchMode()) { packet_creator_.Flush(); } - packet_creator_.MaybeSendFecPacketAndCloseGroup(flush, is_fec_timeout); -} - -void QuicPacketGenerator::OnFecTimeout() { - DCHECK(!InBatchMode()); - if (!packet_creator_.ShouldSendFec(true)) { - QUIC_BUG << "No FEC packet to send on FEC timeout."; - return; - } - // Flush out any pending frames in the generator and the creator, and then - // send out FEC packet. - SendQueuedFrames(/*flush=*/true, /*is_fec_timeout=*/true); -} - -QuicTime::Delta QuicPacketGenerator::GetFecTimeout( - QuicPacketNumber packet_number) { - return packet_creator_.GetFecTimeout(packet_number); } bool QuicPacketGenerator::InBatchMode() { @@ -220,11 +187,11 @@ void QuicPacketGenerator::StartBatchOperations() { void QuicPacketGenerator::FinishBatchOperations() { batch_mode_ = false; - SendQueuedFrames(/*flush=*/false, /*is_fec_timeout=*/false); + SendQueuedFrames(/*flush=*/false); } void QuicPacketGenerator::FlushAllQueuedFrames() { - SendQueuedFrames(/*flush=*/true, /*is_fec_timeout=*/false); + SendQueuedFrames(/*flush=*/true); } bool QuicPacketGenerator::HasQueuedFrames() const { @@ -275,29 +242,13 @@ QuicPacketNumber QuicPacketGenerator::packet_number() const { return packet_creator_.packet_number(); } -QuicByteCount QuicPacketGenerator::GetMaxPacketLength() const { - return max_packet_length_; -} - QuicByteCount QuicPacketGenerator::GetCurrentMaxPacketLength() const { return packet_creator_.max_packet_length(); } -void QuicPacketGenerator::SetMaxPacketLength(QuicByteCount length, bool force) { - // If we cannot immediately set new maximum packet length, and the |force| - // flag is set, we have to flush the contents of the queue and close existing - // FEC group. - if (!packet_creator_.CanSetMaxPacketLength() && force) { - SendQueuedFrames(/*flush=*/true, /*is_fec_timeout=*/false); - packet_creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, - /*is_fec_timeout=*/false); - DCHECK(packet_creator_.CanSetMaxPacketLength()); - } - - max_packet_length_ = length; - if (packet_creator_.CanSetMaxPacketLength()) { - packet_creator_.SetMaxPacketLength(length); - } +void QuicPacketGenerator::SetMaxPacketLength(QuicByteCount length) { + DCHECK(packet_creator_.CanSetMaxPacketLength()); + packet_creator_.SetMaxPacketLength(length); } QuicEncryptedPacket* QuicPacketGenerator::SerializeVersionNegotiationPacket( @@ -348,18 +299,4 @@ void QuicPacketGenerator::SetCurrentPath( max_packets_in_flight); } -void QuicPacketGenerator::set_rtt_multiplier_for_fec_timeout( - float rtt_multiplier_for_fec_timeout) { - packet_creator_.set_rtt_multiplier_for_fec_timeout( - rtt_multiplier_for_fec_timeout); -} - -FecSendPolicy QuicPacketGenerator::fec_send_policy() { - return packet_creator_.fec_send_policy(); -} - -void QuicPacketGenerator::set_fec_send_policy(FecSendPolicy fec_send_policy) { - packet_creator_.set_fec_send_policy(fec_send_policy); -} - } // namespace net diff --git a/net/quic/quic_packet_generator.h b/net/quic/quic_packet_generator.h index 6d956e3..881d973 100644 --- a/net/quic/quic_packet_generator.h +++ b/net/quic/quic_packet_generator.h @@ -36,19 +36,6 @@ // full, it will be serialized and sent to the packet. When batch // mode is ended via |FinishBatchOperations|, the current packet // will be serialzied, even if it is not full. -// -// FEC behavior also depends on batch mode. In batch mode, FEC packets -// will be sent after |max_packets_per_group| have been sent, as well -// as after batch operations are complete. When not in batch mode, -// an FEC packet will be sent after each write call completes. -// -// TODO(rch): This behavior should probably be tuned. When not in batch -// mode, we should probably set a timer so that several independent -// operations can be grouped into the same FEC group. -// -// When an FEC packet is generated, it will be send to the Delegate, -// even if the Delegate has become unwritable after handling the -// data packet immediately proceeding the FEC packet. #ifndef NET_QUIC_QUIC_PACKET_GENERATOR_H_ #define NET_QUIC_QUIC_PACKET_GENERATOR_H_ @@ -91,12 +78,6 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator { ~QuicPacketGenerator(); - // Called by the connection in the event of the congestion window changing. - void OnCongestionWindowChange(QuicPacketCount max_packets_in_flight); - - // Called by the connection when the RTT may have changed. - void OnRttChange(QuicTime::Delta rtt); - // Indicates that an ACK frame should be sent. // If |also_send_stop_waiting| is true, then it also indicates that a // STOP_WAITING frame should be sent as well. @@ -115,7 +96,6 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator { QuicIOVector iov, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface* listener); // Generates an MTU discovery packet of specified size. @@ -146,8 +126,6 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator { // Re-serializes frames with the original packet's packet number length. // Used for retransmitting packets to ensure they aren't too long. - // Caller must ensure that any open FEC group is closed before calling this - // method. void ReserializeAllFrames(const PendingRetransmission& retransmission, char* buffer, size_t buffer_len); @@ -160,16 +138,6 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator { // Set the minimum number of bytes for the connection id length; void SetConnectionIdLength(uint32_t length); - // Called when the FEC alarm fires. - void OnFecTimeout(); - - // Called after sending |packet_number| to determine whether an FEC alarm - // should be set for sending out an FEC packet. Returns a positive and finite - // timeout if an FEC alarm should be set, and infinite if no alarm should be - // set. OnFecTimeout should be called to send the FEC packet when the alarm - // fires. - QuicTime::Delta GetFecTimeout(QuicPacketNumber packet_number); - // Sets the encrypter to use for the encryption level. void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter); @@ -180,18 +148,12 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator { // created. QuicPacketNumber packet_number() const; - // Returns the maximum packet length. Note that this is the long-term maximum - // packet length, and it may not be the maximum length of the current packet, - // if the generator is in the middle of the packet (in batch mode) or FEC - // group. - QuicByteCount GetMaxPacketLength() const; - // Returns the maximum length current packet can actually have. + // Returns the maximum length a current packet can actually have. QuicByteCount GetCurrentMaxPacketLength() const; - // Set maximum packet length sent. If |force| is set to true, all pending - // unfinished packets and FEC groups are closed, and the change is enacted - // immediately. Otherwise, it is enacted at the next opportunity. - void SetMaxPacketLength(QuicByteCount length, bool force); + // Set maximum packet length in the creator immediately. May not be called + // when there are frames queued in the creator. + void SetMaxPacketLength(QuicByteCount length); // Sets |path_id| to be the path on which next packet is generated. void SetCurrentPath(QuicPathId path_id, @@ -202,15 +164,10 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator { packet_creator_.set_debug_delegate(debug_delegate); } - void set_rtt_multiplier_for_fec_timeout(float rtt_multiplier_for_fec_timeout); - - FecSendPolicy fec_send_policy(); - void set_fec_send_policy(FecSendPolicy fec_send_policy); - private: friend class test::QuicPacketGeneratorPeer; - void SendQueuedFrames(bool flush, bool is_fec_timeout); + void SendQueuedFrames(bool flush); // Test to see if we have pending ack, or control frames. bool HasPendingFrames() const; @@ -241,11 +198,6 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator { QuicAckFrame pending_ack_frame_; QuicStopWaitingFrame pending_stop_waiting_frame_; - // Stores the maximum packet size we are allowed to send. This might not be - // the maximum size we are actually using now, if we are in the middle of the - // packet. - QuicByteCount max_packet_length_; - DISALLOW_COPY_AND_ASSIGN(QuicPacketGenerator); }; diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc index e930bc4..133dad5 100644 --- a/net/quic/quic_packet_generator_test.cc +++ b/net/quic/quic_packet_generator_test.cc @@ -34,12 +34,6 @@ namespace net { namespace test { namespace { -const int64_t kMinFecTimeoutMs = 5u; - -static const FecSendPolicy kFecSendPolicyList[] = { - FEC_ANY_TRIGGER, FEC_ALARM_TRIGGER, -}; - class MockDelegate : public QuicPacketGenerator::DelegateInterface { public: MockDelegate() {} @@ -53,7 +47,6 @@ class MockDelegate : public QuicPacketGenerator::DelegateInterface { MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet)); MOCK_METHOD2(OnUnrecoverableError, void(QuicErrorCode, ConnectionCloseSource)); - MOCK_METHOD0(OnResetFecGroup, void()); void SetCanWriteAnything() { EXPECT_CALL(*this, ShouldGeneratePacket(_, _)).WillRepeatedly(Return(true)); @@ -92,8 +85,7 @@ struct PacketContents { num_stop_waiting_frames(0), num_stream_frames(0), num_ping_frames(0), - num_mtu_discovery_frames(0), - fec_group(0) {} + num_mtu_discovery_frames(0) {} size_t num_ack_frames; size_t num_connection_close_frames; @@ -103,13 +95,11 @@ struct PacketContents { size_t num_stream_frames; size_t num_ping_frames; size_t num_mtu_discovery_frames; - - QuicFecGroupNumber fec_group; }; } // namespace -class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> { +class QuicPacketGeneratorTest : public ::testing::Test { public: QuicPacketGeneratorTest() : framer_(QuicSupportedVersions(), @@ -117,10 +107,8 @@ class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> { Perspective::IS_CLIENT), generator_(42, &framer_, &random_, &buffer_allocator_, &delegate_), creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)) { - generator_.set_fec_send_policy(GetParam()); // TODO(ianswett): Fix this test so it uses a non-null encrypter. FLAGS_quic_never_write_unencrypted_data = false; - FLAGS_quic_no_unencrypted_fec = false; } ~QuicPacketGeneratorTest() override { @@ -181,7 +169,6 @@ class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> { simple_framer_.stream_frames().size()); EXPECT_EQ(contents.num_stop_waiting_frames, simple_framer_.stop_waiting_frames().size()); - EXPECT_EQ(contents.fec_group, simple_framer_.header().fec_group); // From the receiver's perspective, MTU discovery frames are ping frames. EXPECT_EQ(contents.num_ping_frames + contents.num_mtu_discovery_frames, @@ -206,16 +193,6 @@ class QuicPacketGeneratorTest : public ::testing::TestWithParam<FecSendPolicy> { } } - void CheckPacketIsFec(size_t packet_index, QuicPacketNumber fec_group) { - ASSERT_GT(packets_.size(), packet_index); - const SerializedPacket& packet = packets_[packet_index]; - ASSERT_TRUE(packet.retransmittable_frames.empty()); - ASSERT_TRUE(packet.encrypted_buffer != nullptr); - ASSERT_TRUE(simple_framer_.ProcessPacket( - QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length))); - EXPECT_TRUE(simple_framer_.header().fec_flag); - } - QuicIOVector CreateData(size_t len) { data_array_.reset(new char[len]); memset(data_array_.get(), '?', len); @@ -247,19 +224,14 @@ class MockDebugDelegate : public QuicPacketCreator::DebugDelegate { MOCK_METHOD1(OnFrameAddedToPacket, void(const QuicFrame&)); }; -// Run all end to end tests with all supported FEC send polocies. -INSTANTIATE_TEST_CASE_P(FecSendPolicy, - QuicPacketGeneratorTest, - ::testing::ValuesIn(kFecSendPolicyList)); - -TEST_P(QuicPacketGeneratorTest, ShouldSendAck_NotWritable) { +TEST_F(QuicPacketGeneratorTest, ShouldSendAck_NotWritable) { delegate_.SetCanNotWrite(); generator_.SetShouldSendAck(false); EXPECT_TRUE(generator_.HasQueuedFrames()); } -TEST_P(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldNotFlush) { +TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldNotFlush) { StrictMock<MockDebugDelegate> debug_delegate; generator_.set_debug_delegate(&debug_delegate); @@ -273,7 +245,7 @@ TEST_P(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldNotFlush) { EXPECT_TRUE(generator_.HasQueuedFrames()); } -TEST_P(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) { +TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) { delegate_.SetCanWriteOnlyNonRetransmittable(); EXPECT_CALL(delegate_, PopulateAckFrame(_)); @@ -288,7 +260,7 @@ TEST_P(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) { CheckPacketContains(contents, 0); } -TEST_P(QuicPacketGeneratorTest, ShouldSendAck_MultipleCalls) { +TEST_F(QuicPacketGeneratorTest, ShouldSendAck_MultipleCalls) { // Make sure that calling SetShouldSendAck multiple times does not result in a // crash. Previously this would result in multiple QuicFrames queued in the // packet generator, with all but the last with internal pointers to freed @@ -307,21 +279,21 @@ TEST_P(QuicPacketGeneratorTest, ShouldSendAck_MultipleCalls) { generator_.FinishBatchOperations(); } -TEST_P(QuicPacketGeneratorTest, AddControlFrame_NotWritable) { +TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritable) { delegate_.SetCanNotWrite(); generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_TRUE(generator_.HasQueuedFrames()); } -TEST_P(QuicPacketGeneratorTest, AddControlFrame_OnlyAckWritable) { +TEST_F(QuicPacketGeneratorTest, AddControlFrame_OnlyAckWritable) { delegate_.SetCanWriteOnlyNonRetransmittable(); generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); EXPECT_TRUE(generator_.HasQueuedFrames()); } -TEST_P(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) { +TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); @@ -329,7 +301,7 @@ TEST_P(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) { EXPECT_TRUE(generator_.HasQueuedFrames()); } -TEST_P(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) { +TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) { delegate_.SetCanNotWrite(); generator_.StartBatchOperations(); @@ -348,7 +320,7 @@ TEST_P(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) { CheckPacketContains(contents, 0); } -TEST_P(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) { +TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) { delegate_.SetCanWriteAnything(); EXPECT_CALL(delegate_, OnSerializedPacket(_)) @@ -362,34 +334,34 @@ TEST_P(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) { CheckPacketContains(contents, 0); } -TEST_P(QuicPacketGeneratorTest, ConsumeData_NotWritable) { +TEST_F(QuicPacketGeneratorTest, ConsumeData_NotWritable) { delegate_.SetCanNotWrite(); QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVector("foo"), 2, true, MAY_FEC_PROTECT, nullptr); + kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr); EXPECT_EQ(0u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); } -TEST_P(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) { +TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVector("foo"), 2, true, MAY_FEC_PROTECT, nullptr); + kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); } -TEST_P(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) { +TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) { delegate_.SetCanWriteAnything(); EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVector("foo"), 2, true, MAY_FEC_PROTECT, nullptr); + kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -402,14 +374,14 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) { // Test the behavior of ConsumeData when the data consumed is for the crypto // handshake stream. Ensure that the packet is always sent and padded even if // the generator operates in batch mode. -TEST_P(QuicPacketGeneratorTest, ConsumeData_Handshake) { +TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); QuicConsumedData consumed = generator_.ConsumeData( - kCryptoStreamId, MakeIOVector("foo"), 0, false, MAY_FEC_PROTECT, nullptr); + kCryptoStreamId, MakeIOVector("foo"), 0, false, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -418,38 +390,38 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_Handshake) { CheckPacketContains(contents, 0); ASSERT_EQ(1u, packets_.size()); - ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetMaxPacketLength()); + ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength()); EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length); } -TEST_P(QuicPacketGeneratorTest, ConsumeData_EmptyData) { +TEST_F(QuicPacketGeneratorTest, ConsumeData_EmptyData) { EXPECT_DFATAL(generator_.ConsumeData(kHeadersStreamId, MakeIOVector(""), 0, - false, MAY_FEC_PROTECT, nullptr), + false, nullptr), "Attempt to consume empty data without FIN."); } -TEST_P(QuicPacketGeneratorTest, +TEST_F(QuicPacketGeneratorTest, ConsumeDataMultipleTimes_WritableAndShouldNotFlush) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 2, true, - MAY_FEC_PROTECT, nullptr); - QuicConsumedData consumed = generator_.ConsumeData( - 3, MakeIOVector("quux"), 7, false, MAY_FEC_PROTECT, nullptr); + nullptr); + QuicConsumedData consumed = + generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, nullptr); EXPECT_EQ(4u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); } -TEST_P(QuicPacketGeneratorTest, ConsumeData_BatchOperations) { +TEST_F(QuicPacketGeneratorTest, ConsumeData_BatchOperations) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 2, true, - MAY_FEC_PROTECT, nullptr); - QuicConsumedData consumed = generator_.ConsumeData( - 3, MakeIOVector("quux"), 7, false, MAY_FEC_PROTECT, nullptr); + nullptr); + QuicConsumedData consumed = + generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, nullptr); EXPECT_EQ(4u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -465,246 +437,19 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_BatchOperations) { CheckPacketContains(contents, 0); } -TEST_P(QuicPacketGeneratorTest, ConsumeDataFecOnMaxGroupSize) { - delegate_.SetCanWriteAnything(); - - // Send FEC every two packets. - creator_->set_max_packets_per_fec_group(2); - - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER, but FEC - // group is closed. - EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); - } else { - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - - // Send enough data to create 3 packets: two full and one partial. Send with - // MUST_FEC_PROTECT flag. - size_t data_len = 2 * kDefaultMaxPacketSize + 100; - QuicConsumedData consumed = generator_.ConsumeData( - 3, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - EXPECT_TRUE(consumed.fin_consumed); - EXPECT_FALSE(generator_.HasQueuedFrames()); - - CheckPacketHasSingleStreamFrame(0); - CheckPacketHasSingleStreamFrame(1); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER. - CheckPacketHasSingleStreamFrame(2); - } else { - CheckPacketIsFec(2, 1); - CheckPacketHasSingleStreamFrame(3); - } - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // If FEC send policy is FEC_ANY_TRIGGER, then the FEC packet under - // construction will be sent when one more packet is sent (since FEC group - // size is 2), or when OnFecTimeout is called. Send more data with - // MAY_FEC_PROTECT. This packet should also be protected, and FEC packet is - // sent since FEC group size is reached. - // - // If FEC send policy is FEC_ALARM_TRIGGER, FEC group is closed when the group - // size is reached. FEC packet is not sent. - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); - } else { - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - } - consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT, - nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - CheckPacketHasSingleStreamFrame(3); - } else { - CheckPacketHasSingleStreamFrame(4); - CheckPacketIsFec(5, 4); - } - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); -} - -TEST_P(QuicPacketGeneratorTest, ConsumeDataSendsFecOnTimeout) { - delegate_.SetCanWriteAnything(); - creator_->set_max_packets_per_fec_group(1000); - - // Send data with MUST_FEC_PROTECT flag. No FEC packet is emitted, but the - // creator FEC protects all data. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - QuicConsumedData consumed = generator_.ConsumeData(3, CreateData(1u), 0, true, - MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - EXPECT_TRUE(consumed.fin_consumed); - CheckPacketHasSingleStreamFrame(0); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Send more data with MAY_FEC_PROTECT. This packet should also be protected, - // and FEC packet is not yet sent. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT, - nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - CheckPacketHasSingleStreamFrame(1); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Calling OnFecTimeout should cause the FEC packet to be emitted. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - generator_.OnFecTimeout(); - CheckPacketIsFec(2, 1); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Subsequent data is protected under the next FEC group. Send enough data to - // create 2 more packets: one full and one partial. - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - size_t data_len = kDefaultMaxPacketSize + 1; - consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true, - MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - EXPECT_TRUE(consumed.fin_consumed); - CheckPacketHasSingleStreamFrame(3); - CheckPacketHasSingleStreamFrame(4); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Calling OnFecTimeout should cause the FEC packet to be emitted. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - generator_.OnFecTimeout(); - CheckPacketIsFec(5, 4); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); -} - -TEST_P(QuicPacketGeneratorTest, GetFecTimeoutFiniteOnlyOnFirstPacketInGroup) { - delegate_.SetCanWriteAnything(); - creator_->set_max_packets_per_fec_group(6); - - // Send enough data to create 2 packets: one full and one partial. Send with - // MUST_FEC_PROTECT flag. No FEC packet is emitted yet, but the creator FEC - // protects all data. - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - size_t data_len = 1 * kDefaultMaxPacketSize + 100; - QuicConsumedData consumed = generator_.ConsumeData( - 3, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - EXPECT_TRUE(consumed.fin_consumed); - EXPECT_FALSE(generator_.HasQueuedFrames()); - CheckPacketHasSingleStreamFrame(0); - CheckPacketHasSingleStreamFrame(1); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // GetFecTimeout returns finite timeout only for first packet in group. - EXPECT_EQ(QuicTime::Delta::FromMilliseconds(kMinFecTimeoutMs), - generator_.GetFecTimeout(/*packet_number=*/1u)); - EXPECT_EQ(QuicTime::Delta::Infinite(), - generator_.GetFecTimeout(/*packet_number=*/2u)); - - // Send more data with MAY_FEC_PROTECT. This packet should also be protected, - // and FEC packet is not yet sent. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT, - nullptr); - CheckPacketHasSingleStreamFrame(2); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // GetFecTimeout returns finite timeout only for first packet in group. - EXPECT_EQ(QuicTime::Delta::Infinite(), - generator_.GetFecTimeout(/*packet_number=*/3u)); - - // Calling OnFecTimeout should cause the FEC packet to be emitted. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - generator_.OnFecTimeout(); - CheckPacketIsFec(3, /*fec_group=*/1u); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Subsequent data is protected under the next FEC group. Send enough data to - // create 2 more packets: one full and one partial. - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - data_len = kDefaultMaxPacketSize + 1u; - consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true, - MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - EXPECT_TRUE(consumed.fin_consumed); - CheckPacketHasSingleStreamFrame(4); - CheckPacketHasSingleStreamFrame(5); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // GetFecTimeout returns finite timeout for first packet in the new group. - EXPECT_EQ(QuicTime::Delta::FromMilliseconds(kMinFecTimeoutMs), - generator_.GetFecTimeout(/*packet_number=*/5u)); - EXPECT_EQ(QuicTime::Delta::Infinite(), - generator_.GetFecTimeout(/*packet_number=*/6u)); - - // Calling OnFecTimeout should cause the FEC packet to be emitted. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - generator_.OnFecTimeout(); - CheckPacketIsFec(6, /*fec_group=*/5u); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Send more data with MAY_FEC_PROTECT. No FEC protection, so GetFecTimeout - // returns infinite. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - consumed = generator_.ConsumeData(9, CreateData(1u), 0, true, MAY_FEC_PROTECT, - nullptr); - CheckPacketHasSingleStreamFrame(7); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - EXPECT_EQ(QuicTime::Delta::Infinite(), - generator_.GetFecTimeout(/*packet_number=*/8u)); -} - -TEST_P(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) { +TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) { // Set the packet size be enough for two stream frames with 0 stream offset, // but not enough for a stream frame of 0 offset and one with non-zero offset. size_t length = NullEncrypter().GetCiphertextSize(0) + GetPacketHeaderSize( creator_->connection_id_length(), kIncludeVersion, !kIncludePathId, - QuicPacketCreatorPeer::NextPacketNumberLength(creator_), - NOT_IN_FEC_GROUP) + + QuicPacketCreatorPeer::NextPacketNumberLength(creator_)) + // Add an extra 3 bytes for the payload and 1 byte so BytesFree is larger // than the GetMinStreamFrameSize. - QuicFramer::GetMinStreamFrameSize(1, 0, false, NOT_IN_FEC_GROUP) + 3 + - QuicFramer::GetMinStreamFrameSize(1, 0, true, NOT_IN_FEC_GROUP) + 1; - generator_.SetMaxPacketLength(length, /*force=*/false); + QuicFramer::GetMinStreamFrameSize(1, 0, false) + 3 + + QuicFramer::GetMinStreamFrameSize(1, 0, true) + 1; + generator_.SetMaxPacketLength(length); delegate_.SetCanWriteAnything(); { InSequence dummy; @@ -716,9 +461,8 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) { generator_.StartBatchOperations(); // Queue enough data to prevent a stream frame with a non-zero offset from // fitting. - QuicConsumedData consumed = - generator_.ConsumeData(kHeadersStreamId, MakeIOVector("foo"), 0, false, - MAY_FEC_PROTECT, nullptr); + QuicConsumedData consumed = generator_.ConsumeData( + kHeadersStreamId, MakeIOVector("foo"), 0, false, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -726,7 +470,7 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) { // 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, MakeIOVector("bar"), 3, - true, MAY_FEC_PROTECT, nullptr); + true, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -740,554 +484,7 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) { CheckPacketContains(contents, 1); } -TEST_P(QuicPacketGeneratorTest, NoFecPacketSentWhenBatchEnds) { - delegate_.SetCanWriteAnything(); - creator_->set_max_packets_per_fec_group(6); - - generator_.StartBatchOperations(); - - generator_.ConsumeData(3, MakeIOVector("foo"), 2, true, MUST_FEC_PROTECT, - nullptr); - QuicConsumedData consumed = generator_.ConsumeData( - 5, MakeIOVector("quux"), 7, false, MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(4u, consumed.bytes_consumed); - EXPECT_FALSE(consumed.fin_consumed); - EXPECT_TRUE(generator_.HasQueuedFrames()); - - // Now both frames will be flushed out, but FEC packet is not yet sent. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - generator_.FinishBatchOperations(); - EXPECT_FALSE(generator_.HasQueuedFrames()); - - PacketContents contents; - contents.num_stream_frames = 2u; - contents.fec_group = 1u; - CheckPacketContains(contents, 0); - - // Forcing FEC timeout causes FEC packet to be emitted. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - generator_.OnFecTimeout(); - CheckPacketIsFec(1, /*fec_group=*/1u); -} - -TEST_P(QuicPacketGeneratorTest, FecTimeoutOnRttChange) { - EXPECT_EQ(QuicTime::Delta::Zero(), - QuicPacketCreatorPeer::GetFecTimeout(creator_)); - generator_.OnRttChange(QuicTime::Delta::FromMilliseconds(300)); - EXPECT_EQ(QuicTime::Delta::FromMilliseconds(150), - QuicPacketCreatorPeer::GetFecTimeout(creator_)); -} - -TEST_P(QuicPacketGeneratorTest, FecGroupSizeOnCongestionWindowChange) { - delegate_.SetCanWriteAnything(); - creator_->set_max_packets_per_fec_group(50); - EXPECT_EQ(50u, creator_->max_packets_per_fec_group()); - EXPECT_FALSE(creator_->IsFecGroupOpen()); - - // On reduced cwnd. - generator_.OnCongestionWindowChange(7); - EXPECT_EQ(3u, creator_->max_packets_per_fec_group()); - - // On increased cwnd. - generator_.OnCongestionWindowChange(100); - EXPECT_EQ(50u, creator_->max_packets_per_fec_group()); - - // On collapsed cwnd. - generator_.OnCongestionWindowChange(1); - EXPECT_EQ(2u, creator_->max_packets_per_fec_group()); -} - -TEST_P(QuicPacketGeneratorTest, FecGroupSizeChangeWithOpenGroup) { - delegate_.SetCanWriteAnything(); - generator_.StartBatchOperations(); - creator_->set_max_packets_per_fec_group(50); - EXPECT_EQ(50u, creator_->max_packets_per_fec_group()); - EXPECT_FALSE(creator_->IsFecGroupOpen()); - - // Send enough data to create 4 packets with MUST_FEC_PROTECT flag. 3 packets - // are sent, one is queued in the creator. - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - size_t data_len = 3 * kDefaultMaxPacketSize + 1; - QuicConsumedData consumed = generator_.ConsumeData( - 7, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - EXPECT_TRUE(creator_->IsFecGroupOpen()); - - // Change FEC groupsize. - generator_.OnCongestionWindowChange(2); - EXPECT_EQ(2u, creator_->max_packets_per_fec_group()); - - // If FEC send policy is FEC_ANY_TRIGGER, then send enough data to trigger one - // unprotected data packet, causing the FEC packet to also be sent. - // - // If FEC send policy is FEC_ALARM_TRIGGER, FEC group is closed and FEC packet - // is not sent. - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); - } else { - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - } - consumed = generator_.ConsumeData(7, CreateData(kDefaultMaxPacketSize), 0, - true, MAY_FEC_PROTECT, nullptr); - EXPECT_EQ(kDefaultMaxPacketSize, consumed.bytes_consumed); - if (generator_.fec_send_policy() == FEC_ANY_TRIGGER) { - // Verify that one FEC packet was sent. - CheckPacketIsFec(4, /*fec_group=*/1u); - } - EXPECT_FALSE(creator_->IsFecGroupOpen()); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); -} - -TEST_P(QuicPacketGeneratorTest, SwitchFecOnOff) { - delegate_.SetCanWriteAnything(); - creator_->set_max_packets_per_fec_group(2); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Send one unprotected data packet. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, - MAY_FEC_PROTECT, nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - EXPECT_FALSE(generator_.HasQueuedFrames()); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - // Verify that one data packet was sent. - PacketContents contents; - contents.num_stream_frames = 1; - CheckPacketContains(contents, 0); - - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - // If FEC send policy is FEC_ALARM_TRIGGER, FEC group is closed. - EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); - } else { - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - // Send enough data to create 3 packets with MUST_FEC_PROTECT flag. - size_t data_len = 2 * kDefaultMaxPacketSize + 100; - consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true, - MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - EXPECT_FALSE(generator_.HasQueuedFrames()); - - // If FEC send policy is FEC_ANY_TRIGGER, verify that packets sent were 3 data - // and 1 FEC. - // - // If FEC send policy is FEC_ALARM_TRIGGER, verify that packets sent were 3 - // data and FEC group is closed. - CheckPacketHasSingleStreamFrame(1); - CheckPacketHasSingleStreamFrame(2); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - CheckPacketHasSingleStreamFrame(3); - } else { - CheckPacketIsFec(3, /*fec_group=*/2u); - CheckPacketHasSingleStreamFrame(4); - } - - // Calling OnFecTimeout should emit the pending FEC packet. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - generator_.OnFecTimeout(); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - CheckPacketIsFec(4, /*fec_group=*/4u); - } else { - CheckPacketIsFec(5, /*fec_group=*/5u); - } - - // Send one unprotected data packet. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - consumed = generator_.ConsumeData(7, CreateData(1u), 0, true, MAY_FEC_PROTECT, - nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - EXPECT_FALSE(generator_.HasQueuedFrames()); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - // Verify that one unprotected data packet was sent. - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - CheckPacketContains(contents, 5); - } else { - CheckPacketContains(contents, 6); - } -} - -TEST_P(QuicPacketGeneratorTest, SwitchFecOnWithPendingFrameInCreator) { - delegate_.SetCanWriteAnything(); - // Enable FEC. - creator_->set_max_packets_per_fec_group(2); - - generator_.StartBatchOperations(); - // Queue enough data to prevent a stream frame with a non-zero offset from - // fitting. - QuicConsumedData consumed = generator_.ConsumeData(7, CreateData(1u), 0, true, - MAY_FEC_PROTECT, nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - EXPECT_TRUE(creator_->HasPendingFrames()); - - // Queue protected data for sending. Should cause queued frames to be flushed. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - consumed = generator_.ConsumeData(7, CreateData(1u), 0, true, - MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - PacketContents contents; - contents.num_stream_frames = 1; - // Transmitted packet was not FEC protected. - CheckPacketContains(contents, 0); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - EXPECT_TRUE(creator_->HasPendingFrames()); -} - -TEST_P(QuicPacketGeneratorTest, SwitchFecOnWithPendingFramesInGenerator) { - // Enable FEC. - creator_->set_max_packets_per_fec_group(2); - - // Queue control frames in generator. - delegate_.SetCanNotWrite(); - generator_.SetShouldSendAck(true); - delegate_.SetCanWriteAnything(); - generator_.StartBatchOperations(); - - // Set up frames to write into the creator when control frames are written. - EXPECT_CALL(delegate_, PopulateAckFrame(_)); - EXPECT_CALL(delegate_, PopulateStopWaitingFrame(_)); - - // Generator should have queued control frames, and creator should be empty. - EXPECT_TRUE(generator_.HasQueuedFrames()); - EXPECT_FALSE(creator_->HasPendingFrames()); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Queue protected data for sending. Should cause queued frames to be flushed. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - QuicConsumedData consumed = generator_.ConsumeData(7, CreateData(1u), 0, true, - MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - PacketContents contents; - contents.num_ack_frames = 1; - contents.num_stop_waiting_frames = 1; - CheckPacketContains(contents, 0); - - // FEC protection should be on in creator. - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); -} - -TEST_P(QuicPacketGeneratorTest, SwitchFecOnOffWithSubsequentFramesProtected) { - delegate_.SetCanWriteAnything(); - - // Enable FEC. - creator_->set_max_packets_per_fec_group(2); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Queue stream frame to be protected in creator. - generator_.StartBatchOperations(); - QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, - MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - // Creator has a pending protected frame. - EXPECT_TRUE(creator_->HasPendingFrames()); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Add enough unprotected data to exceed size of current packet, so that - // current packet is sent. Both frames will be sent out in a single packet. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - size_t data_len = kDefaultMaxPacketSize; - consumed = generator_.ConsumeData(5, CreateData(data_len), 0, true, - MAY_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - PacketContents contents; - contents.num_stream_frames = 2u; - contents.fec_group = 1u; - CheckPacketContains(contents, 0); - // FEC protection should still be on in creator. - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); -} - -TEST_P(QuicPacketGeneratorTest, SwitchFecOnOffWithSubsequentPacketsProtected) { - delegate_.SetCanWriteAnything(); - - // Enable FEC. - creator_->set_max_packets_per_fec_group(2); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Send first packet, FEC protected. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, - MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - PacketContents contents; - contents.num_stream_frames = 1u; - contents.fec_group = 1u; - CheckPacketContains(contents, 0); - - // FEC should still be on in creator. - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Send unprotected data to cause second packet to be sent, which gets - // protected because it happens to fall within an open FEC group. Data packet - // will be followed by FEC packet. - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); - } else { - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - } - consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT, - nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - contents.num_stream_frames = 1u; - CheckPacketContains(contents, 1); - if (generator_.fec_send_policy() == FEC_ANY_TRIGGER) { - // FEC packet is sent when send policy is FEC_ANY_TRIGGER. - CheckPacketIsFec(2, /*fec_group=*/1u); - } - - // FEC protection should be off in creator. - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); -} - -TEST_P(QuicPacketGeneratorTest, SwitchFecOnOffThenOnWithCreatorProtectionOn) { - delegate_.SetCanWriteAnything(); - generator_.StartBatchOperations(); - - // Enable FEC. - creator_->set_max_packets_per_fec_group(2); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Queue one byte of FEC protected data. - QuicConsumedData consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, - MUST_FEC_PROTECT, nullptr); - EXPECT_TRUE(creator_->HasPendingFrames()); - - // Add more unprotected data causing first packet to be sent, FEC protected. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - size_t data_len = kDefaultMaxPacketSize; - consumed = generator_.ConsumeData(5, CreateData(data_len), 0, true, - MAY_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - PacketContents contents; - contents.num_stream_frames = 2u; - contents.fec_group = 1u; - CheckPacketContains(contents, 0); - - // FEC group is still open in creator. - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Add data that should be protected, large enough to cause second packet to - // be sent. Data packet should be followed by FEC packet. - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); - } else { - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - } - consumed = generator_.ConsumeData(5, CreateData(data_len), 0, true, - MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - CheckPacketContains(contents, 1); - if (generator_.fec_send_policy() == FEC_ANY_TRIGGER) { - // FEC packet is sent when send policy is FEC_ANY_TRIGGER. - CheckPacketIsFec(2, /*fec_group=*/1u); - } - - // FEC protection should remain on in creator. - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); -} - -TEST_P(QuicPacketGeneratorTest, ResetFecGroupNoTimeout) { - delegate_.SetCanWriteAnything(); - // Send FEC packet after 2 packets. - creator_->set_max_packets_per_fec_group(2); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Send two packets so that when this data is consumed, two packets are sent - // out. In FEC_TRIGGER_ANY, this will cause an FEC packet to be sent out and - // with FEC_TRIGGER_ALARM, this will cause a Reset to be called. In both - // cases, the creator's fec protection will be turned off afterwards. - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER, but FEC - // group is closed. - EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); - } else { - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - // Fin Packet. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - size_t data_len = 2 * kDefaultMaxPacketSize; - QuicConsumedData consumed = generator_.ConsumeData( - 5, CreateData(data_len), 0, true, MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - EXPECT_TRUE(consumed.fin_consumed); - EXPECT_FALSE(generator_.HasQueuedFrames()); - CheckPacketHasSingleStreamFrame(0); - CheckPacketHasSingleStreamFrame(1); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER. - CheckPacketHasSingleStreamFrame(2); - } else { - // FEC packet is sent after 2 packets and when send policy is - // FEC_ANY_TRIGGER. - CheckPacketIsFec(2, 1); - CheckPacketHasSingleStreamFrame(3); - } - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Do the same send (with MUST_FEC_PROTECT) on a different stream id. - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - // FEC packet is sent after 2 packets and when send policy is - // FEC_ANY_TRIGGER. When policy is FEC_ALARM_TRIGGER, FEC group is closed - // and FEC packet is not sent. - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); - } else { - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - // FEC packet is sent after 2 packets and when send policy is - // FEC_ANY_TRIGGER. When policy is FEC_ALARM_TRIGGER, FEC group is closed - // and FEC packet is not sent. - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); - } else { - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - } - consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true, - MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - EXPECT_TRUE(consumed.fin_consumed); - EXPECT_FALSE(generator_.HasQueuedFrames()); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - CheckPacketHasSingleStreamFrame(3); - CheckPacketHasSingleStreamFrame(4); - CheckPacketHasSingleStreamFrame(5); - } else { - CheckPacketHasSingleStreamFrame(4); - // FEC packet is sent after 2 packets and when send policy is - // FEC_ANY_TRIGGER. - CheckPacketIsFec(5, 4); - CheckPacketHasSingleStreamFrame(6); - CheckPacketHasSingleStreamFrame(7); - // FEC packet is sent after 2 packets and when send policy is - // FEC_ANY_TRIGGER. - CheckPacketIsFec(8, 7); - } - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Do the another send (with MAY_FEC_PROTECT) on a different stream id, which - // should not produce an FEC packet because the last FEC group has been - // closed. - { - InSequence dummy; - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - } - consumed = generator_.ConsumeData(9, CreateData(data_len), 0, true, - MAY_FEC_PROTECT, nullptr); - EXPECT_EQ(data_len, consumed.bytes_consumed); - EXPECT_TRUE(consumed.fin_consumed); - EXPECT_FALSE(generator_.HasQueuedFrames()); - if (generator_.fec_send_policy() == FEC_ALARM_TRIGGER) { - CheckPacketHasSingleStreamFrame(6); - CheckPacketHasSingleStreamFrame(7); - CheckPacketHasSingleStreamFrame(8); - } else { - CheckPacketHasSingleStreamFrame(9); - CheckPacketHasSingleStreamFrame(10); - CheckPacketHasSingleStreamFrame(11); - } - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); -} - -// 1. Create and send one packet with MUST_FEC_PROTECT. -// 2. Call FecTimeout, expect FEC packet is sent. -// 3. Do the same thing over again, with a different stream id. -TEST_P(QuicPacketGeneratorTest, FecPacketSentOnFecTimeout) { - delegate_.SetCanWriteAnything(); - creator_->set_max_packets_per_fec_group(1000); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - for (int i = 1; i < 4; i = i + 2) { - // Send data with MUST_FEC_PROTECT flag. No FEC packet is emitted, but the - // creator FEC protects all data. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - QuicConsumedData consumed = generator_.ConsumeData( - i + 2, CreateData(1u), 0, true, MUST_FEC_PROTECT, nullptr); - EXPECT_EQ(1u, consumed.bytes_consumed); - EXPECT_TRUE(consumed.fin_consumed); - CheckPacketHasSingleStreamFrame(0); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - - // Calling OnFecTimeout should cause the FEC packet to be emitted. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - generator_.OnFecTimeout(); - CheckPacketIsFec(i, i); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(creator_)); - } -} - -TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations) { +TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) { delegate_.SetCanNotWrite(); generator_.SetShouldSendAck(false); @@ -1302,8 +499,7 @@ TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations) { EXPECT_CALL(delegate_, PopulateAckFrame(_)); // Send some data and a control frame - generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, MAY_FEC_PROTECT, - nullptr); + generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, nullptr); generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame())); // All five frames will be flushed out in a single packet. @@ -1320,7 +516,7 @@ TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations) { CheckPacketContains(contents, 0); } -TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) { +TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) { delegate_.SetCanNotWrite(); generator_.SetShouldSendAck(false); @@ -1345,8 +541,8 @@ TEST_P(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, MAY_FEC_PROTECT, nullptr); + QuicConsumedData consumed = + generator_.ConsumeData(3, CreateData(data_len), 0, true, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame())); @@ -1368,7 +564,7 @@ TEST_P(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) { CheckPacketContains(contents2, 1); } -TEST_P(QuicPacketGeneratorTest, TestConnectionIdLength) { +TEST_F(QuicPacketGeneratorTest, TestConnectionIdLength) { generator_.SetConnectionIdLength(0); EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID, creator_->connection_id_length()); generator_.SetConnectionIdLength(1); @@ -1393,14 +589,14 @@ TEST_P(QuicPacketGeneratorTest, TestConnectionIdLength) { // Test whether SetMaxPacketLength() works in the situation when the queue is // empty, and we send three packets worth of data. -TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) { +TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) { delegate_.SetCanWriteAnything(); // Send enough data for three packets. size_t data_len = 3 * kDefaultMaxPacketSize + 1; size_t packet_len = kDefaultMaxPacketSize + 100; ASSERT_LE(packet_len, kMaxPacketSize); - generator_.SetMaxPacketLength(packet_len, /*force=*/false); + generator_.SetMaxPacketLength(packet_len); EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength()); EXPECT_CALL(delegate_, OnSerializedPacket(_)) @@ -1409,7 +605,7 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) { QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), /*offset=*/2, - /*fin=*/true, MAY_FEC_PROTECT, nullptr); + /*fin=*/true, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -1426,7 +622,7 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) { // Test whether SetMaxPacketLength() works in the situation when we first write // data, then change packet size, then write data again. -TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) { +TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) { delegate_.SetCanWriteAnything(); // We send enough data to overflow default packet length, but not the altered @@ -1444,7 +640,7 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) { QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), /*offset=*/2, - /*fin=*/false, MAY_FEC_PROTECT, nullptr); + /*fin=*/false, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -1453,13 +649,13 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) { ASSERT_EQ(2u, packets_.size()); // Increase packet size. - generator_.SetMaxPacketLength(packet_len, /*force=*/false); + generator_.SetMaxPacketLength(packet_len); EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength()); // Send a packet after packet size change. consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), 2 + data_len, - /*fin=*/true, MAY_FEC_PROTECT, nullptr); + /*fin=*/true, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -1472,63 +668,9 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) { CheckAllPacketsHaveSingleStreamFrame(); } -// Test whether SetMaxPacketLength() works correctly when we change the packet -// size in the middle of the batched packet. -TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_Midpacket) { - delegate_.SetCanWriteAnything(); - generator_.StartBatchOperations(); - - size_t first_write_len = kDefaultMaxPacketSize / 2; - size_t second_write_len = kDefaultMaxPacketSize; - size_t packet_len = kDefaultMaxPacketSize + 100; - ASSERT_LE(packet_len, kMaxPacketSize); - - // First send half of the packet worth of data. We are in the batch mode, so - // should not cause packet serialization. - QuicConsumedData consumed = - generator_.ConsumeData(kHeadersStreamId, CreateData(first_write_len), - /*offset=*/2, - /*fin=*/false, MAY_FEC_PROTECT, nullptr); - EXPECT_EQ(first_write_len, consumed.bytes_consumed); - EXPECT_FALSE(consumed.fin_consumed); - EXPECT_TRUE(generator_.HasQueuedFrames()); - - // Make sure we have no packets so far. - ASSERT_EQ(0u, packets_.size()); - - // Increase packet size. Ensure it's not immediately enacted. - generator_.SetMaxPacketLength(packet_len, /*force=*/false); - EXPECT_EQ(packet_len, generator_.GetMaxPacketLength()); - EXPECT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength()); - - // We expect to see exactly one packet serialized after that, since we are in - // batch mode and we have sent approximately 3/2 of our MTU. - EXPECT_CALL(delegate_, OnSerializedPacket(_)) - .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - - // Send a packet worth of data to the same stream. This should trigger - // serialization of other packet. - consumed = - generator_.ConsumeData(kHeadersStreamId, CreateData(second_write_len), - /*offset=*/2 + first_write_len, - /*fin=*/true, MAY_FEC_PROTECT, nullptr); - EXPECT_EQ(second_write_len, consumed.bytes_consumed); - EXPECT_TRUE(consumed.fin_consumed); - EXPECT_TRUE(generator_.HasQueuedFrames()); - - // We expect the first packet to contain two frames, and to not reflect the - // packet size change. - ASSERT_EQ(1u, packets_.size()); - EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length); - - PacketContents contents; - contents.num_stream_frames = 2; - CheckPacketContains(contents, 0); -} - // Test whether SetMaxPacketLength() works correctly when we force the change of // the packet size in the middle of the batched packet. -TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) { +TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); @@ -1542,7 +684,7 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) { QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(first_write_len), /*offset=*/2, - /*fin=*/false, MAY_FEC_PROTECT, nullptr); + /*fin=*/false, nullptr); EXPECT_EQ(first_write_len, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -1554,9 +696,10 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) { EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); - // Increase packet size. Ensure it's immediately enacted. - generator_.SetMaxPacketLength(packet_len, /*force=*/true); - EXPECT_EQ(packet_len, generator_.GetMaxPacketLength()); + // Increase packet size after flushing all frames. + // Ensure it's immediately enacted. + generator_.FlushAllQueuedFrames(); + generator_.SetMaxPacketLength(packet_len); EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength()); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -1571,7 +714,7 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) { consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(second_write_len), /*offset=*/2 + first_write_len, - /*fin=*/true, MAY_FEC_PROTECT, nullptr); + /*fin=*/true, nullptr); EXPECT_EQ(second_write_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -1586,7 +729,7 @@ TEST_P(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) { } // Test sending an MTU probe, without any surrounding data. -TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_Simple) { +TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_Simple) { delegate_.SetCanWriteAnything(); const size_t target_mtu = kDefaultMaxPacketSize + 100; @@ -1609,7 +752,7 @@ TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_Simple) { // Test sending an MTU probe. Surround it with data, to ensure that it resets // the MTU to the value before the probe was sent. -TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) { +TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) { delegate_.SetCanWriteAnything(); const size_t target_mtu = kDefaultMaxPacketSize + 100; @@ -1629,7 +772,7 @@ TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) { QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), /*offset=*/2, - /*fin=*/false, MAY_FEC_PROTECT, nullptr); + /*fin=*/false, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -1641,7 +784,7 @@ TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) { // Send data after the MTU probe. consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), /*offset=*/2 + data_len, - /*fin=*/true, MAY_FEC_PROTECT, nullptr); + /*fin=*/true, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -1661,7 +804,7 @@ TEST_P(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) { CheckPacketHasSingleStreamFrame(4); } -TEST_P(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) { +TEST_F(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) { // Test added to ensure the generator does not crash when an invalid frame is // added. Because this is an indication of internal programming errors, // DFATALs are expected. @@ -1689,12 +832,12 @@ TEST_P(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) { "for least_unacked_delta: 1001"); } -TEST_P(QuicPacketGeneratorTest, SetCurrentPath) { +TEST_F(QuicPacketGeneratorTest, SetCurrentPath) { delegate_.SetCanWriteAnything(); generator_.StartBatchOperations(); QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVector("foo"), 2, true, MAY_FEC_PROTECT, nullptr); + kHeadersStreamId, MakeIOVector("foo"), 2, true, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc index 7de88d7..d41f8f9 100644 --- a/net/quic/quic_protocol.cc +++ b/net/quic/quic_protocol.cc @@ -19,41 +19,33 @@ namespace net { const char* const kFinalOffsetHeaderKey = ":final-offset"; size_t GetPacketHeaderSize(const QuicPacketHeader& header) { - return GetPacketHeaderSize( - header.public_header.connection_id_length, - header.public_header.version_flag, header.public_header.multipath_flag, - header.public_header.packet_number_length, header.is_in_fec_group); + return GetPacketHeaderSize(header.public_header.connection_id_length, + header.public_header.version_flag, + header.public_header.multipath_flag, + header.public_header.packet_number_length); } size_t GetPacketHeaderSize(QuicConnectionIdLength connection_id_length, bool include_version, bool include_path_id, - QuicPacketNumberLength packet_number_length, - InFecGroup is_in_fec_group) { + QuicPacketNumberLength packet_number_length) { return kPublicFlagsSize + connection_id_length + (include_version ? kQuicVersionSize : 0) + (include_path_id ? kQuicPathIdSize : 0) + packet_number_length + - kPrivateFlagsSize + - (is_in_fec_group == IN_FEC_GROUP ? kFecGroupSize : 0); + kPrivateFlagsSize; } -size_t GetStartOfFecProtectedData(QuicConnectionIdLength connection_id_length, - bool include_version, - bool include_path_id, - QuicPacketNumberLength packet_number_length) { - return GetPacketHeaderSize(connection_id_length, include_version, - include_path_id, packet_number_length, - IN_FEC_GROUP); +size_t GetStartOfEncryptedData(const QuicPacketHeader& header) { + return GetPacketHeaderSize(header) - kPrivateFlagsSize; } size_t GetStartOfEncryptedData(QuicConnectionIdLength connection_id_length, bool include_version, bool include_path_id, QuicPacketNumberLength packet_number_length) { - // Don't include the fec size, since encryption starts before private flags. + // Encryption starts before private flags. return GetPacketHeaderSize(connection_id_length, include_version, - include_path_id, packet_number_length, - NOT_IN_FEC_GROUP) - + include_path_id, packet_number_length) - kPrivateFlagsSize; } @@ -296,8 +288,7 @@ QuicAckFrame::QuicAckFrame() entropy_hash(0), is_truncated(false), largest_observed(0), - ack_delay_time(QuicTime::Delta::Infinite()), - latest_revived_packet(0) {} + ack_delay_time(QuicTime::Delta::Infinite()) {} QuicAckFrame::QuicAckFrame(const QuicAckFrame& other) = default; @@ -533,7 +524,6 @@ ostream& operator<<(ostream& os, const QuicAckFrame& ack_frame) { << " ack_delay_time: " << ack_frame.ack_delay_time.ToMicroseconds() << " missing_packets: [ " << ack_frame.missing_packets << " ] is_truncated: " << ack_frame.is_truncated - << " revived_packet: " << ack_frame.latest_revived_packet << " received_packets: [ "; for (const std::pair<QuicPacketNumber, QuicTime>& p : ack_frame.received_packet_times) { @@ -702,13 +692,6 @@ QuicEncryptedPacket::QuicEncryptedPacket(char* buffer, bool owns_buffer) : QuicData(buffer, length, owns_buffer) {} -StringPiece QuicPacket::FecProtectedData() const { - const size_t start_of_fec = - GetStartOfFecProtectedData(connection_id_length_, includes_version_, - includes_path_id_, packet_number_length_); - return StringPiece(data() + start_of_fec, length() - start_of_fec); -} - StringPiece QuicPacket::AssociatedData() const { return StringPiece(data(), GetStartOfEncryptedData( connection_id_length_, includes_version_, @@ -751,7 +734,6 @@ SerializedPacket::SerializedPacket(QuicPathId path_id, packet_number_length(packet_number_length), encryption_level(ENCRYPTION_NONE), entropy_hash(entropy_hash), - is_fec_packet(false), has_ack(has_ack), has_stop_waiting(has_stop_waiting), original_packet_number(0), @@ -781,7 +763,6 @@ TransmissionInfo::TransmissionInfo() transmission_type(NOT_RETRANSMISSION), in_flight(false), is_unackable(false), - is_fec_packet(false), has_crypto_handshake(false), needs_padding(false), retransmission(0) {} @@ -791,7 +772,6 @@ TransmissionInfo::TransmissionInfo(EncryptionLevel level, TransmissionType transmission_type, QuicTime sent_time, QuicPacketLength bytes_sent, - bool is_fec_packet, bool has_crypto_handshake, bool needs_padding) : encryption_level(level), @@ -802,7 +782,6 @@ TransmissionInfo::TransmissionInfo(EncryptionLevel level, transmission_type(transmission_type), in_flight(false), is_unackable(false), - is_fec_packet(is_fec_packet), has_crypto_handshake(has_crypto_handshake), needs_padding(needs_padding), retransmission(0) {} diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h index 1b275cb..25fa411 100644 --- a/net/quic/quic_protocol.h +++ b/net/quic/quic_protocol.h @@ -140,6 +140,9 @@ NET_EXPORT_PRIVATE extern const char* const kFinalOffsetHeaderKey; // Maximum delayed ack time, in ms. const int64_t kMaxDelayedAckTimeMs = 25; +// Minimum tail loss probe time in ms. +static const int64_t kMinTailLossProbeTimeoutMs = 10; + // The timeout before the handshake succeeds. const int64_t kInitialIdleTimeoutSecs = 5; // The default idle timeout. @@ -234,26 +237,6 @@ enum class ConnectionCloseSource { FROM_PEER, FROM_SELF }; NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const Perspective& s); -// Indicates FEC protection level for data being written. -enum FecProtection { - MUST_FEC_PROTECT, // Callee must FEC protect this data. - MAY_FEC_PROTECT // Callee does not have to but may FEC protect this data. -}; - -// Indicates FEC policy. -enum FecPolicy { - FEC_PROTECT_ALWAYS, // All data in the stream should be FEC protected. - FEC_PROTECT_OPTIONAL // Data in the stream does not need FEC protection. -}; - -// Indicates FEC policy about when to send FEC packet. -enum FecSendPolicy { - // Send FEC packet when FEC group is full or when FEC alarm goes off. - FEC_ANY_TRIGGER, - // Send FEC packet only when FEC alarm goes off. - FEC_ALARM_TRIGGER -}; - enum QuicFrameType { // Regular frame types. The values set here cannot change without the // introduction of a new QUIC version. @@ -426,24 +409,19 @@ NET_EXPORT_PRIVATE QuicTag MakeQuicTag(char a, char b, char c, char d); NET_EXPORT_PRIVATE bool ContainsQuicTag(const QuicTagVector& tag_vector, QuicTag tag); -// Size in bytes of the data or fec packet header. +// Size in bytes of the data packet header. NET_EXPORT_PRIVATE size_t GetPacketHeaderSize(const QuicPacketHeader& header); NET_EXPORT_PRIVATE size_t GetPacketHeaderSize(QuicConnectionIdLength connection_id_length, bool include_version, bool include_path_id, - QuicPacketNumberLength packet_number_length, - InFecGroup is_in_fec_group); + QuicPacketNumberLength packet_number_length); -// Index of the first byte in a QUIC packet of FEC protected data. +// Index of the first byte in a QUIC packet of encrypted data. NET_EXPORT_PRIVATE size_t -GetStartOfFecProtectedData(QuicConnectionIdLength connection_id_length, - bool include_version, - bool include_path_id, - QuicPacketNumberLength packet_number_length); +GetStartOfEncryptedData(const QuicPacketHeader& header); -// Index of the first byte in a QUIC packet of encrypted data. NET_EXPORT_PRIVATE size_t GetStartOfEncryptedData(QuicConnectionIdLength connection_id_length, bool include_version, @@ -709,7 +687,7 @@ struct NET_EXPORT_PRIVATE QuicPacketPublicHeader { // An integer which cannot be a packet number. const QuicPacketNumber kInvalidPacketNumber = 0; -// Header for Data or FEC packets. +// Header for Data packets. struct NET_EXPORT_PRIVATE QuicPacketHeader { QuicPacketHeader(); explicit QuicPacketHeader(const QuicPacketPublicHeader& header); @@ -998,10 +976,6 @@ struct NET_EXPORT_PRIVATE QuicAckFrame { // The set of packets which we're expecting and have not received. PacketNumberQueue missing_packets; - - // Packet most recently revived via FEC, 0 if no packet was revived by FEC. - // If non-zero, must be present in missing_packets. - QuicPacketNumber latest_revived_packet; }; // True if the packet number is greater than largest_observed or is listed @@ -1235,7 +1209,6 @@ class NET_EXPORT_PRIVATE QuicPacket : public QuicData { bool includes_path_id, QuicPacketNumberLength packet_number_length); - base::StringPiece FecProtectedData() const; base::StringPiece AssociatedData() const; base::StringPiece Plaintext() const; @@ -1326,7 +1299,6 @@ struct NET_EXPORT_PRIVATE SerializedPacket { QuicPacketNumberLength packet_number_length; EncryptionLevel encryption_level; QuicPacketEntropyHash entropy_hash; - bool is_fec_packet; bool has_ack; bool has_stop_waiting; QuicPacketNumber original_packet_number; @@ -1347,7 +1319,6 @@ struct NET_EXPORT_PRIVATE TransmissionInfo { TransmissionType transmission_type, QuicTime sent_time, QuicPacketLength bytes_sent, - bool is_fec_packet, bool has_crypto_handshake, bool needs_padding); @@ -1367,8 +1338,6 @@ struct NET_EXPORT_PRIVATE TransmissionInfo { bool in_flight; // True if the packet can never be acked, so it can be removed. bool is_unackable; - // True if the packet is an FEC packet. - bool is_fec_packet; // True if the packet contains stream data from the crypto stream. bool has_crypto_handshake; // True if the packet needs padding if it's retransmitted. diff --git a/net/quic/quic_received_packet_manager.cc b/net/quic/quic_received_packet_manager.cc index 984aa6f..aa3c9fd 100644 --- a/net/quic/quic_received_packet_manager.cc +++ b/net/quic/quic_received_packet_manager.cc @@ -178,18 +178,6 @@ void QuicReceivedPacketManager::RecordPacketReceived( ack_frame_.received_packet_times.push_back( std::make_pair(packet_number, receipt_time)); - - if (ack_frame_.latest_revived_packet == packet_number) { - ack_frame_.latest_revived_packet = 0; - } -} - -void QuicReceivedPacketManager::RecordPacketRevived( - QuicPacketNumber packet_number) { - QUIC_BUG_IF(!IsAwaitingPacket(packet_number)) << base::StringPrintf( - "Not waiting for %llu", static_cast<unsigned long long>(packet_number)); - ack_frame_updated_ = true; - ack_frame_.latest_revived_packet = packet_number; } bool QuicReceivedPacketManager::IsMissing(QuicPacketNumber packet_number) { @@ -259,9 +247,6 @@ QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash( bool QuicReceivedPacketManager::DontWaitForPacketsBefore( QuicPacketNumber least_unacked) { - if (ack_frame_.latest_revived_packet < least_unacked) { - ack_frame_.latest_revived_packet = 0; - } return ack_frame_.missing_packets.RemoveUpTo(least_unacked); } @@ -287,6 +272,10 @@ void QuicReceivedPacketManager::UpdatePacketInformationSentByPeer( ack_frame_.missing_packets.Min() >= peer_least_packet_awaiting_ack_); } +bool QuicReceivedPacketManager::HasMissingPackets() const { + return !ack_frame_.missing_packets.Empty(); +} + bool QuicReceivedPacketManager::HasNewMissingPackets() const { return !ack_frame_.missing_packets.Empty() && (ack_frame_.largest_observed - ack_frame_.missing_packets.Max()) <= diff --git a/net/quic/quic_received_packet_manager.h b/net/quic/quic_received_packet_manager.h index 404f24f..173e47f 100644 --- a/net/quic/quic_received_packet_manager.h +++ b/net/quic/quic_received_packet_manager.h @@ -109,8 +109,6 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager const QuicPacketHeader& header, QuicTime receipt_time); - virtual void RecordPacketRevived(QuicPacketNumber packet_number); - // Checks whether |packet_number| is missing and less than largest observed. virtual bool IsMissing(QuicPacketNumber packet_number); @@ -131,6 +129,9 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager virtual void UpdatePacketInformationSentByPeer( const QuicStopWaitingFrame& stop_waiting); + // Returns true if there are any missing packets. + bool HasMissingPackets() const; + // Returns true when there are new missing packets to be reported within 3 // packets of the largest observed. virtual bool HasNewMissingPackets() const; diff --git a/net/quic/quic_received_packet_manager_test.cc b/net/quic/quic_received_packet_manager_test.cc index 4f2443c..535ddab 100644 --- a/net/quic/quic_received_packet_manager_test.cc +++ b/net/quic/quic_received_packet_manager_test.cc @@ -203,10 +203,6 @@ class QuicReceivedPacketManagerTest : public ::testing::Test { received_manager_.RecordPacketReceived(0u, header, receipt_time); } - void RecordPacketRevived(QuicPacketNumber packet_number) { - received_manager_.RecordPacketRevived(packet_number); - } - QuicConnectionStats stats_; QuicReceivedPacketManager received_manager_; }; @@ -354,57 +350,6 @@ TEST_F(QuicReceivedPacketManagerTest, UpdateReceivedConnectionStats) { EXPECT_EQ(1u, stats_.packets_reordered); } -TEST_F(QuicReceivedPacketManagerTest, RevivedPacket) { - EXPECT_FALSE(received_manager_.ack_frame_updated()); - RecordPacketReceipt(1, 0); - EXPECT_TRUE(received_manager_.ack_frame_updated()); - RecordPacketReceipt(3, 0); - RecordPacketRevived(2); - - QuicAckFrame ack; - received_manager_.UpdateReceivedPacketInfo(&ack, QuicTime::Zero()); - EXPECT_FALSE(received_manager_.ack_frame_updated()); - EXPECT_EQ(1u, ack.missing_packets.NumPacketsSlow()); - EXPECT_EQ(2u, ack.missing_packets.Min()); - EXPECT_EQ(2u, ack.latest_revived_packet); -} - -TEST_F(QuicReceivedPacketManagerTest, PacketRevivedThenReceived) { - EXPECT_FALSE(received_manager_.ack_frame_updated()); - RecordPacketReceipt(1, 0); - EXPECT_TRUE(received_manager_.ack_frame_updated()); - RecordPacketReceipt(3, 0); - RecordPacketRevived(2); - RecordPacketReceipt(2, 0); - - QuicAckFrame ack; - received_manager_.UpdateReceivedPacketInfo(&ack, QuicTime::Zero()); - EXPECT_TRUE(ack.missing_packets.Empty()); - EXPECT_EQ(0u, ack.latest_revived_packet); -} - -TEST_F(QuicReceivedPacketManagerTest, RevivedPacketAckFrameUpdated) { - EXPECT_FALSE(received_manager_.ack_frame_updated()); - RecordPacketReceipt(1, 0); - RecordPacketReceipt(3, 0); - EXPECT_TRUE(received_manager_.ack_frame_updated()); - - QuicAckFrame ack; - received_manager_.UpdateReceivedPacketInfo(&ack, QuicTime::Zero()); - EXPECT_FALSE(received_manager_.ack_frame_updated()); - EXPECT_EQ(1u, ack.missing_packets.NumPacketsSlow()); - EXPECT_EQ(2u, ack.missing_packets.Min()); - EXPECT_EQ(0u, ack.latest_revived_packet); - - RecordPacketRevived(2); - EXPECT_TRUE(received_manager_.ack_frame_updated()); - received_manager_.UpdateReceivedPacketInfo(&ack, QuicTime::Zero()); - EXPECT_FALSE(received_manager_.ack_frame_updated()); - EXPECT_EQ(1u, ack.missing_packets.NumPacketsSlow()); - EXPECT_EQ(2u, ack.missing_packets.Min()); - EXPECT_EQ(2u, ack.latest_revived_packet); -} - } // namespace } // namespace test } // namespace net diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc index fbe446b..2bdd196 100644 --- a/net/quic/quic_sent_packet_manager.cc +++ b/net/quic/quic_sent_packet_manager.cc @@ -47,7 +47,6 @@ static const int64_t kMinHandshakeTimeoutMs = 10; // Sends up to two tail loss probes before firing an RTO, // per draft RFC draft-dukkipati-tcpm-tcp-loss-probe. static const size_t kDefaultMaxTailLossProbes = 2; -static const int64_t kMinTailLossProbeTimeoutMs = 10; // Number of unpaced packets to send after quiescence. static const size_t kInitialUnpacedBurst = 10; @@ -322,12 +321,6 @@ void QuicSentPacketManager::HandleAckForSentPackets( } MarkPacketHandled(packet_number, &(*it), ack_delay_time); } - - // Discard any retransmittable frames associated with revived packets. - if (ack_frame.latest_revived_packet != 0) { - MarkPacketNotRetransmittable(ack_frame.latest_revived_packet, - ack_delay_time); - } } bool QuicSentPacketManager::HasRetransmittableFrames( @@ -346,9 +339,6 @@ void QuicSentPacketManager::RetransmitUnackedPackets( (retransmission_type == ALL_UNACKED_RETRANSMISSION || it->encryption_level == ENCRYPTION_INITIAL)) { MarkForRetransmission(packet_number, retransmission_type); - } else if (it->is_fec_packet) { - // Remove FEC packets from the packet map, since we can't retransmit them. - unacked_packets_.RemoveFromInFlight(packet_number); } } } @@ -487,8 +477,6 @@ void QuicSentPacketManager::MarkPacketNotRetransmittable( pending_retransmissions_.erase(newest_transmission); } - // The AckListener needs to be notified for revived packets, - // since it indicates the packet arrived from the appliction's perspective. unacked_packets_.NotifyAndClearListeners(newest_transmission, ack_delay_time); unacked_packets_.RemoveRetransmittability(packet_number); } @@ -568,16 +556,10 @@ bool QuicSentPacketManager::OnPacketSent( --pending_timer_transmission_count_; } - // Only track packets as in flight that the send algorithm wants us to track. - // Since FEC packets should also be counted towards the congestion window, - // consider them as retransmittable for the purposes of congestion control. - HasRetransmittableData has_congestion_controlled_data = - serialized_packet->is_fec_packet ? HAS_RETRANSMITTABLE_DATA - : has_retransmittable_data; // TODO(ianswett): Remove sent_time, because it's unused. const bool in_flight = send_algorithm_->OnPacketSent( sent_time, unacked_packets_.bytes_in_flight(), packet_number, - serialized_packet->encrypted_length, has_congestion_controlled_data); + serialized_packet->encrypted_length, has_retransmittable_data); unacked_packets_.AddSentPacket(serialized_packet, original_packet_number, transmission_type, sent_time, in_flight); @@ -733,8 +715,8 @@ void QuicSentPacketManager::InvokeLossDetection(QuicTime time) { } else { // Since we will not retransmit this, we need to remove it from // unacked_packets_. This is either the current transmission of - // a packet whose previous transmission has been acked, a packet that - // has been TLP retransmitted, or an FEC packet. + // a packet whose previous transmission has been acked or a packet that + // has been TLP retransmitted. unacked_packets_.RemoveFromInFlight(pair.first); } } diff --git a/net/quic/quic_sent_packet_manager.h b/net/quic/quic_sent_packet_manager.h index 15b12d6..af3b953 100644 --- a/net/quic/quic_sent_packet_manager.h +++ b/net/quic/quic_sent_packet_manager.h @@ -133,7 +133,7 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager { // Processes the incoming ack. void OnIncomingAck(const QuicAckFrame& ack_frame, QuicTime ack_receive_time); - // Returns true if the non-FEC packet |packet_number| is unacked. + // Returns true if packet |packet_number| is unacked. bool IsUnacked(QuicPacketNumber packet_number) const; // Requests retransmission of all unacked packets of |retransmission_type|. @@ -337,7 +337,10 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager { QuicByteCount bytes_in_flight); // Called when frames of |packet_number| has been received but the packet - // itself has not been received by the peer (e.g., packet is revived by FEC). + // itself has not been received by the peer. Currently, this method is not + // used. + // TODO(fayang): Update the comment when multipath sent packet manager is + // landed. // The packet needs no longer to be retransmitted, but the packet remains // pending if it is and the congestion control does not consider the packet // acked. @@ -375,8 +378,8 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager { // RTT measurement purposes. void RemoveObsoletePackets(); - // Newly serialized retransmittable and fec packets are added to this map, - // which contains owning pointers to any contained frames. If a packet is + // Newly serialized retransmittable packets are added to this map, which + // contains owning pointers to any contained frames. If a packet is // retransmitted, this map will contain entries for both the old and the new // packet. The old packet's retransmittable frames entry will be nullptr, // while the new packet's entry will contain the frames to retransmit. diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc index f8cfce7..76de6ed 100644 --- a/net/quic/quic_sent_packet_manager_test.cc +++ b/net/quic/quic_sent_packet_manager_test.cc @@ -206,14 +206,6 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> { return packet; } - SerializedPacket CreateFecPacket(QuicPacketNumber packet_number) { - SerializedPacket serialized(kDefaultPathId, packet_number, - PACKET_6BYTE_PACKET_NUMBER, nullptr, - kDefaultLength, 0u, false, false); - serialized.is_fec_packet = true; - return serialized; - } - void SendDataPacket(QuicPacketNumber packet_number) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, BytesInFlight(), packet_number, _, _)) @@ -238,17 +230,6 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> { HAS_RETRANSMITTABLE_DATA); } - void SendFecPacket(QuicPacketNumber packet_number) { - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, BytesInFlight(), packet_number, kDefaultLength, - HAS_RETRANSMITTABLE_DATA)) - .Times(1) - .WillOnce(Return(true)); - SerializedPacket packet(CreateFecPacket(packet_number)); - manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION, - NO_RETRANSMITTABLE_DATA); - } - void SendAckPacket(QuicPacketNumber packet_number) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, BytesInFlight(), packet_number, kDefaultLength, @@ -501,76 +482,6 @@ TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) { EXPECT_EQ(2u, stats_.packets_spuriously_retransmitted); } -TEST_F(QuicSentPacketManagerTest, LoseButDontRetransmitRevivedPacket) { - StrictMock<MockDebugDelegate> debug_delegate; - manager_.set_debug_delegate(&debug_delegate); - - SendDataPacket(1); - SendDataPacket(2); - SendFecPacket(3); - SendDataPacket(4); - - // Ack 2 and 3, and mark 1 as revived. - QuicAckFrame ack_frame; - ack_frame.largest_observed = 3; - ack_frame.missing_packets.Add(1); - ack_frame.latest_revived_packet = 1; - QuicPacketNumber acked[] = {2, 3}; - ExpectAcksAndLosses(true, acked, arraysize(acked), nullptr, 0); - manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()); - - EXPECT_FALSE(manager_.HasPendingRetransmissions()); - QuicPacketNumber unacked[] = {1, 4}; - VerifyUnackedPackets(unacked, arraysize(unacked)); - EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_)); - QuicPacketNumber retransmittable[] = {4}; - VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable)); - - // Ack the 4th packet and expect the 1st to be considered lost. - if (FLAGS_quic_log_loss_event) { - EXPECT_CALL(debug_delegate, OnPacketLoss(1, LOSS_RETRANSMISSION, _)); - } - ack_frame.largest_observed = 4; - ExpectAckAndLoss(true, 4, 1); - manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()); - - EXPECT_FALSE(manager_.HasPendingRetransmissions()); - VerifyRetransmittablePackets(nullptr, 0); -} - -TEST_F(QuicSentPacketManagerTest, MarkLostThenReviveAndDontRetransmitPacket) { - SendDataPacket(1); - SendDataPacket(2); - SendDataPacket(3); - SendDataPacket(4); - SendFecPacket(5); - - // Ack 2, 3, and 4, and expect the 1st to be considered lost. - QuicAckFrame ack_frame; - ack_frame.largest_observed = 4; - ack_frame.missing_packets.Add(1); - QuicPacketNumber acked[] = {2, 3, 4}; - QuicPacketNumber lost[] = {1}; - ExpectAcksAndLosses(true, acked, arraysize(acked), lost, arraysize(lost)); - manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()); - - EXPECT_TRUE(manager_.HasPendingRetransmissions()); - QuicPacketNumber unacked[] = {1, 5}; - VerifyUnackedPackets(unacked, arraysize(unacked)); - QuicPacketNumber retransmittable[] = {1}; - VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable)); - - // Ack 5th packet (FEC) and revive 1st packet. 1st packet should now be - // removed from pending retransmissions map. - ack_frame.largest_observed = 5; - ack_frame.latest_revived_packet = 1; - ExpectAck(5); - manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()); - - EXPECT_FALSE(manager_.HasPendingRetransmissions()); - VerifyRetransmittablePackets(nullptr, 0); -} - TEST_F(QuicSentPacketManagerTest, AckPreviousTransmissionThenTruncatedAck) { SendDataPacket(1); RetransmitAndSendPacket(1, 2); @@ -618,53 +529,6 @@ TEST_F(QuicSentPacketManagerTest, GetLeastUnackedUnacked) { EXPECT_EQ(1u, manager_.GetLeastUnacked()); } -TEST_F(QuicSentPacketManagerTest, GetLeastUnackedUnackedFec) { - SendFecPacket(1); - EXPECT_EQ(1u, manager_.GetLeastUnacked()); -} - -TEST_F(QuicSentPacketManagerTest, GetLeastUnackedAndDiscard) { - VerifyUnackedPackets(nullptr, 0); - - SendFecPacket(1); - EXPECT_EQ(1u, manager_.GetLeastUnacked()); - - SendFecPacket(2); - EXPECT_EQ(1u, manager_.GetLeastUnacked()); - - SendFecPacket(3); - EXPECT_EQ(1u, manager_.GetLeastUnacked()); - - QuicPacketNumber unacked[] = {1, 2, 3}; - VerifyUnackedPackets(unacked, arraysize(unacked)); - VerifyRetransmittablePackets(nullptr, 0); - - // Ack 2, so there's an rtt update. - ExpectAck(2); - QuicAckFrame ack_frame; - ack_frame.largest_observed = 2; - ack_frame.missing_packets.Add(1); - manager_.OnIncomingAck(ack_frame, clock_.Now()); - - EXPECT_EQ(1u, manager_.GetLeastUnacked()); -} - -TEST_F(QuicSentPacketManagerTest, GetSentTime) { - VerifyUnackedPackets(nullptr, 0); - - QuicTime sent_time = clock_.Now(); - SendFecPacket(1); - QuicTime sent_time2 = clock_.Now(); - SendFecPacket(2); - QuicPacketNumber unacked[] = {1, 2}; - VerifyUnackedPackets(unacked, arraysize(unacked)); - VerifyRetransmittablePackets(nullptr, 0); - - EXPECT_TRUE(manager_.HasUnackedPackets()); - EXPECT_EQ(sent_time, QuicSentPacketManagerPeer::GetSentTime(&manager_, 1)); - EXPECT_EQ(sent_time2, QuicSentPacketManagerPeer::GetSentTime(&manager_, 2)); -} - TEST_F(QuicSentPacketManagerTest, AckAckAndUpdateRtt) { SendDataPacket(1); SendAckPacket(2); diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc index d8ec06c..1d880fe 100644 --- a/net/quic/quic_session.cc +++ b/net/quic/quic_session.cc @@ -239,16 +239,14 @@ QuicConsumedData QuicSession::WritevData( QuicIOVector iov, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface* ack_notifier_delegate) { - if (FLAGS_quic_block_unencrypted_writes && !IsEncryptionEstablished() && - id != kCryptoStreamId) { + if (!IsEncryptionEstablished() && id != kCryptoStreamId) { // Do not let streams write without encryption. The calling stream will end // up write blocked until OnCanWrite is next called. return QuicConsumedData(0, false); } - QuicConsumedData data = connection_->SendStreamData( - id, iov, offset, fin, fec_protection, ack_notifier_delegate); + QuicConsumedData data = + connection_->SendStreamData(id, iov, offset, fin, ack_notifier_delegate); write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed); return data; } @@ -530,9 +528,7 @@ void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { // to QuicSession since it is the glue. case ENCRYPTION_FIRST_ESTABLISHED: // Given any streams blocked by encryption a chance to write. - if (FLAGS_quic_block_unencrypted_writes) { - OnCanWrite(); - } + OnCanWrite(); break; case ENCRYPTION_REESTABLISHED: @@ -540,9 +536,7 @@ void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { // decrypted by the peer. connection_->RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION); // Given any streams blocked by encryption a chance to write. - if (FLAGS_quic_block_unencrypted_writes) { - OnCanWrite(); - } + OnCanWrite(); break; case HANDSHAKE_CONFIRMED: diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h index e0e3e809..988c000 100644 --- a/net/quic/quic_session.h +++ b/net/quic/quic_session.h @@ -94,10 +94,7 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { // Returns a pair with the number of bytes consumed from data, and a boolean // indicating if the fin bit was consumed. This does not indicate the data // has been sent on the wire: it may have been turned into a packet and queued - // if the socket was unexpectedly blocked. |fec_protection| indicates if - // data is to be FEC protected. Note that data that is sent immediately - // following MUST_FEC_PROTECT data may get protected by falling within the - // same FEC group. + // if the socket was unexpectedly blocked. // If provided, |ack_notifier_delegate| will be registered to be notified when // we have seen ACKs for all packets resulting from this call. virtual QuicConsumedData WritevData( @@ -105,7 +102,6 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { QuicIOVector iov, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface* ack_notifier_delegate); // Called by streams when they want to close the stream in both directions. diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc index a0da6b9..268b5d2 100644 --- a/net/quic/quic_session_test.cc +++ b/net/quic/quic_session_test.cc @@ -155,12 +155,11 @@ class TestSession : public QuicSpdySession { QuicIOVector data, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface* ack_notifier_delegate) override { QuicConsumedData consumed(data.total_length, fin); if (!writev_consumes_all_data_) { - consumed = QuicSession::WritevData(id, data, offset, fin, fec_protection, - ack_notifier_delegate); + consumed = + QuicSession::WritevData(id, data, offset, fin, ack_notifier_delegate); } QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream( id, consumed.bytes_consumed); @@ -173,8 +172,7 @@ class TestSession : public QuicSpdySession { QuicConsumedData SendStreamData(QuicStreamId id) { struct iovec iov; - return WritevData(id, MakeIOVector("not empty", &iov), 0, true, - MAY_FEC_PROTECT, nullptr); + return WritevData(id, MakeIOVector("not empty", &iov), 0, true, nullptr); } QuicConsumedData SendLargeFakeData(QuicStreamId id, int bytes) { @@ -182,8 +180,7 @@ class TestSession : public QuicSpdySession { struct iovec iov; iov.iov_base = nullptr; // should not be read. iov.iov_len = static_cast<size_t>(bytes); - return WritevData(id, QuicIOVector(&iov, 1, bytes), 0, true, - MAY_FEC_PROTECT, nullptr); + return WritevData(id, QuicIOVector(&iov, 1, bytes), 0, true, nullptr); } using QuicSession::PostProcessAfterData; @@ -388,29 +385,19 @@ TEST_P(QuicSessionTestServer, OnCanWrite) { InSequence s; StreamBlocker stream2_blocker(&session_, stream2->id()); - if (FLAGS_quic_batch_writes) { - // Reregister, to test the loop limit. - EXPECT_CALL(*stream2, OnCanWrite()) - .WillOnce(Invoke(&stream2_blocker, - &StreamBlocker::MarkConnectionLevelWriteBlocked)); - // 2 will get called a second time as it didn't finish its block - EXPECT_CALL(*stream2, OnCanWrite()); - EXPECT_CALL(*stream6, OnCanWrite()); - // 4 will not get called, as we exceeded the loop limit. - } else { - // Reregister, to test the loop limit. - EXPECT_CALL(*stream2, OnCanWrite()) - .WillOnce(Invoke(&stream2_blocker, - &StreamBlocker::MarkConnectionLevelWriteBlocked)); - EXPECT_CALL(*stream6, OnCanWrite()); - EXPECT_CALL(*stream4, OnCanWrite()); - } + // Reregister, to test the loop limit. + EXPECT_CALL(*stream2, OnCanWrite()) + .WillOnce(Invoke(&stream2_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked)); + // 2 will get called a second time as it didn't finish its block + EXPECT_CALL(*stream2, OnCanWrite()); + EXPECT_CALL(*stream6, OnCanWrite()); + // 4 will not get called, as we exceeded the loop limit. session_.OnCanWrite(); EXPECT_TRUE(session_.WillingAndAbleToWrite()); } TEST_P(QuicSessionTestServer, TestBatchedWrites) { - ValueRestore<bool> old_flag(&FLAGS_quic_batch_writes, true); TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority); TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority); TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority); diff --git a/net/quic/quic_spdy_stream_test.cc b/net/quic/quic_spdy_stream_test.cc index 54ebb8a..4f71cb7 100644 --- a/net/quic/quic_spdy_stream_test.cc +++ b/net/quic/quic_spdy_stream_test.cc @@ -363,7 +363,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) { GenerateBody(&body, kWindow + kOverflow); EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)); - EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _)) .WillOnce(Return(QuicConsumedData(kWindow, true))); stream_->WriteOrBufferData(body, false, nullptr); @@ -609,7 +609,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) { bool fin = true; EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)).Times(0); - EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _)) .WillOnce(Return(QuicConsumedData(0, fin))); stream_->WriteOrBufferData(body, fin, nullptr); @@ -732,7 +732,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) { // Test that writing trailers will send a FIN, as Trailers are the last thing // to be sent on a stream. Initialize(kShouldProcessData); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .Times(AnyNumber()) .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); @@ -753,7 +753,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) { // Test that when writing trailers, the trailers that are actually sent to the // peer contain the final offset field indicating last byte of data. Initialize(kShouldProcessData); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .Times(AnyNumber()) .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); @@ -780,7 +780,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) { // Test that if trailers are written after all other data has been written // (headers and body), that this closes the stream for writing. Initialize(kShouldProcessData); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .Times(AnyNumber()) .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); @@ -805,7 +805,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) { // Test that the stream is not closed for writing when trailers are sent // while there are still body bytes queued. Initialize(kShouldProcessData); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .Times(AnyNumber()) .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); @@ -815,7 +815,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) { // Write non-zero body data, but only consume partially, ensuring queueing. const int kBodySize = 1 * 1024; // 1 MB - EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillOnce(Return(QuicConsumedData(kBodySize - 1, false))); stream_->WriteOrBufferData(string(kBodySize, 'x'), false, nullptr); EXPECT_EQ(1u, stream_->queued_data_bytes()); @@ -832,7 +832,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) { TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) { // Test that it is not possible to write Trailers after a FIN has been sent. Initialize(kShouldProcessData); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .Times(AnyNumber()) .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); diff --git a/net/quic/quic_unacked_packet_map.cc b/net/quic/quic_unacked_packet_map.cc index c8a3250..fc72388 100644 --- a/net/quic/quic_unacked_packet_map.cc +++ b/net/quic/quic_unacked_packet_map.cc @@ -49,8 +49,7 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet, packet->has_crypto_handshake == IS_HANDSHAKE; TransmissionInfo info(packet->encryption_level, packet->packet_number_length, transmission_type, sent_time, bytes_sent, - packet->is_fec_packet, has_crypto_handshake, - packet->needs_padding); + has_crypto_handshake, packet->needs_padding); if (old_packet_number > 0) { TransferRetransmissionInfo(old_packet_number, packet_number, transmission_type, &info); diff --git a/net/quic/quic_unacked_packet_map.h b/net/quic/quic_unacked_packet_map.h index 8ed6d0a..31fc7f4 100644 --- a/net/quic/quic_unacked_packet_map.h +++ b/net/quic/quic_unacked_packet_map.h @@ -175,8 +175,8 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap { QuicPacketNumber largest_sent_packet_; QuicPacketNumber largest_observed_; - // Newly serialized retransmittable and fec packets are added to this map, - // which contains owning pointers to any contained frames. If a packet is + // Newly serialized retransmittable packets are added to this map, which + // contains owning pointers to any contained frames. If a packet is // retransmitted, this map will contain entries for both the old and the new // packet. The old packet's retransmittable frames entry will be nullptr, // while the new packet's entry will contain the frames to retransmit. diff --git a/net/quic/quic_write_blocked_list.h b/net/quic/quic_write_blocked_list.h index d004452..2988a9d 100644 --- a/net/quic/quic_write_blocked_list.h +++ b/net/quic/quic_write_blocked_list.h @@ -135,7 +135,6 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList { return; } bool push_front = - FLAGS_quic_batch_writes && stream_id == batch_write_stream_id_[last_priority_popped_] && bytes_left_for_batch_write_[last_priority_popped_] > 0; priority_write_scheduler_.MarkStreamReady(stream_id, push_front); diff --git a/net/quic/quic_write_blocked_list_test.cc b/net/quic/quic_write_blocked_list_test.cc index c970a2f..23009c0 100644 --- a/net/quic/quic_write_blocked_list_test.cc +++ b/net/quic/quic_write_blocked_list_test.cc @@ -115,7 +115,6 @@ TEST(QuicWriteBlockedListTest, NoDuplicateEntries) { } TEST(QuicWriteBlockedListTest, BatchingWrites) { - ValueRestore<bool> old_flag(&FLAGS_quic_batch_writes, true); QuicWriteBlockedList write_blocked_list; const QuicStreamId id1 = kClientDataStreamId1; diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc index eea769d..c4c7d5c 100644 --- a/net/quic/reliable_quic_stream.cc +++ b/net/quic/reliable_quic_stream.cc @@ -66,7 +66,6 @@ ReliableQuicStream::ReliableQuicStream(QuicStreamId id, QuicSession* session) fin_received_(false), rst_sent_(false), rst_received_(false), - fec_policy_(FEC_PROTECT_OPTIONAL), perspective_(session_->perspective()), flow_controller_(session_->connection(), id_, @@ -81,11 +80,7 @@ ReliableQuicStream::ReliableQuicStream(QuicStreamId id, QuicSession* session) ReliableQuicStream::~ReliableQuicStream() {} -void ReliableQuicStream::SetFromConfig() { - if (session_->config()->HasClientSentConnectionOption(kFSTR, perspective_)) { - fec_policy_ = FEC_PROTECT_ALWAYS; - } -} +void ReliableQuicStream::SetFromConfig() {} void ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) { DCHECK_EQ(frame.stream_id, id_); @@ -311,9 +306,9 @@ QuicConsumedData ReliableQuicStream::WritevData( write_length = static_cast<size_t>(send_window); } - QuicConsumedData consumed_data = session()->WritevData( - id(), QuicIOVector(iov, iov_count, write_length), stream_bytes_written_, - fin, GetFecProtection(), ack_listener); + QuicConsumedData consumed_data = + session()->WritevData(id(), QuicIOVector(iov, iov_count, write_length), + stream_bytes_written_, fin, ack_listener); stream_bytes_written_ += consumed_data.bytes_consumed; AddBytesSent(consumed_data.bytes_consumed); @@ -343,10 +338,6 @@ QuicConsumedData ReliableQuicStream::WritevData( return consumed_data; } -FecProtection ReliableQuicStream::GetFecProtection() { - return fec_policy_ == FEC_PROTECT_ALWAYS ? MUST_FEC_PROTECT : MAY_FEC_PROTECT; -} - void ReliableQuicStream::CloseReadSide() { if (read_side_closed_) { return; diff --git a/net/quic/reliable_quic_stream.h b/net/quic/reliable_quic_stream.h index 8e660b2..e0be70b 100644 --- a/net/quic/reliable_quic_stream.h +++ b/net/quic/reliable_quic_stream.h @@ -50,7 +50,7 @@ class NET_EXPORT_PRIVATE ReliableQuicStream { virtual ~ReliableQuicStream(); - // Sets |fec_policy_| parameter from |session_|'s config. + // Not in use currently. void SetFromConfig(); // Called by the session when a (potentially duplicate) stream frame has been @@ -118,9 +118,6 @@ class NET_EXPORT_PRIVATE ReliableQuicStream { void set_fin_received(bool fin_received) { fin_received_ = fin_received; } void set_rst_sent(bool rst_sent) { rst_sent_ = rst_sent; } - void set_fec_policy(FecPolicy fec_policy) { fec_policy_ = fec_policy; } - FecPolicy fec_policy() const { return fec_policy_; } - void set_rst_received(bool rst_received) { rst_received_ = rst_received; } void set_stream_error(QuicRstStreamErrorCode error) { stream_error_ = error; } @@ -198,9 +195,6 @@ class NET_EXPORT_PRIVATE ReliableQuicStream { // Does not send a FIN. May cause the stream to be closed. virtual void CloseWriteSide(); - // Helper method that returns FecProtection to use when writing. - FecProtection GetFecProtection(); - bool fin_buffered() const { return fin_buffered_; } const QuicSession* session() const { return session_; } @@ -287,9 +281,6 @@ class NET_EXPORT_PRIVATE ReliableQuicStream { // True if this stream has received a RST_STREAM frame. bool rst_received_; - // FEC policy to be used for this stream. - FecPolicy fec_policy_; - // Tracks if the session this stream is running under was created by a // server or a client. Perspective perspective_; diff --git a/net/quic/reliable_quic_stream_test.cc b/net/quic/reliable_quic_stream_test.cc index b006895..8de1863 100644 --- a/net/quic/reliable_quic_stream_test.cc +++ b/net/quic/reliable_quic_stream_test.cc @@ -141,7 +141,6 @@ class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> { QuicIOVector /*iov*/, QuicStreamOffset /*offset*/, bool /*fin*/, - FecProtection /*fec_protection*/, QuicAckListenerInterface* /*ack_notifier_delegate*/) { session_->CloseStream(id); return QuicConsumedData(1, false); @@ -163,13 +162,12 @@ class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> { TEST_F(ReliableQuicStreamTest, WriteAllData) { Initialize(kShouldProcessData); - size_t length = - 1 + QuicPacketCreator::StreamFramePacketOverhead( - PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId, - PACKET_6BYTE_PACKET_NUMBER, 0u, NOT_IN_FEC_GROUP); + size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead( + PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, 0u); connection_->SetMaxPacketLength(length); - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(Return(QuicConsumedData(kDataLen, true))); stream_->WriteOrBufferData(kData1, false, nullptr); EXPECT_FALSE(HasWriteBlockedStreams()); @@ -189,7 +187,7 @@ TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) { // Write some data and no fin. If we consume some but not all of the data, // we should be write blocked a not all the data was consumed. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(Return(QuicConsumedData(1, false))); stream_->WriteOrBufferData(StringPiece(kData1, 2), false, nullptr); ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams()); @@ -203,7 +201,7 @@ TEST_F(ReliableQuicStreamTest, BlockIfFinNotConsumedWithData) { // we should be write blocked because the fin was not consumed. // (This should never actually happen as the fin should be sent out with the // last data) - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(Return(QuicConsumedData(2, false))); stream_->WriteOrBufferData(StringPiece(kData1, 2), true, nullptr); ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams()); @@ -214,7 +212,7 @@ TEST_F(ReliableQuicStreamTest, BlockIfSoloFinNotConsumed) { // Write no data and a fin. If we consume nothing we should be write blocked, // as the fin was not consumed. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(Return(QuicConsumedData(0, false))); stream_->WriteOrBufferData(StringPiece(), true, nullptr); ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams()); @@ -226,7 +224,7 @@ TEST_F(ReliableQuicStreamTest, CloseOnPartialWrite) { // Write some data and no fin. However, while writing the data // close the stream and verify that MarkConnectionLevelWriteBlocked does not // crash with an unknown stream. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(Invoke(this, &ReliableQuicStreamTest::CloseStreamOnWriteError)); stream_->WriteOrBufferData(StringPiece(kData1, 2), false, nullptr); ASSERT_EQ(0u, write_blocked_list_->NumBlockedStreams()); @@ -236,13 +234,12 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferData) { Initialize(kShouldProcessData); EXPECT_FALSE(HasWriteBlockedStreams()); - size_t length = - 1 + QuicPacketCreator::StreamFramePacketOverhead( - PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId, - PACKET_6BYTE_PACKET_NUMBER, 0u, NOT_IN_FEC_GROUP); + size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead( + PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, + !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER, 0u); connection_->SetMaxPacketLength(length); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillOnce(Return(QuicConsumedData(kDataLen - 1, false))); stream_->WriteOrBufferData(kData1, false, nullptr); EXPECT_TRUE(HasWriteBlockedStreams()); @@ -252,86 +249,14 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferData) { // Make sure we get the tail of the first write followed by the bytes_consumed InSequence s; - EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillOnce(Return(QuicConsumedData(1, false))); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillOnce(Return(QuicConsumedData(kDataLen - 2, false))); stream_->OnCanWrite(); // And finally the end of the bytes_consumed. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) - .WillOnce(Return(QuicConsumedData(2, true))); - stream_->OnCanWrite(); -} - -TEST_F(ReliableQuicStreamTest, WriteOrBufferDataWithFecProtectAlways) { - Initialize(kShouldProcessData); - - // Set FEC policy on stream. - ReliableQuicStreamPeer::SetFecPolicy(stream_, FEC_PROTECT_ALWAYS); - - EXPECT_FALSE(HasWriteBlockedStreams()); - size_t length = - 1 + QuicPacketCreator::StreamFramePacketOverhead( - PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId, - PACKET_6BYTE_PACKET_NUMBER, 0u, IN_FEC_GROUP); - connection_->SetMaxPacketLength(length); - - // Write first data onto stream, which will cause one session write. - EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _)) - .WillOnce(Return(QuicConsumedData(kDataLen - 1, false))); - stream_->WriteOrBufferData(kData1, false, nullptr); - EXPECT_TRUE(HasWriteBlockedStreams()); - - // Queue a bytes_consumed write. - stream_->WriteOrBufferData(kData2, false, nullptr); - - // Make sure we get the tail of the first write followed by the bytes_consumed - InSequence s; - EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _)) - .WillOnce(Return(QuicConsumedData(1, false))); - EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _)) - .WillOnce(Return(QuicConsumedData(kDataLen - 2, false))); - stream_->OnCanWrite(); - - // And finally the end of the bytes_consumed. - EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _)) - .WillOnce(Return(QuicConsumedData(2, true))); - stream_->OnCanWrite(); -} - -TEST_F(ReliableQuicStreamTest, WriteOrBufferDataWithFecProtectOptional) { - Initialize(kShouldProcessData); - - // Set FEC policy on stream. - ReliableQuicStreamPeer::SetFecPolicy(stream_, FEC_PROTECT_OPTIONAL); - - EXPECT_FALSE(HasWriteBlockedStreams()); - size_t length = - 1 + QuicPacketCreator::StreamFramePacketOverhead( - PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, !kIncludePathId, - PACKET_6BYTE_PACKET_NUMBER, 0u, NOT_IN_FEC_GROUP); - connection_->SetMaxPacketLength(length); - - // Write first data onto stream, which will cause one session write. - EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _)) - .WillOnce(Return(QuicConsumedData(kDataLen - 1, false))); - stream_->WriteOrBufferData(kData1, false, nullptr); - EXPECT_TRUE(HasWriteBlockedStreams()); - - // Queue a bytes_consumed write. - stream_->WriteOrBufferData(kData2, false, nullptr); - - // Make sure we get the tail of the first write followed by the bytes_consumed - InSequence s; - EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _)) - .WillOnce(Return(QuicConsumedData(1, false))); - EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _)) - .WillOnce(Return(QuicConsumedData(kDataLen - 2, false))); - stream_->OnCanWrite(); - - // And finally the end of the bytes_consumed. - EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillOnce(Return(QuicConsumedData(2, true))); stream_->OnCanWrite(); } @@ -359,7 +284,7 @@ TEST_F(ReliableQuicStreamTest, RstAlwaysSentIfNoFinSent) { EXPECT_FALSE(rst_sent()); // Write some data, with no FIN. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(Return(QuicConsumedData(1, false))); stream_->WriteOrBufferData(StringPiece(kData1, 1), false, nullptr); EXPECT_FALSE(fin_sent()); @@ -382,7 +307,7 @@ TEST_F(ReliableQuicStreamTest, RstNotSentIfFinSent) { EXPECT_FALSE(rst_sent()); // Write some data, with FIN. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(Return(QuicConsumedData(1, true))); stream_->WriteOrBufferData(StringPiece(kData1, 1), true, nullptr); EXPECT_TRUE(fin_sent()); @@ -476,26 +401,23 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferDataWithQuicAckNotifier) { scoped_refptr<QuicAckListenerInterface> ack_listener; - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(DoAll( - WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))), + WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))), Return(QuicConsumedData(kFirstWriteSize, false)))); stream_->WriteOrBufferData(kData, false, delegate.get()); EXPECT_TRUE(HasWriteBlockedStreams()); - EXPECT_CALL(*session_, - WritevData(kTestStreamId, _, _, _, _, ack_listener.get())) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, ack_listener.get())) .WillOnce(Return(QuicConsumedData(kSecondWriteSize, false))); stream_->OnCanWrite(); // No ack expected for an empty write. - EXPECT_CALL(*session_, - WritevData(kTestStreamId, _, _, _, _, ack_listener.get())) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, ack_listener.get())) .WillOnce(Return(QuicConsumedData(0, false))); stream_->OnCanWrite(); - EXPECT_CALL(*session_, - WritevData(kTestStreamId, _, _, _, _, ack_listener.get())) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, ack_listener.get())) .WillOnce(Return(QuicConsumedData(kLastWriteSize, false))); stream_->OnCanWrite(); } @@ -518,16 +440,16 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferDataAckNotificationBeforeFlush) { scoped_refptr<QuicAckListenerInterface> proxy_delegate; - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(DoAll( - WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), + WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), Return(QuicConsumedData(kInitialWriteSize, false)))); stream_->WriteOrBufferData(kData, false, ack_listener.get()); EXPECT_TRUE(HasWriteBlockedStreams()); - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(DoAll( - WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), + WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), Return(QuicConsumedData(kDataSize - kInitialWriteSize, false)))); stream_->OnCanWrite(); } @@ -540,9 +462,9 @@ TEST_F(ReliableQuicStreamTest, WriteAndBufferDataWithAckNotiferNoBuffer) { scoped_refptr<QuicAckListenerInterface> proxy_delegate; - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(DoAll( - WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), + WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), Return(QuicConsumedData(kDataLen, true)))); stream_->WriteOrBufferData(kData1, true, delegate.get()); EXPECT_FALSE(HasWriteBlockedStreams()); @@ -556,14 +478,14 @@ TEST_F(ReliableQuicStreamTest, BufferOnWriteAndBufferDataWithAckNotifer) { scoped_refptr<QuicAckListenerInterface> proxy_delegate; - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(Return(QuicConsumedData(0, false))); stream_->WriteOrBufferData(kData1, true, delegate.get()); EXPECT_TRUE(HasWriteBlockedStreams()); - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(DoAll( - WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), + WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), Return(QuicConsumedData(kDataLen, true)))); stream_->OnCanWrite(); } @@ -577,16 +499,16 @@ TEST_F(ReliableQuicStreamTest, WriteAndBufferDataWithAckNotiferOnlyFinRemains) { scoped_refptr<QuicAckListenerInterface> proxy_delegate; - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(DoAll( - WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), + WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), Return(QuicConsumedData(kDataLen, false)))); stream_->WriteOrBufferData(kData1, true, delegate.get()); EXPECT_TRUE(HasWriteBlockedStreams()); - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(DoAll( - WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), + WithArgs<4>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))), Return(QuicConsumedData(0, true)))); stream_->OnCanWrite(); } @@ -678,7 +600,7 @@ TEST_F(ReliableQuicStreamTest, SetDrainingIncomingOutgoing) { EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); // Outgoing data with FIN. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(Return(QuicConsumedData(2, true))); stream_->WriteOrBufferData(StringPiece(kData1, 2), true, nullptr); EXPECT_TRUE(stream_->write_side_closed()); @@ -693,7 +615,7 @@ TEST_F(ReliableQuicStreamTest, SetDrainingOutgoingIncoming) { Initialize(kShouldNotProcessData); // Outgoing data with FIN. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) .WillOnce(Return(QuicConsumedData(2, true))); stream_->WriteOrBufferData(StringPiece(kData1, 2), true, nullptr); EXPECT_TRUE(stream_->write_side_closed()); @@ -714,26 +636,13 @@ TEST_F(ReliableQuicStreamTest, SetDrainingOutgoingIncoming) { EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); } -TEST_F(ReliableQuicStreamTest, FecSendPolicyReceivedConnectionOption) { - Initialize(kShouldProcessData); - - // Test ReceivedConnectionOptions. - QuicConfig* config = session_->config(); - QuicTagVector copt; - copt.push_back(kFSTR); - QuicConfigPeer::SetReceivedConnectionOptions(config, copt); - EXPECT_EQ(FEC_PROTECT_OPTIONAL, stream_->fec_policy()); - stream_->SetFromConfig(); - EXPECT_EQ(FEC_PROTECT_ALWAYS, stream_->fec_policy()); -} - TEST_F(ReliableQuicStreamTest, EarlyResponseFinHandling) { // Verify that if the server completes the response before reading the end of // the request, the received FIN is recorded. Initialize(kShouldProcessData); EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); // Receive data for the request. diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc index 4d18cca..bb5f36b 100644 --- a/net/quic/test_tools/crypto_test_utils.cc +++ b/net/quic/test_tools/crypto_test_utils.cc @@ -136,11 +136,14 @@ int CryptoTestUtils::HandshakeWithFakeServer( QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), ProofSourceForTesting()); + QuicCompressedCertsCache compressed_certs_cache( + QuicCompressedCertsCache::kQuicCompressedCertsCacheSize); SetupCryptoServerConfigForTest(server_conn->clock(), server_conn->random_generator(), &config, &crypto_config, options); - TestQuicSpdyServerSession server_session(server_conn, config, &crypto_config); + TestQuicSpdyServerSession server_session(server_conn, config, &crypto_config, + &compressed_certs_cache); // The client's handshake must have been started already. CHECK_NE(0u, client_conn->encrypted_packets_.size()); diff --git a/net/quic/test_tools/mock_quic_dispatcher.cc b/net/quic/test_tools/mock_quic_dispatcher.cc index 66b940b..a313651 100644 --- a/net/quic/test_tools/mock_quic_dispatcher.cc +++ b/net/quic/test_tools/mock_quic_dispatcher.cc @@ -13,10 +13,7 @@ MockQuicDispatcher::MockQuicDispatcher( const QuicConfig& config, const QuicCryptoServerConfig* crypto_config, QuicConnectionHelperInterface* helper) - : QuicDispatcher(config, - crypto_config, - QuicSupportedVersions(), - helper) {} + : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), helper) {} MockQuicDispatcher::~MockQuicDispatcher() {} diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc index f171bff..8f16fc8d 100644 --- a/net/quic/test_tools/quic_connection_peer.cc +++ b/net/quic/test_tools/quic_connection_peer.cc @@ -6,7 +6,6 @@ #include "base/stl_util.h" #include "net/quic/congestion_control/send_algorithm_interface.h" -#include "net/quic/quic_connection.h" #include "net/quic/quic_packet_writer.h" #include "net/quic/quic_received_packet_manager.h" #include "net/quic/test_tools/quic_framer_peer.h" @@ -151,13 +150,6 @@ QuicFramer* QuicConnectionPeer::GetFramer(QuicConnection* connection) { } // static -QuicFecGroup* QuicConnectionPeer::GetFecGroup(QuicConnection* connection, - int fec_group) { - connection->last_header_.fec_group = fec_group; - return connection->GetFecGroup(); -} - -// static QuicAlarm* QuicConnectionPeer::GetAckAlarm(QuicConnection* connection) { return connection->ack_alarm_.get(); } @@ -168,11 +160,6 @@ QuicAlarm* QuicConnectionPeer::GetPingAlarm(QuicConnection* connection) { } // static -QuicAlarm* QuicConnectionPeer::GetFecAlarm(QuicConnection* connection) { - return connection->fec_alarm_.get(); -} - -// static QuicAlarm* QuicConnectionPeer::GetResumeWritesAlarm( QuicConnection* connection) { return connection->resume_writes_alarm_.get(); @@ -268,8 +255,9 @@ void QuicConnectionPeer::SetNextMtuProbeAt(QuicConnection* connection, } // static -void QuicConnectionPeer::EnableAckDecimation(QuicConnection* connection) { - connection->ack_decimation_enabled_ = true; +void QuicConnectionPeer::SetAckMode(QuicConnection* connection, + QuicConnection::AckMode ack_mode) { + connection->ack_mode_ = ack_mode; } } // namespace test diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h index 524eb15..d547dc4 100644 --- a/net/quic/test_tools/quic_connection_peer.h +++ b/net/quic/test_tools/quic_connection_peer.h @@ -7,6 +7,7 @@ #include "base/macros.h" #include "net/base/ip_endpoint.h" +#include "net/quic/quic_connection.h" #include "net/quic/quic_connection_stats.h" #include "net/quic/quic_protocol.h" @@ -15,11 +16,9 @@ namespace net { struct QuicAckFrame; struct QuicPacketHeader; class QuicAlarm; -class QuicConnection; class QuicConnectionHelperInterface; class QuicConnectionVisitorInterface; class QuicEncryptedPacket; -class QuicFecGroup; class QuicFramer; class QuicPacketCreator; class QuicPacketGenerator; @@ -88,12 +87,8 @@ class QuicConnectionPeer { static QuicFramer* GetFramer(QuicConnection* connection); - // Set last_header_->fec_group = fec_group and return connection->GetFecGroup - static QuicFecGroup* GetFecGroup(QuicConnection* connection, int fec_group); - static QuicAlarm* GetAckAlarm(QuicConnection* connection); static QuicAlarm* GetPingAlarm(QuicConnection* connection); - static QuicAlarm* GetFecAlarm(QuicConnection* connection); static QuicAlarm* GetResumeWritesAlarm(QuicConnection* connection); static QuicAlarm* GetRetransmissionAlarm(QuicConnection* connection); static QuicAlarm* GetSendAlarm(QuicConnection* connection); @@ -122,7 +117,8 @@ class QuicConnectionPeer { QuicPacketCount packets); static void SetNextMtuProbeAt(QuicConnection* connection, QuicPacketNumber number); - static void EnableAckDecimation(QuicConnection* connection); + static void SetAckMode(QuicConnection* connection, + QuicConnection::AckMode ack_mode); private: DISALLOW_COPY_AND_ASSIGN(QuicConnectionPeer); diff --git a/net/quic/test_tools/quic_packet_creator_peer.cc b/net/quic/test_tools/quic_packet_creator_peer.cc index 6ec2a72..83b783c 100644 --- a/net/quic/test_tools/quic_packet_creator_peer.cc +++ b/net/quic/test_tools/quic_packet_creator_peer.cc @@ -65,10 +65,8 @@ void QuicPacketCreatorPeer::SetPacketNumber(QuicPacketCreator* creator, // static void QuicPacketCreatorPeer::FillPacketHeader(QuicPacketCreator* creator, - QuicFecGroupNumber fec_group, - bool fec_flag, QuicPacketHeader* header) { - creator->FillPacketHeader(fec_group, fec_flag, header); + creator->FillPacketHeader(header); } // static @@ -83,35 +81,6 @@ size_t QuicPacketCreatorPeer::CreateStreamFrame(QuicPacketCreator* creator, } // static -bool QuicPacketCreatorPeer::IsFecProtected(QuicPacketCreator* creator) { - return creator->fec_protect_; -} - -// static -bool QuicPacketCreatorPeer::IsFecEnabled(QuicPacketCreator* creator) { - return creator->max_packets_per_fec_group_ > 0; -} - -// static -void QuicPacketCreatorPeer::StartFecProtectingPackets( - QuicPacketCreator* creator) { - creator->StartFecProtectingPackets(); -} - -// static -void QuicPacketCreatorPeer::StopFecProtectingPackets( - QuicPacketCreator* creator) { - creator->StopFecProtectingPackets(); -} - -// static -void QuicPacketCreatorPeer::SerializeFec(QuicPacketCreator* creator, - char* buffer, - size_t buffer_len) { - creator->SerializeFec(buffer, buffer_len); -} - -// static SerializedPacket QuicPacketCreatorPeer::SerializeAllFrames( QuicPacketCreator* creator, const QuicFrames& frames, @@ -132,23 +101,6 @@ SerializedPacket QuicPacketCreatorPeer::SerializeAllFrames( } // static -void QuicPacketCreatorPeer::ResetFecGroup(QuicPacketCreator* creator) { - creator->ResetFecGroup(); -} - -// static -QuicTime::Delta QuicPacketCreatorPeer::GetFecTimeout( - QuicPacketCreator* creator) { - return creator->fec_timeout_; -} - -// static -float QuicPacketCreatorPeer::GetRttMultiplierForFecTimeout( - QuicPacketCreator* creator) { - return creator->rtt_multiplier_for_fec_timeout_; -} - -// static EncryptionLevel QuicPacketCreatorPeer::GetEncryptionLevel( QuicPacketCreator* creator) { return creator->packet_.encryption_level; diff --git a/net/quic/test_tools/quic_packet_creator_peer.h b/net/quic/test_tools/quic_packet_creator_peer.h index cc17ca9..6849c1f 100644 --- a/net/quic/test_tools/quic_packet_creator_peer.h +++ b/net/quic/test_tools/quic_packet_creator_peer.h @@ -36,8 +36,6 @@ class QuicPacketCreatorPeer { QuicPacketCreator* creator); static void SetPacketNumber(QuicPacketCreator* creator, QuicPacketNumber s); static void FillPacketHeader(QuicPacketCreator* creator, - QuicFecGroupNumber fec_group, - bool fec_flag, QuicPacketHeader* header); static size_t CreateStreamFrame(QuicPacketCreator* creator, QuicStreamId id, @@ -46,21 +44,10 @@ class QuicPacketCreatorPeer { QuicStreamOffset offset, bool fin, QuicFrame* frame); - static bool IsFecProtected(QuicPacketCreator* creator); - static bool IsFecEnabled(QuicPacketCreator* creator); - static void StartFecProtectingPackets(QuicPacketCreator* creator); - static void StopFecProtectingPackets(QuicPacketCreator* creator); - static void SerializeFec(QuicPacketCreator* creator, - char* buffer, - size_t buffer_len); static SerializedPacket SerializeAllFrames(QuicPacketCreator* creator, const QuicFrames& frames, char* buffer, size_t buffer_len); - static void ResetFecGroup(QuicPacketCreator* creator); - static QuicTime::Delta GetFecTimeout(QuicPacketCreator* creator); - // TODO(rtenneti): Delete this code after the 0.25 RTT FEC experiment. - static float GetRttMultiplierForFecTimeout(QuicPacketCreator* creator); static EncryptionLevel GetEncryptionLevel(QuicPacketCreator* creator); static QuicPathId GetCurrentPath(QuicPacketCreator* creator); diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc index 9911757..1041569 100644 --- a/net/quic/test_tools/quic_test_utils.cc +++ b/net/quic/test_tools/quic_test_utils.cc @@ -61,7 +61,7 @@ QuicPacket* BuildUnsizedDataPacket(QuicFramer* framer, bool last_frame = i == frames.size() - 1; const size_t frame_size = framer->GetSerializedFrameLength( frames[i], max_plaintext_size - packet_size, first_frame, last_frame, - header.is_in_fec_group, header.public_header.packet_number_length); + header.public_header.packet_number_length); DCHECK(frame_size); packet_size += frame_size; } @@ -309,7 +309,7 @@ MockQuicSpdySession::MockQuicSpdySession(QuicConnection* connection) : QuicSpdySession(connection, DefaultQuicConfig()) { crypto_stream_.reset(new QuicCryptoStream(this)); Initialize(); - ON_CALL(*this, WritevData(_, _, _, _, _, _)) + ON_CALL(*this, WritevData(_, _, _, _, _)) .WillByDefault(testing::Return(QuicConsumedData(0, false))); } @@ -321,7 +321,6 @@ QuicConsumedData MockQuicSpdySession::ConsumeAllData( const QuicIOVector& data, QuicStreamOffset /*offset*/, bool fin, - FecProtection /*fec_protection*/, QuicAckListenerInterface* /*ack_notifier_delegate*/) { return QuicConsumedData(data.total_length, fin); } @@ -329,8 +328,13 @@ QuicConsumedData MockQuicSpdySession::ConsumeAllData( TestQuicSpdyServerSession::TestQuicSpdyServerSession( QuicConnection* connection, const QuicConfig& config, - const QuicCryptoServerConfig* crypto_config) - : QuicServerSessionBase(config, connection, &visitor_, crypto_config) { + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) + : QuicServerSessionBase(config, + connection, + &visitor_, + crypto_config, + compressed_certs_cache) { Initialize(); } @@ -338,8 +342,11 @@ TestQuicSpdyServerSession::~TestQuicSpdyServerSession() {} QuicCryptoServerStreamBase* TestQuicSpdyServerSession::CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config) { - return new QuicCryptoServerStream(crypto_config, this); + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) { + return new QuicCryptoServerStream(crypto_config, compressed_certs_cache, + FLAGS_enable_quic_stateless_reject_support, + this); } QuicCryptoServerStream* TestQuicSpdyServerSession::GetCryptoStream() { @@ -672,20 +679,18 @@ size_t GetPacketLengthForOneStream(QuicVersion version, bool include_path_id, QuicConnectionIdLength connection_id_length, QuicPacketNumberLength packet_number_length, - InFecGroup is_in_fec_group, size_t* payload_length) { *payload_length = 1; const size_t stream_length = NullEncrypter().GetCiphertextSize(*payload_length) + QuicPacketCreator::StreamFramePacketOverhead( PACKET_8BYTE_CONNECTION_ID, include_version, include_path_id, - packet_number_length, 0u, is_in_fec_group); + packet_number_length, 0u); const size_t ack_length = NullEncrypter().GetCiphertextSize( QuicFramer::GetMinAckFrameSize(PACKET_1BYTE_PACKET_NUMBER)) + GetPacketHeaderSize(connection_id_length, include_version, - include_path_id, packet_number_length, - is_in_fec_group); + include_path_id, packet_number_length); if (stream_length < ack_length) { *payload_length = 1 + ack_length - stream_length; } @@ -693,7 +698,7 @@ size_t GetPacketLengthForOneStream(QuicVersion version, return NullEncrypter().GetCiphertextSize(*payload_length) + QuicPacketCreator::StreamFramePacketOverhead( connection_id_length, include_version, include_path_id, - packet_number_length, 0u, is_in_fec_group); + packet_number_length, 0u); } TestEntropyCalculator::TestEntropyCalculator() {} @@ -766,13 +771,15 @@ void CreateClientSessionForTest(QuicServerId server_id, (*client_connection)->AdvanceTime(connection_start_time); } -void CreateServerSessionForTest(QuicServerId server_id, - QuicTime::Delta connection_start_time, - QuicVersionVector supported_versions, - MockConnectionHelper* helper, - QuicCryptoServerConfig* server_crypto_config, - PacketSavingConnection** server_connection, - TestQuicSpdyServerSession** server_session) { +void CreateServerSessionForTest( + QuicServerId server_id, + QuicTime::Delta connection_start_time, + QuicVersionVector supported_versions, + MockConnectionHelper* helper, + QuicCryptoServerConfig* server_crypto_config, + QuicCompressedCertsCache* compressed_certs_cache, + PacketSavingConnection** server_connection, + TestQuicSpdyServerSession** server_session) { CHECK(server_crypto_config); CHECK(server_connection); CHECK(server_session); @@ -783,7 +790,8 @@ void CreateServerSessionForTest(QuicServerId server_id, *server_connection = new PacketSavingConnection( helper, Perspective::IS_SERVER, supported_versions); *server_session = new TestQuicSpdyServerSession( - *server_connection, DefaultQuicConfig(), server_crypto_config); + *server_connection, DefaultQuicConfig(), server_crypto_config, + compressed_certs_cache); // We advance the clock initially because the default time is zero and the // strike register worries that we've just overflowed a uint32_t time. diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h index e669b0c..276490b 100644 --- a/net/quic/test_tools/quic_test_utils.h +++ b/net/quic/test_tools/quic_test_utils.h @@ -142,7 +142,6 @@ size_t GetPacketLengthForOneStream(QuicVersion version, bool include_path_id, QuicConnectionIdLength connection_id_length, QuicPacketNumberLength packet_number_length, - InFecGroup is_in_fec_group, size_t* payload_length); // Returns QuicConfig set to default values. @@ -221,7 +220,6 @@ class MockFramerVisitor : public QuicFramerVisitorInterface { MOCK_METHOD1(OnPublicResetPacket, void(const QuicPublicResetPacket& header)); MOCK_METHOD1(OnVersionNegotiationPacket, void(const QuicVersionNegotiationPacket& packet)); - MOCK_METHOD0(OnRevivedPacket, void()); // The constructor sets this up to return true by default. MOCK_METHOD1(OnUnauthenticatedHeader, bool(const QuicPacketHeader& header)); // The constructor sets this up to return true by default. @@ -229,12 +227,10 @@ class MockFramerVisitor : public QuicFramerVisitorInterface { bool(const QuicPacketPublicHeader& header)); MOCK_METHOD1(OnDecryptedPacket, void(EncryptionLevel level)); MOCK_METHOD1(OnPacketHeader, bool(const QuicPacketHeader& header)); - MOCK_METHOD1(OnFecProtectedPayload, void(base::StringPiece payload)); MOCK_METHOD1(OnStreamFrame, bool(const QuicStreamFrame& frame)); MOCK_METHOD1(OnAckFrame, bool(const QuicAckFrame& frame)); MOCK_METHOD1(OnStopWaitingFrame, bool(const QuicStopWaitingFrame& frame)); MOCK_METHOD1(OnPingFrame, bool(const QuicPingFrame& frame)); - MOCK_METHOD1(OnFecData, void(StringPiece redundancy)); MOCK_METHOD1(OnRstStreamFrame, bool(const QuicRstStreamFrame& frame)); MOCK_METHOD1(OnConnectionCloseFrame, bool(const QuicConnectionCloseFrame& frame)); @@ -257,19 +253,16 @@ class NoOpFramerVisitor : public QuicFramerVisitorInterface { void OnPublicResetPacket(const QuicPublicResetPacket& packet) override {} void OnVersionNegotiationPacket( const QuicVersionNegotiationPacket& packet) override {} - void OnRevivedPacket() override {} bool OnProtocolVersionMismatch(QuicVersion version) override; bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override; bool OnUnauthenticatedPublicHeader( const QuicPacketPublicHeader& header) override; void OnDecryptedPacket(EncryptionLevel level) override {} bool OnPacketHeader(const QuicPacketHeader& header) override; - void OnFecProtectedPayload(base::StringPiece payload) override {} bool OnStreamFrame(const QuicStreamFrame& frame) override; bool OnAckFrame(const QuicAckFrame& frame) override; bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override; bool OnPingFrame(const QuicPingFrame& frame) override; - void OnFecData(StringPiece redundancy) override {} bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override; bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override; bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override; @@ -461,13 +454,13 @@ class MockQuicSpdySession : public QuicSpdySession { MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id)); MOCK_METHOD1(CreateOutgoingDynamicStream, QuicSpdyStream*(SpdyPriority priority)); - MOCK_METHOD6(WritevData, + MOCK_METHOD5(WritevData, QuicConsumedData(QuicStreamId id, QuicIOVector data, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface*)); + MOCK_METHOD3(SendRstStream, void(QuicStreamId stream_id, QuicRstStreamErrorCode error, @@ -503,7 +496,6 @@ class MockQuicSpdySession : public QuicSpdySession { const QuicIOVector& data, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface* ack_notifier_delegate); private: @@ -516,14 +508,16 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase { public: TestQuicSpdyServerSession(QuicConnection* connection, const QuicConfig& config, - const QuicCryptoServerConfig* crypto_config); + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache); ~TestQuicSpdyServerSession() override; MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id)); MOCK_METHOD1(CreateOutgoingDynamicStream, QuicSpdyStream*(SpdyPriority priority)); QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config) override; + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) override; QuicCryptoServerStream* GetCryptoStream() override; @@ -742,9 +736,6 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor { MOCK_METHOD1(OnVersionNegotiationPacket, void(const QuicVersionNegotiationPacket&)); - - MOCK_METHOD2(OnRevivedPacket, - void(const QuicPacketHeader&, StringPiece payload)); }; class MockReceivedPacketManager : public QuicReceivedPacketManager { @@ -756,7 +747,6 @@ class MockReceivedPacketManager : public QuicReceivedPacketManager { void(QuicByteCount bytes, const QuicPacketHeader& header, QuicTime receipt_time)); - MOCK_METHOD1(RecordPacketRevived, void(QuicPacketNumber packet_number)); MOCK_METHOD1(IsMissing, bool(QuicPacketNumber packet_number)); MOCK_METHOD1(IsAwaitingPacket, bool(QuicPacketNumber packet_number)); MOCK_METHOD1(UpdatePacketInformationSentByPeer, @@ -805,13 +795,15 @@ void CreateClientSessionForTest(QuicServerId server_id, // server_session. // server_session: Pointer reference for the newly created server // session. The new object will be owned by the caller. -void CreateServerSessionForTest(QuicServerId server_id, - QuicTime::Delta connection_start_time, - QuicVersionVector supported_versions, - MockConnectionHelper* helper, - QuicCryptoServerConfig* crypto_server_config, - PacketSavingConnection** server_connection, - TestQuicSpdyServerSession** server_session); +void CreateServerSessionForTest( + QuicServerId server_id, + QuicTime::Delta connection_start_time, + QuicVersionVector supported_versions, + MockConnectionHelper* helper, + QuicCryptoServerConfig* crypto_server_config, + QuicCompressedCertsCache* compressed_certs_cache, + PacketSavingConnection** server_connection, + TestQuicSpdyServerSession** server_session); // Helper to generate client side stream ids, generalizes // kClientDataStreamId1 etc. above. diff --git a/net/quic/test_tools/reliable_quic_stream_peer.cc b/net/quic/test_tools/reliable_quic_stream_peer.cc index 97a7278..2b419bf 100644 --- a/net/quic/test_tools/reliable_quic_stream_peer.cc +++ b/net/quic/test_tools/reliable_quic_stream_peer.cc @@ -79,12 +79,6 @@ uint32_t ReliableQuicStreamPeer::SizeOfQueuedData(ReliableQuicStream* stream) { } // static -void ReliableQuicStreamPeer::SetFecPolicy(ReliableQuicStream* stream, - FecPolicy fec_policy) { - stream->set_fec_policy(fec_policy); -} - -// static bool ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl( ReliableQuicStream* stream) { return stream->stream_contributes_to_connection_flow_control_; diff --git a/net/quic/test_tools/reliable_quic_stream_peer.h b/net/quic/test_tools/reliable_quic_stream_peer.h index db172da..04bbe7b 100644 --- a/net/quic/test_tools/reliable_quic_stream_peer.h +++ b/net/quic/test_tools/reliable_quic_stream_peer.h @@ -35,8 +35,6 @@ class ReliableQuicStreamPeer { static uint32_t SizeOfQueuedData(ReliableQuicStream* stream); - static void SetFecPolicy(ReliableQuicStream* stream, FecPolicy fec_policy); - static bool StreamContributesToConnectionFlowControl( ReliableQuicStream* stream); diff --git a/net/quic/test_tools/simple_quic_framer.cc b/net/quic/test_tools/simple_quic_framer.cc index 977a367..dd0e0cb 100644 --- a/net/quic/test_tools/simple_quic_framer.cc +++ b/net/quic/test_tools/simple_quic_framer.cc @@ -37,7 +37,6 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface { const QuicVersionNegotiationPacket& packet) override { version_negotiation_packet_.reset(new QuicVersionNegotiationPacket(packet)); } - void OnRevivedPacket() override {} bool OnUnauthenticatedPublicHeader( const QuicPacketPublicHeader& header) override { @@ -53,8 +52,6 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface { return true; } - void OnFecProtectedPayload(StringPiece payload) override {} - bool OnStreamFrame(const QuicStreamFrame& frame) override { // Save a copy of the data so it is valid after the packet is processed. string* string_data = new string(); @@ -82,10 +79,6 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface { return true; } - void OnFecData(StringPiece redundancy) override { - fec_redundancy_ = redundancy.as_string(); - } - bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override { rst_stream_frames_.push_back(frame); return true; @@ -136,7 +129,6 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface { return stop_waiting_frames_; } const vector<QuicPingFrame>& ping_frames() const { return ping_frames_; } - StringPiece fec_data() const { return fec_redundancy_; } const QuicVersionNegotiationPacket* version_negotiation_packet() const { return version_negotiation_packet_.get(); } @@ -147,7 +139,6 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface { QuicPacketHeader header_; scoped_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_; scoped_ptr<QuicPublicResetPacket> public_reset_packet_; - string fec_redundancy_; vector<QuicAckFrame> ack_frames_; vector<QuicStopWaitingFrame> stop_waiting_frames_; vector<QuicPingFrame> ping_frames_; @@ -187,10 +178,6 @@ const QuicPacketHeader& SimpleQuicFramer::header() const { return visitor_->header(); } -StringPiece SimpleQuicFramer::fec_data() const { - return visitor_->fec_data(); -} - const QuicVersionNegotiationPacket* SimpleQuicFramer::version_negotiation_packet() const { return visitor_->version_negotiation_packet(); diff --git a/net/quic/test_tools/simple_quic_framer.h b/net/quic/test_tools/simple_quic_framer.h index c476550..f09db61 100644 --- a/net/quic/test_tools/simple_quic_framer.h +++ b/net/quic/test_tools/simple_quic_framer.h @@ -46,7 +46,6 @@ class SimpleQuicFramer { const std::vector<QuicGoAwayFrame>& goaway_frames() const; const std::vector<QuicRstStreamFrame>& rst_stream_frames() const; const std::vector<QuicStreamFrame*>& stream_frames() const; - base::StringPiece fec_data() const; const QuicVersionNegotiationPacket* version_negotiation_packet() const; QuicFramer* framer(); diff --git a/net/spdy/buffered_spdy_framer.cc b/net/spdy/buffered_spdy_framer.cc index e76b83d..e7e3d3d 100644 --- a/net/spdy/buffered_spdy_framer.cc +++ b/net/spdy/buffered_spdy_framer.cc @@ -202,7 +202,7 @@ void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id, } void BufferedSpdyFramer::OnStreamEnd(SpdyStreamId stream_id) { - LOG(DFATAL) << "Unimplemented"; + visitor_->OnStreamFrameData(stream_id, nullptr, 0, true); } void BufferedSpdyFramer::OnStreamPadding(SpdyStreamId stream_id, size_t len) { diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc index e34345a..5c8d011 100644 --- a/net/spdy/spdy_framer.cc +++ b/net/spdy/spdy_framer.cc @@ -14,6 +14,7 @@ #include "base/lazy_instance.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram_macros.h" +#include "net/quic/quic_flags.h" #include "net/spdy/hpack/hpack_constants.h" #include "net/spdy/spdy_frame_builder.h" #include "net/spdy/spdy_frame_reader.h" @@ -171,7 +172,8 @@ SpdyFramer::SpdyFramer(SpdyMajorVersion version) enable_compression_(true), syn_frame_processed_(false), probable_http_response_(false), - end_stream_when_done_(false) { + end_stream_when_done_(false), + spdy_on_stream_end_(FLAGS_spdy_on_stream_end) { DCHECK(protocol_version_ == SPDY3 || protocol_version_ == HTTP2); DCHECK_LE(kMaxControlFrameSize, SpdyConstants::GetFrameMaximumSize(protocol_version_) + @@ -830,8 +832,12 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) { } else { // Empty data frame. if (current_frame_flags_ & DATA_FLAG_FIN) { - visitor_->OnStreamFrameData( - current_frame_stream_id_, NULL, 0, true); + if (spdy_on_stream_end_) { + visitor_->OnStreamEnd(current_frame_stream_id_); + } else { + visitor_->OnStreamFrameData(current_frame_stream_id_, nullptr, 0, + true); + } } CHANGE_STATE(SPDY_FRAME_COMPLETE); } @@ -2099,7 +2105,11 @@ size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) { ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 || end_stream_when_done_)) { end_stream_when_done_ = false; - visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); + if (spdy_on_stream_end_) { + visitor_->OnStreamEnd(current_frame_stream_id_); + } else { + visitor_->OnStreamFrameData(current_frame_stream_id_, nullptr, 0, true); + } } CHANGE_STATE(SPDY_FRAME_COMPLETE); } diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h index 30e7899..6261777 100644 --- a/net/spdy/spdy_framer.h +++ b/net/spdy/spdy_framer.h @@ -795,6 +795,11 @@ class NET_EXPORT_PRIVATE SpdyFramer { // If true, then ProcessInput returns after processing a full frame, // rather than reading all available input. bool process_single_input_frame_ = false; + + // Latched value of --FLAGS_spdy_on_stream_end. + // If true, OnStreamEnd will be called instead of the sentinel call of + // OnStreamFrameData(stream_id, nullptr, 0, true) + bool spdy_on_stream_end_; }; } // namespace net diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc index 2dcc855..5e41327 100644 --- a/net/spdy/spdy_framer_test.cc +++ b/net/spdy/spdy_framer_test.cc @@ -16,6 +16,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" +#include "net/quic/quic_flags.h" #include "net/spdy/hpack/hpack_constants.h" #include "net/spdy/mock_spdy_framer_visitor.h" #include "net/spdy/spdy_frame_builder.h" @@ -281,7 +282,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, fin_frame_count_(0), fin_opaque_data_(), fin_flag_count_(0), - zero_length_data_frame_count_(0), + end_of_stream_count_(0), control_frame_header_data_count_(0), zero_length_control_frame_header_data_count_(0), data_frame_count_(0), @@ -312,8 +313,10 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, size_t len, bool fin) override { EXPECT_EQ(header_stream_id_, stream_id); - if (len == 0) { - ++zero_length_data_frame_count_; + if (!FLAGS_spdy_on_stream_end) { + if (len == 0) { + ++end_of_stream_count_; + } } data_bytes_ += len; @@ -328,7 +331,9 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, } void OnStreamEnd(SpdyStreamId stream_id) override { - LOG(DFATAL) << "Unimplemented."; + LOG(INFO) << "OnStreamEnd(" << stream_id << ")"; + EXPECT_EQ(header_stream_id_, stream_id); + ++end_of_stream_count_; } void OnStreamPadding(SpdyStreamId stream_id, size_t len) override { @@ -587,7 +592,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, int fin_frame_count_; // The count of RST_STREAM type frames received. string fin_opaque_data_; int fin_flag_count_; // The count of frames with the FIN flag set. - int zero_length_data_frame_count_; // The count of zero-length data frames. + int end_of_stream_count_; // The count of zero-length data frames. int control_frame_header_data_count_; // The count of chunks received. // The count of zero-length control frame header data chunks received. int zero_length_control_frame_header_data_count_; @@ -1207,7 +1212,7 @@ TEST_P(SpdyFramerTest, Basic) { } EXPECT_EQ(0, visitor.fin_flag_count_); - EXPECT_EQ(0, visitor.zero_length_data_frame_count_); + EXPECT_EQ(0, visitor.end_of_stream_count_); EXPECT_EQ(4, visitor.data_frame_count_); visitor.fin_opaque_data_.clear(); } @@ -1289,7 +1294,7 @@ TEST_P(SpdyFramerTest, FinOnDataFrame) { EXPECT_EQ(16, visitor.data_bytes_); EXPECT_EQ(0, visitor.fin_frame_count_); EXPECT_EQ(0, visitor.fin_flag_count_); - EXPECT_EQ(1, visitor.zero_length_data_frame_count_); + EXPECT_EQ(1, visitor.end_of_stream_count_); EXPECT_EQ(2, visitor.data_frame_count_); } @@ -1348,7 +1353,7 @@ TEST_P(SpdyFramerTest, FinOnSynReplyFrame) { EXPECT_EQ(0, visitor.data_bytes_); EXPECT_EQ(0, visitor.fin_frame_count_); EXPECT_EQ(1, visitor.fin_flag_count_); - EXPECT_EQ(1, visitor.zero_length_data_frame_count_); + EXPECT_EQ(1, visitor.end_of_stream_count_); EXPECT_EQ(0, visitor.data_frame_count_); } @@ -1466,7 +1471,7 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) { EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_)); EXPECT_EQ(0, visitor.fin_frame_count_); EXPECT_EQ(0, visitor.fin_flag_count_); - EXPECT_EQ(1, visitor.zero_length_data_frame_count_); + EXPECT_EQ(1, visitor.end_of_stream_count_); EXPECT_EQ(1, visitor.data_frame_count_); } @@ -3196,7 +3201,7 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) { // at least twice. EXPECT_LE(2, visitor.control_frame_header_data_count_); EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); - EXPECT_EQ(0, visitor.zero_length_data_frame_count_); + EXPECT_EQ(0, visitor.end_of_stream_count_); EXPECT_EQ(headers, visitor.headers_); } @@ -3221,7 +3226,7 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) { // at least twice. EXPECT_LE(2, visitor.control_frame_header_data_count_); EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); - EXPECT_EQ(1, visitor.zero_length_data_frame_count_); + EXPECT_EQ(1, visitor.end_of_stream_count_); EXPECT_EQ(headers, visitor.headers_); } @@ -3258,7 +3263,7 @@ TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) { EXPECT_EQ(0, visitor.error_count_); EXPECT_EQ(1, visitor.syn_frame_count_); EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); - EXPECT_EQ(0, visitor.zero_length_data_frame_count_); + EXPECT_EQ(0, visitor.end_of_stream_count_); EXPECT_LT(kBigValueSize, visitor.header_buffer_length_); } @@ -3403,7 +3408,7 @@ TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) { EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_); // The framer should not have sent half-close to the visitor. - EXPECT_EQ(0, visitor.zero_length_data_frame_count_); + EXPECT_EQ(0, visitor.end_of_stream_count_); } TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) { @@ -3860,7 +3865,7 @@ TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) { EXPECT_EQ(2, visitor.continuation_count_); EXPECT_EQ(1, visitor.fin_flag_count_); EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); - EXPECT_EQ(1, visitor.zero_length_data_frame_count_); + EXPECT_EQ(1, visitor.end_of_stream_count_); EXPECT_THAT(visitor.headers_, testing::ElementsAre( @@ -3910,7 +3915,7 @@ TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) { EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_); EXPECT_EQ(2, visitor.continuation_count_); EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); - EXPECT_EQ(0, visitor.zero_length_data_frame_count_); + EXPECT_EQ(0, visitor.end_of_stream_count_); EXPECT_THAT(visitor.headers_, testing::ElementsAre( @@ -4384,6 +4389,50 @@ TEST_P(SpdyFramerTest, CatchProbableHttpResponse) { } TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) { + FLAGS_spdy_on_stream_end = true; + + if (!IsSpdy3()) { + return; + } + + uint8_t flags = 0; + do { + SCOPED_TRACE(testing::Message() << "Flags " << flags); + + testing::StrictMock<test::MockSpdyFramerVisitor> visitor; + SpdyFramer framer(spdy_version_); + framer.set_visitor(&visitor); + + SpdyDataIR data_ir(1, "hello"); + scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); + SetFrameFlags(frame.get(), flags, spdy_version_); + + if (flags & ~DATA_FLAG_FIN) { + EXPECT_CALL(visitor, OnError(_)); + } else { + EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN)); + EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false)); + if (flags & DATA_FLAG_FIN) { + EXPECT_CALL(visitor, OnStreamEnd(_)); + } + } + + framer.ProcessInput(frame->data(), frame->size()); + if (flags & ~DATA_FLAG_FIN) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } + } while (++flags != 0); +} + +TEST_P(SpdyFramerTest, DataFrameFlagsV2V3disabled) { + FLAGS_spdy_on_stream_end = false; + if (!IsSpdy3()) { return; } @@ -4425,6 +4474,60 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) { } TEST_P(SpdyFramerTest, DataFrameFlagsV4) { + FLAGS_spdy_on_stream_end = true; + + if (!IsHttp2()) { + return; + } + + uint8_t valid_data_flags = + DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | DATA_FLAG_PADDED; + + uint8_t flags = 0; + do { + SCOPED_TRACE(testing::Message() << "Flags " << flags); + + testing::StrictMock<test::MockSpdyFramerVisitor> visitor; + SpdyFramer framer(spdy_version_); + framer.set_visitor(&visitor); + + SpdyDataIR data_ir(1, "hello"); + scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); + SetFrameFlags(frame.get(), flags, spdy_version_); + + if (flags & ~valid_data_flags) { + EXPECT_CALL(visitor, OnError(_)); + } else { + EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN)); + if (flags & DATA_FLAG_PADDED) { + // The first byte of payload is parsed as padding length. + EXPECT_CALL(visitor, OnStreamPadding(_, 1)); + // Expect Error since the frame ends prematurely. + EXPECT_CALL(visitor, OnError(_)); + } else { + EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false)); + if (flags & DATA_FLAG_FIN) { + EXPECT_CALL(visitor, OnStreamEnd(_)); + } + } + } + + framer.ProcessInput(frame->data(), frame->size()); + if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } + } while (++flags != 0); +} + +TEST_P(SpdyFramerTest, DataFrameFlagsV4disabled) { + FLAGS_spdy_on_stream_end = false; + if (!IsHttp2()) { return; } @@ -4475,6 +4578,64 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV4) { } TEST_P(SpdyFramerTest, SynStreamFrameFlags) { + FLAGS_spdy_on_stream_end = true; + + if (!IsSpdy3()) { + return; + } + + uint8_t flags = 0; + do { + SCOPED_TRACE(testing::Message() << "Flags " << flags); + + testing::StrictMock<test::MockSpdyFramerVisitor> visitor; + testing::StrictMock<test::MockDebugVisitor> debug_visitor; + SpdyFramer framer(spdy_version_); + framer.set_visitor(&visitor); + framer.set_debug_visitor(&debug_visitor); + + EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _)); + + SpdySynStreamIR syn_stream(8); + syn_stream.set_associated_to_stream_id(3); + syn_stream.set_priority(1); + syn_stream.SetHeader("foo", "bar"); + scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream)); + SetFrameFlags(frame.get(), flags, spdy_version_); + + if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { + EXPECT_CALL(visitor, OnError(_)); + } else { + EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _)); + EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN, + flags & CONTROL_FLAG_UNIDIRECTIONAL)); + EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _)) + .WillRepeatedly(testing::Return(true)); + if (flags & DATA_FLAG_FIN) { + EXPECT_CALL(visitor, OnStreamEnd(_)); + } else { + // Do not close the stream if we are expecting a CONTINUATION frame. + EXPECT_CALL(visitor, OnStreamEnd(_)).Times(0); + } + } + + framer.ProcessInput(frame->data(), frame->size()); + if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, + framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } + } while (++flags != 0); +} + +TEST_P(SpdyFramerTest, SynStreamFrameFlagsDisabled) { + FLAGS_spdy_on_stream_end = false; + if (!IsSpdy3()) { return; } @@ -4529,6 +4690,53 @@ TEST_P(SpdyFramerTest, SynStreamFrameFlags) { } TEST_P(SpdyFramerTest, SynReplyFrameFlags) { + FLAGS_spdy_on_stream_end = true; + + if (!IsSpdy3()) { + return; + } + + uint8_t flags = 0; + do { + SCOPED_TRACE(testing::Message() << "Flags " << flags); + + testing::StrictMock<test::MockSpdyFramerVisitor> visitor; + SpdyFramer framer(spdy_version_); + framer.set_visitor(&visitor); + + SpdySynReplyIR syn_reply(37); + syn_reply.SetHeader("foo", "bar"); + scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply)); + SetFrameFlags(frame.get(), flags, spdy_version_); + + if (flags & ~CONTROL_FLAG_FIN) { + EXPECT_CALL(visitor, OnError(_)); + } else { + EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN)); + EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _)) + .WillRepeatedly(testing::Return(true)); + if (flags & DATA_FLAG_FIN) { + EXPECT_CALL(visitor, OnStreamEnd(_)); + } + } + + framer.ProcessInput(frame->data(), frame->size()); + if (flags & ~CONTROL_FLAG_FIN) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, + framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } + } while (++flags != 0); +} + +TEST_P(SpdyFramerTest, SynReplyFrameFlagsDisabled) { + FLAGS_spdy_on_stream_end = false; + if (!IsSpdy3()) { return; } @@ -4729,6 +4937,99 @@ TEST_P(SpdyFramerTest, GoawayFrameFlags) { } TEST_P(SpdyFramerTest, HeadersFrameFlags) { + FLAGS_spdy_on_stream_end = true; + + uint8_t flags = 0; + do { + SCOPED_TRACE(testing::Message() << "Flags " << flags); + + testing::StrictMock<test::MockSpdyFramerVisitor> visitor; + SpdyFramer framer(spdy_version_); + framer.set_visitor(&visitor); + + SpdyHeadersIR headers_ir(57); + if (IsHttp2() && (flags & HEADERS_FLAG_PRIORITY)) { + headers_ir.set_priority(3); + headers_ir.set_has_priority(true); + headers_ir.set_parent_stream_id(5); + headers_ir.set_exclusive(true); + } + headers_ir.SetHeader("foo", "bar"); + std::unique_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir)); + uint8_t set_flags = flags; + if (IsHttp2()) { + // TODO(jgraettinger): Add padding to SpdyHeadersIR, + // and implement framing. + set_flags &= ~HEADERS_FLAG_PADDED; + } + SetFrameFlags(frame.get(), set_flags, spdy_version_); + + if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) { + EXPECT_CALL(visitor, OnError(_)); + } else if (IsHttp2() && + flags & + ~(CONTROL_FLAG_FIN | HEADERS_FLAG_END_HEADERS | + HEADERS_FLAG_END_SEGMENT | HEADERS_FLAG_PADDED | + HEADERS_FLAG_PRIORITY)) { + EXPECT_CALL(visitor, OnError(_)); + } else { + // Expected callback values + SpdyStreamId stream_id = 57; + bool has_priority = false; + SpdyPriority priority = 0; + SpdyStreamId parent_stream_id = 0; + bool exclusive = false; + bool fin = flags & CONTROL_FLAG_FIN; + bool end = IsSpdy3() || (flags & HEADERS_FLAG_END_HEADERS); + if (IsHttp2() && flags & HEADERS_FLAG_PRIORITY) { + has_priority = true; + priority = 3; + parent_stream_id = 5; + exclusive = true; + } + EXPECT_CALL(visitor, OnHeaders(stream_id, has_priority, priority, + parent_stream_id, exclusive, fin, end)); + EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _)) + .WillRepeatedly(testing::Return(true)); + if (flags & DATA_FLAG_FIN && + (IsSpdy3() || flags & HEADERS_FLAG_END_HEADERS)) { + EXPECT_CALL(visitor, OnStreamEnd(_)); + } else { + // Do not close the stream if we are expecting a CONTINUATION frame. + EXPECT_CALL(visitor, OnStreamEnd(_)).Times(0); + } + } + + framer.ProcessInput(frame->data(), frame->size()); + if (IsSpdy3() && flags & ~CONTROL_FLAG_FIN) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, + framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else if (IsHttp2() && + flags & + ~(CONTROL_FLAG_FIN | HEADERS_FLAG_END_HEADERS | + HEADERS_FLAG_END_SEGMENT | HEADERS_FLAG_PADDED | + HEADERS_FLAG_PRIORITY)) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, + framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else if (IsHttp2() && ~(flags & HEADERS_FLAG_END_HEADERS)) { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } + } while (++flags != 0); +} + +TEST_P(SpdyFramerTest, HeadersFrameFlagsDisabled) { + FLAGS_spdy_on_stream_end = false; + uint8_t flags = 0; do { SCOPED_TRACE(testing::Message() << "Flags " << flags); @@ -4756,11 +5057,11 @@ TEST_P(SpdyFramerTest, HeadersFrameFlags) { if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) { EXPECT_CALL(visitor, OnError(_)); - } else if (IsHttp2() && flags & ~(CONTROL_FLAG_FIN | - HEADERS_FLAG_END_HEADERS | - HEADERS_FLAG_END_SEGMENT | - HEADERS_FLAG_PADDED | - HEADERS_FLAG_PRIORITY)) { + } else if (IsHttp2() && + flags & + ~(CONTROL_FLAG_FIN | HEADERS_FLAG_END_HEADERS | + HEADERS_FLAG_END_SEGMENT | HEADERS_FLAG_PADDED | + HEADERS_FLAG_PRIORITY)) { EXPECT_CALL(visitor, OnError(_)); } else { // Expected callback values diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index 08e2c8b..441a5d9 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc @@ -92,7 +92,6 @@ struct TestParams { TestParams(const QuicVersionVector& client_supported_versions, const QuicVersionVector& server_supported_versions, QuicVersion negotiated_version, - bool use_fec, bool client_supports_stateless_rejects, bool server_uses_stateless_rejects_if_peer_supported, QuicTag congestion_control_tag, @@ -100,7 +99,6 @@ struct TestParams { : client_supported_versions(client_supported_versions), server_supported_versions(server_supported_versions), negotiated_version(negotiated_version), - use_fec(use_fec), client_supports_stateless_rejects(client_supports_stateless_rejects), server_uses_stateless_rejects_if_peer_supported( server_uses_stateless_rejects_if_peer_supported), @@ -117,7 +115,6 @@ struct TestParams { << p.client_supports_stateless_rejects; os << " server_uses_stateless_rejects_if_peer_supported: " << p.server_uses_stateless_rejects_if_peer_supported; - os << " use_fec: " << p.use_fec; os << " congestion_control_tag: " << QuicUtils::TagToString(p.congestion_control_tag); os << " auto_tune_flow_control_window: " << p.auto_tune_flow_control_window @@ -128,7 +125,6 @@ struct TestParams { QuicVersionVector client_supported_versions; QuicVersionVector server_supported_versions; QuicVersion negotiated_version; - bool use_fec; bool client_supports_stateless_rejects; bool server_uses_stateless_rejects_if_peer_supported; QuicTag congestion_control_tag; @@ -164,62 +160,56 @@ vector<TestParams> GetTestParams() { // TODO(rtenneti): Add kTBBR after BBR code is checked in. for (const QuicTag congestion_control_tag : {kRENO, kQBIC}) { for (bool auto_tune_flow_control_window : {true, false}) { - for (const bool use_fec : {false, true}) { - const int kMaxEnabledOptions = 5; - int enabled_options = 0; - if (congestion_control_tag != kQBIC) { - ++enabled_options; - } - if (use_fec) { - ++enabled_options; - } - if (auto_tune_flow_control_window) { - ++enabled_options; - } - if (client_supports_stateless_rejects) { - ++enabled_options; - } - if (server_uses_stateless_rejects_if_peer_supported) { - ++enabled_options; - } - CHECK_GE(kMaxEnabledOptions, enabled_options); + const int kMaxEnabledOptions = 5; + int enabled_options = 0; + if (congestion_control_tag != kQBIC) { + ++enabled_options; + } + if (auto_tune_flow_control_window) { + ++enabled_options; + } + if (client_supports_stateless_rejects) { + ++enabled_options; + } + if (server_uses_stateless_rejects_if_peer_supported) { + ++enabled_options; + } + CHECK_GE(kMaxEnabledOptions, enabled_options); + + // Run tests with no options, a single option, or all the options + // enabled to avoid a combinatorial explosion. + if (enabled_options > 1 && enabled_options < kMaxEnabledOptions) { + continue; + } - // Run tests with no options, a single option, or all the options - // enabled to avoid a combinatorial explosion. - if (enabled_options > 1 && enabled_options < kMaxEnabledOptions) { + for (const QuicVersionVector& client_versions : version_buckets) { + CHECK(!client_versions.empty()); + // Add an entry for server and client supporting all versions. + params.push_back(TestParams( + client_versions, all_supported_versions, + client_versions.front(), client_supports_stateless_rejects, + server_uses_stateless_rejects_if_peer_supported, + congestion_control_tag, auto_tune_flow_control_window)); + + // Run version negotiation tests tests with no options, or all + // the options enabled to avoid a combinatorial explosion. + if (enabled_options > 0 && enabled_options < kMaxEnabledOptions) { continue; } - for (const QuicVersionVector& client_versions : version_buckets) { - CHECK(!client_versions.empty()); - // Add an entry for server and client supporting all versions. + // Test client supporting all versions and server supporting 1 + // version. Simulate an old server and exercise version downgrade + // in the client. Protocol negotiation should occur. Skip the i = + // 0 case because it is essentially the same as the default case. + for (size_t i = 1; i < client_versions.size(); ++i) { + QuicVersionVector server_supported_versions; + server_supported_versions.push_back(client_versions[i]); params.push_back(TestParams( - client_versions, all_supported_versions, - client_versions.front(), use_fec, + client_versions, server_supported_versions, + server_supported_versions.front(), client_supports_stateless_rejects, server_uses_stateless_rejects_if_peer_supported, congestion_control_tag, auto_tune_flow_control_window)); - - // Run version negotiation tests tests with no options, or all - // the options enabled to avoid a combinatorial explosion. - if (enabled_options > 0 && enabled_options < kMaxEnabledOptions) { - continue; - } - - // Test client supporting all versions and server supporting 1 - // version. Simulate an old server and exercise version downgrade - // in the client. Protocol negotiation should occur. Skip the i = - // 0 case because it is essentially the same as the default case. - for (size_t i = 1; i < client_versions.size(); ++i) { - QuicVersionVector server_supported_versions; - server_supported_versions.push_back(client_versions[i]); - params.push_back(TestParams( - client_versions, server_supported_versions, - server_supported_versions.front(), use_fec, - client_supports_stateless_rejects, - server_uses_stateless_rejects_if_peer_supported, - congestion_control_tag, auto_tune_flow_control_window)); - } } } } @@ -352,10 +342,6 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> { // client as well according to the test parameter. copt.push_back(GetParam().congestion_control_tag); - if (GetParam().use_fec) { - // Set FEC config in client's connection options and in client session. - copt.push_back(kFHDR); - } if (GetParam().client_supports_stateless_rejects) { copt.push_back(kSREJ); } @@ -801,14 +787,9 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) { client_->WaitForResponseForMs(-1); ASSERT_TRUE(client_->client()->connected()); EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request)); - if (FLAGS_require_strike_register_or_server_nonce) { - EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->session()->GetNumSentClientHellos()); - EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); - } else { - EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos()); - EXPECT_EQ(1, client_->client()->GetNumSentClientHellos()); - } + EXPECT_EQ(expected_num_hellos_latest_session, + client_->client()->session()->GetNumSentClientHellos()); + EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); client_->Disconnect(); @@ -859,14 +840,9 @@ TEST_P(EndToEndTest, SynchronousRequestZeroRTTFailure) { client_->WaitForInitialResponse(); ASSERT_TRUE(client_->client()->connected()); EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - if (FLAGS_require_strike_register_or_server_nonce) { - EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->session()->GetNumSentClientHellos()); - EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); - } else { - EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos()); - EXPECT_EQ(1, client_->client()->GetNumSentClientHellos()); - } + EXPECT_EQ(expected_num_hellos_latest_session, + client_->client()->session()->GetNumSentClientHellos()); + EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); client_->Disconnect(); @@ -923,14 +899,9 @@ TEST_P(EndToEndTest, LargePostSynchronousRequest) { client_->WaitForInitialResponse(); ASSERT_TRUE(client_->client()->connected()); EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request)); - if (FLAGS_require_strike_register_or_server_nonce) { - EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->session()->GetNumSentClientHellos()); - EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); - } else { - EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos()); - EXPECT_EQ(1, client_->client()->GetNumSentClientHellos()); - } + EXPECT_EQ(expected_num_hellos_latest_session, + client_->client()->session()->GetNumSentClientHellos()); + EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); client_->Disconnect(); @@ -988,30 +959,6 @@ TEST_P(EndToEndTest, SetInitialReceivedConnectionOptions) { ContainsQuicTag(server_config_.ReceivedConnectionOptions(), kPRST)); } -TEST_P(EndToEndTest, CorrectlyConfiguredFec) { - ASSERT_TRUE(Initialize()); - client_->client()->WaitForCryptoHandshakeConfirmed(); - server_thread_->WaitForCryptoHandshakeConfirmed(); - - FecPolicy expected_policy = FEC_PROTECT_OPTIONAL; - - // Verify that server's FEC configuration is correct. - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - ASSERT_EQ(1u, dispatcher->session_map().size()); - QuicSpdySession* session = dispatcher->session_map().begin()->second; - EXPECT_EQ(expected_policy, - QuicSpdySessionPeer::GetHeadersStream(session)->fec_policy()); - server_thread_->Resume(); - - // Verify that client's FEC configuration is correct. - EXPECT_EQ(expected_policy, - QuicSpdySessionPeer::GetHeadersStream(client_->client()->session()) - ->fec_policy()); - EXPECT_EQ(expected_policy, client_->GetOrCreateStream()->fec_policy()); -} - TEST_P(EndToEndTest, LargePostSmallBandwidthLargeBuffer) { ASSERT_TRUE(Initialize()); SetPacketSendDelay(QuicTime::Delta::FromMicroseconds(1)); diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc index ac65bf5..aef861c 100644 --- a/net/tools/quic/quic_client_session_test.cc +++ b/net/tools/quic/quic_client_session_test.cc @@ -137,7 +137,6 @@ TEST_P(QuicClientSessionTest, CryptoConnect) { } TEST_P(QuicClientSessionTest, NoEncryptionAfterInitialEncryption) { - ValueRestore<bool> old_flag(&FLAGS_quic_block_unencrypted_writes, true); // Complete a handshake in order to prime the crypto config for 0-RTT. CompleteCryptoHandshake(); @@ -171,8 +170,8 @@ TEST_P(QuicClientSessionTest, NoEncryptionAfterInitialEncryption) { char data[] = "hello world"; struct iovec iov = {data, arraysize(data)}; QuicIOVector iovector(&iov, 1, iov.iov_len); - QuicConsumedData consumed = session_->WritevData( - stream->id(), iovector, 0, false, MAY_FEC_PROTECT, nullptr); + QuicConsumedData consumed = + session_->WritevData(stream->id(), iovector, 0, false, nullptr); EXPECT_FALSE(consumed.fin_consumed); EXPECT_EQ(0u, consumed.bytes_consumed); } diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc index 9cb1059..f662ee3 100644 --- a/net/tools/quic/quic_dispatcher.cc +++ b/net/tools/quic/quic_dispatcher.cc @@ -30,11 +30,7 @@ class DeleteSessionsAlarm : public QuicAlarm::Delegate { explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher) : dispatcher_(dispatcher) {} - QuicTime OnAlarm() override { - dispatcher_->DeleteSessions(); - // Let the dispatcher register the alarm at appropriate time. - return QuicTime::Zero(); - } + void OnAlarm() override { dispatcher_->DeleteSessions(); } private: // Not owned. @@ -51,6 +47,8 @@ QuicDispatcher::QuicDispatcher(const QuicConfig& config, QuicConnectionHelperInterface* helper) : config_(config), crypto_config_(crypto_config), + compressed_certs_cache_( + QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), helper_(helper), delete_sessions_alarm_( helper_->CreateAlarm(new DeleteSessionsAlarm(this))), @@ -387,14 +385,6 @@ bool QuicDispatcher::OnPacketHeader(const QuicPacketHeader& /*header*/) { return false; } -void QuicDispatcher::OnRevivedPacket() { - DCHECK(false); -} - -void QuicDispatcher::OnFecProtectedPayload(StringPiece /*payload*/) { - DCHECK(false); -} - bool QuicDispatcher::OnStreamFrame(const QuicStreamFrame& /*frame*/) { DCHECK(false); return false; @@ -447,10 +437,6 @@ bool QuicDispatcher::OnPathCloseFrame(const QuicPathCloseFrame& frame) { return false; } -void QuicDispatcher::OnFecData(StringPiece /*redundancy*/) { - DCHECK(false); -} - void QuicDispatcher::OnPacketComplete() { DCHECK(false); } @@ -463,8 +449,8 @@ QuicServerSessionBase* QuicDispatcher::CreateQuicSession( connection_id, client_address, helper_.get(), CreatePerConnectionWriter(), /* owns_writer= */ true, Perspective::IS_SERVER, supported_versions_); - QuicServerSessionBase* session = - new QuicSimpleServerSession(config_, connection, this, crypto_config_); + QuicServerSessionBase* session = new QuicSimpleServerSession( + config_, connection, this, crypto_config_, &compressed_certs_cache_); session->Initialize(); return session; } diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h index 3a96176..6ba8f2b 100644 --- a/net/tools/quic/quic_dispatcher.h +++ b/net/tools/quic/quic_dispatcher.h @@ -16,6 +16,7 @@ #include "base/memory/scoped_ptr.h" #include "net/base/ip_endpoint.h" #include "net/base/linked_hash_map.h" +#include "net/quic/crypto/quic_compressed_certs_cache.h" #include "net/quic/quic_blocked_writer_interface.h" #include "net/quic/quic_connection.h" #include "net/quic/quic_protocol.h" @@ -131,8 +132,6 @@ class QuicDispatcher : public QuicServerSessionVisitor, const QuicVersionNegotiationPacket& packet) override; void OnDecryptedPacket(EncryptionLevel level) override; bool OnPacketHeader(const QuicPacketHeader& header) override; - void OnRevivedPacket() override; - void OnFecProtectedPayload(base::StringPiece payload) override; bool OnStreamFrame(const QuicStreamFrame& frame) override; bool OnAckFrame(const QuicAckFrame& frame) override; bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override; @@ -143,7 +142,6 @@ class QuicDispatcher : public QuicServerSessionVisitor, bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override; bool OnBlockedFrame(const QuicBlockedFrame& frame) override; bool OnPathCloseFrame(const QuicPathCloseFrame& frame) override; - void OnFecData(base::StringPiece redundancy) override; void OnPacketComplete() override; protected: @@ -190,6 +188,10 @@ class QuicDispatcher : public QuicServerSessionVisitor, const QuicCryptoServerConfig* crypto_config() const { return crypto_config_; } + QuicCompressedCertsCache* compressed_certs_cache() { + return &compressed_certs_cache_; + } + QuicFramer* framer() { return &framer_; } QuicConnectionHelperInterface* helper() { return helper_.get(); } @@ -223,6 +225,9 @@ class QuicDispatcher : public QuicServerSessionVisitor, const QuicCryptoServerConfig* crypto_config_; + // The cache for most recently compressed certs. + QuicCompressedCertsCache compressed_certs_cache_; + // The list of connections waiting to write. WriteBlockedList write_blocked_list_; diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc index 169dc63..67fb2d6 100644 --- a/net/tools/quic/quic_dispatcher_test.cc +++ b/net/tools/quic/quic_dispatcher_test.cc @@ -50,8 +50,13 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase { public: TestQuicSpdyServerSession(const QuicConfig& config, QuicConnection* connection, - const QuicCryptoServerConfig* crypto_config) - : QuicServerSessionBase(config, connection, nullptr, crypto_config), + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) + : QuicServerSessionBase(config, + connection, + nullptr, + crypto_config, + compressed_certs_cache), crypto_stream_(QuicServerSessionBase::GetCryptoStream()) {} ~TestQuicSpdyServerSession() override{}; @@ -62,8 +67,11 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase { QuicSpdyStream*(SpdyPriority priority)); QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config) override { - return new QuicCryptoServerStream(crypto_config, this); + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) override { + return new QuicCryptoServerStream( + crypto_config, compressed_certs_cache, + FLAGS_enable_quic_stateless_reject_support, this); } void SetCryptoStream(QuicCryptoServerStream* crypto_stream) { @@ -126,10 +134,12 @@ QuicServerSessionBase* CreateSession( const IPEndPoint& client_address, MockConnectionHelper* helper, const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache, TestQuicSpdyServerSession** session) { MockServerConnection* connection = new MockServerConnection(connection_id, helper, dispatcher); - *session = new TestQuicSpdyServerSession(config, connection, crypto_config); + *session = new TestQuicSpdyServerSession(config, connection, crypto_config, + compressed_certs_cache); connection->set_visitor(*session); ON_CALL(*connection, SendConnectionCloseWithDetails(_, _)) .WillByDefault(WithoutArgs(Invoke( @@ -255,17 +265,19 @@ TEST_F(QuicDispatcherTest, ProcessPackets) { server_address_ = IPEndPoint(net::test::Any4(), 5); EXPECT_CALL(dispatcher_, CreateQuicSession(1, client_address)) - .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1, - client_address, &mock_helper_, - &crypto_config_, &session1_))); + .WillOnce(testing::Return(CreateSession( + &dispatcher_, config_, 1, client_address, &mock_helper_, + &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_), + &session1_))); ProcessPacket(client_address, 1, true, false, "foo"); EXPECT_EQ(client_address, dispatcher_.current_client_address()); EXPECT_EQ(server_address_, dispatcher_.current_server_address()); EXPECT_CALL(dispatcher_, CreateQuicSession(2, client_address)) - .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 2, - client_address, &mock_helper_, - &crypto_config_, &session2_))); + .WillOnce(testing::Return(CreateSession( + &dispatcher_, config_, 2, client_address, &mock_helper_, + &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_), + &session2_))); ProcessPacket(client_address, 2, true, false, "bar"); EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()), @@ -293,9 +305,10 @@ TEST_F(QuicDispatcherTest, StatefulVersionNegotiation) { server_address_ = IPEndPoint(net::test::Any4(), 5); EXPECT_CALL(dispatcher_, CreateQuicSession(1, client_address)) - .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1, - client_address, &mock_helper_, - &crypto_config_, &session1_))); + .WillOnce(testing::Return(CreateSession( + &dispatcher_, config_, 1, client_address, &mock_helper_, + &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_), + &session1_))); QuicVersion version = static_cast<QuicVersion>(QuicVersionMin() - 1); ProcessPacket(client_address, 1, true, version, "foo", PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, 1); @@ -305,9 +318,10 @@ TEST_F(QuicDispatcherTest, Shutdown) { IPEndPoint client_address(net::test::Loopback4(), 1); EXPECT_CALL(dispatcher_, CreateQuicSession(_, client_address)) - .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1, - client_address, &mock_helper_, - &crypto_config_, &session1_))); + .WillOnce(testing::Return(CreateSession( + &dispatcher_, config_, 1, client_address, &mock_helper_, + &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_), + &session1_))); ProcessPacket(client_address, 1, true, false, "foo"); @@ -324,9 +338,10 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) { IPEndPoint client_address(net::test::Loopback4(), 1); QuicConnectionId connection_id = 1; EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, client_address)) - .WillOnce(testing::Return( - CreateSession(&dispatcher_, config_, connection_id, client_address, - &mock_helper_, &crypto_config_, &session1_))); + .WillOnce(testing::Return(CreateSession( + &dispatcher_, config_, connection_id, client_address, &mock_helper_, + &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_), + &session1_))); ProcessPacket(client_address, connection_id, true, false, "foo"); // Close the connection by sending public reset packet. @@ -382,8 +397,12 @@ TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) { class MockQuicCryptoServerStream : public QuicCryptoServerStream { public: MockQuicCryptoServerStream(const QuicCryptoServerConfig& crypto_config, + QuicCompressedCertsCache* compressed_certs_cache, QuicSession* session) - : QuicCryptoServerStream(&crypto_config, session) {} + : QuicCryptoServerStream(&crypto_config, + compressed_certs_cache, + FLAGS_enable_quic_stateless_reject_support, + session) {} void set_handshake_confirmed_for_testing(bool handshake_confirmed) { handshake_confirmed_ = handshake_confirmed; } @@ -468,9 +487,11 @@ class QuicDispatcherStatelessRejectTest QuicConnectionId connection_id, const IPEndPoint& client_address) { CreateSession(&dispatcher_, config_, connection_id, client_address, - &mock_helper_, &crypto_config_, &session1_); + &mock_helper_, &crypto_config_, + QuicDispatcherPeer::GetCache(&dispatcher_), &session1_); - crypto_stream1_ = new MockQuicCryptoServerStream(crypto_config_, session1_); + crypto_stream1_ = new MockQuicCryptoServerStream( + crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_), session1_); session1_->SetCryptoStream(crypto_stream1_); crypto_stream1_->set_handshake_confirmed_for_testing( GetParam().crypto_handshake_successful); @@ -502,9 +523,10 @@ TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) { server_address_ = IPEndPoint(net::test::Any4(), 5); EXPECT_CALL(dispatcher_, CreateQuicSession(1, client_address)) - .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1, - client_address, &mock_helper_, - &crypto_config_, &session1_))); + .WillOnce(testing::Return(CreateSession( + &dispatcher_, config_, 1, client_address, &mock_helper_, + &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_), + &session1_))); // A packet whose packet number is the largest that is allowed to start a // connection. ProcessPacket(client_address, connection_id, true, false, "data", @@ -650,15 +672,15 @@ class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest { IPEndPoint client_address(net::test::Loopback4(), 1); EXPECT_CALL(dispatcher_, CreateQuicSession(_, client_address)) - .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1, - client_address, &helper_, - &crypto_config_, &session1_))); + .WillOnce(testing::Return(CreateSession( + &dispatcher_, config_, 1, client_address, &helper_, &crypto_config_, + QuicDispatcherPeer::GetCache(&dispatcher_), &session1_))); ProcessPacket(client_address, 1, true, false, "foo"); EXPECT_CALL(dispatcher_, CreateQuicSession(_, client_address)) - .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 2, - client_address, &helper_, - &crypto_config_, &session2_))); + .WillOnce(testing::Return(CreateSession( + &dispatcher_, config_, 2, client_address, &helper_, &crypto_config_, + QuicDispatcherPeer::GetCache(&dispatcher_), &session2_))); ProcessPacket(client_address, 2, true, false, "bar"); blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(&dispatcher_); diff --git a/net/tools/quic/quic_epoll_connection_helper_test.cc b/net/tools/quic/quic_epoll_connection_helper_test.cc index 1e1d22e..f79e0ff 100644 --- a/net/tools/quic/quic_epoll_connection_helper_test.cc +++ b/net/tools/quic/quic_epoll_connection_helper_test.cc @@ -18,10 +18,7 @@ class TestDelegate : public QuicAlarm::Delegate { public: TestDelegate() : fired_(false) {} - QuicTime OnAlarm() override { - fired_ = true; - return QuicTime::Zero(); - } + void OnAlarm() override { fired_ = true; } bool fired() const { return fired_; } diff --git a/net/tools/quic/quic_server_session_base.cc b/net/tools/quic/quic_server_session_base.cc index 63618d4..c8a6dfb 100644 --- a/net/tools/quic/quic_server_session_base.cc +++ b/net/tools/quic/quic_server_session_base.cc @@ -18,9 +18,11 @@ QuicServerSessionBase::QuicServerSessionBase( const QuicConfig& config, QuicConnection* connection, QuicServerSessionVisitor* visitor, - const QuicCryptoServerConfig* crypto_config) + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) : QuicSpdySession(connection, config), crypto_config_(crypto_config), + compressed_certs_cache_(compressed_certs_cache), visitor_(visitor), bandwidth_resumption_enabled_(false), bandwidth_estimate_sent_to_client_(QuicBandwidth::Zero()), @@ -30,7 +32,8 @@ QuicServerSessionBase::QuicServerSessionBase( QuicServerSessionBase::~QuicServerSessionBase() {} void QuicServerSessionBase::Initialize() { - crypto_stream_.reset(CreateQuicCryptoServerStream(crypto_config_)); + crypto_stream_.reset( + CreateQuicCryptoServerStream(crypto_config_, compressed_certs_cache_)); QuicSpdySession::Initialize(); } diff --git a/net/tools/quic/quic_server_session_base.h b/net/tools/quic/quic_server_session_base.h index ddfaa98..a93fd9c 100644 --- a/net/tools/quic/quic_server_session_base.h +++ b/net/tools/quic/quic_server_session_base.h @@ -16,6 +16,7 @@ #include "base/containers/hash_tables.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" +#include "net/quic/crypto/quic_compressed_certs_cache.h" #include "net/quic/quic_crypto_server_stream.h" #include "net/quic/quic_protocol.h" #include "net/quic/quic_spdy_session.h" @@ -58,7 +59,8 @@ class QuicServerSessionBase : public QuicSpdySession { QuicServerSessionBase(const QuicConfig& config, QuicConnection* connection, QuicServerSessionVisitor* visitor, - const QuicCryptoServerConfig* crypto_config); + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache); // Override the base class to notify the owner of the connection close. void OnConnectionClosed(QuicErrorCode error, @@ -77,7 +79,8 @@ class QuicServerSessionBase : public QuicSpdySession { return crypto_stream_.get(); } - // Override base class to process FEC config received from client. + // Override base class to process bandwidth related config received from + // client. void OnConfigNegotiated() override; void set_serving_region(const std::string& serving_region) { @@ -92,7 +95,7 @@ class QuicServerSessionBase : public QuicSpdySession { // Return false when connection is closed or forward secure encryption hasn't // established yet or number of server initiated streams already reaches the // upper limit. - bool ShouldCreateOutgoingDynamicStream(); + virtual bool ShouldCreateOutgoingDynamicStream(); // If we should create an incoming stream, returns true. Otherwise // does error handling, including communicating the error to the client and @@ -100,7 +103,8 @@ class QuicServerSessionBase : public QuicSpdySession { virtual bool ShouldCreateIncomingDynamicStream(QuicStreamId id); virtual QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config) = 0; + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) = 0; const QuicCryptoServerConfig* crypto_config() { return crypto_config_; } @@ -109,6 +113,11 @@ class QuicServerSessionBase : public QuicSpdySession { friend class test::QuicSimpleServerSessionPeer; const QuicCryptoServerConfig* crypto_config_; + + // The cache which contains most recently compressed certs. + // Owned by QuicDispatcher. + QuicCompressedCertsCache* compressed_certs_cache_; + scoped_ptr<QuicCryptoServerStreamBase> crypto_stream_; QuicServerSessionVisitor* visitor_; diff --git a/net/tools/quic/quic_server_session_base_test.cc b/net/tools/quic/quic_server_session_base_test.cc index 1d4ed11..4de21a3 100644 --- a/net/tools/quic/quic_server_session_base_test.cc +++ b/net/tools/quic/quic_server_session_base_test.cc @@ -73,8 +73,13 @@ class TestServerSession : public QuicServerSessionBase { TestServerSession(const QuicConfig& config, QuicConnection* connection, QuicServerSessionVisitor* visitor, - const QuicCryptoServerConfig* crypto_config) - : QuicServerSessionBase(config, connection, visitor, crypto_config) {} + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) + : QuicServerSessionBase(config, + connection, + visitor, + crypto_config, + compressed_certs_cache) {} ~TestServerSession() override{}; @@ -101,8 +106,11 @@ class TestServerSession : public QuicServerSessionBase { } QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config) override { - return new QuicCryptoServerStream(crypto_config, this); + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) override { + return new QuicCryptoServerStream( + crypto_config, compressed_certs_cache, + FLAGS_enable_quic_stateless_reject_support, this); } }; @@ -113,7 +121,10 @@ class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> { QuicServerSessionBaseTest() : crypto_config_(QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), - CryptoTestUtils::ProofSourceForTesting()) { + CryptoTestUtils::ProofSourceForTesting()), + compressed_certs_cache_( + QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) { + FLAGS_quic_always_log_bugs_for_tests = true; config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest); config_.SetInitialStreamFlowControlWindowToSend( kInitialStreamFlowControlWindowForTest); @@ -122,8 +133,9 @@ class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> { connection_ = new StrictMock<MockConnection>( &helper_, Perspective::IS_SERVER, SupportedVersions(GetParam())); - session_.reset( - new TestServerSession(config_, connection_, &owner_, &crypto_config_)); + session_.reset(new TestServerSession(config_, connection_, &owner_, + &crypto_config_, + &compressed_certs_cache_)); MockClock clock; handshake_message_.reset(crypto_config_.AddDefaultConfig( QuicRandom::GetInstance(), &clock, @@ -137,6 +149,7 @@ class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> { StrictMock<MockConnection>* connection_; QuicConfig config_; QuicCryptoServerConfig crypto_config_; + QuicCompressedCertsCache compressed_certs_cache_; scoped_ptr<TestServerSession> session_; scoped_ptr<CryptoHandshakeMessage> handshake_message_; QuicConnectionVisitorInterface* visitor_; @@ -331,8 +344,12 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream { public: explicit MockQuicCryptoServerStream( const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache, QuicSession* session) - : QuicCryptoServerStream(crypto_config, session) {} + : QuicCryptoServerStream(crypto_config, + compressed_certs_cache, + FLAGS_enable_quic_stateless_reject_support, + session) {} ~MockQuicCryptoServerStream() override {} MOCK_METHOD1(SendServerConfigUpdate, @@ -366,8 +383,8 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) { const string serving_region = "not a real region"; session_->set_serving_region(serving_region); - MockQuicCryptoServerStream* crypto_stream = - new MockQuicCryptoServerStream(&crypto_config_, session_.get()); + MockQuicCryptoServerStream* crypto_stream = new MockQuicCryptoServerStream( + &crypto_config_, &compressed_certs_cache_, session_.get()); QuicServerSessionBasePeer::SetCryptoStream(session_.get(), crypto_stream); // Set some initial bandwidth values. diff --git a/net/tools/quic/quic_simple_server_session.cc b/net/tools/quic/quic_simple_server_session.cc index e72383a..5b5b57e 100644 --- a/net/tools/quic/quic_simple_server_session.cc +++ b/net/tools/quic/quic_simple_server_session.cc @@ -20,16 +20,24 @@ QuicSimpleServerSession::QuicSimpleServerSession( const QuicConfig& config, QuicConnection* connection, QuicServerSessionVisitor* visitor, - const QuicCryptoServerConfig* crypto_config) - : QuicServerSessionBase(config, connection, visitor, crypto_config), + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) + : QuicServerSessionBase(config, + connection, + visitor, + crypto_config, + compressed_certs_cache), highest_promised_stream_id_(0) {} QuicSimpleServerSession::~QuicSimpleServerSession() {} QuicCryptoServerStreamBase* QuicSimpleServerSession::CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config) { - return new QuicCryptoServerStream(crypto_config, this); + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) { + return new QuicCryptoServerStream(crypto_config, compressed_certs_cache, + FLAGS_enable_quic_stateless_reject_support, + this); } void QuicSimpleServerSession::StreamDraining(QuicStreamId id) { diff --git a/net/tools/quic/quic_simple_server_session.h b/net/tools/quic/quic_simple_server_session.h index 0329a66..ea7860dd 100644 --- a/net/tools/quic/quic_simple_server_session.h +++ b/net/tools/quic/quic_simple_server_session.h @@ -59,7 +59,8 @@ class QuicSimpleServerSession : public QuicServerSessionBase { QuicSimpleServerSession(const QuicConfig& config, QuicConnection* connection, QuicServerSessionVisitor* visitor, - const QuicCryptoServerConfig* crypto_config); + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache); ~QuicSimpleServerSession() override; @@ -97,7 +98,8 @@ class QuicSimpleServerSession : public QuicServerSessionBase { // QuicServerSessionBaseMethod: QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config) override; + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) override; private: friend class test::QuicSimpleServerSessionPeer; diff --git a/net/tools/quic/quic_simple_server_session_test.cc b/net/tools/quic/quic_simple_server_session_test.cc index e6dcdc9..029fa11 100644 --- a/net/tools/quic/quic_simple_server_session_test.cc +++ b/net/tools/quic/quic_simple_server_session_test.cc @@ -83,8 +83,12 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream { public: explicit MockQuicCryptoServerStream( const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache, QuicSession* session) - : QuicCryptoServerStream(crypto_config, session) {} + : QuicCryptoServerStream(crypto_config, + compressed_certs_cache, + FLAGS_enable_quic_stateless_reject_support, + session) {} ~MockQuicCryptoServerStream() override {} MOCK_METHOD1(SendServerConfigUpdate, @@ -105,12 +109,11 @@ class MockConnectionWithSendStreamData : public MockConnection { const QuicVersionVector& supported_versions) : MockConnection(helper, perspective, supported_versions) {} - MOCK_METHOD6(SendStreamData, + MOCK_METHOD5(SendStreamData, QuicConsumedData(QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface* listern)); }; @@ -153,7 +156,9 @@ class QuicSimpleServerSessionTest QuicSimpleServerSessionTest() : crypto_config_(QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), - CryptoTestUtils::ProofSourceForTesting()) { + CryptoTestUtils::ProofSourceForTesting()), + compressed_certs_cache_( + QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) { FLAGS_quic_always_log_bugs_for_tests = true; config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest); config_.SetInitialStreamFlowControlWindowToSend( @@ -164,7 +169,8 @@ class QuicSimpleServerSessionTest connection_ = new StrictMock<MockConnectionWithSendStreamData>( &helper_, Perspective::IS_SERVER, SupportedVersions(GetParam())); session_.reset(new QuicSimpleServerSession(config_, connection_, &owner_, - &crypto_config_)); + &crypto_config_, + &compressed_certs_cache_)); MockClock clock; handshake_message_.reset(crypto_config_.AddDefaultConfig( QuicRandom::GetInstance(), &clock, @@ -182,6 +188,7 @@ class QuicSimpleServerSessionTest StrictMock<MockConnectionWithSendStreamData>* connection_; QuicConfig config_; QuicCryptoServerConfig crypto_config_; + QuicCompressedCertsCache compressed_certs_cache_; scoped_ptr<QuicSimpleServerSession> session_; scoped_ptr<CryptoHandshakeMessage> handshake_message_; QuicConnectionVisitorInterface* visitor_; @@ -323,8 +330,8 @@ TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) { EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams()); // Assume encryption already established. - MockQuicCryptoServerStream* crypto_stream = - new MockQuicCryptoServerStream(&crypto_config_, session_.get()); + MockQuicCryptoServerStream* crypto_stream = new MockQuicCryptoServerStream( + &crypto_config_, &compressed_certs_cache_, session_.get()); crypto_stream->set_encryption_established(true); QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream); @@ -398,7 +405,8 @@ class QuicSimpleServerSessionServerPushTest connection_ = new StrictMock<MockConnectionWithSendStreamData>( &helper_, Perspective::IS_SERVER, SupportedVersions(GetParam())); session_.reset(new QuicSimpleServerSession(config_, connection_, &owner_, - &crypto_config_)); + &crypto_config_, + &compressed_certs_cache_)); session_->Initialize(); // Needed to make new session flow control window work. session_->OnConfigNegotiated(); @@ -408,8 +416,8 @@ class QuicSimpleServerSessionServerPushTest QuicSpdySessionPeer::SetHeadersStream(session_.get(), headers_stream_); // Assume encryption already established. - MockQuicCryptoServerStream* crypto_stream = - new MockQuicCryptoServerStream(&crypto_config_, session_.get()); + MockQuicCryptoServerStream* crypto_stream = new MockQuicCryptoServerStream( + &crypto_config_, &compressed_certs_cache_, session_.get()); crypto_stream->set_encryption_established(true); QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream); } @@ -455,7 +463,7 @@ class QuicSimpleServerSessionServerPushTest // Since flow control window is smaller than response body, not the // whole body will be sent. EXPECT_CALL(*connection_, - SendStreamData(stream_id, _, 0, false, _, nullptr)) + SendStreamData(stream_id, _, 0, false, nullptr)) .WillOnce( Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); EXPECT_CALL(*connection_, SendBlocked(stream_id)); @@ -492,7 +500,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest, EXPECT_CALL(*headers_stream_, WriteHeaders(next_out_going_stream_id, _, false, kDefaultPriority, nullptr)); EXPECT_CALL(*connection_, - SendStreamData(next_out_going_stream_id, _, 0, false, _, nullptr)) + SendStreamData(next_out_going_stream_id, _, 0, false, nullptr)) .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); EXPECT_CALL(*connection_, SendBlocked(next_out_going_stream_id)); session_->StreamDraining(2); @@ -526,7 +534,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest, EXPECT_CALL(*headers_stream_, WriteHeaders(stream_not_reset, _, false, kDefaultPriority, nullptr)); EXPECT_CALL(*connection_, - SendStreamData(stream_not_reset, _, 0, false, _, nullptr)) + SendStreamData(stream_not_reset, _, 0, false, nullptr)) .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); EXPECT_CALL(*connection_, SendBlocked(stream_not_reset)); EXPECT_CALL(*headers_stream_, WriteHeaders(stream_got_reset, _, false, @@ -553,7 +561,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest, EXPECT_CALL(*headers_stream_, WriteHeaders(stream_to_open, _, false, kDefaultPriority, nullptr)); EXPECT_CALL(*connection_, - SendStreamData(stream_to_open, _, 0, false, _, nullptr)) + SendStreamData(stream_to_open, _, 0, false, nullptr)) .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); EXPECT_CALL(*connection_, SendBlocked(stream_to_open)); diff --git a/net/tools/quic/quic_simple_server_stream_test.cc b/net/tools/quic/quic_simple_server_stream_test.cc index 91b8ada..594e34c 100644 --- a/net/tools/quic/quic_simple_server_stream_test.cc +++ b/net/tools/quic/quic_simple_server_stream_test.cc @@ -84,16 +84,19 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession { public: const size_t kMaxStreamsForTest = 100; - explicit MockQuicSimpleServerSession(QuicConnection* connection, - MockQuicServerSessionVisitor* owner, - QuicCryptoServerConfig* crypto_config) - : QuicSimpleServerSession(::net::test::DefaultQuicConfig(), + explicit MockQuicSimpleServerSession( + QuicConnection* connection, + MockQuicServerSessionVisitor* owner, + QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) + : QuicSimpleServerSession(DefaultQuicConfig(), connection, owner, - crypto_config) { + crypto_config, + compressed_certs_cache) { set_max_open_incoming_streams(kMaxStreamsForTest); set_max_open_outgoing_streams(kMaxStreamsForTest); - ON_CALL(*this, WritevData(_, _, _, _, _, _)) + ON_CALL(*this, WritevData(_, _, _, _, _)) .WillByDefault(testing::Return(QuicConsumedData(0, false))); } @@ -102,12 +105,11 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession { MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, ConnectionCloseSource source)); MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id)); - MOCK_METHOD6(WritevData, + MOCK_METHOD5(WritevData, QuicConsumedData(QuicStreamId id, QuicIOVector data, QuicStreamOffset offset, bool fin, - FecProtection fec_protection, QuicAckListenerInterface*)); MOCK_METHOD2(OnStreamHeaders, void(QuicStreamId stream_id, StringPiece headers_data)); @@ -153,7 +155,12 @@ class QuicSimpleServerStreamTest QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), ::net::test::CryptoTestUtils::ProofSourceForTesting())), - session_(connection_, session_owner_, crypto_config_.get()), + compressed_certs_cache_( + QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), + session_(connection_, + session_owner_, + crypto_config_.get(), + &compressed_certs_cache_), body_("hello world") { FLAGS_quic_always_log_bugs_for_tests = true; SpdyHeaderBlock request_headers; @@ -198,6 +205,7 @@ class QuicSimpleServerStreamTest StrictMock<MockConnection>* connection_; StrictMock<MockQuicServerSessionVisitor>* session_owner_; std::unique_ptr<QuicCryptoServerConfig> crypto_config_; + QuicCompressedCertsCache compressed_certs_cache_; StrictMock<MockQuicSimpleServerSession> session_; QuicSimpleServerStreamPeer* stream_; // Owned by session_. string headers_string_; @@ -209,7 +217,7 @@ INSTANTIATE_TEST_CASE_P(Tests, ::testing::ValuesIn(QuicSupportedVersions())); TEST_P(QuicSimpleServerStreamTest, TestFraming) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(AnyNumber()) .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); stream_->OnStreamHeaders(headers_string_); @@ -223,7 +231,7 @@ TEST_P(QuicSimpleServerStreamTest, TestFraming) { } TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(AnyNumber()) .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); @@ -238,7 +246,7 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) { } TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorInStopReading) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(AnyNumber()) .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); @@ -261,7 +269,7 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingExtraData) { // We'll automatically write out an error (headers + body) EXPECT_CALL(session_, WriteHeaders(_, _, _, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .WillOnce(Invoke(MockQuicSpdySession::ConsumeAllData)); EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0); @@ -298,7 +306,7 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) { InSequence s; EXPECT_CALL(session_, WriteHeaders(stream_->id(), _, false, _, nullptr)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData( strlen(QuicSimpleServerStream::kErrorResponseBody), true))); @@ -355,7 +363,7 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) { InSequence s; EXPECT_CALL(session_, WriteHeaders(stream_->id(), _, false, _, nullptr)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData(body.length(), true))); @@ -394,7 +402,7 @@ TEST_P(QuicSimpleServerStreamTest, SendReponseWithPushResources) { ::net::test::kClientDataStreamId1, *request_headers)); EXPECT_CALL(session_, WriteHeaders(stream_->id(), _, false, _, nullptr)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData(body.length(), true))); QuicSimpleServerStreamPeer::SendResponse(stream_); @@ -440,7 +448,7 @@ TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) { EXPECT_CALL(session_, WriteHeaders(kServerInitiatedStreamId, _, false, server_initiated_stream->priority(), nullptr)); - EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, _, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData(kBody.size(), true))); server_initiated_stream->PushResponse(headers); @@ -462,7 +470,7 @@ TEST_P(QuicSimpleServerStreamTest, TestSendErrorResponse) { InSequence s; EXPECT_CALL(session_, WriteHeaders(_, _, _, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData(3, true))); @@ -482,7 +490,7 @@ TEST_P(QuicSimpleServerStreamTest, InvalidMultipleContentLength) { headers_string_ = SpdyUtils::SerializeUncompressedHeaders(request_headers); EXPECT_CALL(session_, WriteHeaders(_, _, _, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(AnyNumber()) .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); stream_->OnStreamHeaders(headers_string_); @@ -503,7 +511,7 @@ TEST_P(QuicSimpleServerStreamTest, InvalidLeadingNullContentLength) { headers_string_ = SpdyUtils::SerializeUncompressedHeaders(request_headers); EXPECT_CALL(session_, WriteHeaders(_, _, _, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(AnyNumber()) .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); stream_->OnStreamHeaders(headers_string_); @@ -537,7 +545,7 @@ TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorWithEarlyResponse) { InSequence s; EXPECT_CALL(session_, WriteHeaders(stream_->id(), _, _, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData(3, true))); if (GetParam() > QUIC_VERSION_28) { diff --git a/net/tools/quic/quic_socket_utils.cc b/net/tools/quic/quic_socket_utils.cc index 42141df..9c8cac7 100644 --- a/net/tools/quic/quic_socket_utils.cc +++ b/net/tools/quic/quic_socket_utils.cc @@ -213,7 +213,10 @@ WriteResult QuicSocketUtils::WritePacket(int fd, hdr.msg_controllen = cmsg->cmsg_len; } - int rc = sendmsg(fd, &hdr, 0); + int rc; + do { + rc = sendmsg(fd, &hdr, 0); + } while (rc < 0 && errno == EINTR); if (rc >= 0) { return WriteResult(WRITE_STATUS_OK, rc); } diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc index 64ff05e..91c48d0 100644 --- a/net/tools/quic/quic_time_wait_list_manager.cc +++ b/net/tools/quic/quic_time_wait_list_manager.cc @@ -34,10 +34,8 @@ class ConnectionIdCleanUpAlarm : public QuicAlarm::Delegate { QuicTimeWaitListManager* time_wait_list_manager) : time_wait_list_manager_(time_wait_list_manager) {} - QuicTime OnAlarm() override { + void OnAlarm() override { time_wait_list_manager_->CleanUpOldConnectionIds(); - // Let the time wait manager register the alarm at appropriate time. - return QuicTime::Zero(); } private: diff --git a/net/tools/quic/test_tools/packet_dropping_test_writer.cc b/net/tools/quic/test_tools/packet_dropping_test_writer.cc index ed46a07..3858b78 100644 --- a/net/tools/quic/test_tools/packet_dropping_test_writer.cc +++ b/net/tools/quic/test_tools/packet_dropping_test_writer.cc @@ -20,10 +20,9 @@ class WriteUnblockedAlarm : public QuicAlarm::Delegate { explicit WriteUnblockedAlarm(PacketDroppingTestWriter* writer) : writer_(writer) {} - QuicTime OnAlarm() override { + void OnAlarm() override { DVLOG(1) << "Unblocking socket."; writer_->OnCanWrite(); - return QuicTime::Zero(); } private: @@ -36,7 +35,12 @@ class DelayAlarm : public QuicAlarm::Delegate { public: explicit DelayAlarm(PacketDroppingTestWriter* writer) : writer_(writer) {} - QuicTime OnAlarm() override { return writer_->ReleaseOldPackets(); } + void OnAlarm() override { + QuicTime new_deadline = writer_->ReleaseOldPackets(); + if (new_deadline.IsInitialized()) { + writer_->SetDelayAlarm(new_deadline); + } + } private: PacketDroppingTestWriter* writer_; @@ -203,6 +207,10 @@ QuicTime PacketDroppingTestWriter::ReleaseOldPackets() { return QuicTime::Zero(); } +void PacketDroppingTestWriter::SetDelayAlarm(QuicTime new_deadline) { + delay_alarm_->Set(new_deadline); +} + void PacketDroppingTestWriter::OnCanWrite() { on_can_write_->OnCanWrite(); } diff --git a/net/tools/quic/test_tools/packet_dropping_test_writer.h b/net/tools/quic/test_tools/packet_dropping_test_writer.h index be948f6..20d2c27 100644 --- a/net/tools/quic/test_tools/packet_dropping_test_writer.h +++ b/net/tools/quic/test_tools/packet_dropping_test_writer.h @@ -63,6 +63,9 @@ class PacketDroppingTestWriter : public QuicPacketWriterWrapper { // for the next delayed packet to be written. QuicTime ReleaseOldPackets(); + // Sets |delay_alarm_| to fire at |new_deadline|. + void SetDelayAlarm(QuicTime new_deadline); + void OnCanWrite(); // The percent of time a packet is simulated as being lost. diff --git a/net/tools/quic/test_tools/quic_dispatcher_peer.cc b/net/tools/quic/test_tools/quic_dispatcher_peer.cc index 03e8e46..232043f 100644 --- a/net/tools/quic/test_tools/quic_dispatcher_peer.cc +++ b/net/tools/quic/test_tools/quic_dispatcher_peer.cc @@ -30,6 +30,12 @@ QuicPacketWriter* QuicDispatcherPeer::GetWriter(QuicDispatcher* dispatcher) { } // static +QuicCompressedCertsCache* QuicDispatcherPeer::GetCache( + QuicDispatcher* dispatcher) { + return dispatcher->compressed_certs_cache(); +} + +// static QuicConnectionHelperInterface* QuicDispatcherPeer::GetHelper( QuicDispatcher* dispatcher) { return dispatcher->helper_.get(); diff --git a/net/tools/quic/test_tools/quic_dispatcher_peer.h b/net/tools/quic/test_tools/quic_dispatcher_peer.h index 7c3536f..cbd60e2 100644 --- a/net/tools/quic/test_tools/quic_dispatcher_peer.h +++ b/net/tools/quic/test_tools/quic_dispatcher_peer.h @@ -28,6 +28,8 @@ class QuicDispatcherPeer { static QuicPacketWriter* GetWriter(QuicDispatcher* dispatcher); + static QuicCompressedCertsCache* GetCache(QuicDispatcher* dispatcher); + static QuicConnectionHelperInterface* GetHelper(QuicDispatcher* dispatcher); static QuicDispatcher::WriteBlockedList* GetWriteBlockedList( diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc index cf1abec..e926279a 100644 --- a/net/tools/quic/test_tools/quic_test_client.cc +++ b/net/tools/quic/test_tools/quic_test_client.cc @@ -201,7 +201,6 @@ void QuicTestClient::Initialize() { connect_attempted_ = false; auto_reconnect_ = false; buffer_body_ = true; - fec_policy_ = FEC_PROTECT_OPTIONAL; ClearPerRequestState(); // As chrome will generally do this, we want it to be the default when it's // not overridden. @@ -394,8 +393,6 @@ QuicSpdyClientStream* QuicTestClient::GetOrCreateStream() { QuicSpdyClientStream* cs = reinterpret_cast<QuicSpdyClientStream*>(stream_); cs->SetPriority(priority_); cs->set_allow_bidirectional_data(allow_bidirectional_data_); - // Set FEC policy on stream. - ReliableQuicStreamPeer::SetFecPolicy(stream_, fec_policy_); } return stream_; @@ -651,15 +648,6 @@ void QuicTestClient::WaitForWriteToFlush() { } } -void QuicTestClient::SetFecPolicy(FecPolicy fec_policy) { - fec_policy_ = fec_policy; - // Set policy for headers and crypto streams. - ReliableQuicStreamPeer::SetFecPolicy( - QuicSpdySessionPeer::GetHeadersStream(client()->session()), fec_policy); - ReliableQuicStreamPeer::SetFecPolicy(client()->session()->GetCryptoStream(), - fec_policy); -} - void QuicTestClient::TestClientDataToResend::Resend() { test_client_->GetOrCreateStreamAndSendRequest(headers_, body_, fin_, delegate_); diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h index 6dc3ea5..93cc385 100644 --- a/net/tools/quic/test_tools/quic_test_client.h +++ b/net/tools/quic/test_tools/quic_test_client.h @@ -185,10 +185,6 @@ class QuicTestClient : public test::SimpleClient, void set_priority(SpdyPriority priority) { priority_ = priority; } - // Sets client's FEC policy. This policy applies to the data stream(s), and - // also to the headers and crypto streams. - void SetFecPolicy(FecPolicy fec_policy); - void WaitForWriteToFlush(); EpollServer* epoll_server() { return &epoll_server_; } @@ -265,8 +261,6 @@ class QuicTestClient : public test::SimpleClient, bool auto_reconnect_; // Should we buffer the response body? Defaults to true. bool buffer_body_; - // FEC policy for data sent by this client. - FecPolicy fec_policy_; // When true allows the sending of a request to continue while the response is // arriving. bool allow_bidirectional_data_; diff --git a/net/tools/quic/test_tools/quic_test_server.cc b/net/tools/quic/test_tools/quic_test_server.cc index 31ddef8..d513a69 100644 --- a/net/tools/quic/test_tools/quic_test_server.cc +++ b/net/tools/quic/test_tools/quic_test_server.cc @@ -33,9 +33,14 @@ class CustomStreamSession : public QuicSimpleServerSession { QuicConnection* connection, QuicServerSessionVisitor* visitor, const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache, QuicTestServer::StreamFactory* factory, QuicTestServer::CryptoStreamFactory* crypto_stream_factory) - : QuicSimpleServerSession(config, connection, visitor, crypto_config), + : QuicSimpleServerSession(config, + connection, + visitor, + crypto_config, + compressed_certs_cache), stream_factory_(factory), crypto_stream_factory_(crypto_stream_factory) {} @@ -52,11 +57,13 @@ class CustomStreamSession : public QuicSimpleServerSession { } QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config) override { + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) override { if (crypto_stream_factory_) { return crypto_stream_factory_->CreateCryptoStream(crypto_config, this); } - return QuicSimpleServerSession::CreateQuicCryptoServerStream(crypto_config); + return QuicSimpleServerSession::CreateQuicCryptoServerStream( + crypto_config, compressed_certs_cache); } private: @@ -88,12 +95,13 @@ class QuicTestDispatcher : public QuicDispatcher { QuicServerSessionBase* session = nullptr; if (stream_factory_ != nullptr || crypto_stream_factory_ != nullptr) { - session = - new CustomStreamSession(config(), connection, this, crypto_config(), - stream_factory_, crypto_stream_factory_); + session = new CustomStreamSession( + config(), connection, this, crypto_config(), compressed_certs_cache(), + stream_factory_, crypto_stream_factory_); } else { session = session_factory_->CreateSession(config(), connection, this, - crypto_config()); + crypto_config(), + compressed_certs_cache()); } session->Initialize(); return session; @@ -165,8 +173,13 @@ ImmediateGoAwaySession::ImmediateGoAwaySession( const QuicConfig& config, QuicConnection* connection, QuicServerSessionVisitor* visitor, - const QuicCryptoServerConfig* crypto_config) - : QuicSimpleServerSession(config, connection, visitor, crypto_config) { + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) + : QuicSimpleServerSession(config, + connection, + visitor, + crypto_config, + compressed_certs_cache) { SendGoAway(QUIC_PEER_GOING_AWAY, ""); } diff --git a/net/tools/quic/test_tools/quic_test_server.h b/net/tools/quic/test_tools/quic_test_server.h index ac02682..7af5f51 100644 --- a/net/tools/quic/test_tools/quic_test_server.h +++ b/net/tools/quic/test_tools/quic_test_server.h @@ -35,7 +35,8 @@ class QuicTestServer : public QuicServer { const QuicConfig& config, QuicConnection* connection, QuicServerSessionVisitor* visitor, - const QuicCryptoServerConfig* crypto_config) = 0; + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache) = 0; }; // Factory for creating QuicSimpleServerStreams. @@ -89,7 +90,8 @@ class ImmediateGoAwaySession : public QuicSimpleServerSession { ImmediateGoAwaySession(const QuicConfig& config, QuicConnection* connection, QuicServerSessionVisitor* visitor, - const QuicCryptoServerConfig* crypto_config); + const QuicCryptoServerConfig* crypto_config, + QuicCompressedCertsCache* compressed_certs_cache); }; } // namespace test |
