diff options
author | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-07 02:42:02 +0000 |
---|---|---|
committer | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-07 02:42:02 +0000 |
commit | ffc34bf0f1eda7817216eb2ce9cdd31f97bc3b60 (patch) | |
tree | abe432a1c24028cfb0a1c649550914209809eec6 /net | |
parent | e6f7a0abccc7a0513e1e3654e06f6fc819933ebd (diff) | |
download | chromium_src-ffc34bf0f1eda7817216eb2ce9cdd31f97bc3b60.zip chromium_src-ffc34bf0f1eda7817216eb2ce9cdd31f97bc3b60.tar.gz chromium_src-ffc34bf0f1eda7817216eb2ce9cdd31f97bc3b60.tar.bz2 |
Land Recent QUIC Changes.
Refactor of QUIC's rtt storage and calculation to have a single RttStats
object used by the SentPacketManager, LossDetectionAlgorithms, and SendAlgorithms.
Merge internal change: 62624956
https://codereview.chromium.org/185053006/
QUIC refactor to move the pending_crypto_packet_count_ from the
QuicSentPacketManager to the QuicUnackedPacketMap.
Merge internal change: 62614116
https://codereview.chromium.org/188273003/
QUIC - Fix the spelling error in "frame received." message.
Merge internal change: 62491376
https://codereview.chromium.org/188173003/
Doing a best-effort attempt to send connection close packet for open
quic connection before we call exit().
The actual sending of the connection close is flag protected, though
worst case we'd crash right before exit() anyway.
Merge internal change: 62484710
https://codereview.chromium.org/180953008/
Test only change to QUIC TCPLossAlgorithmTest to ensure the early
retransmit alarms is set for the earliest outstanding packet.
Merge internal change: 62438180
https://codereview.chromium.org/188153003/
CL generated with data from dead-code analysis using Scythe
remove_dead_code tool.
Cleanup of net/quic using Scythe
Merge internal change: 62404986
https://codereview.chromium.org/183683025/
Allow fixed (non-negotiated) values to be sent in QUIC CHLO/SHLO. Also
adds IFCW tag for describing initial flow control window in CHLO/SHLO.
Not used yet.
Merge internal change: 62403534
https://codereview.chromium.org/188183002/
Sync'ing changes with internal tree.
https://codereview.chromium.org/184853014/
Merge internal change: 62295877
Make the VER tag required in QUIC CHLO and SHLO messages.
Merge internal change: 62286870
https://codereview.chromium.org/186313002/
R=rch@chromium.org
Review URL: https://codereview.chromium.org/188333003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@255503 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
59 files changed, 737 insertions, 530 deletions
diff --git a/net/net.gyp b/net/net.gyp index d8a547c..efdeda3 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -772,6 +772,8 @@ 'quic/congestion_control/quic_max_sized_map.h', 'quic/congestion_control/receive_algorithm_interface.cc', 'quic/congestion_control/receive_algorithm_interface.h', + 'quic/congestion_control/rtt_stats.cc', + '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_sender.cc', diff --git a/net/quic/congestion_control/cubic_test.cc b/net/quic/congestion_control/cubic_test.cc index 7844c26..730c1cc 100644 --- a/net/quic/congestion_control/cubic_test.cc +++ b/net/quic/congestion_control/cubic_test.cc @@ -66,7 +66,7 @@ TEST_F(CubicTest, AboveOrigin) { } // Total time elapsed so far; add min_rtt (0.1s) here as well. float elapsed_time_s = 10.0f + 0.1f; - // expected_cwnd is initial value of cwnd + K * t^3, where K = 0.4. + // |expected_cwnd| is initial value of cwnd + K * t^3, where K = 0.4. expected_cwnd = 11 + (elapsed_time_s * elapsed_time_s * elapsed_time_s * 410) / 1024; EXPECT_EQ(expected_cwnd, current_cwnd); @@ -108,7 +108,7 @@ TEST_F(CubicTest, CwndIncreaseStatsDuringConvexRegion) { } // Total time elapsed so far; add min_rtt (0.1s) here as well. float elapsed_time_s = 10.0f + 0.1f; - // expected_cwnd is initial value of cwnd + K * t^3, where K = 0.4. + // |expected_cwnd| is initial value of cwnd + K * t^3, where K = 0.4. expected_cwnd = 11 + (elapsed_time_s * elapsed_time_s * elapsed_time_s * 410) / 1024; EXPECT_EQ(expected_cwnd - old_cwnd, stats_.cwnd_increase_cubic_mode); diff --git a/net/quic/congestion_control/fix_rate_sender.cc b/net/quic/congestion_control/fix_rate_sender.cc index fe10cdf..c848280 100644 --- a/net/quic/congestion_control/fix_rate_sender.cc +++ b/net/quic/congestion_control/fix_rate_sender.cc @@ -121,11 +121,6 @@ void FixRateSender::UpdateRtt(QuicTime::Delta rtt_sample) { latest_rtt_ = rtt_sample; } -QuicTime::Delta FixRateSender::SmoothedRtt() const { - // TODO(satyamshekhar): Calculate and return smoothed rtt. - return latest_rtt_; -} - QuicTime::Delta FixRateSender::RetransmissionDelay() const { // TODO(pwestin): Calculate and return retransmission delay. // Use 2 * the latest RTT for now. diff --git a/net/quic/congestion_control/fix_rate_sender.h b/net/quic/congestion_control/fix_rate_sender.h index a3c1bde..4a56da0 100644 --- a/net/quic/congestion_control/fix_rate_sender.h +++ b/net/quic/congestion_control/fix_rate_sender.h @@ -49,7 +49,6 @@ class NET_EXPORT_PRIVATE FixRateSender : public SendAlgorithmInterface { IsHandshake handshake) OVERRIDE; virtual QuicBandwidth BandwidthEstimate() const OVERRIDE; virtual void UpdateRtt(QuicTime::Delta rtt_sample) OVERRIDE; - virtual QuicTime::Delta SmoothedRtt() const OVERRIDE; virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE; virtual QuicByteCount GetCongestionWindow() const OVERRIDE; // End implementation of SendAlgorithmInterface. diff --git a/net/quic/congestion_control/inter_arrival_probe.cc b/net/quic/congestion_control/inter_arrival_probe.cc index ba535a8..694c3d7 100644 --- a/net/quic/congestion_control/inter_arrival_probe.cc +++ b/net/quic/congestion_control/inter_arrival_probe.cc @@ -30,10 +30,6 @@ InterArrivalProbe::InterArrivalProbe(QuicByteCount max_segment_size) InterArrivalProbe::~InterArrivalProbe() { } -void InterArrivalProbe::set_max_segment_size(QuicByteCount max_segment_size) { - max_segment_size_ = max_segment_size; -} - bool InterArrivalProbe::GetEstimate(QuicBandwidth* available_channel_estimate) { if (!estimate_available_) { return false; diff --git a/net/quic/congestion_control/inter_arrival_probe.h b/net/quic/congestion_control/inter_arrival_probe.h index af82a5b..142f1c9 100644 --- a/net/quic/congestion_control/inter_arrival_probe.h +++ b/net/quic/congestion_control/inter_arrival_probe.h @@ -20,8 +20,6 @@ class NET_EXPORT_PRIVATE InterArrivalProbe { explicit InterArrivalProbe(QuicByteCount max_segment_size); ~InterArrivalProbe(); - void set_max_segment_size(QuicByteCount max_segment_size); - // Call every time a packet is sent to the network. void OnPacketSent(QuicByteCount bytes); diff --git a/net/quic/congestion_control/inter_arrival_sender.cc b/net/quic/congestion_control/inter_arrival_sender.cc index 6931560..1b46455 100644 --- a/net/quic/congestion_control/inter_arrival_sender.cc +++ b/net/quic/congestion_control/inter_arrival_sender.cc @@ -7,6 +7,7 @@ #include <algorithm> #include "base/stl_util.h" +#include "net/quic/congestion_control/rtt_stats.h" using std::max; using std::min; @@ -20,9 +21,6 @@ const float kUncertainSafetyMargin = 0.7f; const float kMaxBitrateReduction = 0.9f; const float kMinBitrateReduction = 0.05f; const uint64 kMinBitrateKbit = 10; -const int kInitialRttMs = 60; // At a typical RTT 60 ms. -const float kAlpha = 0.125f; -const float kOneMinusAlpha = 1 - kAlpha; static const int kHistoryPeriodMs = 5000; static const int kBitrateSmoothingPeriodMs = 1000; @@ -30,8 +28,10 @@ static const int kMinBitrateSmoothingPeriodMs = 500; } // namespace -InterArrivalSender::InterArrivalSender(const QuicClock* clock) +InterArrivalSender::InterArrivalSender(const QuicClock* clock, + const RttStats* rtt_stats) : clock_(clock), + rtt_stats_(rtt_stats), probing_(true), max_segment_size_(kDefaultMaxPacketSize), current_bandwidth_(QuicBandwidth::Zero()), @@ -305,34 +305,13 @@ QuicBandwidth InterArrivalSender::BandwidthEstimate() const { } void InterArrivalSender::UpdateRtt(QuicTime::Delta rtt) { - // RTT can't be negative. - DCHECK_LE(0, rtt.ToMicroseconds()); - - if (rtt.IsInfinite()) { - return; - } - - if (smoothed_rtt_.IsZero()) { - smoothed_rtt_ = rtt; - } else { - smoothed_rtt_ = QuicTime::Delta::FromMicroseconds( - kOneMinusAlpha * smoothed_rtt_.ToMicroseconds() + - kAlpha * rtt.ToMicroseconds()); - } - state_machine_->set_rtt(smoothed_rtt_); -} - -QuicTime::Delta InterArrivalSender::SmoothedRtt() const { - if (smoothed_rtt_.IsZero()) { - return QuicTime::Delta::FromMilliseconds(kInitialRttMs); - } - return smoothed_rtt_; + state_machine_->set_rtt(rtt_stats_->SmoothedRtt()); } QuicTime::Delta InterArrivalSender::RetransmissionDelay() const { // TODO(pwestin): Calculate and return retransmission delay. // Use 2 * the smoothed RTT for now. - return smoothed_rtt_.Add(smoothed_rtt_); + return rtt_stats_->SmoothedRtt().Multiply(2); } QuicByteCount InterArrivalSender::GetCongestionWindow() const { @@ -381,7 +360,8 @@ void InterArrivalSender::EstimateNewBandwidthAfterDraining( QuicTime::Delta buffer_reduction = back_down_congestion_delay_.Subtract(estimated_congestion_delay); QuicTime::Delta elapsed_time = - feedback_receive_time.Subtract(back_down_time_).Subtract(SmoothedRtt()); + feedback_receive_time.Subtract(back_down_time_).Subtract( + rtt_stats_->SmoothedRtt()); QuicBandwidth new_estimate = QuicBandwidth::Zero(); if (buffer_reduction >= elapsed_time) { @@ -454,7 +434,7 @@ void InterArrivalSender::EstimateBandwidthAfterDelayEvent( // bitrate with the following. // TODO(pwestin): this is a crude first implementation. int64 draining_rate_per_rtt = (estimated_byte_buildup * - kNumMicrosPerSecond) / SmoothedRtt().ToMicroseconds(); + kNumMicrosPerSecond) / rtt_stats_->SmoothedRtt().ToMicroseconds(); float decrease_factor = draining_rate_per_rtt / current_bandwidth_.ToBytesPerSecond(); @@ -467,18 +447,16 @@ void InterArrivalSender::EstimateBandwidthAfterDelayEvent( // While in delay sensing mode send at least one packet per RTT. QuicBandwidth min_delay_bitrate = - QuicBandwidth::FromBytesAndTimeDelta(max_segment_size_, SmoothedRtt()); + QuicBandwidth::FromBytesAndTimeDelta(max_segment_size_, + rtt_stats_->SmoothedRtt()); new_target_bitrate = max(new_target_bitrate, min_delay_bitrate); ResetCurrentBandwidth(feedback_receive_time, new_target_bitrate); DVLOG(1) << "New bandwidth estimate after delay event:" - << current_bandwidth_.ToKBitsPerSecond() - << " Kbits/s min delay bitrate:" - << min_delay_bitrate.ToKBitsPerSecond() - << " Kbits/s RTT:" - << SmoothedRtt().ToMicroseconds() - << " us"; + << current_bandwidth_.ToKBitsPerSecond() << " Kbits/s min delay bitrate:" + << min_delay_bitrate.ToKBitsPerSecond() << " Kbits/s RTT:" + << rtt_stats_->SmoothedRtt().ToMicroseconds() << " us"; } void InterArrivalSender::EstimateBandwidthAfterLossEvent( @@ -486,8 +464,7 @@ void InterArrivalSender::EstimateBandwidthAfterLossEvent( ResetCurrentBandwidth(feedback_receive_time, current_bandwidth_.Scale(kPacketLossBitrateReduction)); DVLOG(1) << "New bandwidth estimate after loss event:" - << current_bandwidth_.ToKBitsPerSecond() - << " Kbits/s"; + << current_bandwidth_.ToKBitsPerSecond() << " Kbits/s"; } void InterArrivalSender::ResetCurrentBandwidth(QuicTime feedback_receive_time, diff --git a/net/quic/congestion_control/inter_arrival_sender.h b/net/quic/congestion_control/inter_arrival_sender.h index 1501b5a..2de370d 100644 --- a/net/quic/congestion_control/inter_arrival_sender.h +++ b/net/quic/congestion_control/inter_arrival_sender.h @@ -24,7 +24,7 @@ namespace net { class NET_EXPORT_PRIVATE InterArrivalSender : public SendAlgorithmInterface { public: - explicit InterArrivalSender(const QuicClock* clock); + InterArrivalSender(const QuicClock* clock, const RttStats* rtt_stats); virtual ~InterArrivalSender(); // Start implementation of SendAlgorithmInterface. @@ -52,7 +52,6 @@ class NET_EXPORT_PRIVATE InterArrivalSender : public SendAlgorithmInterface { IsHandshake handshake) OVERRIDE; virtual QuicBandwidth BandwidthEstimate() const OVERRIDE; virtual void UpdateRtt(QuicTime::Delta rtt_sample) OVERRIDE; - virtual QuicTime::Delta SmoothedRtt() const OVERRIDE; virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE; virtual QuicByteCount GetCongestionWindow() const OVERRIDE; // End implementation of SendAlgorithmInterface. @@ -95,6 +94,7 @@ class NET_EXPORT_PRIVATE InterArrivalSender : public SendAlgorithmInterface { SentPacketsMap packet_history_map_; const QuicClock* clock_; + const RttStats* rtt_stats_; bool probing_; // Are we currently in the probing phase? QuicByteCount max_segment_size_; QuicBandwidth current_bandwidth_; diff --git a/net/quic/congestion_control/inter_arrival_sender_test.cc b/net/quic/congestion_control/inter_arrival_sender_test.cc index 4a6bec4..048cbb0 100644 --- a/net/quic/congestion_control/inter_arrival_sender_test.cc +++ b/net/quic/congestion_control/inter_arrival_sender_test.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/stl_util.h" +#include "net/quic/congestion_control/rtt_stats.h" #include "net/quic/test_tools/mock_clock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -21,12 +22,13 @@ class InterArrivalSenderTest : public ::testing::Test { one_s_(QuicTime::Delta::FromMilliseconds(1000)), nine_ms_(QuicTime::Delta::FromMilliseconds(9)), send_start_time_(send_clock_.Now()), - sender_(&send_clock_), + sender_(&send_clock_, &rtt_stats_), sequence_number_(1), acked_sequence_number_(1), feedback_sequence_number_(1) { send_clock_.AdvanceTime(one_ms_); receive_clock_.AdvanceTime(one_ms_); + rtt_stats_.set_initial_rtt_us(60 * base::Time::kMicrosecondsPerMillisecond); } virtual ~InterArrivalSenderTest() { @@ -101,6 +103,7 @@ class InterArrivalSenderTest : public ::testing::Test { MockClock send_clock_; MockClock receive_clock_; const QuicTime send_start_time_; + RttStats rtt_stats_; InterArrivalSender sender_; QuicPacketSequenceNumber sequence_number_; QuicPacketSequenceNumber acked_sequence_number_; diff --git a/net/quic/congestion_control/loss_detection_interface.h b/net/quic/congestion_control/loss_detection_interface.h index bb1f86d..21cc4f7 100644 --- a/net/quic/congestion_control/loss_detection_interface.h +++ b/net/quic/congestion_control/loss_detection_interface.h @@ -14,6 +14,7 @@ namespace net { class QuicUnackedPacketMap; +class RttStats; class NET_EXPORT_PRIVATE LossDetectionInterface { public: @@ -27,8 +28,7 @@ class NET_EXPORT_PRIVATE LossDetectionInterface { const QuicUnackedPacketMap& unacked_packets, const QuicTime& time, QuicPacketSequenceNumber largest_observed, - QuicTime::Delta srtt, - QuicTime::Delta latest_rtt) = 0; + const RttStats& rtt_stats) = 0; // Get the time the LossDetectionAlgorithm wants to re-evaluate losses. // Returns QuicTime::Zero if no alarm needs to be set. diff --git a/net/quic/congestion_control/paced_sender.cc b/net/quic/congestion_control/paced_sender.cc index 9a5cc44..731fdc5 100644 --- a/net/quic/congestion_control/paced_sender.cc +++ b/net/quic/congestion_control/paced_sender.cc @@ -22,10 +22,6 @@ PacedSender::PacedSender(QuicBandwidth estimate, QuicByteCount max_segment_size) max_segment_size_(kDefaultMaxPacketSize) { } -void PacedSender::set_max_segment_size(QuicByteCount max_segment_size) { - max_segment_size_ = max_segment_size; -} - void PacedSender::UpdateBandwidthEstimate(QuicTime now, QuicBandwidth estimate) { leaky_bucket_.SetDrainingRate(now, estimate); diff --git a/net/quic/congestion_control/paced_sender.h b/net/quic/congestion_control/paced_sender.h index 6d7c429..d600dcb 100644 --- a/net/quic/congestion_control/paced_sender.h +++ b/net/quic/congestion_control/paced_sender.h @@ -19,8 +19,6 @@ class NET_EXPORT_PRIVATE PacedSender { public: PacedSender(QuicBandwidth bandwidth_estimate, QuicByteCount max_segment_size); - void set_max_segment_size(QuicByteCount max_segment_size); - // The estimated bandidth from the congestion algorithm changed. void UpdateBandwidthEstimate(QuicTime now, QuicBandwidth bandwidth_estimate); diff --git a/net/quic/congestion_control/pacing_sender.cc b/net/quic/congestion_control/pacing_sender.cc index 49dd1af..3a16667 100644 --- a/net/quic/congestion_control/pacing_sender.cc +++ b/net/quic/congestion_control/pacing_sender.cc @@ -12,7 +12,6 @@ PacingSender::PacingSender(SendAlgorithmInterface* sender, alarm_granularity_(alarm_granularity), next_packet_send_time_(QuicTime::Zero()), was_last_send_delayed_(false), - max_segment_size_(kDefaultMaxPacketSize), updated_rtt_(false) { } @@ -127,10 +126,6 @@ void PacingSender::UpdateRtt(QuicTime::Delta rtt_sample) { sender_->UpdateRtt(rtt_sample); } -QuicTime::Delta PacingSender::SmoothedRtt() const { - return sender_->SmoothedRtt(); -} - QuicTime::Delta PacingSender::RetransmissionDelay() const { return sender_->RetransmissionDelay(); } diff --git a/net/quic/congestion_control/pacing_sender.h b/net/quic/congestion_control/pacing_sender.h index 120063d..9fa4eb6 100644 --- a/net/quic/congestion_control/pacing_sender.h +++ b/net/quic/congestion_control/pacing_sender.h @@ -53,18 +53,14 @@ class NET_EXPORT_PRIVATE PacingSender : public SendAlgorithmInterface { IsHandshake handshake) OVERRIDE; virtual QuicBandwidth BandwidthEstimate() const OVERRIDE; virtual void UpdateRtt(QuicTime::Delta rtt_sample) OVERRIDE; - virtual QuicTime::Delta SmoothedRtt() const OVERRIDE; virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE; virtual QuicByteCount GetCongestionWindow() const OVERRIDE; private: - QuicTime::Delta GetTransferTime(QuicByteCount bytes); - scoped_ptr<SendAlgorithmInterface> sender_; // Underlying sender. QuicTime::Delta alarm_granularity_; QuicTime next_packet_send_time_; // When can the next packet be sent. bool was_last_send_delayed_; // True when the last send was delayed. - QuicByteCount max_segment_size_; bool updated_rtt_; // True if we have at least one RTT update. DISALLOW_COPY_AND_ASSIGN(PacingSender); diff --git a/net/quic/congestion_control/rtt_stats.cc b/net/quic/congestion_control/rtt_stats.cc new file mode 100644 index 0000000..4161859 --- /dev/null +++ b/net/quic/congestion_control/rtt_stats.cc @@ -0,0 +1,81 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/quic/congestion_control/rtt_stats.h" + +namespace net { + +namespace { + +// Default initial rtt used before any samples are received. +const int kInitialRttMs = 100; +const float kAlpha = 0.125f; +const float kOneMinusAlpha = (1 - kAlpha); +const float kBeta = 0.25f; +const float kOneMinusBeta = (1 - kBeta); + +} + +RttStats::RttStats() + : latest_rtt_(QuicTime::Delta::Zero()), + min_rtt_(QuicTime::Delta::Zero()), + smoothed_rtt_(QuicTime::Delta::Zero()), + mean_deviation_(QuicTime::Delta::Zero()), + initial_rtt_us_(kInitialRttMs * base::Time::kMicrosecondsPerMillisecond) { +} + +bool RttStats::HasUpdates() const { + return !smoothed_rtt_.IsZero(); +} + +// Updates the RTT based on a new sample. +void RttStats::UpdateRtt(QuicTime::Delta send_delta, + QuicTime::Delta ack_delay) { + QuicTime::Delta rtt_sample(QuicTime::Delta::Zero()); + if (send_delta > ack_delay) { + rtt_sample = send_delta.Subtract(ack_delay); + } else if (!HasUpdates()) { + // Even though we received information from the peer suggesting + // an invalid (negative) RTT, we can use the send delta as an + // approximation until we get a better estimate. + rtt_sample = send_delta; + } + + if (rtt_sample.IsInfinite() || rtt_sample.IsZero()) { + DVLOG(1) << "Ignoring rtt, because it's " + << (rtt_sample.IsZero() ? "Zero" : "Infinite"); + return; + } + // RTT can't be negative. + DCHECK_LT(0, rtt_sample.ToMicroseconds()); + + latest_rtt_ = rtt_sample; + // First time call or link delay decreases. + if (min_rtt_.IsZero() || min_rtt_ > rtt_sample) { + min_rtt_ = rtt_sample; + } + // First time call. + if (!HasUpdates()) { + smoothed_rtt_ = rtt_sample; + mean_deviation_ = QuicTime::Delta::FromMicroseconds( + rtt_sample.ToMicroseconds() / 2); + } else { + mean_deviation_ = QuicTime::Delta::FromMicroseconds( + kOneMinusBeta * mean_deviation_.ToMicroseconds() + + kBeta * std::abs(smoothed_rtt_.Subtract(rtt_sample).ToMicroseconds())); + smoothed_rtt_ = smoothed_rtt_.Multiply(kOneMinusAlpha).Add( + rtt_sample.Multiply(kAlpha)); + DVLOG(1) << "Cubic; smoothed_rtt(us):" << smoothed_rtt_.ToMicroseconds() + << " mean_deviation(us):" << mean_deviation_.ToMicroseconds(); + } +} + +QuicTime::Delta RttStats::SmoothedRtt() const { + if (!HasUpdates()) { + return QuicTime::Delta::FromMicroseconds(initial_rtt_us_); + } + return smoothed_rtt_; +} + +} // namespace net diff --git a/net/quic/congestion_control/rtt_stats.h b/net/quic/congestion_control/rtt_stats.h new file mode 100644 index 0000000..6e04498 --- /dev/null +++ b/net/quic/congestion_control/rtt_stats.h @@ -0,0 +1,61 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// A convenience class to store rtt samples and calculate smoothed rtt. + +#ifndef NET_QUIC_CONGESTION_CONTROL_RTT_STATS_H_ +#define NET_QUIC_CONGESTION_CONTROL_RTT_STATS_H_ + +#include <algorithm> + +#include "base/basictypes.h" +#include "net/quic/quic_protocol.h" +#include "net/quic/quic_time.h" + +namespace net { + +class NET_EXPORT_PRIVATE RttStats { + public: + RttStats(); + + // Returns true if any RTT measurements have been made. + bool HasUpdates() const; + + // Updates the RTT from an incoming ack which is received |send_delta| after + // the packet is sent and the peer reports the ack being delayed |ack_delay|. + void UpdateRtt(QuicTime::Delta send_delta, QuicTime::Delta ack_delay); + + QuicTime::Delta SmoothedRtt() const; + + // Sets an initial RTT to be used for SmoothedRtt before any RTT updates. + void set_initial_rtt_us(int64 initial_rtt_us) { + initial_rtt_us_ = initial_rtt_us; + } + + QuicTime::Delta latest_rtt() const { + return latest_rtt_; + } + + QuicTime::Delta min_rtt() const { + return min_rtt_; + } + + QuicTime::Delta mean_deviation() const { + return mean_deviation_; + } + + private: + QuicTime::Delta latest_rtt_; + QuicTime::Delta min_rtt_; + QuicTime::Delta smoothed_rtt_; + // Mean RTT deviation during this session. + // Approximation of standard deviation, the error is roughly 1.25 times + // larger than the standard deviation, for a normally distributed signal. + QuicTime::Delta mean_deviation_; + int64 initial_rtt_us_; +}; + +} // namespace net + +#endif // NET_QUIC_CONGESTION_CONTROL_RTT_STATS_H_ diff --git a/net/quic/congestion_control/send_algorithm_interface.cc b/net/quic/congestion_control/send_algorithm_interface.cc index c884c02..3ab023c 100644 --- a/net/quic/congestion_control/send_algorithm_interface.cc +++ b/net/quic/congestion_control/send_algorithm_interface.cc @@ -13,17 +13,20 @@ namespace net { const bool kUseReno = false; +class RttStats; + // Factory for send side congestion control algorithm. SendAlgorithmInterface* SendAlgorithmInterface::Create( const QuicClock* clock, + const RttStats* rtt_stats, CongestionFeedbackType type, QuicConnectionStats* stats) { switch (type) { case kTCP: - return new TcpCubicSender(clock, kUseReno, kMaxTcpCongestionWindow, - stats); + return new TcpCubicSender(clock, rtt_stats, kUseReno, + kMaxTcpCongestionWindow, stats); case kInterArrival: - return new InterArrivalSender(clock); + return new InterArrivalSender(clock, rtt_stats); case kFixRate: return new FixRateSender(clock); } diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h index 359c65c..afd5258 100644 --- a/net/quic/congestion_control/send_algorithm_interface.h +++ b/net/quic/congestion_control/send_algorithm_interface.h @@ -21,9 +21,12 @@ namespace net { +class RttStats; + class NET_EXPORT_PRIVATE SendAlgorithmInterface { public: static SendAlgorithmInterface* Create(const QuicClock* clock, + const RttStats* rtt_stats, CongestionFeedbackType type, QuicConnectionStats* stats); @@ -76,11 +79,10 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface { virtual QuicBandwidth BandwidthEstimate() const = 0; // Updates the smoothed RTT based on a new sample. + // TODO(ianswett): Now that the RTT is managed by RTTStats, it may be + // possible to remove this method. virtual void UpdateRtt(QuicTime::Delta rtt_sample) = 0; - // TODO(satyamshekhar): Monitor MinRtt. - virtual QuicTime::Delta SmoothedRtt() const = 0; - // Get the send algorithm specific retransmission delay, called RTO in TCP, // Note 1: the caller is responsible for sanity checking this value. // Note 2: this will return zero if we don't have enough data for an estimate. diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc index 7f6678d..a267438 100644 --- a/net/quic/congestion_control/tcp_cubic_sender.cc +++ b/net/quic/congestion_control/tcp_cubic_sender.cc @@ -7,6 +7,7 @@ #include <algorithm> #include "base/metrics/histogram.h" +#include "net/quic/congestion_control/rtt_stats.h" using std::max; using std::min; @@ -23,21 +24,17 @@ const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS; const QuicByteCount kDefaultReceiveWindow = 64000; const int64 kInitialCongestionWindow = 10; const int kMaxBurstLength = 3; -// Constants used for RTT calculation. -const int kInitialRttMs = 100; // At a typical RTT 100 ms. -const float kAlpha = 0.125f; -const float kOneMinusAlpha = (1 - kAlpha); -const float kBeta = 0.25f; -const float kOneMinusBeta = (1 - kBeta); }; // namespace TcpCubicSender::TcpCubicSender( const QuicClock* clock, + const RttStats* rtt_stats, bool reno, QuicTcpCongestionWindow max_tcp_congestion_window, QuicConnectionStats* stats) : hybrid_slow_start_(clock), cubic_(clock, stats), + rtt_stats_(rtt_stats), reno_(reno), congestion_window_count_(0), receive_window_(kDefaultReceiveWindow), @@ -53,10 +50,7 @@ TcpCubicSender::TcpCubicSender( largest_sent_at_last_cutback_(0), congestion_window_(kInitialCongestionWindow), slowstart_threshold_(max_tcp_congestion_window), - max_tcp_congestion_window_(max_tcp_congestion_window), - delay_min_(QuicTime::Delta::Zero()), - smoothed_rtt_(QuicTime::Delta::Zero()), - mean_deviation_(QuicTime::Delta::Zero()) { + max_tcp_congestion_window_(max_tcp_congestion_window) { } TcpCubicSender::~TcpCubicSender() { @@ -221,30 +215,22 @@ QuicByteCount TcpCubicSender::SendWindow() { QuicBandwidth TcpCubicSender::BandwidthEstimate() const { return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), - SmoothedRtt()); -} - -QuicTime::Delta TcpCubicSender::SmoothedRtt() const { - if (smoothed_rtt_.IsZero()) { - return QuicTime::Delta::FromMilliseconds(kInitialRttMs); - } - return smoothed_rtt_; + rtt_stats_->SmoothedRtt()); } QuicTime::Delta TcpCubicSender::RetransmissionDelay() const { + if (!rtt_stats_->HasUpdates()) { + return QuicTime::Delta::Zero(); + } return QuicTime::Delta::FromMicroseconds( - smoothed_rtt_.ToMicroseconds() + 4 * mean_deviation_.ToMicroseconds()); + rtt_stats_->SmoothedRtt().ToMicroseconds() + + 4 * rtt_stats_->mean_deviation().ToMicroseconds()); } QuicByteCount TcpCubicSender::GetCongestionWindow() const { return congestion_window_ * kMaxSegmentSize; } -void TcpCubicSender::Reset() { - delay_min_ = QuicTime::Delta::Zero(); - hybrid_slow_start_.Restart(); -} - bool TcpCubicSender::IsCwndLimited() const { const QuicByteCount congestion_window_bytes = congestion_window_ * kMaxSegmentSize; @@ -305,9 +291,9 @@ void TcpCubicSender::MaybeIncreaseCwnd( << " slowstart threshold: " << slowstart_threshold_ << " congestion window count: " << congestion_window_count_; } else { - congestion_window_ = min( - max_tcp_congestion_window_, - cubic_.CongestionWindowAfterAck(congestion_window_, delay_min_)); + 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_; } @@ -323,38 +309,6 @@ void TcpCubicSender::OnRetransmissionTimeout(bool packets_retransmitted) { } void TcpCubicSender::UpdateRtt(QuicTime::Delta rtt) { - if (rtt.IsInfinite() || rtt.IsZero()) { - DVLOG(1) << "Ignoring rtt, because it's " - << (rtt.IsZero() ? "Zero" : "Infinite"); - return; - } - // RTT can't be negative. - DCHECK_LT(0, rtt.ToMicroseconds()); - - // TODO(pwestin): Discard delay samples right after fast recovery, - // during 1 second?. - - // First time call or link delay decreases. - if (delay_min_.IsZero() || delay_min_ > rtt) { - delay_min_ = rtt; - } - // First time call. - if (smoothed_rtt_.IsZero()) { - smoothed_rtt_ = rtt; - mean_deviation_ = QuicTime::Delta::FromMicroseconds( - rtt.ToMicroseconds() / 2); - } else { - mean_deviation_ = QuicTime::Delta::FromMicroseconds( - kOneMinusBeta * mean_deviation_.ToMicroseconds() + - kBeta * - std::abs(smoothed_rtt_.ToMicroseconds() - rtt.ToMicroseconds())); - smoothed_rtt_ = QuicTime::Delta::FromMicroseconds( - kOneMinusAlpha * smoothed_rtt_.ToMicroseconds() + - kAlpha * rtt.ToMicroseconds()); - DVLOG(1) << "Cubic; smoothed_rtt_:" << smoothed_rtt_.ToMicroseconds() - << " mean_deviation_:" << mean_deviation_.ToMicroseconds(); - } - // Hybrid start triggers when cwnd is larger than some threshold. if (congestion_window_ <= slowstart_threshold_ && congestion_window_ >= kHybridStartLowWindow) { @@ -362,7 +316,7 @@ void TcpCubicSender::UpdateRtt(QuicTime::Delta rtt) { // Time to start the hybrid slow start. hybrid_slow_start_.Reset(end_sequence_number_); } - hybrid_slow_start_.Update(rtt, delay_min_); + hybrid_slow_start_.Update(rtt, rtt_stats_->min_rtt()); if (hybrid_slow_start_.Exit()) { slowstart_threshold_ = congestion_window_; } diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h index 21a0256..89e9bd6 100644 --- a/net/quic/congestion_control/tcp_cubic_sender.h +++ b/net/quic/congestion_control/tcp_cubic_sender.h @@ -24,6 +24,8 @@ namespace net { // Default maximum packet size used in Linux TCP implementations. const QuicByteCount kDefaultTCPMSS = 1460; +class RttStats; + namespace test { class TcpCubicSenderPeer; } // namespace test @@ -32,6 +34,7 @@ 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, QuicTcpCongestionWindow max_tcp_congestion_window, QuicConnectionStats* stats); @@ -61,7 +64,6 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface { IsHandshake handshake) OVERRIDE; virtual QuicBandwidth BandwidthEstimate() const OVERRIDE; virtual void UpdateRtt(QuicTime::Delta rtt_sample) OVERRIDE; - virtual QuicTime::Delta SmoothedRtt() const OVERRIDE; virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE; virtual QuicByteCount GetCongestionWindow() const OVERRIDE; // End implementation of SendAlgorithmInterface. @@ -71,14 +73,13 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface { QuicByteCount AvailableSendWindow(); QuicByteCount SendWindow(); - void Reset(); void MaybeIncreaseCwnd(QuicPacketSequenceNumber acked_sequence_number); bool IsCwndLimited() const; bool InRecovery() const; - void OnTimeOut(); HybridSlowStart hybrid_slow_start_; Cubic cubic_; + const RttStats* rtt_stats_; // Reno provided for testing. const bool reno_; @@ -122,17 +123,6 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface { // Maximum number of outstanding packets for tcp. QuicTcpCongestionWindow max_tcp_congestion_window_; - // Min RTT during this session. - QuicTime::Delta delay_min_; - - // Smoothed RTT during this session. - QuicTime::Delta smoothed_rtt_; - - // Mean RTT deviation during this session. - // Approximation of standard deviation, the error is roughly 1.25 times - // larger than the standard deviation, for a normally distributed signal. - QuicTime::Delta mean_deviation_; - DISALLOW_COPY_AND_ASSIGN(TcpCubicSender); }; diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc index bc586c7..fe3e4fd 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_test.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "net/quic/congestion_control/rtt_stats.h" #include "net/quic/congestion_control/tcp_cubic_sender.h" #include "net/quic/congestion_control/tcp_receiver.h" #include "net/quic/test_tools/mock_clock.h" @@ -26,13 +27,15 @@ class TcpCubicSenderPeer : public TcpCubicSender { TcpCubicSenderPeer(const QuicClock* clock, bool reno, QuicTcpCongestionWindow max_tcp_congestion_window) - : TcpCubicSender(clock, reno, max_tcp_congestion_window, &stats_) { + : TcpCubicSender( + clock, &rtt_stats_, reno, max_tcp_congestion_window, &stats_) { } QuicTcpCongestionWindow congestion_window() { return congestion_window_; } + RttStats rtt_stats_; QuicConnectionStats stats_; using TcpCubicSender::AvailableSendWindow; @@ -67,11 +70,16 @@ class TcpCubicSenderTest : public ::testing::Test { return packets_sent; } + void UpdateRtt(QuicTime::Delta rtt) { + sender_->rtt_stats_.UpdateRtt(rtt, QuicTime::Delta::Zero()); + sender_->UpdateRtt(rtt); + } + // Normal is that TCP acks every other segment. void AckNPackets(int n) { for (int i = 0; i < n; ++i) { ++acked_sequence_number_; - sender_->UpdateRtt(QuicTime::Delta::FromMilliseconds(60)); + UpdateRtt(QuicTime::Delta::FromMilliseconds(60)); sender_->OnPacketAcked(acked_sequence_number_, kDefaultTCPMSS); } clock_.AdvanceTime(one_ms_); // 1 millisecond. @@ -401,7 +409,7 @@ TEST_F(TcpCubicSenderTest, RetransmissionDelay) { const int64 kDeviationMs = 3; EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay()); - sender_->UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs)); + UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs)); // 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 @@ -412,20 +420,18 @@ TEST_F(TcpCubicSenderTest, RetransmissionDelay) { for (int i = 0; i < 100; ++i) { // Run to make sure that we converge. - sender_->UpdateRtt( - QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs)); - sender_->UpdateRtt( - QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs)); + UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs)); + UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs)); } expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4); - EXPECT_NEAR(kRttMs, sender_->SmoothedRtt().ToMilliseconds(), 1); + EXPECT_NEAR(kRttMs, sender_->rtt_stats_.SmoothedRtt().ToMilliseconds(), 1); EXPECT_NEAR(expected_delay.ToMilliseconds(), sender_->RetransmissionDelay().ToMilliseconds(), 1); EXPECT_EQ(static_cast<int64>( sender_->GetCongestionWindow() * kNumMicrosPerSecond / - sender_->SmoothedRtt().ToMicroseconds()), + sender_->rtt_stats_.SmoothedRtt().ToMicroseconds()), sender_->BandwidthEstimate().ToBytesPerSecond()); } diff --git a/net/quic/congestion_control/tcp_loss_algorithm.cc b/net/quic/congestion_control/tcp_loss_algorithm.cc index 3fe662c..d63742a 100644 --- a/net/quic/congestion_control/tcp_loss_algorithm.cc +++ b/net/quic/congestion_control/tcp_loss_algorithm.cc @@ -4,6 +4,7 @@ #include "net/quic/congestion_control/tcp_loss_algorithm.h" +#include "net/quic/congestion_control/rtt_stats.h" #include "net/quic/quic_protocol.h" namespace net { @@ -27,12 +28,11 @@ SequenceNumberSet TCPLossAlgorithm::DetectLostPackets( const QuicUnackedPacketMap& unacked_packets, const QuicTime& time, QuicPacketSequenceNumber largest_observed, - QuicTime::Delta srtt, - QuicTime::Delta latest_rtt) { + const RttStats& rtt_stats) { SequenceNumberSet lost_packets; loss_detection_timeout_ = QuicTime::Zero(); QuicTime::Delta loss_delay = - srtt.Multiply(kEarlyRetransmitLossDelayMultiplier); + rtt_stats.SmoothedRtt().Multiply(kEarlyRetransmitLossDelayMultiplier); for (QuicUnackedPacketMap::const_iterator it = unacked_packets.begin(); it != unacked_packets.end() && it->first <= largest_observed; ++it) { diff --git a/net/quic/congestion_control/tcp_loss_algorithm.h b/net/quic/congestion_control/tcp_loss_algorithm.h index df6bc47..e8b2da1 100644 --- a/net/quic/congestion_control/tcp_loss_algorithm.h +++ b/net/quic/congestion_control/tcp_loss_algorithm.h @@ -28,8 +28,7 @@ class NET_EXPORT_PRIVATE TCPLossAlgorithm : public LossDetectionInterface { const QuicUnackedPacketMap& unacked_packets, const QuicTime& time, QuicPacketSequenceNumber largest_observed, - QuicTime::Delta srtt, - QuicTime::Delta latest_rtt) OVERRIDE; + const RttStats& rtt_stats) OVERRIDE; // Returns a non-zero value when the early retransmit timer is active. virtual QuicTime GetLossTimeout() const OVERRIDE; diff --git a/net/quic/congestion_control/tcp_loss_algorithm_test.cc b/net/quic/congestion_control/tcp_loss_algorithm_test.cc index b8cf12b..9a42d36 100644 --- a/net/quic/congestion_control/tcp_loss_algorithm_test.cc +++ b/net/quic/congestion_control/tcp_loss_algorithm_test.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/stl_util.h" +#include "net/quic/congestion_control/rtt_stats.h" #include "net/quic/quic_unacked_packet_map.h" #include "net/quic/test_tools/mock_clock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -19,8 +20,10 @@ namespace { class TcpLossAlgorithmTest : public ::testing::Test { protected: TcpLossAlgorithmTest() - : unacked_packets_(true), - srtt_(QuicTime::Delta::FromMilliseconds(100)) { } + : unacked_packets_() { + rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(100), + QuicTime::Delta::Zero()); + } void SendDataPacket(QuicPacketSequenceNumber sequence_number) { SerializedPacket packet(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER, @@ -34,7 +37,7 @@ class TcpLossAlgorithmTest : public ::testing::Test { size_t num_losses) { SequenceNumberSet lost_packets = loss_algorithm_.DetectLostPackets( - unacked_packets_, clock_.Now(), largest_observed, srtt_, srtt_); + unacked_packets_, clock_.Now(), largest_observed, rtt_stats_); EXPECT_EQ(num_losses, lost_packets.size()); for (size_t i = 0; i < num_losses; ++i) { EXPECT_TRUE(ContainsKey(lost_packets, losses_expected[i])); @@ -43,7 +46,7 @@ class TcpLossAlgorithmTest : public ::testing::Test { QuicUnackedPacketMap unacked_packets_; TCPLossAlgorithm loss_algorithm_; - QuicTime::Delta srtt_; + RttStats rtt_stats_; MockClock clock_; }; @@ -116,10 +119,10 @@ TEST_F(TcpLossAlgorithmTest, EarlyRetransmit1Packet) { unacked_packets_.SetNotPending(2); unacked_packets_.NackPacket(1, 1); VerifyLosses(2, NULL, 0); - EXPECT_EQ(clock_.Now().Add(srtt_.Multiply(1.25)), + EXPECT_EQ(clock_.Now().Add(rtt_stats_.SmoothedRtt().Multiply(1.25)), loss_algorithm_.GetLossTimeout()); - clock_.AdvanceTime(srtt_.Multiply(1.25)); + clock_.AdvanceTime(rtt_stats_.latest_rtt().Multiply(1.25)); QuicPacketSequenceNumber lost[] = { 1 }; VerifyLosses(2, lost, arraysize(lost)); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -129,21 +132,34 @@ TEST_F(TcpLossAlgorithmTest, EarlyRetransmitAllPackets) { const size_t kNumSentPackets = 5; for (size_t i = 1; i <= kNumSentPackets; ++i) { SendDataPacket(i); + // Advance the time 1/4 RTT between 3 and 4. + if (i == 3) { + clock_.AdvanceTime(rtt_stats_.SmoothedRtt().Multiply(0.25)); + } } - // Early retransmit when the final packet gets acked and the first 4 are - // nacked multiple times via FACK. + + // Early retransmit when the final packet gets acked and 1.25 RTTs have + // elapsed since the packets were sent. unacked_packets_.SetNotPending(kNumSentPackets); + // This simulates a single ack following multiple missing packets with FACK. for (size_t i = 1; i < kNumSentPackets; ++i) { unacked_packets_.NackPacket(i, kNumSentPackets - i); } QuicPacketSequenceNumber lost[] = { 1, 2 }; VerifyLosses(kNumSentPackets, lost, arraysize(lost)); - EXPECT_EQ(clock_.Now().Add(srtt_.Multiply(1.25)), + // The time has already advanced 1/4 an RTT, so ensure the timeout is set + // 1.25 RTTs after the earliest pending packet(3), not the last(4). + EXPECT_EQ(clock_.Now().Add(rtt_stats_.SmoothedRtt()), loss_algorithm_.GetLossTimeout()); - clock_.AdvanceTime(srtt_.Multiply(1.25)); - QuicPacketSequenceNumber lost2[] = { 1, 2, 3, 4 }; + clock_.AdvanceTime(rtt_stats_.SmoothedRtt()); + QuicPacketSequenceNumber lost2[] = { 1, 2, 3 }; VerifyLosses(kNumSentPackets, lost2, arraysize(lost2)); + EXPECT_EQ(clock_.Now().Add(rtt_stats_.SmoothedRtt().Multiply(0.25)), + loss_algorithm_.GetLossTimeout()); + clock_.AdvanceTime(rtt_stats_.SmoothedRtt().Multiply(0.25)); + QuicPacketSequenceNumber lost3[] = { 1, 2, 3, 4 }; + VerifyLosses(kNumSentPackets, lost3, arraysize(lost3)); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } diff --git a/net/quic/congestion_control/time_loss_algorithm.cc b/net/quic/congestion_control/time_loss_algorithm.cc index c11f1ad..dbdb52a 100644 --- a/net/quic/congestion_control/time_loss_algorithm.cc +++ b/net/quic/congestion_control/time_loss_algorithm.cc @@ -4,6 +4,7 @@ #include "net/quic/congestion_control/time_loss_algorithm.h" +#include "net/quic/congestion_control/rtt_stats.h" #include "net/quic/quic_protocol.h" namespace net { @@ -26,13 +27,13 @@ SequenceNumberSet TimeLossAlgorithm::DetectLostPackets( const QuicUnackedPacketMap& unacked_packets, const QuicTime& time, QuicPacketSequenceNumber largest_observed, - QuicTime::Delta srtt, - QuicTime::Delta latest_rtt) { + const RttStats& rtt_stats) { SequenceNumberSet lost_packets; loss_detection_timeout_ = QuicTime::Zero(); QuicTime::Delta loss_delay = QuicTime::Delta::Max( QuicTime::Delta::FromMilliseconds(kMinLossDelayMs), - QuicTime::Delta::Max(srtt, latest_rtt).Multiply(kLossDelayMultiplier)); + QuicTime::Delta::Max(rtt_stats.SmoothedRtt(), rtt_stats.latest_rtt()) + .Multiply(kLossDelayMultiplier)); for (QuicUnackedPacketMap::const_iterator it = unacked_packets.begin(); it != unacked_packets.end() && it->first <= largest_observed; ++it) { diff --git a/net/quic/congestion_control/time_loss_algorithm.h b/net/quic/congestion_control/time_loss_algorithm.h index eaa949e..a5cecc1 100644 --- a/net/quic/congestion_control/time_loss_algorithm.h +++ b/net/quic/congestion_control/time_loss_algorithm.h @@ -30,8 +30,7 @@ class NET_EXPORT_PRIVATE TimeLossAlgorithm : public LossDetectionInterface { const QuicUnackedPacketMap& unacked_packets, const QuicTime& time, QuicPacketSequenceNumber largest_observed, - QuicTime::Delta srtt, - QuicTime::Delta latest_rtt) OVERRIDE; + const RttStats& rtt_stats) OVERRIDE; // Returns the time the next packet will be lost, or zero if there // are no nacked pending packets outstanding. diff --git a/net/quic/congestion_control/time_loss_algorithm_test.cc b/net/quic/congestion_control/time_loss_algorithm_test.cc index 0ccd305..ffca816 100644 --- a/net/quic/congestion_control/time_loss_algorithm_test.cc +++ b/net/quic/congestion_control/time_loss_algorithm_test.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/stl_util.h" +#include "net/quic/congestion_control/rtt_stats.h" #include "net/quic/congestion_control/time_loss_algorithm.h" #include "net/quic/quic_unacked_packet_map.h" #include "net/quic/test_tools/mock_clock.h" @@ -18,8 +19,10 @@ namespace { class TimeLossAlgorithmTest : public ::testing::Test { protected: TimeLossAlgorithmTest() - : unacked_packets_(true), - srtt_(QuicTime::Delta::FromMilliseconds(100)) { } + : unacked_packets_() { + rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(100), + QuicTime::Delta::Zero()); + } void SendDataPacket(QuicPacketSequenceNumber sequence_number) { SerializedPacket packet(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER, @@ -33,7 +36,7 @@ class TimeLossAlgorithmTest : public ::testing::Test { size_t num_losses) { SequenceNumberSet lost_packets = loss_algorithm_.DetectLostPackets( - unacked_packets_, clock_.Now(), largest_observed, srtt_, srtt_); + unacked_packets_, clock_.Now(), largest_observed, rtt_stats_); EXPECT_EQ(num_losses, lost_packets.size()); for (size_t i = 0; i < num_losses; ++i) { EXPECT_TRUE(ContainsKey(lost_packets, losses_expected[i])); @@ -42,7 +45,7 @@ class TimeLossAlgorithmTest : public ::testing::Test { QuicUnackedPacketMap unacked_packets_; TimeLossAlgorithm loss_algorithm_; - QuicTime::Delta srtt_; + RttStats rtt_stats_; MockClock clock_; }; @@ -57,7 +60,7 @@ TEST_F(TimeLossAlgorithmTest, NoLossFor500Nacks) { unacked_packets_.NackPacket(1, i); VerifyLosses(2, NULL, 0); } - EXPECT_EQ(srtt_.Multiply(1.25), + EXPECT_EQ(rtt_stats_.SmoothedRtt().Multiply(1.25), loss_algorithm_.GetLossTimeout().Subtract(clock_.Now())); } @@ -66,7 +69,7 @@ TEST_F(TimeLossAlgorithmTest, NoLossUntilTimeout) { // Transmit 10 packets at 1/10th an RTT interval. for (size_t i = 1; i <= kNumSentPackets; ++i) { SendDataPacket(i); - clock_.AdvanceTime(srtt_.Multiply(0.1)); + clock_.AdvanceTime(rtt_stats_.SmoothedRtt().Multiply(0.1)); } // Expect the timer to not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -75,11 +78,11 @@ TEST_F(TimeLossAlgorithmTest, NoLossUntilTimeout) { unacked_packets_.SetNotPending(2); VerifyLosses(2, NULL, 0); // Expect the timer to be set to 0.25 RTT's in the future. - EXPECT_EQ(srtt_.Multiply(0.25), + EXPECT_EQ(rtt_stats_.SmoothedRtt().Multiply(0.25), loss_algorithm_.GetLossTimeout().Subtract(clock_.Now())); unacked_packets_.NackPacket(1, 5); VerifyLosses(2, NULL, 0); - clock_.AdvanceTime(srtt_.Multiply(0.25)); + clock_.AdvanceTime(rtt_stats_.SmoothedRtt().Multiply(0.25)); QuicPacketSequenceNumber lost[] = { 1 }; VerifyLosses(2, lost, arraysize(lost)); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -90,7 +93,7 @@ TEST_F(TimeLossAlgorithmTest, NoLossWithoutNack) { // Transmit 10 packets at 1/10th an RTT interval. for (size_t i = 1; i <= kNumSentPackets; ++i) { SendDataPacket(i); - clock_.AdvanceTime(srtt_.Multiply(0.1)); + clock_.AdvanceTime(rtt_stats_.SmoothedRtt().Multiply(0.1)); } // Expect the timer to not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -99,9 +102,9 @@ TEST_F(TimeLossAlgorithmTest, NoLossWithoutNack) { VerifyLosses(1, NULL, 0); // The timer should still not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); - clock_.AdvanceTime(srtt_.Multiply(0.25)); + clock_.AdvanceTime(rtt_stats_.SmoothedRtt().Multiply(0.25)); VerifyLosses(1, NULL, 0); - clock_.AdvanceTime(srtt_); + clock_.AdvanceTime(rtt_stats_.SmoothedRtt()); VerifyLosses(1, NULL, 0); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -113,7 +116,7 @@ TEST_F(TimeLossAlgorithmTest, MultipleLossesAtOnce) { for (size_t i = 1; i <= kNumSentPackets; ++i) { SendDataPacket(i); } - clock_.AdvanceTime(srtt_); + clock_.AdvanceTime(rtt_stats_.SmoothedRtt()); // Expect the timer to not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // The packet should not be lost until 1.25 RTTs pass. @@ -123,9 +126,9 @@ TEST_F(TimeLossAlgorithmTest, MultipleLossesAtOnce) { unacked_packets_.SetNotPending(10); VerifyLosses(10, NULL, 0); // Expect the timer to be set to 0.25 RTT's in the future. - EXPECT_EQ(srtt_.Multiply(0.25), + EXPECT_EQ(rtt_stats_.SmoothedRtt().Multiply(0.25), loss_algorithm_.GetLossTimeout().Subtract(clock_.Now())); - clock_.AdvanceTime(srtt_.Multiply(0.25)); + clock_.AdvanceTime(rtt_stats_.SmoothedRtt().Multiply(0.25)); QuicPacketSequenceNumber lost[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; VerifyLosses(10, lost, arraysize(lost)); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h index 764eb01..8b276cf 100644 --- a/net/quic/crypto/crypto_protocol.h +++ b/net/quic/crypto/crypto_protocol.h @@ -80,6 +80,8 @@ const QuicTag kPROF = TAG('P', 'R', 'O', 'F'); // Proof (signature). const QuicTag kCCS = TAG('C', 'C', 'S', 0); // Common certificate set const QuicTag kCCRT = TAG('C', 'C', 'R', 'T'); // Cached certificate const QuicTag kEXPY = TAG('E', 'X', 'P', 'Y'); // Expiry +const QuicTag kIFCW = TAG('I', 'F', 'C', 'W'); // Initial flow control receive + // window. // Server hello tags const QuicTag kCADR = TAG('C', 'A', 'D', 'R'); // Client IP address and port diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc index 0cce264..f1892d3 100644 --- a/net/quic/crypto/crypto_server_test.cc +++ b/net/quic/crypto/crypto_server_test.cc @@ -44,6 +44,8 @@ class CryptoServerTest : public ::testing::Test { config_(QuicCryptoServerConfig::TESTING, rand_) { config_.SetProofSource(CryptoTestUtils::ProofSourceForTesting()); supported_versions_ = QuicSupportedVersions(); + client_version_ = QuicUtils::TagToString( + QuicVersionToQuicTag(supported_versions_.front())); } virtual void SetUp() { @@ -69,6 +71,7 @@ class CryptoServerTest : public ::testing::Test { "KEXS", "C255", "PUBS", pub_hex_.c_str(), "NONC", nonce_hex_.c_str(), + "VER\0", client_version_.data(), "$padding", static_cast<int>(kClientHelloMinimumSize), NULL); ShouldSucceed(client_hello); @@ -221,6 +224,7 @@ class CryptoServerTest : public ::testing::Test { MockClock clock_; const IPEndPoint client_address_; QuicVersionVector supported_versions_; + string client_version_; QuicCryptoServerConfig config_; QuicCryptoServerConfig::ConfigOptions config_options_; QuicCryptoNegotiatedParameters params_; @@ -243,10 +247,14 @@ TEST_F(CryptoServerTest, BadSNI) { "ffee::1", }; + string client_version = QuicUtils::TagToString( + QuicVersionToQuicTag(supported_versions_.front())); + for (size_t i = 0; i < arraysize(kBadSNIs); i++) { ShouldFailMentioning("SNI", InchoateClientHello( "CHLO", "SNI", kBadSNIs[i], + "VER\0", client_version.data(), NULL)); } } @@ -265,6 +273,7 @@ TEST_F(CryptoServerTest, DISABLED_DefaultCert) { "NONC", nonce_hex_.c_str(), "$padding", static_cast<int>(kClientHelloMinimumSize), "PDMD", "X509", + "VER\0", client_version_.data(), NULL)); StringPiece cert, proof; @@ -277,6 +286,7 @@ TEST_F(CryptoServerTest, DISABLED_DefaultCert) { TEST_F(CryptoServerTest, TooSmall) { ShouldFailMentioning("too small", CryptoTestUtils::Message( "CHLO", + "VER\0", client_version_.data(), NULL)); } @@ -293,6 +303,7 @@ TEST_F(CryptoServerTest, BadSourceAddressToken) { ShouldSucceed(InchoateClientHello( "CHLO", "STK", kBadSourceAddressTokens[i], + "VER\0", client_version_.data(), NULL)); } } @@ -309,6 +320,7 @@ TEST_F(CryptoServerTest, BadClientNonce) { ShouldSucceed(InchoateClientHello( "CHLO", "NONC", kBadNonces[i], + "VER\0", client_version_.data(), NULL)); } } @@ -320,12 +332,12 @@ TEST_F(CryptoServerTest, DowngradeAttack) { } // Set the client's preferred version to a supported version that // is not the "current" version (supported_versions_.front()). - string client_version = QuicUtils::TagToString( + string bad_version = QuicUtils::TagToString( QuicVersionToQuicTag(supported_versions_.back())); ShouldFailMentioning("Downgrade", InchoateClientHello( "CHLO", - "VER\0", client_version.data(), + "VER\0", bad_version.data(), NULL)); } @@ -339,6 +351,7 @@ TEST_F(CryptoServerTest, ReplayProtection) { "#004b5453", srct_hex_.c_str(), "PUBS", pub_hex_.c_str(), "NONC", nonce_hex_.c_str(), + "VER\0", client_version_.data(), "$padding", static_cast<int>(kClientHelloMinimumSize), NULL); ShouldSucceed(msg); @@ -439,6 +452,7 @@ class CryptoServerTestNoConfig : public CryptoServerTest { TEST_F(CryptoServerTestNoConfig, DontCrash) { ShouldFailMentioning("No config", InchoateClientHello( "CHLO", + "VER\0", client_version_.data(), NULL)); } @@ -474,6 +488,7 @@ TEST_F(AsyncStrikeServerVerificationTest, AsyncReplayProtection) { "#004b5453", srct_hex_.c_str(), "PUBS", pub_hex_.c_str(), "NONC", nonce_hex_.c_str(), + "VER\0", client_version_.data(), "$padding", static_cast<int>(kClientHelloMinimumSize), NULL); diff --git a/net/quic/crypto/quic_crypto_client_config.cc b/net/quic/crypto/quic_crypto_client_config.cc index ac6480a..970f9b3 100644 --- a/net/quic/crypto/quic_crypto_client_config.cc +++ b/net/quic/crypto/quic_crypto_client_config.cc @@ -647,22 +647,23 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( const QuicTag* supported_version_tags; size_t num_supported_versions; - // TODO(rch): Make it a failure if the server does not have a version list. if (server_hello.GetTaglist(kVER, &supported_version_tags, - &num_supported_versions) == QUIC_NO_ERROR) { - if (!negotiated_versions.empty()) { - bool mismatch = num_supported_versions != negotiated_versions.size(); - for (size_t i = 0; i < num_supported_versions && !mismatch; ++i) { - mismatch = QuicTagToQuicVersion(supported_version_tags[i]) != - negotiated_versions[i]; - } - // The server sent a list of supported versions, and the connection - // reports that there was a version negotiation during the handshake. + &num_supported_versions) != QUIC_NO_ERROR) { + *error_details = "server hello missing version list"; + return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; + } + if (!negotiated_versions.empty()) { + bool mismatch = num_supported_versions != negotiated_versions.size(); + for (size_t i = 0; i < num_supported_versions && !mismatch; ++i) { + mismatch = QuicTagToQuicVersion(supported_version_tags[i]) != + negotiated_versions[i]; + } + // The server sent a list of supported versions, and the connection + // reports that there was a version negotiation during the handshake. // Ensure that these two lists are identical. - if (mismatch) { - *error_details = "Downgrade attack detected"; - return QUIC_VERSION_NEGOTIATION_MISMATCH; - } + if (mismatch) { + *error_details = "Downgrade attack detected"; + return QUIC_VERSION_NEGOTIATION_MISMATCH; } } diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc index 9b9bcb5..52e338b 100644 --- a/net/quic/crypto/quic_crypto_server_config.cc +++ b/net/quic/crypto/quic_crypto_server_config.cc @@ -482,18 +482,19 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( // case, we need to make sure that we actually do not support this version // and that it wasn't a downgrade attack. QuicTag client_version_tag; - // TODO(rch): Make this check mandatory. - if (client_hello.GetUint32(kVER, &client_version_tag) == QUIC_NO_ERROR) { - QuicVersion client_version = QuicTagToQuicVersion(client_version_tag); - if (client_version != version) { - // Just because client_version is a valid version enum doesn't mean that - // this server actually supports that version, so we check to see if - // it's actually in the supported versions list. - for (size_t i = 0; i < supported_versions.size(); ++i) { - if (client_version == supported_versions[i]) { - *error_details = "Downgrade attack detected"; - return QUIC_VERSION_NEGOTIATION_MISMATCH; - } + if (client_hello.GetUint32(kVER, &client_version_tag) != QUIC_NO_ERROR) { + *error_details = "client hello missing version list"; + return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; + } + QuicVersion client_version = QuicTagToQuicVersion(client_version_tag); + if (client_version != version) { + // Just because client_version is a valid version enum doesn't mean that + // this server actually supports that version, so we check to see if + // it's actually in the supported versions list. + for (size_t i = 0; i < supported_versions.size(); ++i) { + if (client_version == supported_versions[i]) { + *error_details = "Downgrade attack detected"; + return QUIC_VERSION_NEGOTIATION_MISMATCH; } } } diff --git a/net/quic/quic_config.cc b/net/quic/quic_config.cc index 86a37b3..9a5f403 100644 --- a/net/quic/quic_config.cc +++ b/net/quic/quic_config.cc @@ -16,17 +16,57 @@ using std::string; namespace net { -QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence) +// Reads the value corresponding to |name_| from |msg| into |out|. If the +// |name_| is absent in |msg| and |presence| is set to OPTIONAL |out| is set +// to |default_value|. +QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg, + QuicTag tag, + QuicConfigPresence presence, + uint32 default_value, + uint32* out, + string* error_details) { + DCHECK(error_details != NULL); + QuicErrorCode error = msg.GetUint32(tag, out); + switch (error) { + case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: + if (presence == PRESENCE_REQUIRED) { + *error_details = "Missing " + QuicUtils::TagToString(tag); + break; + } + error = QUIC_NO_ERROR; + *out = default_value; + break; + case QUIC_NO_ERROR: + break; + default: + *error_details = "Bad " + QuicUtils::TagToString(tag); + break; + } + return error; +} + + +QuicConfigValue::QuicConfigValue(QuicTag tag, + QuicConfigPresence presence) : tag_(tag), - presence_(presence), + presence_(presence) { +} +QuicConfigValue::~QuicConfigValue() {} + +QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, + QuicConfigPresence presence) + : QuicConfigValue(tag, presence), negotiated_(false) { } +QuicNegotiableValue::~QuicNegotiableValue() {} -QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence) +QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, + QuicConfigPresence presence) : QuicNegotiableValue(tag, presence), max_value_(0), default_value_(0) { } +QuicNegotiableUint32::~QuicNegotiableUint32() {} void QuicNegotiableUint32::set(uint32 max, uint32 default_value) { DCHECK_LE(default_value, max); @@ -50,41 +90,21 @@ void QuicNegotiableUint32::ToHandshakeMessage( } } -QuicErrorCode QuicNegotiableUint32::ReadUint32( - const CryptoHandshakeMessage& msg, - uint32* out, - string* error_details) const { - DCHECK(error_details != NULL); - QuicErrorCode error = msg.GetUint32(tag_, out); - switch (error) { - case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: - if (presence_ == QuicNegotiableValue::PRESENCE_REQUIRED) { - *error_details = "Missing " + QuicUtils::TagToString(tag_); - break; - } - error = QUIC_NO_ERROR; - *out = default_value_; - - case QUIC_NO_ERROR: - break; - default: - *error_details = "Bad " + QuicUtils::TagToString(tag_); - break; - } - return error; -} - QuicErrorCode QuicNegotiableUint32::ProcessClientHello( const CryptoHandshakeMessage& client_hello, string* error_details) { DCHECK(!negotiated_); DCHECK(error_details != NULL); uint32 value; - QuicErrorCode error = ReadUint32(client_hello, &value, error_details); + QuicErrorCode error = ReadUint32(client_hello, + tag_, + presence_, + default_value_, + &value, + error_details); if (error != QUIC_NO_ERROR) { return error; } - negotiated_ = true; negotiated_value_ = std::min(value, max_value_); @@ -97,7 +117,12 @@ QuicErrorCode QuicNegotiableUint32::ProcessServerHello( DCHECK(!negotiated_); DCHECK(error_details != NULL); uint32 value; - QuicErrorCode error = ReadUint32(server_hello, &value, error_details); + QuicErrorCode error = ReadUint32(server_hello, + tag_, + presence_, + max_value_, + &value, + error_details); if (error != QUIC_NO_ERROR) { return error; } @@ -113,7 +138,7 @@ QuicErrorCode QuicNegotiableUint32::ProcessServerHello( return QUIC_NO_ERROR; } -QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, Presence presence) +QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence) : QuicNegotiableValue(tag, presence), negotiated_tag_(0), default_value_(0) { @@ -226,16 +251,58 @@ QuicErrorCode QuicNegotiableTag::ProcessServerHello( return QUIC_NO_ERROR; } -QuicConfig::QuicConfig() : - congestion_control_(kCGST, QuicNegotiableValue::PRESENCE_REQUIRED), - idle_connection_state_lifetime_seconds_( - kICSL, QuicNegotiableValue::PRESENCE_REQUIRED), - keepalive_timeout_seconds_(kKATO, QuicNegotiableValue::PRESENCE_OPTIONAL), - max_streams_per_connection_(kMSPC, QuicNegotiableValue::PRESENCE_REQUIRED), - max_time_before_crypto_handshake_(QuicTime::Delta::Zero()), - server_initial_congestion_window_( - kSWND, QuicNegotiableValue::PRESENCE_OPTIONAL), - initial_round_trip_time_us_(kIRTT, QuicNegotiableValue::PRESENCE_OPTIONAL) { +QuicFixedUint32::QuicFixedUint32(QuicTag tag, + QuicConfigPresence presence, + uint32 default_value) + : QuicConfigValue(tag, presence), + value_(default_value) { +} +QuicFixedUint32::~QuicFixedUint32() {} + +uint32 QuicFixedUint32::GetUint32() const { + return value_; +} + +void QuicFixedUint32::ToHandshakeMessage( + CryptoHandshakeMessage* out) const { + out->SetValue(tag_, value_); +} + +QuicErrorCode QuicFixedUint32::ProcessClientHello( + const CryptoHandshakeMessage& client_hello, + string* error_details) { + DCHECK(error_details != NULL); + QuicErrorCode error = + ReadUint32(client_hello, tag_, presence_, value_, &value_, error_details); + if (error != QUIC_NO_ERROR) { + return error; + } + return QUIC_NO_ERROR; +} + +QuicErrorCode QuicFixedUint32::ProcessServerHello( + const CryptoHandshakeMessage& server_hello, + string* error_details) { + DCHECK(error_details != NULL); + QuicErrorCode error = + ReadUint32(server_hello, tag_, presence_, value_, &value_, error_details); + if (error != QUIC_NO_ERROR) { + return error; + } + return QUIC_NO_ERROR; +} + +QuicConfig::QuicConfig() + : congestion_control_(kCGST, PRESENCE_REQUIRED), + idle_connection_state_lifetime_seconds_(kICSL, PRESENCE_REQUIRED), + keepalive_timeout_seconds_(kKATO, PRESENCE_OPTIONAL), + max_streams_per_connection_(kMSPC, PRESENCE_REQUIRED), + max_time_before_crypto_handshake_(QuicTime::Delta::Zero()), + server_initial_congestion_window_(kSWND, PRESENCE_OPTIONAL), + initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL), + // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring + // QUIC_VERSION_17. + peer_initial_flow_control_window_bytes_(kIFCW, PRESENCE_OPTIONAL, 0) { // All optional non-zero parameters should be initialized here. server_initial_congestion_window_.set(kMaxInitialWindow, kDefaultInitialWindow); @@ -308,6 +375,14 @@ uint32 QuicConfig::initial_round_trip_time_us() const { return initial_round_trip_time_us_.GetUint32(); } +void QuicConfig::set_peer_initial_flow_control_window_bytes(uint32 window) { + peer_initial_flow_control_window_bytes_.set_value(window); +} + +uint32 QuicConfig::peer_initial_flow_control_window_bytes() const { + return peer_initial_flow_control_window_bytes_.GetUint32(); +} + bool QuicConfig::negotiated() { // TODO(ianswett): Add the negotiated parameters once and iterate over all // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and @@ -356,6 +431,7 @@ void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const { server_initial_congestion_window_.ToHandshakeMessage(out); // TODO(ianswett): Don't transmit parameters which are optional and not set. initial_round_trip_time_us_.ToHandshakeMessage(out); + peer_initial_flow_control_window_bytes_.ToHandshakeMessage(out); } QuicErrorCode QuicConfig::ProcessClientHello( @@ -387,6 +463,10 @@ QuicErrorCode QuicConfig::ProcessClientHello( error = initial_round_trip_time_us_.ProcessClientHello( client_hello, error_details); } + if (error == QUIC_NO_ERROR) { + error = peer_initial_flow_control_window_bytes_.ProcessClientHello( + client_hello, error_details); + } return error; } @@ -419,6 +499,10 @@ QuicErrorCode QuicConfig::ProcessServerHello( error = initial_round_trip_time_us_.ProcessServerHello( server_hello, error_details); } + if (error == QUIC_NO_ERROR) { + error = peer_initial_flow_control_window_bytes_.ProcessServerHello( + server_hello, error_details); + } return error; } diff --git a/net/quic/quic_config.h b/net/quic/quic_config.h index 7bba457..7e61a9d 100644 --- a/net/quic/quic_config.h +++ b/net/quic/quic_config.h @@ -15,33 +15,62 @@ namespace net { class CryptoHandshakeMessage; -class NET_EXPORT_PRIVATE QuicNegotiableValue { +// Describes whether or not a given QuicTag is required or optional in the +// handshake message. +enum QuicConfigPresence { + // This value can be absent from the handshake message. Default value is + // selected as the negotiated value in such a case. + PRESENCE_OPTIONAL, + // This value is required in the handshake message otherwise the Process*Hello + // function returns an error. + PRESENCE_REQUIRED, +}; + +// An abstract base class that stores a value that can be sent in CHLO/SHLO +// message. These values can be OPTIONAL or REQUIRED, depending on |presence_|. +class NET_EXPORT_PRIVATE QuicConfigValue { public: - enum Presence { - // This negotiable value can be absent from the handshake message. Default - // value is selected as the negotiated value in such a case. - PRESENCE_OPTIONAL, - // This negotiable value is required in the handshake message otherwise the - // Process*Hello function returns an error. - PRESENCE_REQUIRED, - }; + QuicConfigValue(QuicTag tag, QuicConfigPresence presence); + virtual ~QuicConfigValue(); + + // Serialises tag name and value(s) to |out|. + virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const = 0; + + // Selects a mutually acceptable value from those offered in |client_hello| + // and those defined in the subclass. + virtual QuicErrorCode ProcessClientHello( + const CryptoHandshakeMessage& client_hello, + std::string* error_details) = 0; + + // Selects a mutually acceptable value from those offered in |server_hello| + // and those defined in the subclass. + virtual QuicErrorCode ProcessServerHello( + const CryptoHandshakeMessage& server_hello, + std::string* error_details) = 0; - QuicNegotiableValue(QuicTag tag, Presence presence); + protected: + const QuicTag tag_; + const QuicConfigPresence presence_; +}; + +class NET_EXPORT_PRIVATE QuicNegotiableValue : public QuicConfigValue { + public: + QuicNegotiableValue(QuicTag tag, QuicConfigPresence presence); + virtual ~QuicNegotiableValue(); bool negotiated() const { return negotiated_; } protected: - const QuicTag tag_; - const Presence presence_; bool negotiated_; }; class NET_EXPORT_PRIVATE QuicNegotiableUint32 : public QuicNegotiableValue { public: // Default and max values default to 0. - QuicNegotiableUint32(QuicTag name, Presence presence); + QuicNegotiableUint32(QuicTag name, QuicConfigPresence presence); + virtual ~QuicNegotiableUint32(); // Sets the maximum possible value that can be achieved after negotiation and // also the default values to be assumed if PRESENCE_OPTIONAL and the *HLO msg @@ -55,30 +84,25 @@ class NET_EXPORT_PRIVATE QuicNegotiableUint32 : public QuicNegotiableValue { // Serialises |name_| and value to |out|. If |negotiated_| is true then // |negotiated_value_| is serialised, otherwise |max_value_| is serialised. - void ToHandshakeMessage(CryptoHandshakeMessage* out) const; + virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const OVERRIDE; // Sets |negotiated_value_| to the minimum of |max_value_| and the // corresponding value from |client_hello|. If the corresponding value is // missing and PRESENCE_OPTIONAL then |negotiated_value_| is set to // |default_value_|. - QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello, - std::string* error_details); + virtual QuicErrorCode ProcessClientHello( + const CryptoHandshakeMessage& client_hello, + std::string* error_details) OVERRIDE; // Sets the |negotiated_value_| to the corresponding value from // |server_hello|. Returns error if the value received in |server_hello| is // greater than |max_value_|. If the corresponding value is missing and // PRESENCE_OPTIONAL then |negotiated_value_| is set to |0|, - QuicErrorCode ProcessServerHello(const CryptoHandshakeMessage& server_hello, - std::string* error_details); + virtual QuicErrorCode ProcessServerHello( + const CryptoHandshakeMessage& server_hello, + std::string* error_details) OVERRIDE; private: - // Reads the value corresponding to |name_| from |msg| into |out|. If the - // |name_| is absent in |msg| and |presence_| is set to OPTIONAL |out| is set - // to |max_value_|. - QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg, - uint32* out, - std::string* error_details) const; - uint32 max_value_; uint32 default_value_; uint32 negotiated_value_; @@ -86,8 +110,8 @@ class NET_EXPORT_PRIVATE QuicNegotiableUint32 : public QuicNegotiableValue { class NET_EXPORT_PRIVATE QuicNegotiableTag : public QuicNegotiableValue { public: - QuicNegotiableTag(QuicTag name, Presence presence); - ~QuicNegotiableTag(); + QuicNegotiableTag(QuicTag name, QuicConfigPresence presence); + virtual ~QuicNegotiableTag(); // Sets the possible values that |negotiated_tag_| can take after negotiation // and the default value that |negotiated_tag_| takes if OPTIONAL and *HLO @@ -101,19 +125,21 @@ class NET_EXPORT_PRIVATE QuicNegotiableTag : public QuicNegotiableValue { // Serialises |name_| and vector (either possible or negotiated) to |out|. If // |negotiated_| is true then |negotiated_tag_| is serialised, otherwise // |possible_values_| is serialised. - void ToHandshakeMessage(CryptoHandshakeMessage* out) const; + virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const OVERRIDE; // Selects the tag common to both tags in |client_hello| for |name_| and // |possible_values_| with preference to tag in |possible_values_|. The // selected tag is set as |negotiated_tag_|. - QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello, - std::string* error_details); + virtual QuicErrorCode ProcessClientHello( + const CryptoHandshakeMessage& client_hello, + std::string* error_details) OVERRIDE; // Sets the value for |name_| tag in |server_hello| as |negotiated_value_|. // Returns error if the value received in |server_hello| isn't present in // |possible_values_|. - QuicErrorCode ProcessServerHello(const CryptoHandshakeMessage& server_hello, - std::string* error_details); + virtual QuicErrorCode ProcessServerHello( + const CryptoHandshakeMessage& server_hello, + std::string* error_details) OVERRIDE; private: // Reads the vector corresponding to |name_| from |msg| into |out|. If the @@ -129,6 +155,36 @@ class NET_EXPORT_PRIVATE QuicNegotiableTag : public QuicNegotiableValue { QuicTag default_value_; }; +// Stores uint32 from CHLO or SHLO messages that are not negotiated. +class NET_EXPORT_PRIVATE QuicFixedUint32 : public QuicConfigValue { + public: + QuicFixedUint32(QuicTag name, + QuicConfigPresence presence, + uint32 default_value); + virtual ~QuicFixedUint32(); + + // Returns the value in the *HLO message (or the default if not). + uint32 GetUint32() const; + + void set_value(uint32 value) { value_ = value; } + + // Serialises |name_| and |value_| to |out|. + virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const OVERRIDE; + + // Sets |value_| to the corresponding value from |client_hello_| if it exists. + virtual QuicErrorCode ProcessClientHello( + const CryptoHandshakeMessage& client_hello, + std::string* error_details) OVERRIDE; + + // Sets |value_| to the corresponding value from |server_hello_| if it exists. + virtual QuicErrorCode ProcessServerHello( + const CryptoHandshakeMessage& server_hello, + std::string* error_details) OVERRIDE; + + private: + uint32 value_; +}; + // QuicConfig contains non-crypto configuration options that are negotiated in // the crypto handshake. class NET_EXPORT_PRIVATE QuicConfig { @@ -171,6 +227,10 @@ class NET_EXPORT_PRIVATE QuicConfig { uint32 initial_round_trip_time_us() const; + void set_peer_initial_flow_control_window_bytes(uint32 window); + + uint32 peer_initial_flow_control_window_bytes() const; + bool negotiated(); // SetDefaults sets the members to sensible, default values. @@ -209,6 +269,8 @@ class NET_EXPORT_PRIVATE QuicConfig { QuicNegotiableUint32 server_initial_congestion_window_; // Initial round trip time estimate in microseconds. QuicNegotiableUint32 initial_round_trip_time_us_; + // Peer's initial flow control receive window in bytes. + QuicFixedUint32 peer_initial_flow_control_window_bytes_; }; } // namespace net diff --git a/net/quic/quic_config_test.cc b/net/quic/quic_config_test.cc index f4a7952..8cf17d1 100644 --- a/net/quic/quic_config_test.cc +++ b/net/quic/quic_config_test.cc @@ -35,6 +35,7 @@ TEST_F(QuicConfigTest, ToHandshakeMessage) { config_.set_idle_connection_state_lifetime(QuicTime::Delta::FromSeconds(5), QuicTime::Delta::FromSeconds(2)); config_.set_max_streams_per_connection(4, 2); + config_.set_peer_initial_flow_control_window_bytes(6); CryptoHandshakeMessage msg; config_.ToHandshakeMessage(&msg); @@ -47,6 +48,10 @@ TEST_F(QuicConfigTest, ToHandshakeMessage) { EXPECT_EQ(QUIC_NO_ERROR, error); EXPECT_EQ(4u, value); + error = msg.GetUint32(kIFCW, &value); + EXPECT_EQ(QUIC_NO_ERROR, error); + EXPECT_EQ(6u, value); + const QuicTag* out; size_t out_len; error = msg.GetTaglist(kCGST, &out, &out_len); @@ -83,6 +88,8 @@ TEST_F(QuicConfigTest, ProcessClientHello) { client_config.set_initial_round_trip_time_us( 10 * base::Time::kMicrosecondsPerMillisecond, 10 * base::Time::kMicrosecondsPerMillisecond); + const uint32 kFlowControlWindow = 1234; + client_config.set_peer_initial_flow_control_window_bytes(kFlowControlWindow); CryptoHandshakeMessage msg; client_config.ToHandshakeMessage(&msg); @@ -98,6 +105,8 @@ TEST_F(QuicConfigTest, ProcessClientHello) { EXPECT_EQ(QuicTime::Delta::FromSeconds(0), config_.keepalive_timeout()); EXPECT_EQ(10 * base::Time::kMicrosecondsPerMillisecond, config_.initial_round_trip_time_us()); + EXPECT_EQ(kFlowControlWindow, + config_.peer_initial_flow_control_window_bytes()); } TEST_F(QuicConfigTest, ProcessServerHello) { @@ -116,6 +125,8 @@ TEST_F(QuicConfigTest, ProcessServerHello) { server_config.set_initial_round_trip_time_us( 10 * base::Time::kMicrosecondsPerMillisecond, 10 * base::Time::kMicrosecondsPerMillisecond); + const uint32 kFlowControlWindow = 1234; + server_config.set_peer_initial_flow_control_window_bytes(kFlowControlWindow); CryptoHandshakeMessage msg; server_config.ToHandshakeMessage(&msg); @@ -133,6 +144,42 @@ TEST_F(QuicConfigTest, ProcessServerHello) { EXPECT_EQ(QuicTime::Delta::FromSeconds(0), config_.keepalive_timeout()); EXPECT_EQ(10 * base::Time::kMicrosecondsPerMillisecond, config_.initial_round_trip_time_us()); + EXPECT_EQ(kFlowControlWindow, + config_.peer_initial_flow_control_window_bytes()); +} + +TEST_F(QuicConfigTest, MissingOptionalValuesInCHLO) { + CryptoHandshakeMessage msg; + msg.SetValue(kICSL, 1); + msg.SetVector(kCGST, QuicTagVector(1, kQBIC)); + + // Set all REQUIRED tags. + msg.SetValue(kICSL, 1); + msg.SetVector(kCGST, QuicTagVector(1, kQBIC)); + msg.SetValue(kMSPC, 1); + + // No error, as rest are optional. + string error_details; + const QuicErrorCode error = config_.ProcessClientHello(msg, &error_details); + EXPECT_EQ(QUIC_NO_ERROR, error); + + EXPECT_EQ(0u, config_.peer_initial_flow_control_window_bytes()); +} + +TEST_F(QuicConfigTest, MissingOptionalValuesInSHLO) { + CryptoHandshakeMessage msg; + + // Set all REQUIRED tags. + msg.SetValue(kICSL, 1); + msg.SetVector(kCGST, QuicTagVector(1, kQBIC)); + msg.SetValue(kMSPC, 1); + + // No error, as rest are optional. + string error_details; + const QuicErrorCode error = config_.ProcessServerHello(msg, &error_details); + EXPECT_EQ(QUIC_NO_ERROR, error); + + EXPECT_EQ(0u, config_.peer_initial_flow_control_window_bytes()); } TEST_F(QuicConfigTest, MissingValueInCHLO) { diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h index 7d42cb7..99cc591 100644 --- a/net/quic/quic_connection.h +++ b/net/quic/quic_connection.h @@ -527,18 +527,6 @@ class NET_EXPORT_PRIVATE QuicConnection // Clears any accumulated frames from the last received packet. void ClearLastFrames(); - // Calculates the smallest sequence number length that can also represent four - // times the maximum of the congestion window and the difference between the - // least_packet_awaited_by_peer_ and |sequence_number|. - QuicSequenceNumberLength CalculateSequenceNumberLength( - QuicPacketSequenceNumber sequence_number); - - // Drop packet corresponding to |sequence_number| by deleting entries from - // |unacked_packets_| and |retransmission_map_|, if present. We need to drop - // all packets with encryption level NONE after the default level has been set - // to FORWARD_SECURE. - void DropPacket(QuicPacketSequenceNumber sequence_number); - // Writes as many queued packets as possible. The connection must not be // blocked when this is called. void WriteQueuedPackets(); diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc index 0eaad97..19edfd0 100644 --- a/net/quic/quic_connection_test.cc +++ b/net/quic/quic_connection_test.cc @@ -407,7 +407,6 @@ class TestConnection : public QuicConnection { QuicVersion version) : QuicConnection(connection_id, address, helper, writer, is_server, SupportedVersions(version)), - helper_(helper), writer_(writer) { // Disable tail loss probes for most tests. QuicSentPacketManagerPeer::SetMaxTailLossProbes( @@ -532,7 +531,6 @@ class TestConnection : public QuicConnection { using QuicConnection::SelectMutualVersion; private: - TestConnectionHelper* helper_; TestPacketWriter* writer_; DISALLOW_COPY_AND_ASSIGN(TestConnection); @@ -570,8 +568,6 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> { Return(QuicTime::Delta::Zero())); EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(Return( QuicBandwidth::FromKBitsPerSecond(100))); - EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillRepeatedly(Return( - QuicTime::Delta::FromMilliseconds(100))); ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillByDefault(Return(true)); EXPECT_CALL(visitor_, HasPendingWrites()).Times(AnyNumber()); @@ -580,7 +576,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> { EXPECT_CALL(*loss_algorithm_, GetLossTimeout()) .WillRepeatedly(Return(QuicTime::Zero())); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillRepeatedly(Return(SequenceNumberSet())); } @@ -1060,7 +1056,7 @@ TEST_P(QuicConnectionTest, TruncatedAck) { lost_packets.insert(i * 2); } } - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(entropy_calculator_, EntropyHash(511)).WillOnce(testing::Return(0)); @@ -1080,7 +1076,7 @@ TEST_P(QuicConnectionTest, TruncatedAck) { // Removing one missing packet allows us to ack 192 and one more range, but // 192 has already been declared lost, so it doesn't register as an ack. - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(SequenceNumberSet())); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(1); @@ -1144,7 +1140,7 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) { // First nack triggers early retransmit. SequenceNumberSet lost_packets; lost_packets.insert(1); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1); @@ -1161,7 +1157,7 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) { NackPacket(original, &frame2); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(SequenceNumberSet())); ProcessAckPacket(&frame2); @@ -1177,7 +1173,7 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) { writer_->Reset(); // No more packet loss for the rest of the test. - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillRepeatedly(Return(SequenceNumberSet())); ProcessAckPacket(&frame2); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, @@ -1557,7 +1553,7 @@ TEST_P(QuicConnectionTest, AbandonAllFEC) { // Lose the first FEC packet and ack the three data packets. SequenceNumberSet lost_packets; lost_packets.insert(2); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(3); @@ -1844,7 +1840,7 @@ TEST_P(QuicConnectionTest, RetransmitOnNack) { NackPacket(2, &nack_two); SequenceNumberSet lost_packets; lost_packets.insert(2); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(3, _)); @@ -1872,7 +1868,7 @@ TEST_P(QuicConnectionTest, DiscardRetransmit) { BlockOnNextWrite(); SequenceNumberSet lost_packets; lost_packets.insert(2); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(2); @@ -1882,7 +1878,7 @@ TEST_P(QuicConnectionTest, DiscardRetransmit) { EXPECT_EQ(1u, connection_.NumQueuedPackets()); // Now, ack the previous transmission. - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(SequenceNumberSet())); QuicAckFrame ack_all = InitAckFrame(3, 0); ProcessAckPacket(&ack_all); @@ -1913,7 +1909,7 @@ TEST_P(QuicConnectionTest, RetransmitNackedLargestObserved) { // The first nack should retransmit the largest observed packet. SequenceNumberSet lost_packets; lost_packets.insert(1); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1); @@ -2037,7 +2033,7 @@ TEST_P(QuicConnectionTest, NoLimitPacketsPerNack) { // 14 packets have been NACK'd and lost. In TCP cubic, PRR limits // the retransmission rate in the case of burst losses. - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(15, _)).Times(1); @@ -2401,7 +2397,7 @@ TEST_P(QuicConnectionTest, RetransmissionCountCalculation) { // Once by explicit nack. SequenceNumberSet lost_packets; lost_packets.insert(rto_sequence_number); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)).Times(1); EXPECT_CALL(*send_algorithm_, OnPacketLost(rto_sequence_number, _)).Times(1); @@ -2449,6 +2445,8 @@ TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) { connection_.SendStreamDataWithString(3, "bar", 0, !kFin, NULL); QuicAlarm* retransmission_alarm = connection_.GetRetransmissionAlarm(); EXPECT_TRUE(retransmission_alarm->IsSet()); + EXPECT_EQ(clock_.Now().Add(DefaultRetransmissionTime()), + retransmission_alarm->deadline()); // Advance the time right before the RTO, then receive an ack for the first // packet to delay the RTO. @@ -2458,9 +2456,10 @@ TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) { QuicAckFrame ack = InitAckFrame(1, 0); ProcessAckPacket(&ack); EXPECT_TRUE(retransmission_alarm->IsSet()); + EXPECT_GT(retransmission_alarm->deadline(), clock_.Now()); // Move forward past the original RTO and ensure the RTO is still pending. - clock_.AdvanceTime(DefaultRetransmissionTime()); + clock_.AdvanceTime(DefaultRetransmissionTime().Multiply(2)); // Ensure the second packet gets retransmitted when it finally fires. EXPECT_TRUE(retransmission_alarm->IsSet()); @@ -2918,7 +2917,7 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) { NackPacket(1, &ack); SequenceNumberSet lost_packets; lost_packets.insert(1); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(2, _)).Times(1); @@ -2933,7 +2932,7 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) { // and see if there is more data to send. ack = InitAckFrame(3, 0); NackPacket(1, &ack); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(SequenceNumberSet())); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(3, _)).Times(1); @@ -2947,7 +2946,7 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) { // Send the same ack, but send both data and an ack together. ack = InitAckFrame(3, 0); NackPacket(1, &ack); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(SequenceNumberSet())); EXPECT_CALL(visitor_, OnCanWrite()).WillOnce( IgnoreResult(InvokeWithoutArgs( @@ -3406,7 +3405,7 @@ TEST_P(QuicConnectionTest, CheckSendStats) { SequenceNumberSet lost_packets; lost_packets.insert(1); lost_packets.insert(3); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(4, _)).Times(1); @@ -3415,8 +3414,6 @@ TEST_P(QuicConnectionTest, CheckSendStats) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); ProcessAckPacket(&nack_three); - EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillOnce( - Return(QuicTime::Delta::Zero())); EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillOnce( Return(QuicBandwidth::Zero())); @@ -3443,8 +3440,6 @@ TEST_P(QuicConnectionTest, CheckReceiveStats) { received_bytes += ProcessDataPacket(3, 1, !kEntropyFlag); received_bytes += ProcessFecPacket(4, 1, true, !kEntropyFlag, NULL); - EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillOnce( - Return(QuicTime::Delta::Zero())); EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillOnce( Return(QuicBandwidth::Zero())); @@ -3640,7 +3635,7 @@ TEST_P(QuicConnectionTest, AckNotifierFailToTriggerCallback) { NackPacket(1, &frame); SequenceNumberSet lost_packets; lost_packets.insert(1); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)); EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)); @@ -3665,7 +3660,7 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) { NackPacket(2, &frame); SequenceNumberSet lost_packets; lost_packets.insert(2); - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillOnce(Return(lost_packets)); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(3); @@ -3676,7 +3671,7 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) { // Now we get an ACK for packet 5 (retransmitted packet 2), which should // trigger the callback. - EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) .WillRepeatedly(Return(SequenceNumberSet())); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(5, _)); diff --git a/net/quic/quic_data_stream_test.cc b/net/quic/quic_data_stream_test.cc index 59b11ff..40e6b9a 100644 --- a/net/quic/quic_data_stream_test.cc +++ b/net/quic/quic_data_stream_test.cc @@ -17,9 +17,7 @@ using base::StringPiece; using std::min; using testing::_; using testing::InSequence; -using testing::Return; using testing::SaveArg; -using testing::StrEq; using testing::StrictMock; namespace net { diff --git a/net/quic/quic_framer.h b/net/quic/quic_framer.h index d75bb2a..b29de2c 100644 --- a/net/quic/quic_framer.h +++ b/net/quic/quic_framer.h @@ -265,9 +265,6 @@ class NET_EXPORT_PRIVATE QuicFramer { static size_t GetWindowUpdateFrameSize(); // Size in bytes of all Blocked frame fields. static size_t GetBlockedFrameSize(); - // The maximum number of nacks which can be transmitted in a single ack packet - // without exceeding kDefaultMaxPacketSize. - static size_t GetMaxUnackedPackets(QuicPacketHeader header); // Size in bytes required to serialize the stream id. static size_t GetStreamIdSize(QuicStreamId stream_id); // Size in bytes required to serialize the stream offset. diff --git a/net/quic/quic_headers_stream.cc b/net/quic/quic_headers_stream.cc index b7ab0f6..1712a2e 100644 --- a/net/quic/quic_headers_stream.cc +++ b/net/quic/quic_headers_stream.cc @@ -134,7 +134,7 @@ class QuicHeadersStream::SpdyFramerVisitor } virtual void OnContinuation(SpdyStreamId stream_id, bool end) OVERRIDE { - CloseConnection("SPDY CONTINUATION frame recevied."); + CloseConnection("SPDY CONTINUATION frame received."); } // SpdyFramerDebugVisitorInterface implementation diff --git a/net/quic/quic_headers_stream_test.cc b/net/quic/quic_headers_stream_test.cc index e08ad6e..61ea335 100644 --- a/net/quic/quic_headers_stream_test.cc +++ b/net/quic/quic_headers_stream_test.cc @@ -15,7 +15,6 @@ using base::StringPiece; using std::string; using testing::Invoke; -using testing::Return; using testing::StrictMock; using testing::WithArgs; using testing::_; diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc index b694e59..7fef0c5 100644 --- a/net/quic/quic_http_stream_test.cc +++ b/net/quic/quic_http_stream_test.cc @@ -186,8 +186,6 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> { Return(QuicTime::Delta::Zero())); EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)). WillRepeatedly(Return(QuicTime::Delta::Zero())); - EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillRepeatedly( - Return(QuicTime::Delta::Zero())); EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly( Return(QuicBandwidth::Zero())); EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber()); diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc index 389917b..8592ea7 100644 --- a/net/quic/quic_sent_packet_manager.cc +++ b/net/quic/quic_sent_packet_manager.cc @@ -67,15 +67,14 @@ QuicSentPacketManager::QuicSentPacketManager(bool is_server, const QuicClock* clock, QuicConnectionStats* stats, CongestionFeedbackType type) - : unacked_packets_(is_server), + : unacked_packets_(), is_server_(is_server), clock_(clock), stats_(stats), - send_algorithm_(SendAlgorithmInterface::Create(clock, type, stats)), + send_algorithm_( + SendAlgorithmInterface::Create(clock, &rtt_stats_, type, stats)), loss_algorithm_(LossDetectionInterface::Create()), - rtt_sample_(QuicTime::Delta::Infinite()), largest_observed_(0), - pending_crypto_packet_count_(0), consecutive_rto_count_(0), consecutive_tlp_count_(0), consecutive_crypto_retransmission_count_(0), @@ -87,14 +86,11 @@ QuicSentPacketManager::~QuicSentPacketManager() { } void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) { - if (config.initial_round_trip_time_us() > 0 && - rtt_sample_.IsInfinite()) { + if (config.initial_round_trip_time_us() > 0) { // The initial rtt should already be set on the client side. DVLOG_IF(1, !is_server_) << "Client did not set an initial RTT, but did negotiate one."; - rtt_sample_ = - QuicTime::Delta::FromMicroseconds(config.initial_round_trip_time_us()); - send_algorithm_->UpdateRtt(rtt_sample_); + rtt_stats_.set_initial_rtt_us(config.initial_round_trip_time_us()); } if (config.congestion_control() == kPACE) { MaybeEnablePacing(); @@ -108,11 +104,6 @@ void QuicSentPacketManager::OnSerializedPacket( const SerializedPacket& serialized_packet) { if (serialized_packet.retransmittable_frames) { ack_notifier_manager_.OnSerializedPacket(serialized_packet); - - if (serialized_packet.retransmittable_frames->HasCryptoHandshake() - == IS_HANDSHAKE) { - ++pending_crypto_packet_count_; - } } unacked_packets_.AddPacket(serialized_packet); @@ -313,11 +304,8 @@ QuicSentPacketManager::MarkPacketHandled( ++stats_->packets_spuriously_retransmitted; } - bool has_cryto_handshake = HasCryptoHandshake( + bool has_crypto_handshake = HasCryptoHandshake( unacked_packets_.GetTransmissionInfo(newest_transmission)); - if (has_cryto_handshake) { - --pending_crypto_packet_count_; - } while (all_transmissions_it != all_transmissions.rend()) { QuicPacketSequenceNumber previous_transmission = *all_transmissions_it; const QuicUnackedPacketMap::TransmissionInfo& transmission_info = @@ -327,7 +315,7 @@ QuicSentPacketManager::MarkPacketHandled( // marked for retransmission. pending_retransmissions_.erase(previous_transmission); } - if (has_cryto_handshake) { + if (has_crypto_handshake) { // If it's a crypto handshake packet, discard it and all retransmissions, // since they won't be acked now that one has been processed. if (transmission_info.pending) { @@ -499,7 +487,7 @@ void QuicSentPacketManager::RetransmitAllPackets() { QuicSentPacketManager::RetransmissionTimeoutMode QuicSentPacketManager::GetRetransmissionMode() const { DCHECK(unacked_packets_.HasPendingPackets()); - if (pending_crypto_packet_count_ > 0) { + if (unacked_packets_.HasPendingCryptoPackets()) { return HANDSHAKE_MODE; } if (loss_algorithm_->GetLossTimeout() != QuicTime::Zero()) { @@ -562,8 +550,7 @@ void QuicSentPacketManager::InvokeLossDetection(QuicTime time) { loss_algorithm_->DetectLostPackets(unacked_packets_, time, largest_observed_, - send_algorithm_->SmoothedRtt(), - rtt_sample_); + rtt_stats_); for (SequenceNumberSet::const_iterator it = lost_packets.begin(); it != lost_packets.end(); ++it) { QuicPacketSequenceNumber sequence_number = *it; @@ -603,16 +590,8 @@ void QuicSentPacketManager::MaybeUpdateRTT( QuicTime::Delta send_delta = ack_receive_time.Subtract(transmission_info.sent_time); - if (send_delta > received_info.delta_time_largest_observed) { - rtt_sample_ = send_delta.Subtract( - received_info.delta_time_largest_observed); - } else if (rtt_sample_.IsInfinite()) { - // Even though we received information from the peer suggesting - // an invalid (negative) RTT, we can use the send delta as an - // approximation until we get a better estimate. - rtt_sample_ = send_delta; - } - send_algorithm_->UpdateRtt(rtt_sample_); + rtt_stats_.UpdateRtt(send_delta, received_info.delta_time_largest_observed); + send_algorithm_->UpdateRtt(rtt_stats_.latest_rtt()); } QuicTime::Delta QuicSentPacketManager::TimeUntilSend( @@ -666,10 +645,10 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const { // The RTO is based on the first pending packet. const QuicTime sent_time = unacked_packets_.GetFirstPendingPacketSentTime(); - // Always wait at least 1.5 * RTT after the first sent packet. + QuicTime rto_timeout = sent_time.Add(GetRetransmissionDelay()); + // Always wait at least 1.5 * RTT from now. QuicTime min_timeout = clock_->ApproximateNow().Add( SmoothedRtt().Multiply(1.5)); - QuicTime rto_timeout = sent_time.Add(GetRetransmissionDelay()); return QuicTime::Max(min_timeout, rto_timeout); } @@ -722,7 +701,7 @@ const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const { } const QuicTime::Delta QuicSentPacketManager::SmoothedRtt() const { - return send_algorithm_->SmoothedRtt(); + return rtt_stats_.SmoothedRtt(); } QuicBandwidth QuicSentPacketManager::BandwidthEstimate() const { diff --git a/net/quic/quic_sent_packet_manager.h b/net/quic/quic_sent_packet_manager.h index c8d5a90..8279775 100644 --- a/net/quic/quic_sent_packet_manager.h +++ b/net/quic/quic_sent_packet_manager.h @@ -17,6 +17,7 @@ #include "base/memory/scoped_ptr.h" #include "net/base/linked_hash_map.h" #include "net/quic/congestion_control/loss_detection_interface.h" +#include "net/quic/congestion_control/rtt_stats.h" #include "net/quic/congestion_control/send_algorithm_interface.h" #include "net/quic/quic_ack_notifier_manager.h" #include "net/quic/quic_protocol.h" @@ -269,12 +270,11 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager { const QuicClock* clock_; QuicConnectionStats* stats_; + RttStats rtt_stats_; scoped_ptr<SendAlgorithmInterface> send_algorithm_; scoped_ptr<LossDetectionInterface> loss_algorithm_; - QuicTime::Delta rtt_sample_; // RTT estimate from the most recent ACK. + QuicPacketSequenceNumber largest_observed_; // From the most recent ACK. - // Number of outstanding crypto handshake packets. - size_t pending_crypto_packet_count_; // Number of times the RTO timer has fired in a row without receiving an ack. size_t consecutive_rto_count_; // Number of times the tail loss probe has been sent. diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc index 61240af..cfd04d2 100644 --- a/net/quic/quic_sent_packet_manager_test.cc +++ b/net/quic/quic_sent_packet_manager_test.cc @@ -35,12 +35,6 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> { STLDeleteElements(&packets_); } - virtual void SetUp() { - // Ack handling requests a smoothed rtt for loss detection. - EXPECT_CALL(*send_algorithm_, SmoothedRtt()) - .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(1))); - } - void VerifyUnackedPackets(QuicPacketSequenceNumber* packets, size_t num_packets) { if (num_packets == 0) { @@ -77,20 +71,6 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> { EXPECT_EQ(num_packets, num_retransmittable); } - void VerifyAckedPackets(QuicPacketSequenceNumber* expected, - size_t num_expected, - const SequenceNumberSet& actual) { - if (num_expected == 0) { - EXPECT_TRUE(actual.empty()); - return; - } - - EXPECT_EQ(num_expected, actual.size()); - for (size_t i = 0; i < num_expected; ++i) { - EXPECT_TRUE(ContainsKey(actual, expected[i])) << expected[i]; - } - } - void RetransmitPacket(QuicPacketSequenceNumber old_sequence_number, QuicPacketSequenceNumber new_sequence_number) { QuicSentPacketManagerPeer::MarkForRetransmission( @@ -226,7 +206,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAck) { received_info.missing_packets.insert(1); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(2, _)).Times(1); - manager_.OnIncomingAck(received_info, QuicTime::Zero()); + manager_.OnIncomingAck(received_info, clock_.Now()); // Packet 1 is unacked, pending, but not retransmittable. QuicPacketSequenceNumber unacked[] = { 1 }; @@ -246,7 +226,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) { received_info.largest_observed = 1; EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _)).Times(1); - manager_.OnIncomingAck(received_info, QuicTime::Zero()); + manager_.OnIncomingAck(received_info, clock_.Now()); // There should no longer be a pending retransmission. EXPECT_FALSE(manager_.HasPendingRetransmissions()); @@ -479,7 +459,7 @@ TEST_F(QuicSentPacketManagerTest, TruncatedAck) { EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)); EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)); - manager_.OnIncomingAck(received_info, QuicTime::Zero()); + manager_.OnIncomingAck(received_info, clock_.Now()); // High water mark will be raised. QuicPacketSequenceNumber unacked[] = { 2, 3, 4 }; @@ -506,7 +486,7 @@ TEST_F(QuicSentPacketManagerTest, AckPreviousTransmissionThenTruncatedAck) { received_info.missing_packets.insert(1); EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(2, _)); - manager_.OnIncomingAck(received_info, QuicTime::Zero()); + manager_.OnIncomingAck(received_info, clock_.Now()); EXPECT_TRUE(manager_.IsUnacked(4)); } @@ -522,7 +502,7 @@ TEST_F(QuicSentPacketManagerTest, AckPreviousTransmissionThenTruncatedAck) { EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _)); EXPECT_CALL(*send_algorithm_, OnPacketLost(3, _)); EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(3, _)); - manager_.OnIncomingAck(received_info, QuicTime::Zero()); + manager_.OnIncomingAck(received_info, clock_.Now()); } // High water mark will be raised. @@ -583,7 +563,7 @@ TEST_F(QuicSentPacketManagerTest, GetLeastUnackedPacketAndDiscard) { // Ack 2. ReceivedPacketInfo received_info; received_info.largest_observed = 2; - manager_.OnIncomingAck(received_info, QuicTime::Zero()); + manager_.OnIncomingAck(received_info, clock_.Now()); EXPECT_EQ(3u, manager_.GetLeastUnackedSentPacket()); @@ -707,7 +687,8 @@ TEST_F(QuicSentPacketManagerTest, Rtt) { received_info.delta_time_largest_observed = QuicTime::Delta::FromMilliseconds(5); manager_.OnIncomingAck(received_info, clock_.Now()); - EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_)); + EXPECT_EQ(expected_rtt, + QuicSentPacketManagerPeer::GetRttStats(&manager_)->latest_rtt()); } TEST_F(QuicSentPacketManagerTest, RttWithInvalidDelta) { @@ -727,7 +708,8 @@ TEST_F(QuicSentPacketManagerTest, RttWithInvalidDelta) { received_info.delta_time_largest_observed = QuicTime::Delta::FromMilliseconds(11); manager_.OnIncomingAck(received_info, clock_.Now()); - EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_)); + EXPECT_EQ(expected_rtt, + QuicSentPacketManagerPeer::GetRttStats(&manager_)->latest_rtt()); } TEST_F(QuicSentPacketManagerTest, RttWithInfiniteDelta) { @@ -745,7 +727,8 @@ TEST_F(QuicSentPacketManagerTest, RttWithInfiniteDelta) { received_info.largest_observed = sequence_number; received_info.delta_time_largest_observed = QuicTime::Delta::Infinite(); manager_.OnIncomingAck(received_info, clock_.Now()); - EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_)); + EXPECT_EQ(expected_rtt, + QuicSentPacketManagerPeer::GetRttStats(&manager_)->latest_rtt()); } TEST_F(QuicSentPacketManagerTest, RttZeroDelta) { @@ -763,7 +746,8 @@ TEST_F(QuicSentPacketManagerTest, RttZeroDelta) { received_info.largest_observed = sequence_number; received_info.delta_time_largest_observed = QuicTime::Delta::Zero(); manager_.OnIncomingAck(received_info, clock_.Now()); - EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_)); + EXPECT_EQ(expected_rtt, + QuicSentPacketManagerPeer::GetRttStats(&manager_)->latest_rtt()); } TEST_F(QuicSentPacketManagerTest, TailLossProbeTimeout) { @@ -984,30 +968,27 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeCryptoHandshake) { SendCryptoPacket(1); // Check the min. - EXPECT_CALL(*send_algorithm_, SmoothedRtt()) - .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(1))); + QuicSentPacketManagerPeer::GetRttStats(&manager_)->set_initial_rtt_us( + 1 * base::Time::kMicrosecondsPerMillisecond); EXPECT_EQ(clock_.Now().Add(QuicTime::Delta::FromMilliseconds(10)), manager_.GetRetransmissionTime()); // Test with a standard smoothed RTT. - EXPECT_CALL(*send_algorithm_, SmoothedRtt()) - .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(100))); + QuicSentPacketManagerPeer::GetRttStats(&manager_)->set_initial_rtt_us( + 100 * base::Time::kMicrosecondsPerMillisecond); QuicTime::Delta srtt = manager_.SmoothedRtt(); - QuicTime expected_time = clock_.Now().Add(QuicTime::Delta::FromMilliseconds( - static_cast<int64>(1.5 * srtt.ToMilliseconds()))); + QuicTime expected_time = clock_.Now().Add(srtt.Multiply(1.5)); EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); // Retransmit the packet by invoking the retransmission timeout. - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds( - static_cast<int64>(1.5 * srtt.ToMilliseconds()))); + clock_.AdvanceTime(srtt.Multiply(1.5)); EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)); manager_.OnRetransmissionTimeout(); RetransmitNextPacket(2); // The retransmission time should now be twice as far in the future. - expected_time = clock_.Now().Add(QuicTime::Delta::FromMilliseconds( - static_cast<int64>(2 * 1.5 * srtt.ToMilliseconds()))); + expected_time = clock_.Now().Add(srtt.Multiply(2).Multiply(1.5)); EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); } @@ -1017,17 +998,16 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeTailLossProbe) { SendDataPacket(2); // Check the min. - EXPECT_CALL(*send_algorithm_, SmoothedRtt()) - .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(1))); + QuicSentPacketManagerPeer::GetRttStats(&manager_)->set_initial_rtt_us( + 1 * base::Time::kMicrosecondsPerMillisecond); EXPECT_EQ(clock_.Now().Add(QuicTime::Delta::FromMilliseconds(10)), manager_.GetRetransmissionTime()); // Test with a standard smoothed RTT. - EXPECT_CALL(*send_algorithm_, SmoothedRtt()) - .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(100))); + QuicSentPacketManagerPeer::GetRttStats(&manager_)->set_initial_rtt_us( + 100 * base::Time::kMicrosecondsPerMillisecond); QuicTime::Delta srtt = manager_.SmoothedRtt(); - QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMilliseconds( - static_cast<int64>(2 * srtt.ToMilliseconds())); + QuicTime::Delta expected_tlp_delay = srtt.Multiply(2); QuicTime expected_time = clock_.Now().Add(expected_tlp_delay); EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); @@ -1042,8 +1022,8 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeTailLossProbe) { } TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeRTO) { - EXPECT_CALL(*send_algorithm_, SmoothedRtt()) - .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(100))); + QuicSentPacketManagerPeer::GetRttStats(&manager_)->UpdateRtt( + QuicTime::Delta::FromMilliseconds(100), QuicTime::Delta::Zero()); SendDataPacket(1); SendDataPacket(2); @@ -1133,7 +1113,7 @@ TEST_F(QuicSentPacketManagerTest, GetLossDelay) { // set the loss timeout. EXPECT_CALL(*send_algorithm_, UpdateRtt(_)); EXPECT_CALL(*send_algorithm_, OnPacketAcked(2, _)); - EXPECT_CALL(*loss_algorithm, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm, DetectLostPackets(_, _, _, _)) .WillOnce(Return(SequenceNumberSet())); ReceivedPacketInfo received_info; received_info.largest_observed = 2; @@ -1147,7 +1127,7 @@ TEST_F(QuicSentPacketManagerTest, GetLossDelay) { // Fire the retransmission timeout and ensure the loss detection algorithm // is invoked. - EXPECT_CALL(*loss_algorithm, DetectLostPackets(_, _, _, _, _)) + EXPECT_CALL(*loss_algorithm, DetectLostPackets(_, _, _, _)) .WillOnce(Return(SequenceNumberSet())); manager_.OnRetransmissionTimeout(); } diff --git a/net/quic/quic_unacked_packet_map.cc b/net/quic/quic_unacked_packet_map.cc index c222ac9..b89d73b 100644 --- a/net/quic/quic_unacked_packet_map.cc +++ b/net/quic/quic_unacked_packet_map.cc @@ -13,8 +13,6 @@ using std::max; namespace net { -#define ENDPOINT (is_server_ ? "Server: " : " Client: ") - QuicUnackedPacketMap::TransmissionInfo::TransmissionInfo() : retransmittable_frames(NULL), sequence_number_length(PACKET_1BYTE_SEQUENCE_NUMBER), @@ -53,10 +51,10 @@ QuicUnackedPacketMap::TransmissionInfo::TransmissionInfo( all_transmissions->insert(sequence_number); } -QuicUnackedPacketMap::QuicUnackedPacketMap(bool is_server) +QuicUnackedPacketMap::QuicUnackedPacketMap() : largest_sent_packet_(0), bytes_in_flight_(0), - is_server_(is_server) { + pending_crypto_packet_count_(0) { } QuicUnackedPacketMap::~QuicUnackedPacketMap() { @@ -87,6 +85,11 @@ void QuicUnackedPacketMap::AddPacket( TransmissionInfo(serialized_packet.retransmittable_frames, serialized_packet.sequence_number, serialized_packet.sequence_number_length); + if (serialized_packet.retransmittable_frames != NULL && + serialized_packet.retransmittable_frames->HasCryptoHandshake() + == IS_HANDSHAKE) { + ++pending_crypto_packet_count_; + } } void QuicUnackedPacketMap::OnRetransmittedPacket( @@ -167,6 +170,10 @@ void QuicUnackedPacketMap::RemovePacket( delete transmission_info.all_transmissions; } if (transmission_info.retransmittable_frames != NULL) { + if (transmission_info.retransmittable_frames->HasCryptoHandshake() + == IS_HANDSHAKE) { + --pending_crypto_packet_count_; + } delete transmission_info.retransmittable_frames; } unacked_packets_.erase(it); @@ -282,6 +289,10 @@ bool QuicUnackedPacketMap::HasMultiplePendingPackets() const { return false; } +bool QuicUnackedPacketMap::HasPendingCryptoPackets() const { + return pending_crypto_packet_count_ > 0; +} + bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const { for (UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin(); it != unacked_packets_.rend(); ++it) { diff --git a/net/quic/quic_unacked_packet_map.h b/net/quic/quic_unacked_packet_map.h index 1331049..d739b91 100644 --- a/net/quic/quic_unacked_packet_map.h +++ b/net/quic/quic_unacked_packet_map.h @@ -46,7 +46,7 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap { bool pending; }; - explicit QuicUnackedPacketMap(bool is_server); + QuicUnackedPacketMap(); ~QuicUnackedPacketMap(); // Adds |serialized_packet| to the map. Does not mark it pending. @@ -89,11 +89,6 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap { // Returns the number of unacked packets which have retransmittable frames. size_t GetNumRetransmittablePackets() const; - // Returns the total number of bytes associated with pending packets. - size_t bytes_in_flight() const { - return bytes_in_flight_; - } - // Returns the largest sequence number that has been sent. QuicPacketSequenceNumber largest_sent_packet() const { return largest_sent_packet_; @@ -144,6 +139,9 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap { // Returns true if there are multiple packet pending. bool HasMultiplePendingPackets() const; + // Returns true if there are any pending crypto packets. + bool HasPendingCryptoPackets() const; + // Removes entries from the unacked packet map, and deletes // the retransmittable frames associated with the packet. // Does not remove any previous or subsequent transmissions of this packet. @@ -167,8 +165,8 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap { UnackedPacketMap unacked_packets_; size_t bytes_in_flight_; - - bool is_server_; + // Number of outstanding crypto handshake packets. + size_t pending_crypto_packet_count_; DISALLOW_COPY_AND_ASSIGN(QuicUnackedPacketMap); }; diff --git a/net/quic/reliable_quic_stream_test.cc b/net/quic/reliable_quic_stream_test.cc index 84d839f..0576715 100644 --- a/net/quic/reliable_quic_stream_test.cc +++ b/net/quic/reliable_quic_stream_test.cc @@ -21,7 +21,6 @@ using testing::_; using testing::InSequence; using testing::Return; using testing::SaveArg; -using testing::StrEq; using testing::StrictMock; namespace net { @@ -59,8 +58,6 @@ class TestStream : public ReliableQuicStream { using ReliableQuicStream::CloseWriteSide; using ReliableQuicStream::OnClose; - const string& data() const { return data_; } - private: bool should_process_data_; string data_; diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.cc b/net/quic/test_tools/quic_sent_packet_manager_peer.cc index be8730f..f1643d7 100644 --- a/net/quic/test_tools/quic_sent_packet_manager_peer.cc +++ b/net/quic/test_tools/quic_sent_packet_manager_peer.cc @@ -34,6 +34,12 @@ void QuicSentPacketManagerPeer::SetLossAlgorithm( } // static +RttStats* QuicSentPacketManagerPeer::GetRttStats( + QuicSentPacketManager* sent_packet_manager) { + return &sent_packet_manager->rtt_stats_; +} + +// static size_t QuicSentPacketManagerPeer::GetNackCount( const QuicSentPacketManager* sent_packet_manager, QuicPacketSequenceNumber sequence_number) { @@ -64,12 +70,6 @@ QuicTime QuicSentPacketManagerPeer::GetSentTime( } // static -QuicTime::Delta QuicSentPacketManagerPeer::rtt( - QuicSentPacketManager* sent_packet_manager) { - return sent_packet_manager->rtt_sample_; -} - -// static bool QuicSentPacketManagerPeer::IsRetransmission( QuicSentPacketManager* sent_packet_manager, QuicPacketSequenceNumber sequence_number) { @@ -97,7 +97,7 @@ QuicTime::Delta QuicSentPacketManagerPeer::GetRetransmissionDelay( // static bool QuicSentPacketManagerPeer::HasUnackedCryptoPackets( const QuicSentPacketManager* sent_packet_manager) { - return sent_packet_manager->pending_crypto_packet_count_ > 0; + return sent_packet_manager->unacked_packets_.HasPendingCryptoPackets(); } // static diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.h b/net/quic/test_tools/quic_sent_packet_manager_peer.h index 163e10c..ff86189 100644 --- a/net/quic/test_tools/quic_sent_packet_manager_peer.h +++ b/net/quic/test_tools/quic_sent_packet_manager_peer.h @@ -25,6 +25,8 @@ class QuicSentPacketManagerPeer { static void SetLossAlgorithm(QuicSentPacketManager* sent_packet_manager, LossDetectionInterface* loss_detector); + static RttStats* GetRttStats(QuicSentPacketManager* sent_packet_manager); + static size_t GetNackCount( const QuicSentPacketManager* sent_packet_manager, QuicPacketSequenceNumber sequence_number); @@ -38,8 +40,6 @@ class QuicSentPacketManagerPeer { static QuicTime GetSentTime(const QuicSentPacketManager* sent_packet_manager, QuicPacketSequenceNumber sequence_number); - static QuicTime::Delta rtt(QuicSentPacketManager* sent_packet_manager); - // Returns true if |sequence_number| is a retransmission of a packet. static bool IsRetransmission(QuicSentPacketManager* sent_packet_manager, QuicPacketSequenceNumber sequence_number); diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc index bddfc63..c3e20ae 100644 --- a/net/quic/test_tools/quic_test_utils.cc +++ b/net/quic/test_tools/quic_test_utils.cc @@ -441,6 +441,39 @@ IPAddressNumber Loopback4() { return addr; } +QuicEncryptedPacket* ConstructEncryptedPacket( + QuicConnectionId connection_id, + bool version_flag, + bool reset_flag, + QuicPacketSequenceNumber sequence_number, + const string& data) { + QuicPacketHeader header; + header.public_header.connection_id = connection_id; + header.public_header.connection_id_length = PACKET_8BYTE_CONNECTION_ID; + header.public_header.version_flag = version_flag; + header.public_header.reset_flag = reset_flag; + header.public_header.sequence_number_length = PACKET_6BYTE_SEQUENCE_NUMBER; + header.packet_sequence_number = sequence_number; + header.entropy_flag = false; + header.entropy_hash = 0; + header.fec_flag = false; + header.is_in_fec_group = NOT_IN_FEC_GROUP; + header.fec_group = 0; + QuicStreamFrame stream_frame(1, false, 0, MakeIOVector(data)); + QuicFrame frame(&stream_frame); + QuicFrames frames; + frames.push_back(frame); + QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false); + scoped_ptr<QuicPacket> packet( + framer.BuildUnsizedDataPacket(header, frames).packet); + EXPECT_TRUE(packet != NULL); + QuicEncryptedPacket* encrypted = framer.EncryptPacket(ENCRYPTION_NONE, + sequence_number, + *packet); + EXPECT_TRUE(encrypted != NULL); + return encrypted; +} + void CompareCharArraysWithHexError( const string& description, const char* actual, diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h index 85fde68..0199e68 100644 --- a/net/quic/test_tools/quic_test_utils.h +++ b/net/quic/test_tools/quic_test_utils.h @@ -41,6 +41,14 @@ QuicVersion QuicVersionMin(); // Returns an address for 127.0.0.1. IPAddressNumber Loopback4(); +// Create an encrypted packet for testing. +QuicEncryptedPacket* ConstructEncryptedPacket( + QuicConnectionId connection_id, + bool version_flag, + bool reset_flag, + QuicPacketSequenceNumber sequence_number, + const std::string& data); + void CompareCharArraysWithHexError(const std::string& description, const char* actual, const int actual_len, @@ -296,6 +304,8 @@ class MockConnection : public QuicConnection { MOCK_METHOD1(SendConnectionClose, void(QuicErrorCode error)); MOCK_METHOD2(SendConnectionCloseWithDetails, void(QuicErrorCode error, const string& details)); + MOCK_METHOD2(SendConnectionClosePacket, void(QuicErrorCode error, + const string& details)); MOCK_METHOD3(SendRstStream, void(QuicStreamId id, QuicRstStreamErrorCode error, QuicStreamOffset bytes_written)); @@ -432,7 +442,6 @@ class MockSendAlgorithm : public SendAlgorithmInterface { IsHandshake)); MOCK_CONST_METHOD0(BandwidthEstimate, QuicBandwidth(void)); MOCK_METHOD1(UpdateRtt, void(QuicTime::Delta rtt_sample)); - MOCK_CONST_METHOD0(SmoothedRtt, QuicTime::Delta(void)); MOCK_CONST_METHOD0(RetransmissionDelay, QuicTime::Delta(void)); MOCK_CONST_METHOD0(GetCongestionWindow, QuicByteCount()); @@ -445,12 +454,11 @@ class MockLossAlgorithm : public LossDetectionInterface { MockLossAlgorithm(); virtual ~MockLossAlgorithm(); - MOCK_METHOD5(DetectLostPackets, + MOCK_METHOD4(DetectLostPackets, SequenceNumberSet(const QuicUnackedPacketMap& unacked_packets, const QuicTime& time, QuicPacketSequenceNumber largest_observed, - QuicTime::Delta srtt, - QuicTime::Delta latest_rtt)); + const RttStats& rtt_stats)); MOCK_CONST_METHOD0(GetLossTimeout, QuicTime()); }; diff --git a/net/quic/test_tools/simple_quic_framer.cc b/net/quic/test_tools/simple_quic_framer.cc index fca7f79..6c1efb1 100644 --- a/net/quic/test_tools/simple_quic_framer.cc +++ b/net/quic/test_tools/simple_quic_framer.cc @@ -140,12 +140,6 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface { const vector<QuicStopWaitingFrame>& stop_waiting_frames() const { return stop_waiting_frames_; } - const vector<QuicWindowUpdateFrame>& window_update_frames() const { - return window_update_frames_; - } - const vector<QuicBlockedFrame>& blocked_frames() const { - return blocked_frames_; - } const QuicFecData& fec_data() const { return fec_data_; } diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h index 504b27d..1fe9af2 100644 --- a/net/tools/quic/quic_dispatcher.h +++ b/net/tools/quic/quic_dispatcher.h @@ -126,7 +126,6 @@ class QuicDispatcher : public QuicServerSessionVisitor { return time_wait_list_manager_.get(); } - QuicEpollConnectionHelper* helper() { return helper_.get(); } EpollServer* epoll_server() { return epoll_server_; } const QuicVersionVector& supported_versions() const { @@ -137,10 +136,6 @@ class QuicDispatcher : public QuicServerSessionVisitor { virtual bool OnUnauthenticatedPublicHeader( const QuicPacketPublicHeader& header); - // Information about the packet currently being dispatched. - const IPEndPoint& current_client_address() { - return current_client_address_; - } const IPEndPoint& current_server_address() { return current_server_address_; } diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc index e894e1b5..fa63c2f 100644 --- a/net/tools/quic/quic_dispatcher_test.cc +++ b/net/tools/quic/quic_dispatcher_test.cc @@ -24,13 +24,13 @@ using base::StringPiece; using net::EpollServer; using net::test::MockSession; +using net::test::ConstructEncryptedPacket; using net::tools::test::MockConnection; using std::make_pair; using testing::_; using testing::DoAll; using testing::Invoke; using testing::InSequence; -using testing::Return; using testing::WithoutArgs; namespace net { @@ -109,46 +109,13 @@ class QuicDispatcherTest : public ::testing::Test { return reinterpret_cast<MockConnection*>(session2_->connection()); } - QuicEncryptedPacket* ConstructEncryptedPacket( - QuicConnectionId connection_id, - bool version_flag, - bool reset_flag, - QuicPacketSequenceNumber sequence_number, - const string& data) { - QuicPacketHeader header; - header.public_header.connection_id = connection_id; - header.public_header.connection_id_length = PACKET_8BYTE_CONNECTION_ID; - header.public_header.version_flag = version_flag; - header.public_header.reset_flag = reset_flag; - header.public_header.sequence_number_length = PACKET_6BYTE_SEQUENCE_NUMBER; - header.packet_sequence_number = sequence_number; - header.entropy_flag = false; - header.entropy_hash = 0; - header.fec_flag = false; - header.is_in_fec_group = NOT_IN_FEC_GROUP; - header.fec_group = 0; - QuicStreamFrame stream_frame(1, false, 0, MakeIOVector(data)); - QuicFrame frame(&stream_frame); - QuicFrames frames; - frames.push_back(frame); - QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false); - scoped_ptr<QuicPacket> packet( - framer.BuildUnsizedDataPacket(header, frames).packet); - EXPECT_TRUE(packet != NULL); - QuicEncryptedPacket* encrypted = framer.EncryptPacket(ENCRYPTION_NONE, - sequence_number, - *packet); - EXPECT_TRUE(encrypted != NULL); - data_ = string(encrypted->data(), encrypted->length()); - return encrypted; - } - void ProcessPacket(IPEndPoint addr, QuicConnectionId connection_id, bool has_version_flag, const string& data) { scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( connection_id, has_version_flag, false, 1, data)); + data_ = string(packet->data(), packet->length()); dispatcher_.ProcessPacket(IPEndPoint(), addr, *packet.get()); } diff --git a/net/tools/quic/quic_spdy_server_stream.cc b/net/tools/quic/quic_spdy_server_stream.cc index 4050047..edf493d 100644 --- a/net/tools/quic/quic_spdy_server_stream.cc +++ b/net/tools/quic/quic_spdy_server_stream.cc @@ -28,22 +28,23 @@ QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id, QuicSpdyServerStream::~QuicSpdyServerStream() { } -uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 length) { +uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 data_len) { uint32 total_bytes_processed = 0; // Are we still reading the request headers. if (!request_headers_received_) { // Grow the read buffer if necessary. - if (read_buf_->RemainingCapacity() < (int)length) { + if (read_buf_->RemainingCapacity() < (int)data_len) { read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); } - memcpy(read_buf_->data(), data, length); - read_buf_->set_offset(read_buf_->offset() + length); + memcpy(read_buf_->data(), data, data_len); + read_buf_->set_offset(read_buf_->offset() + data_len); ParseRequestHeaders(); } else { - body_.append(data + total_bytes_processed, length - total_bytes_processed); + body_.append(data + total_bytes_processed, + data_len - total_bytes_processed); } - return length; + return data_len; } void QuicSpdyServerStream::OnFinRead() { diff --git a/net/tools/quic/quic_spdy_server_stream_test.cc b/net/tools/quic/quic_spdy_server_stream_test.cc index cf29e52..7fb9375 100644 --- a/net/tools/quic/quic_spdy_server_stream_test.cc +++ b/net/tools/quic/quic_spdy_server_stream_test.cc @@ -29,7 +29,6 @@ using testing::Invoke; using testing::InvokeArgument; using testing::InSequence; using testing::Return; -using testing::StrEq; using testing::StrictMock; using testing::WithArgs; @@ -46,14 +45,6 @@ class QuicSpdyServerStreamPeer : public QuicSpdyServerStream { using QuicSpdyServerStream::SendResponse; using QuicSpdyServerStream::SendErrorResponse; - const string& body() { - return body_; - } - - const BalsaHeaders& headers() { - return headers_; - } - BalsaHeaders* mutable_headers() { return &headers_; } diff --git a/net/tools/quic/test_tools/quic_server_peer.cc b/net/tools/quic/test_tools/quic_server_peer.cc index 15f3129..33a086f 100644 --- a/net/tools/quic/test_tools/quic_server_peer.cc +++ b/net/tools/quic/test_tools/quic_server_peer.cc @@ -28,11 +28,6 @@ QuicDispatcher* QuicServerPeer::GetDispatcher(QuicServer* server) { return server->dispatcher_.get(); } -// static -int QuicServerPeer::GetFD(QuicServer* server) { - return server->fd_; -} - } // namespace test } // namespace tools } // namespace net diff --git a/net/tools/quic/test_tools/quic_server_peer.h b/net/tools/quic/test_tools/quic_server_peer.h index 65e2c5e..a3d8c5e 100644 --- a/net/tools/quic/test_tools/quic_server_peer.h +++ b/net/tools/quic/test_tools/quic_server_peer.h @@ -19,7 +19,6 @@ class QuicServerPeer { static bool SetSmallSocket(QuicServer* server); static void DisableRecvmmsg(QuicServer* server); static QuicDispatcher* GetDispatcher(QuicServer* server); - static int GetFD(QuicServer* server); }; } // namespace test diff --git a/net/tools/quic/test_tools/quic_test_utils.h b/net/tools/quic/test_tools/quic_test_utils.h index 49ef27d..0cdd7cb 100644 --- a/net/tools/quic/test_tools/quic_test_utils.h +++ b/net/tools/quic/test_tools/quic_test_utils.h @@ -72,6 +72,8 @@ class MockConnection : public QuicConnection { MOCK_METHOD2(SendConnectionCloseWithDetails, void( QuicErrorCode error, const std::string& details)); + MOCK_METHOD2(SendConnectionClosePacket, void(QuicErrorCode error, + const std::string& details)); MOCK_METHOD3(SendRstStream, void(QuicStreamId id, QuicRstStreamErrorCode error, QuicStreamOffset bytes_written)); |