Update from https://crrev.com/305340
Added a few #includes of base/compiler_specific.h for upstream cleanup.
Changed callers for cc::BeginFrameArgs and cc::RendererSettings API
changes.
Review URL: https://codereview.chromium.org/754433003
diff --git a/net/quic/congestion_control/pacing_sender.cc b/net/quic/congestion_control/pacing_sender.cc
index 8073c5b..7e9f81a 100644
--- a/net/quic/congestion_control/pacing_sender.cc
+++ b/net/quic/congestion_control/pacing_sender.cc
@@ -27,6 +27,11 @@
sender_->SetFromConfig(config, is_server, using_pacing);
}
+void PacingSender::ResumeConnectionState(
+ const CachedNetworkParameters& cached_network_params) {
+ sender_->ResumeConnectionState(cached_network_params);
+}
+
void PacingSender::SetNumEmulatedConnections(int num_connections) {
sender_->SetNumEmulatedConnections(num_connections);
}
diff --git a/net/quic/congestion_control/pacing_sender.h b/net/quic/congestion_control/pacing_sender.h
index 4eb3dab..d7d3b2d 100644
--- a/net/quic/congestion_control/pacing_sender.h
+++ b/net/quic/congestion_control/pacing_sender.h
@@ -16,6 +16,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/crypto/cached_network_parameters.h"
#include "net/quic/quic_bandwidth.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_protocol.h"
@@ -38,6 +39,8 @@
void SetFromConfig(const QuicConfig& config,
bool is_server,
bool using_pacing) override;
+ void ResumeConnectionState(
+ const CachedNetworkParameters& cached_network_params) override;
void SetNumEmulatedConnections(int num_connections) override;
void OnCongestionEvent(bool rtt_updated,
QuicByteCount bytes_in_flight,
@@ -63,6 +66,7 @@
bool InRecovery() const override;
QuicByteCount GetSlowStartThreshold() const override;
CongestionControlType GetCongestionControlType() const override;
+ // End implementation of SendAlgorithmInterface.
private:
scoped_ptr<SendAlgorithmInterface> sender_; // Underlying sender.
diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h
index 7195f81..322ff1d 100644
--- a/net/quic/congestion_control/send_algorithm_interface.h
+++ b/net/quic/congestion_control/send_algorithm_interface.h
@@ -12,6 +12,7 @@
#include "base/basictypes.h"
#include "net/base/net_export.h"
+#include "net/quic/crypto/cached_network_parameters.h"
#include "net/quic/quic_bandwidth.h"
#include "net/quic/quic_clock.h"
#include "net/quic/quic_config.h"
@@ -113,6 +114,10 @@
virtual QuicByteCount GetSlowStartThreshold() const = 0;
virtual CongestionControlType GetCongestionControlType() const = 0;
+
+ // Called by the Session when we get a bandwidth estimate from the client.
+ virtual void ResumeConnectionState(
+ const CachedNetworkParameters& cached_network_params) = 0;
};
} // namespace net
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc
index 2d0efd7..5fa1559 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -27,13 +27,12 @@
const uint32 kDefaultNumConnections = 2; // N-connection emulation.
} // namespace
-TcpCubicSender::TcpCubicSender(
- const QuicClock* clock,
- const RttStats* rtt_stats,
- bool reno,
- QuicPacketCount initial_tcp_congestion_window,
- QuicPacketCount max_tcp_congestion_window,
- QuicConnectionStats* stats)
+TcpCubicSender::TcpCubicSender(const QuicClock* clock,
+ const RttStats* rtt_stats,
+ bool reno,
+ QuicPacketCount initial_tcp_congestion_window,
+ QuicPacketCount max_tcp_congestion_window,
+ QuicConnectionStats* stats)
: hybrid_slow_start_(clock),
cubic_(clock, stats),
rtt_stats_(rtt_stats),
@@ -49,8 +48,8 @@
slowstart_threshold_(max_tcp_congestion_window),
previous_slowstart_threshold_(0),
last_cutback_exited_slowstart_(false),
- max_tcp_congestion_window_(max_tcp_congestion_window) {
-}
+ max_tcp_congestion_window_(max_tcp_congestion_window),
+ clock_(clock) {}
TcpCubicSender::~TcpCubicSender() {
UMA_HISTOGRAM_COUNTS("Net.QuicSession.FinalTcpCwnd", congestion_window_);
@@ -73,6 +72,26 @@
}
}
+void TcpCubicSender::ResumeConnectionState(
+ const CachedNetworkParameters& cached_network_params) {
+ // If the previous bandwidth estimate is less than an hour old, store in
+ // preparation for doing bandwidth resumption.
+ int64 seconds_since_estimate =
+ clock_->WallNow().ToUNIXSeconds() - cached_network_params.timestamp();
+ if (seconds_since_estimate > kNumSecondsPerHour) {
+ return;
+ }
+
+ QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond(
+ cached_network_params.bandwidth_estimate_bytes_per_second());
+ QuicTime::Delta rtt_ms =
+ QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms());
+ congestion_window_ = bandwidth.ToBytesPerPeriod(rtt_ms) / kMaxPacketSize;
+
+ // TODO(rjshade): Set appropriate CWND when previous connection was in slow
+ // start at time of estimate.
+}
+
void TcpCubicSender::SetNumEmulatedConnections(int num_connections) {
num_connections_ = max(1, num_connections);
cubic_.SetNumConnections(num_connections_);
diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h
index a7507a2..eeb9331 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.h
+++ b/net/quic/congestion_control/tcp_cubic_sender.h
@@ -15,6 +15,7 @@
#include "net/quic/congestion_control/hybrid_slow_start.h"
#include "net/quic/congestion_control/prr_sender.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/crypto/cached_network_parameters.h"
#include "net/quic/quic_bandwidth.h"
#include "net/quic/quic_connection_stats.h"
#include "net/quic/quic_protocol.h"
@@ -43,6 +44,8 @@
void SetFromConfig(const QuicConfig& config,
bool is_server,
bool using_pacing) override;
+ void ResumeConnectionState(
+ const CachedNetworkParameters& cached_network_params) override;
void SetNumEmulatedConnections(int num_connections) override;
void OnCongestionEvent(bool rtt_updated,
QuicByteCount bytes_in_flight,
@@ -130,6 +133,8 @@
// Maximum number of outstanding packets for tcp.
QuicPacketCount max_tcp_congestion_window_;
+ const QuicClock* clock_;
+
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 427dd8c..e4737eb 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -701,5 +701,32 @@
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
}
+TEST_F(TcpCubicSenderTest, BandwidthResumption) {
+ // Test that when provided with CachedNetworkParameters and opted in to the
+ // bandwidth resumption experiment, that the TcpCubicSender sets initial CWND
+ // appropriately.
+
+ // Set some common values.
+ CachedNetworkParameters cached_network_params;
+ const QuicPacketCount kNumberOfPackets = 123;
+ const int kBandwidthEstimateBytesPerSecond =
+ kNumberOfPackets * kMaxPacketSize;
+ cached_network_params.set_bandwidth_estimate_bytes_per_second(
+ kBandwidthEstimateBytesPerSecond);
+ cached_network_params.set_min_rtt_ms(1000);
+
+ // Ensure that an old estimate is not used for bandwidth resumption.
+ cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() -
+ (kNumSecondsPerHour + 1));
+ sender_->ResumeConnectionState(cached_network_params);
+ EXPECT_EQ(10u, sender_->congestion_window());
+
+ // If the estimate is new enough, make sure it is used.
+ cached_network_params.set_timestamp(clock_.WallNow().ToUNIXSeconds() -
+ (kNumSecondsPerHour - 1));
+ sender_->ResumeConnectionState(cached_network_params);
+ EXPECT_EQ(kNumberOfPackets, sender_->congestion_window());
+}
+
} // namespace test
} // namespace net
diff --git a/net/quic/congestion_control/tcp_loss_algorithm.cc b/net/quic/congestion_control/tcp_loss_algorithm.cc
index 6cf56d8..9366105 100644
--- a/net/quic/congestion_control/tcp_loss_algorithm.cc
+++ b/net/quic/congestion_control/tcp_loss_algorithm.cc
@@ -40,7 +40,7 @@
continue;
}
- LOG_IF(DFATAL, it->nack_count == 0)
+ LOG_IF(DFATAL, it->nack_count == 0 && it->sent_time.IsInitialized())
<< "All packets less than largest observed should have been nacked."
<< "sequence_number:" << sequence_number
<< " largest_observed:" << largest_observed;
diff --git a/net/quic/congestion_control/tcp_loss_algorithm_test.cc b/net/quic/congestion_control/tcp_loss_algorithm_test.cc
index 5819fb1..fe6a6ea 100644
--- a/net/quic/congestion_control/tcp_loss_algorithm_test.cc
+++ b/net/quic/congestion_control/tcp_loss_algorithm_test.cc
@@ -12,8 +12,14 @@
#include "net/quic/test_tools/mock_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using std::vector;
+
namespace net {
namespace test {
+namespace {
+
+// Default packet length.
+const uint32 kDefaultLength = 1000;
class TcpLossAlgorithmTest : public ::testing::Test {
protected:
@@ -24,9 +30,16 @@
clock_.Now());
}
+ ~TcpLossAlgorithmTest() override {
+ STLDeleteElements(&packets_);
+ }
+
void SendDataPacket(QuicPacketSequenceNumber sequence_number) {
+ packets_.push_back(QuicPacket::NewDataPacket(
+ nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
+ PACKET_1BYTE_SEQUENCE_NUMBER));
SerializedPacket packet(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
- nullptr, 0, new RetransmittableFrames());
+ packets_.back(), 0, new RetransmittableFrames());
unacked_packets_.AddSentPacket(packet, 0, NOT_RETRANSMISSION, clock_.Now(),
1000, true);
}
@@ -43,6 +56,7 @@
}
}
+ vector<QuicPacket*> packets_;
QuicUnackedPacketMap unacked_packets_;
TCPLossAlgorithm loss_algorithm_;
RttStats rtt_stats_;
@@ -179,5 +193,6 @@
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
+} // namespace
} // namespace test
} // namespace net
diff --git a/net/quic/congestion_control/time_loss_algorithm.cc b/net/quic/congestion_control/time_loss_algorithm.cc
index 9dd9ae9..b5f90b7 100644
--- a/net/quic/congestion_control/time_loss_algorithm.cc
+++ b/net/quic/congestion_control/time_loss_algorithm.cc
@@ -46,8 +46,10 @@
if (!it->in_flight) {
continue;
}
- LOG_IF(DFATAL, it->nack_count == 0)
- << "All packets less than largest observed should have been nacked.";
+ LOG_IF(DFATAL, it->nack_count == 0 && it->sent_time.IsInitialized())
+ << "All packets less than largest observed should have been nacked."
+ << "sequence_number:" << sequence_number
+ << " largest_observed:" << largest_observed;
// Packets are sent in order, so break when we haven't waited long enough
// to lose any more packets and leave the loss_time_ set for the timeout.
diff --git a/net/quic/congestion_control/time_loss_algorithm_test.cc b/net/quic/congestion_control/time_loss_algorithm_test.cc
index b964d28..1e9b7e5 100644
--- a/net/quic/congestion_control/time_loss_algorithm_test.cc
+++ b/net/quic/congestion_control/time_loss_algorithm_test.cc
@@ -12,8 +12,14 @@
#include "net/quic/test_tools/mock_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using std::vector;
+
namespace net {
namespace test {
+namespace {
+
+// Default packet length.
+const uint32 kDefaultLength = 1000;
class TimeLossAlgorithmTest : public ::testing::Test {
protected:
@@ -24,9 +30,16 @@
clock_.Now());
}
+ ~TimeLossAlgorithmTest() override {
+ STLDeleteElements(&packets_);
+ }
+
void SendDataPacket(QuicPacketSequenceNumber sequence_number) {
+ packets_.push_back(QuicPacket::NewDataPacket(
+ nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
+ PACKET_1BYTE_SEQUENCE_NUMBER));
SerializedPacket packet(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
- nullptr, 0, new RetransmittableFrames());
+ packets_.back(), 0, new RetransmittableFrames());
unacked_packets_.AddSentPacket(packet, 0, NOT_RETRANSMISSION, clock_.Now(),
1000, true);
}
@@ -43,6 +56,7 @@
}
}
+ vector<QuicPacket*> packets_;
QuicUnackedPacketMap unacked_packets_;
TimeLossAlgorithm loss_algorithm_;
RttStats rtt_stats_;
@@ -134,5 +148,6 @@
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
+} // namespace
} // namespace test
} // namespace net
diff --git a/net/quic/crypto/common_cert_set.cc b/net/quic/crypto/common_cert_set.cc
index 09379f3..b2ea3a7 100644
--- a/net/quic/crypto/common_cert_set.cc
+++ b/net/quic/crypto/common_cert_set.cc
@@ -153,7 +153,7 @@
private:
CommonCertSetsQUIC() {}
- virtual ~CommonCertSetsQUIC() {}
+ ~CommonCertSetsQUIC() override {}
friend struct DefaultSingletonTraits<CommonCertSetsQUIC>;
DISALLOW_COPY_AND_ASSIGN(CommonCertSetsQUIC);
diff --git a/net/quic/crypto/crypto_handshake_message.cc b/net/quic/crypto/crypto_handshake_message.cc
index 9125968..23e8ea2 100644
--- a/net/quic/crypto/crypto_handshake_message.cc
+++ b/net/quic/crypto/crypto_handshake_message.cc
@@ -302,8 +302,9 @@
static_cast<int>(it->second.size()));
done = true;
break;
+ case kSNI:
case kUAID:
- ret += it->second;
+ ret += "\"" + it->second + "\"";
done = true;
break;
}
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h
index d010776..57a5508 100644
--- a/net/quic/crypto/crypto_protocol.h
+++ b/net/quic/crypto/crypto_protocol.h
@@ -71,6 +71,9 @@
// FEC options
const QuicTag kFHDR = TAG('F', 'H', 'D', 'R'); // FEC protect headers
+// Enable bandwidth resumption experiment.
+const QuicTag kBWRE = TAG('B', 'W', 'R', 'E'); // Bandwidth resumption.
+
// Proof types (i.e. certificate types)
// NOTE: although it would be silly to do so, specifying both kX509 and kX59R
// is allowed and is equivalent to specifying only kX509.
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index 274099c..97d6c3b 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/base/network_activity_monitor.h"
#include "net/http/transport_security_state.h"
#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/quic/crypto/quic_server_info.h"
@@ -633,6 +634,18 @@
"Net.QuicSession.TimedOutWithOpenStreams.ConsecutiveTLPCount",
connection()->sent_packet_manager().consecutive_tlp_count());
}
+ if (connection()->sent_packet_manager().HasUnackedPackets()) {
+ UMA_HISTOGRAM_TIMES(
+ "Net.QuicSession.LocallyTimedOutWithOpenStreams."
+ "TimeSinceLastReceived.UnackedPackets",
+ NetworkActivityMonitor::GetInstance()->GetTimeSinceLastReceived());
+ } else {
+ UMA_HISTOGRAM_TIMES(
+ "Net.QuicSession.LocallyTimedOutWithOpenStreams."
+ "TimeSinceLastReceived.NoUnackedPackets",
+ NetworkActivityMonitor::GetInstance()->GetTimeSinceLastReceived());
+ }
+
} else {
UMA_HISTOGRAM_COUNTS(
"Net.QuicSession.ConnectionClose.NumOpenStreams.HandshakeTimedOut",
diff --git a/net/quic/quic_client_session_test.cc b/net/quic/quic_client_session_test.cc
index 66583b8..88beca7 100644
--- a/net/quic/quic_client_session_test.cc
+++ b/net/quic/quic_client_session_test.cc
@@ -52,6 +52,8 @@
/*is_secure=*/false,
PRIVACY_MODE_DISABLED),
&crypto_config_, nullptr);
+ // Advance the time, because timers do not like uninitialized times.
+ connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
void TearDown() override { session_.CloseSessionOnError(ERR_ABORTED); }
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index fd9ec5f..62cbc64 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -282,6 +282,11 @@
max_undecryptable_packets_ = config.max_undecryptable_packets();
}
+void QuicConnection::ResumeConnectionState(
+ const CachedNetworkParameters& cached_network_params) {
+ sent_packet_manager_.ResumeConnectionState(cached_network_params);
+}
+
void QuicConnection::SetNumOpenStreams(size_t num_streams) {
sent_packet_manager_.SetNumOpenStreams(num_streams);
}
@@ -911,10 +916,6 @@
} else {
// Send an ack much more quickly for crypto handshake packets.
QuicTime::Delta delayed_ack_time = sent_packet_manager_.DelayedAckTime();
- if (last_stream_frames_.size() == 1 &&
- last_stream_frames_[0].stream_id == kCryptoStreamId) {
- delayed_ack_time = QuicTime::Delta::Zero();
- }
ack_alarm_->Set(clock_->ApproximateNow().Add(delayed_ack_time));
DVLOG(1) << "Ack timer set; next packet or timer will trigger ACK.";
}
@@ -1449,6 +1450,13 @@
<< QuicUtils::StringToHexASCIIDump(
packet->serialized_packet.packet->AsStringPiece());
+ QuicTime packet_send_time = QuicTime::Zero();
+ if (FLAGS_quic_record_send_time_before_write) {
+ // Measure the RTT from before the write begins to avoid underestimating the
+ // min_rtt_, especially in cases where the thread blocks or gets swapped out
+ // during the WritePacket below.
+ packet_send_time = clock_->Now();
+ }
WriteResult result = writer_->WritePacket(encrypted->data(),
encrypted->length(),
self_address().address(),
@@ -1467,7 +1475,16 @@
return false;
}
}
- QuicTime now = clock_->Now();
+ if (!FLAGS_quic_record_send_time_before_write) {
+ packet_send_time = clock_->Now();
+ }
+ if (!packet_send_time.IsInitialized()) {
+ // TODO(jokulik): This is only needed because of the two code paths for
+ // initializing packet_send_time. Once "quic_record_send_time_before_write"
+ // is deprecated, this check can be removed.
+ LOG(DFATAL) << "The packet send time should never be zero. "
+ << "This is a programming bug, please report it.";
+ }
if (result.status != WRITE_STATUS_ERROR && debug_visitor_.get() != nullptr) {
// Pass the write result to the visitor.
debug_visitor_->OnPacketSent(packet->serialized_packet,
@@ -1475,14 +1492,17 @@
packet->encryption_level,
packet->transmission_type,
*encrypted,
- now);
+ packet_send_time);
}
if (packet->transmission_type == NOT_RETRANSMISSION) {
- time_of_last_sent_new_packet_ = now;
+ time_of_last_sent_new_packet_ = packet_send_time;
}
SetPingAlarm();
- DVLOG(1) << ENDPOINT << "time of last sent packet: "
- << now.ToDebuggingValue();
+ DVLOG(1) << ENDPOINT << "time "
+ << (FLAGS_quic_record_send_time_before_write ?
+ "we began writing " : "we finished writing ")
+ << "last sent packet: "
+ << packet_send_time.ToDebuggingValue();
// TODO(ianswett): Change the sequence number length and other packet creator
// options by a more explicit API than setting a struct value directly,
@@ -1494,7 +1514,7 @@
bool reset_retransmission_alarm = sent_packet_manager_.OnPacketSent(
&packet->serialized_packet,
packet->original_sequence_number,
- now,
+ packet_send_time,
encrypted->length(),
packet->transmission_type,
IsRetransmittable(*packet));
@@ -1585,6 +1605,12 @@
void QuicConnection::OnHandshakeComplete() {
sent_packet_manager_.SetHandshakeConfirmed();
+ // The client should immediately ack the SHLO to confirm the handshake is
+ // complete with the server.
+ if (!is_server_ && !ack_queued_) {
+ ack_alarm_->Cancel();
+ ack_alarm_->Set(clock_->ApproximateNow());
+ }
}
void QuicConnection::SendOrQueuePacket(QueuedPacket packet) {
@@ -1598,8 +1624,6 @@
sent_entropy_manager_.RecordPacketEntropyHash(
packet.serialized_packet.sequence_number,
packet.serialized_packet.entropy_hash);
- LOG_IF(DFATAL, !queued_packets_.empty() && !writer_->IsWriteBlocked())
- << "Packets should only be left queued if we're write blocked.";
if (!WritePacket(&packet)) {
queued_packets_.push_back(packet);
}
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 96f5cbc..abab048 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -24,6 +24,7 @@
#include <string>
#include <vector>
+#include "base/basictypes.h"
#include "base/logging.h"
#include "net/base/iovec.h"
#include "net/base/ip_endpoint.h"
@@ -258,6 +259,11 @@
// Sets connection parameters from the supplied |config|.
void SetFromConfig(const QuicConfig& config);
+ // Called by the Session when the client has provided CachedNetworkParameters.
+ // Virtual for tests.
+ virtual void ResumeConnectionState(
+ const CachedNetworkParameters& cached_network_params);
+
// Sets the number of active streams on the connection for congestion control.
void SetNumOpenStreams(size_t num_streams);
@@ -689,7 +695,7 @@
IPEndPoint self_address_;
IPEndPoint peer_address_;
// Used to store latest peer port to possibly migrate to later.
- int migrating_peer_port_;
+ uint16 migrating_peer_port_;
// True if the last packet has gotten far enough in the framer to be
// decrypted.
@@ -783,8 +789,8 @@
// This is used for timeouts, and does not indicate the packet was processed.
QuicTime time_of_last_received_packet_;
- // The last time a new (non-retransmitted) packet was sent for this
- // connection.
+ // The last time this connection began sending a new (non-retransmitted)
+ // packet.
QuicTime time_of_last_sent_new_packet_;
// Sequence number of the last sent packet. Packets are guaranteed to be sent
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 4e58dfd..ede61c8 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -67,7 +67,7 @@
}
bool GenerateCongestionFeedback(
- QuicCongestionFeedbackFrame* congestion_feedback) {
+ QuicCongestionFeedbackFrame* congestion_feedback) override {
if (feedback_ == nullptr) {
return false;
}
@@ -95,6 +95,7 @@
// QuicEncrypter interface.
bool SetKey(StringPiece key) override { return true; }
+
bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
bool Encrypt(StringPiece nonce,
@@ -149,6 +150,7 @@
// QuicDecrypter interface
bool SetKey(StringPiece key) override { return true; }
+
bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
bool Decrypt(StringPiece nonce,
@@ -258,7 +260,7 @@
class TestPacketWriter : public QuicPacketWriter {
public:
- explicit TestPacketWriter(QuicVersion version)
+ TestPacketWriter(QuicVersion version, MockClock *clock)
: version_(version),
framer_(SupportedVersions(version_)),
last_packet_size_(0),
@@ -268,7 +270,9 @@
final_bytes_of_last_packet_(0),
final_bytes_of_previous_packet_(0),
use_tagging_decrypter_(false),
- packets_write_attempts_(0) {
+ packets_write_attempts_(0),
+ clock_(clock),
+ write_pause_time_delta_(QuicTime::Delta::Zero()) {
}
// QuicPacketWriter interface
@@ -297,6 +301,10 @@
return WriteResult(WRITE_STATUS_BLOCKED, -1);
}
last_packet_size_ = packet.length();
+
+ if (!write_pause_time_delta_.IsZero()) {
+ clock_->AdvanceTime(write_pause_time_delta_);
+ }
return WriteResult(WRITE_STATUS_OK, last_packet_size_);
}
@@ -310,6 +318,11 @@
void BlockOnNextWrite() { block_on_next_write_ = true; }
+ // Sets the amount of time that the writer should before the actual write.
+ void SetWritePauseTimeDelta(QuicTime::Delta delta) {
+ write_pause_time_delta_ = delta;
+ }
+
const QuicPacketHeader& header() { return framer_.header(); }
size_t frame_count() const { return framer_.num_frames(); }
@@ -390,6 +403,10 @@
uint32 final_bytes_of_previous_packet_;
bool use_tagging_decrypter_;
uint32 packets_write_attempts_;
+ MockClock *clock_;
+ // If non-zero, the clock will pause during WritePacket for this amount of
+ // time.
+ QuicTime::Delta write_pause_time_delta_;
DISALLOW_COPY_AND_ASSIGN(TestPacketWriter);
};
@@ -597,7 +614,7 @@
MockPacketWriterFactory(QuicPacketWriter* writer) {
ON_CALL(*this, Create(_)).WillByDefault(Return(writer));
}
- virtual ~MockPacketWriterFactory() {}
+ ~MockPacketWriterFactory() override {}
MOCK_CONST_METHOD1(Create, QuicPacketWriter*(QuicConnection* connection));
};
@@ -611,7 +628,7 @@
send_algorithm_(new StrictMock<MockSendAlgorithm>),
loss_algorithm_(new MockLossAlgorithm()),
helper_(new TestConnectionHelper(&clock_, &random_generator_)),
- writer_(new TestPacketWriter(version())),
+ writer_(new TestPacketWriter(version(), &clock_)),
factory_(writer_.get()),
connection_(connection_id_, IPEndPoint(), helper_.get(),
factory_, false, version()),
@@ -974,6 +991,10 @@
EXPECT_CALL(visitor_, OnWriteBlocked()).Times(AtLeast(1));
}
+ void SetWritePauseTimeDelta(QuicTime::Delta delta) {
+ writer_->SetWritePauseTimeDelta(delta);
+ }
+
void CongestionBlockWrites() {
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, _, _)).WillRepeatedly(
@@ -1548,6 +1569,74 @@
EXPECT_EQ(7u, least_unacked());
}
+// If FLAGS_quic_record_send_time_before_write is disabled, QuicConnection
+// should record the packet sen-tdime after the packet is sent.
+TEST_P(QuicConnectionTest, RecordSentTimeAfterPacketSent) {
+ ValueRestore<bool> old_flag(&FLAGS_quic_record_send_time_before_write, false);
+ // We're using a MockClock for the tests, so we have complete control over the
+ // time.
+ // Our recorded timestamp for the last packet sent time will be passed in to
+ // the send_algorithm. Make sure that it is set to the correct value.
+ QuicTime actual_recorded_send_time = QuicTime::Zero();
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<0>(&actual_recorded_send_time), Return(true)));
+
+ // First send without any pause and check the result.
+ QuicTime expected_recorded_send_time = clock_.Now();
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr);
+ EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time)
+ << "Expected time = " << expected_recorded_send_time.ToDebuggingValue()
+ << ". Actual time = " << actual_recorded_send_time.ToDebuggingValue();
+
+ // Now pause during the write, and check the results.
+ actual_recorded_send_time = QuicTime::Zero();
+ const QuicTime::Delta kWritePauseTimeDelta =
+ QuicTime::Delta::FromMilliseconds(5000);
+ SetWritePauseTimeDelta(kWritePauseTimeDelta);
+ expected_recorded_send_time = clock_.Now().Add(kWritePauseTimeDelta);
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<0>(&actual_recorded_send_time), Return(true)));
+ connection_.SendStreamDataWithString(2, "baz", 0, !kFin, nullptr);
+ EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time)
+ << "Expected time = " << expected_recorded_send_time.ToDebuggingValue()
+ << ". Actual time = " << actual_recorded_send_time.ToDebuggingValue();
+}
+
+// If FLAGS_quic_record_send_time_before_write is enabled, QuicConnection should
+// record the the packet sent-time prior to sending the packet.
+TEST_P(QuicConnectionTest, RecordSentTimeBeforePacketSent) {
+ ValueRestore<bool> old_flag(&FLAGS_quic_record_send_time_before_write, true);
+ // We're using a MockClock for the tests, so we have complete control over the
+ // time.
+ // Our recorded timestamp for the last packet sent time will be passed in to
+ // the send_algorithm. Make sure that it is set to the correct value.
+ QuicTime actual_recorded_send_time = QuicTime::Zero();
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<0>(&actual_recorded_send_time), Return(true)));
+
+ // First send without any pause and check the result.
+ QuicTime expected_recorded_send_time = clock_.Now();
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr);
+ EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time)
+ << "Expected time = " << expected_recorded_send_time.ToDebuggingValue()
+ << ". Actual time = " << actual_recorded_send_time.ToDebuggingValue();
+
+ // Now pause during the write, and check the results.
+ actual_recorded_send_time = QuicTime::Zero();
+ const QuicTime::Delta kWritePauseTimeDelta =
+ QuicTime::Delta::FromMilliseconds(5000);
+ SetWritePauseTimeDelta(kWritePauseTimeDelta);
+ expected_recorded_send_time = clock_.Now();
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<0>(&actual_recorded_send_time), Return(true)));
+ connection_.SendStreamDataWithString(2, "baz", 0, !kFin, nullptr);
+ EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time)
+ << "Expected time = " << expected_recorded_send_time.ToDebuggingValue()
+ << ". Actual time = " << actual_recorded_send_time.ToDebuggingValue();
+}
+
TEST_P(QuicConnectionTest, FECSending) {
// All packets carry version info till version is negotiated.
QuicPacketCreator* creator =
@@ -1565,7 +1654,8 @@
creator->set_max_packet_length(length);
// Send 4 protected data packets, which should also trigger 1 FEC packet.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(5);
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(5);
// The first stream frame will have 2 fewer overhead bytes than the other 3.
const string payload(payload_length * 4 + 2, 'a');
connection_.SendStreamDataWithStringWithFec(1, payload, 0, !kFin, nullptr);
@@ -1601,7 +1691,8 @@
&connection_)->IsFecEnabled());
// 1 Data and 1 FEC packet.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(2);
connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr);
const QuicTime::Delta retransmission_time =
@@ -1620,8 +1711,9 @@
EXPECT_TRUE(QuicConnectionPeer::GetPacketCreator(
&connection_)->IsFecEnabled());
- // 1 Data and 1 FEC packet.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6);
+ // 3 Data and 3 FEC packets.
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(6);
connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr);
// Send some more data afterwards to ensure early retransmit doesn't trigger.
connection_.SendStreamDataWithStringWithFec(3, "foo", 3, !kFin, nullptr);
@@ -1648,8 +1740,9 @@
EXPECT_TRUE(QuicConnectionPeer::GetPacketCreator(
&connection_)->IsFecEnabled());
- // 1 Data and 1 FEC packet.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6);
+ // 3 Data and 3 FEC packet.
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)).Times(6);
connection_.SendStreamDataWithStringWithFec(3, "foo", 0, !kFin, nullptr);
// Send some more data afterwards to ensure early retransmit doesn't trigger.
connection_.SendStreamDataWithStringWithFec(3, "foo", 3, !kFin, nullptr);
@@ -3070,22 +3163,25 @@
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
}
-TEST_P(QuicConnectionTest, SendEarlyDelayedAckForCrypto) {
- QuicTime ack_time = clock_.ApproximateNow();
+TEST_P(QuicConnectionTest, SendDelayedAckOnHandshakeConfirmed) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
- // Process a packet from the crypto stream, which is frame1_'s default.
ProcessPacket(1);
- // Check if delayed ack timer is running for the expected interval.
+ // Check that ack is sent and that delayed ack alarm is set.
+ EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+ QuicTime ack_time = clock_.ApproximateNow().Add(DefaultDelayedAckTime());
+ EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
+
+ // Completing the handshake as the server does nothing.
+ QuicConnectionPeer::SetIsServer(&connection_, true);
+ connection_.OnHandshakeComplete();
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
- // Simulate delayed ack alarm firing.
- connection_.GetAckAlarm()->Fire();
- // Check that ack is sent and that delayed ack alarm is reset.
- EXPECT_EQ(2u, writer_->frame_count());
- EXPECT_FALSE(writer_->stop_waiting_frames().empty());
- EXPECT_FALSE(writer_->ack_frames().empty());
- EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+
+ // Complete the handshake as the client decreases the delayed ack time to 0ms.
+ QuicConnectionPeer::SetIsServer(&connection_, false);
+ connection_.OnHandshakeComplete();
+ EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+ EXPECT_EQ(clock_.ApproximateNow(), connection_.GetAckAlarm()->deadline());
}
TEST_P(QuicConnectionTest, SendDelayedAckOnSecondPacket) {
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
index 1df2313..8e14d77 100644
--- a/net/quic/quic_crypto_client_stream_test.cc
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -34,6 +34,8 @@
stream_(new QuicCryptoClientStream(server_id_, session_.get(), nullptr,
&crypto_config_)) {
session_->SetCryptoStream(stream_.get());
+ // Advance the time, because timers do not like uninitialized times.
+ connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
void CompleteCryptoHandshake() {
@@ -128,8 +130,8 @@
// Advance time 5 years to ensure that we pass the expiry time of the cached
// server config.
- reinterpret_cast<MockClock*>(const_cast<QuicClock*>(connection_->clock()))
- ->AdvanceTime(QuicTime::Delta::FromSeconds(60 * 60 * 24 * 365 * 5));
+ connection_->AdvanceTime(
+ QuicTime::Delta::FromSeconds(60 * 60 * 24 * 365 * 5));
// Check that a client hello was sent and that CryptoConnect doesn't fail
// with an error.
diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc
index 1d62376..c4b5893 100644
--- a/net/quic/quic_crypto_server_stream.cc
+++ b/net/quic/quic_crypto_server_stream.cc
@@ -245,8 +245,8 @@
void QuicCryptoServerStream::OverrideQuicConfigDefaults(QuicConfig* config) {
}
-CachedNetworkParameters*
-QuicCryptoServerStream::get_previous_cached_network_params() {
+const CachedNetworkParameters*
+QuicCryptoServerStream::previous_cached_network_params() const {
return previous_cached_network_params_.get();
}
diff --git a/net/quic/quic_crypto_server_stream.h b/net/quic/quic_crypto_server_stream.h
index 09d9bd8..f88affe 100644
--- a/net/quic/quic_crypto_server_stream.h
+++ b/net/quic/quic_crypto_server_stream.h
@@ -82,6 +82,8 @@
void set_previous_cached_network_params(
CachedNetworkParameters cached_network_params);
+ const CachedNetworkParameters* previous_cached_network_params() const;
+
protected:
virtual QuicErrorCode ProcessClientHello(
const CryptoHandshakeMessage& message,
@@ -93,8 +95,6 @@
// before going through the parameter negotiation step.
virtual void OverrideQuicConfigDefaults(QuicConfig* config);
- CachedNetworkParameters* get_previous_cached_network_params();
-
private:
friend class test::CryptoTestUtils;
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc
index 47d58ce..e737933 100644
--- a/net/quic/quic_flags.cc
+++ b/net/quic/quic_flags.cc
@@ -54,3 +54,14 @@
// If true, QUIC connections will delay moving to forward security until the
// client starts sending foward secure encrypted packets.
bool FLAGS_enable_quic_delay_forward_security = true;
+
+// Do not flip this flag. jokulik plans more testing and additional monitoring
+// before the flag can go the auto-flip process.
+//
+// If true, record the timestamp for the last sent new packet before the call to
+// WritePacket, rather than after in QUIC.
+bool FLAGS_quic_record_send_time_before_write = false;
+
+// If true, enables the QUIC bandwidth resumption experiment (triggered by
+// Chrome/Finch).
+bool FLAGS_quic_enable_bandwidth_resumption_experiment = true;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h
index a75f79b..2ffe618 100644
--- a/net/quic/quic_flags.h
+++ b/net/quic/quic_flags.h
@@ -20,5 +20,8 @@
NET_EXPORT_PRIVATE extern bool FLAGS_allow_truncated_connection_ids_for_quic;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_too_many_outstanding_packets;
NET_EXPORT_PRIVATE extern bool FLAGS_enable_quic_delay_forward_security;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_record_send_time_before_write;
+NET_EXPORT_PRIVATE
+extern bool FLAGS_quic_enable_bandwidth_resumption_experiment;
#endif // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc
index 4e03e3a..578acea 100644
--- a/net/quic/quic_packet_creator_test.cc
+++ b/net/quic/quic_packet_creator_test.cc
@@ -87,8 +87,7 @@
server_framer_.set_visitor(&framer_visitor_);
}
- virtual ~QuicPacketCreatorTest() override {
- }
+ ~QuicPacketCreatorTest() override {}
void ProcessPacket(QuicPacket* packet) {
scoped_ptr<QuicEncryptedPacket> encrypted(
diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc
index 3f2472c..ac99144 100644
--- a/net/quic/quic_packet_generator_test.cc
+++ b/net/quic/quic_packet_generator_test.cc
@@ -33,7 +33,7 @@
class MockDelegate : public QuicPacketGenerator::DelegateInterface {
public:
MockDelegate() {}
- virtual ~MockDelegate() override {}
+ ~MockDelegate() override {}
MOCK_METHOD3(ShouldGeneratePacket,
bool(TransmissionType transmission_type,
@@ -116,7 +116,7 @@
packet6_(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0, nullptr),
packet7_(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0, nullptr) {}
- virtual ~QuicPacketGeneratorTest() override {
+ ~QuicPacketGeneratorTest() override {
delete packet_.packet;
delete packet_.retransmittable_frames;
delete packet2_.packet;
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index 5aa831e..b631b07 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -704,7 +704,8 @@
transmission_type(NOT_RETRANSMISSION),
all_transmissions(nullptr),
in_flight(false),
- is_unackable(false) {}
+ is_unackable(false),
+ is_fec_packet(false) {}
TransmissionInfo::TransmissionInfo(
RetransmittableFrames* retransmittable_frames,
@@ -719,6 +720,7 @@
transmission_type(transmission_type),
all_transmissions(nullptr),
in_flight(false),
- is_unackable(false) {}
+ is_unackable(false),
+ is_fec_packet(false) {}
} // namespace net
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index 00064ff..4cd53a9 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -1099,6 +1099,8 @@
bool in_flight;
// True if the packet can never be acked, so it can be removed.
bool is_unackable;
+ // True if the packet is an FEC packet.
+ bool is_fec_packet;
};
} // namespace net
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc
index 7978fed..142871e 100644
--- a/net/quic/quic_sent_packet_manager.cc
+++ b/net/quic/quic_sent_packet_manager.cc
@@ -163,6 +163,11 @@
}
}
+void QuicSentPacketManager::ResumeConnectionState(
+ const CachedNetworkParameters& cached_network_params) {
+ send_algorithm_->ResumeConnectionState(cached_network_params);
+}
+
void QuicSentPacketManager::SetNumOpenStreams(size_t num_streams) {
if (n_connection_simulation_) {
// Ensure the number of connections is between 1 and 5.
@@ -323,6 +328,9 @@
(retransmission_type == ALL_UNACKED_RETRANSMISSION ||
frames->encryption_level() == ENCRYPTION_INITIAL)) {
MarkForRetransmission(sequence_number, retransmission_type);
+ } else if (it->is_fec_packet) {
+ // Remove FEC packets from the packet map, since we can't retransmit them.
+ unacked_packets_.RemoveFromInFlight(sequence_number);
}
}
}
@@ -549,12 +557,18 @@
}
// Only track packets as in flight that the send algorithm wants us to track.
+ // Since FEC packets should also be counted towards the congestion window,
+ // consider them as retransmittable for the purposes of congestion control.
+ HasRetransmittableData has_congestion_controlled_data =
+ serialized_packet->packet->is_fec_packet() ?
+ HAS_RETRANSMITTABLE_DATA : has_retransmittable_data;
const bool in_flight =
send_algorithm_->OnPacketSent(sent_time,
unacked_packets_.bytes_in_flight(),
sequence_number,
bytes,
- has_retransmittable_data);
+ has_congestion_controlled_data);
+
unacked_packets_.AddSentPacket(*serialized_packet,
original_sequence_number,
transmission_type,
diff --git a/net/quic/quic_sent_packet_manager.h b/net/quic/quic_sent_packet_manager.h
index 2a3ea64..2a94e09 100644
--- a/net/quic/quic_sent_packet_manager.h
+++ b/net/quic/quic_sent_packet_manager.h
@@ -16,6 +16,7 @@
#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/crypto/cached_network_parameters.h"
#include "net/quic/quic_ack_notifier_manager.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_sustained_bandwidth_recorder.h"
@@ -99,6 +100,10 @@
virtual void SetFromConfig(const QuicConfig& config);
+ // Pass the CachedNetworkParameters to the send algorithm.
+ void ResumeConnectionState(
+ const CachedNetworkParameters& cached_network_params);
+
void SetNumOpenStreams(size_t num_streams);
void SetHandshakeConfirmed() { handshake_confirmed_ = true; }
@@ -111,6 +116,13 @@
bool IsUnacked(QuicPacketSequenceNumber sequence_number) const;
// Requests retransmission of all unacked packets of |retransmission_type|.
+ // The behavior of this method depends on the value of |retransmission_type|:
+ // ALL_UNACKED_RETRANSMISSION - All unacked packets will be retransmitted.
+ // This can happen, for example, after a version negotiation packet has been
+ // received and all packets needs to be retransmitted with the new version.
+ // ALL_INITIAL_RETRANSMISSION - Only initially encrypted packets will be
+ // retransmitted. This can happen, for example, when a CHLO has been rejected
+ // and the previously encrypted data needs to be encrypted with a new key.
void RetransmitUnackedPackets(TransmissionType retransmission_type);
// Retransmits the oldest pending packet there is still a tail loss probe
diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc
index d710120..c1e6f20 100644
--- a/net/quic/quic_sent_packet_manager_test.cc
+++ b/net/quic/quic_sent_packet_manager_test.cc
@@ -64,9 +64,7 @@
EXPECT_CALL(*send_algorithm_, InRecovery()).Times(AnyNumber());
}
- virtual ~QuicSentPacketManagerTest() override {
- STLDeleteElements(&packets_);
- }
+ ~QuicSentPacketManagerTest() override { STLDeleteElements(&packets_); }
QuicByteCount BytesInFlight() {
return QuicSentPacketManagerPeer::GetBytesInFlight(&manager_);
@@ -216,7 +214,7 @@
void SendFecPacket(QuicPacketSequenceNumber sequence_number) {
EXPECT_CALL(*send_algorithm_,
OnPacketSent(_, BytesInFlight(), sequence_number,
- kDefaultLength, NO_RETRANSMITTABLE_DATA))
+ kDefaultLength, HAS_RETRANSMITTABLE_DATA))
.Times(1).WillOnce(Return(true));
SerializedPacket packet(CreateFecPacket(sequence_number));
manager_.OnPacketSent(&packet, 0, clock_.Now(),
diff --git a/net/quic/quic_server_session.cc b/net/quic/quic_server_session.cc
index 1d48182..e0defd6 100644
--- a/net/quic/quic_server_session.cc
+++ b/net/quic/quic_server_session.cc
@@ -37,14 +37,29 @@
void QuicServerSession::OnConfigNegotiated() {
QuicSession::OnConfigNegotiated();
- if (!FLAGS_enable_quic_fec ||
- !config()->HasReceivedConnectionOptions() ||
- !ContainsQuicTag(config()->ReceivedConnectionOptions(), kFHDR)) {
+
+ if (!config()->HasReceivedConnectionOptions()) {
return;
}
- // kFHDR config maps to FEC protection always for headers stream.
- // TODO(jri): Add crypto stream in addition to headers for kHDR.
- headers_stream_->set_fec_policy(FEC_PROTECT_ALWAYS);
+
+ // If the client has provided a bandwidth estimate from the same serving
+ // region, then pass it to the sent packet manager in preparation for possible
+ // bandwidth resumption.
+ const CachedNetworkParameters* cached_network_params =
+ crypto_stream_->previous_cached_network_params();
+ if (FLAGS_quic_enable_bandwidth_resumption_experiment &&
+ cached_network_params != nullptr &&
+ ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWRE) &&
+ cached_network_params->serving_region() == serving_region_) {
+ connection()->ResumeConnectionState(*cached_network_params);
+ }
+
+ if (FLAGS_enable_quic_fec &&
+ ContainsQuicTag(config()->ReceivedConnectionOptions(), kFHDR)) {
+ // kFHDR config maps to FEC protection always for headers stream.
+ // TODO(jri): Add crypto stream in addition to headers for kHDR.
+ headers_stream_->set_fec_policy(FEC_PROTECT_ALWAYS);
+ }
}
void QuicServerSession::OnConnectionClosed(QuicErrorCode error,
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index 2318ab4..e4b163f 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -48,8 +48,8 @@
session_->PostProcessAfterData();
}
- void OnWindowUpdateFrames(const vector<QuicWindowUpdateFrame>& frames)
- override {
+ void OnWindowUpdateFrames(
+ const vector<QuicWindowUpdateFrame>& frames) override {
session_->OnWindowUpdateFrames(frames);
session_->PostProcessAfterData();
}
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc
index d14d875..d953678 100644
--- a/net/quic/quic_session_test.cc
+++ b/net/quic/quic_session_test.cc
@@ -54,8 +54,7 @@
: QuicCryptoStream(session) {
}
- virtual void OnHandshakeMessage(
- const CryptoHandshakeMessage& message) override {
+ void OnHandshakeMessage(const CryptoHandshakeMessage& message) override {
encryption_established_ = true;
handshake_confirmed_ = true;
CryptoHandshakeMessage msg;
@@ -94,7 +93,7 @@
using ReliableQuicStream::CloseWriteSide;
- virtual uint32 ProcessData(const char* data, uint32 data_len) override {
+ uint32 ProcessData(const char* data, uint32 data_len) override {
return data_len;
}
@@ -131,17 +130,15 @@
InitializeSession();
}
- virtual TestCryptoStream* GetCryptoStream() override {
- return &crypto_stream_;
- }
+ TestCryptoStream* GetCryptoStream() override { return &crypto_stream_; }
- virtual TestStream* CreateOutgoingDataStream() override {
+ TestStream* CreateOutgoingDataStream() override {
TestStream* stream = new TestStream(GetNextStreamId(), this);
ActivateStream(stream);
return stream;
}
- virtual TestStream* CreateIncomingDataStream(QuicStreamId id) override {
+ TestStream* CreateIncomingDataStream(QuicStreamId id) override {
return new TestStream(id, this);
}
@@ -153,7 +150,7 @@
return QuicSession::GetIncomingDataStream(stream_id);
}
- virtual QuicConsumedData WritevData(
+ QuicConsumedData WritevData(
QuicStreamId id,
const IOVector& data,
QuicStreamOffset offset,
@@ -223,6 +220,7 @@
"Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
"EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
"JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
+ connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
void CheckClosedStreams() {
diff --git a/net/quic/quic_stream_sequencer_test.cc b/net/quic/quic_stream_sequencer_test.cc
index 8c90c9f..43a105b 100644
--- a/net/quic/quic_stream_sequencer_test.cc
+++ b/net/quic/quic_stream_sequencer_test.cc
@@ -44,7 +44,7 @@
const string& details));
MOCK_METHOD1(Reset, void(QuicRstStreamErrorCode error));
MOCK_METHOD0(OnCanWrite, void());
- virtual QuicPriority EffectivePriority() const override {
+ QuicPriority EffectivePriority() const override {
return QuicUtils::HighestPriority();
}
virtual bool IsFlowControlEnabled() const {
diff --git a/net/quic/quic_time.h b/net/quic/quic_time.h
index 53e5ebe..62bf582 100644
--- a/net/quic/quic_time.h
+++ b/net/quic/quic_time.h
@@ -17,6 +17,8 @@
namespace net {
+static const int kNumSecondsPerMinute = 60;
+static const int kNumSecondsPerHour = kNumSecondsPerMinute * 60;
static const uint64 kNumMicrosPerSecond = base::Time::kMicrosecondsPerSecond;
static const uint64 kNumMicrosPerMilli =
base::Time::kMicrosecondsPerMillisecond;
diff --git a/net/quic/quic_unacked_packet_map.cc b/net/quic/quic_unacked_packet_map.cc
index 04eb1b8..bbff3c9 100644
--- a/net/quic/quic_unacked_packet_map.cc
+++ b/net/quic/quic_unacked_packet_map.cc
@@ -53,6 +53,9 @@
packet.sequence_number_length,
transmission_type,
sent_time);
+ DCHECK(packet.packet != nullptr);
+ info.is_fec_packet = packet.packet->is_fec_packet();
+
if (old_sequence_number == 0) {
if (packet.retransmittable_frames != nullptr &&
packet.retransmittable_frames->HasCryptoHandshake() == IS_HANDSHAKE) {
diff --git a/net/quic/quic_unacked_packet_map_test.cc b/net/quic/quic_unacked_packet_map_test.cc
index d31ce44..7840495 100644
--- a/net/quic/quic_unacked_packet_map_test.cc
+++ b/net/quic/quic_unacked_packet_map_test.cc
@@ -8,6 +8,7 @@
#include "testing/gtest/include/gtest/gtest.h"
using std::min;
+using std::vector;
namespace net {
namespace test {
@@ -23,16 +24,26 @@
: now_(QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(1000))) {
}
+ ~QuicUnackedPacketMapTest() override {
+ STLDeleteElements(&packets_);
+ }
+
SerializedPacket CreateRetransmittablePacket(
QuicPacketSequenceNumber sequence_number) {
+ packets_.push_back(QuicPacket::NewDataPacket(
+ nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
+ PACKET_1BYTE_SEQUENCE_NUMBER));
return SerializedPacket(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
- nullptr, 0, new RetransmittableFrames());
+ packets_.back(), 0, new RetransmittableFrames());
}
SerializedPacket CreateNonRetransmittablePacket(
QuicPacketSequenceNumber sequence_number) {
+ packets_.push_back(QuicPacket::NewDataPacket(
+ nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
+ PACKET_1BYTE_SEQUENCE_NUMBER));
return SerializedPacket(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
- nullptr, 0, nullptr);
+ packets_.back(), 0, nullptr);
}
void VerifyInFlightPackets(QuicPacketSequenceNumber* packets,
@@ -94,7 +105,7 @@
<< " packets[" << i << "]:" << packets[i];
}
}
-
+ vector<QuicPacket*> packets_;
QuicUnackedPacketMap unacked_packets_;
QuicTime now_;
};
@@ -185,8 +196,8 @@
unacked_packets_.RemoveFromInFlight(2);
QuicPacketSequenceNumber unacked2[] = { 1 };
- VerifyUnackedPackets(unacked, arraysize(unacked2));
- VerifyInFlightPackets(unacked, arraysize(unacked2));
+ VerifyUnackedPackets(unacked2, arraysize(unacked2));
+ VerifyInFlightPackets(unacked2, arraysize(unacked2));
VerifyRetransmittablePackets(nullptr, 0);
unacked_packets_.RemoveFromInFlight(1);
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index 814be7b..b24316f 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -214,6 +214,8 @@
QuicCryptoServerStream* server,
const FakeClientOptions& options) {
PacketSavingConnection* client_conn = new PacketSavingConnection(false);
+ // Advance the time, because timers do not like uninitialized times.
+ client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1));
TestClientSession client_session(client_conn, DefaultQuicConfig());
QuicCryptoClientConfig crypto_config;
diff --git a/net/quic/test_tools/mock_quic_dispatcher.h b/net/quic/test_tools/mock_quic_dispatcher.h
index f923790..4945724 100644
--- a/net/quic/test_tools/mock_quic_dispatcher.h
+++ b/net/quic/test_tools/mock_quic_dispatcher.h
@@ -22,7 +22,7 @@
PacketWriterFactory* packet_writer_factory,
QuicConnectionHelperInterface* helper);
- virtual ~MockQuicDispatcher();
+ ~MockQuicDispatcher() override;
MOCK_METHOD3(ProcessPacket, void(const IPEndPoint& server_address,
const IPEndPoint& client_address,
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index fa987de..9df03eb 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -10,6 +10,7 @@
#include <string>
#include <vector>
+#include "base/basictypes.h"
#include "base/strings/string_piece.h"
#include "net/quic/congestion_control/loss_detection_interface.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
@@ -31,7 +32,7 @@
namespace test {
static const QuicConnectionId kTestConnectionId = 42;
-static const int kTestPort = 123;
+static const uint16 kTestPort = 123;
static const uint32 kInitialStreamFlowControlWindowForTest =
32 * 1024; // 32 KB
static const uint32 kInitialSessionFlowControlWindowForTest =
@@ -150,7 +151,7 @@
class MockFramerVisitor : public QuicFramerVisitorInterface {
public:
MockFramerVisitor();
- virtual ~MockFramerVisitor();
+ ~MockFramerVisitor() override;
MOCK_METHOD1(OnError, void(QuicFramer* framer));
// The constructor sets this up to return false by default.
@@ -225,7 +226,7 @@
class MockConnectionVisitor : public QuicConnectionVisitorInterface {
public:
MockConnectionVisitor();
- virtual ~MockConnectionVisitor();
+ ~MockConnectionVisitor() override;
MOCK_METHOD1(OnStreamFrames, void(const std::vector<QuicStreamFrame>& frame));
MOCK_METHOD1(OnWindowUpdateFrames,
@@ -293,7 +294,7 @@
// Uses a Mock helper, ConnectionId of 42, and 127.0.0.1:123.
MockConnection(bool is_server, const QuicVersionVector& supported_versions);
- virtual ~MockConnection();
+ ~MockConnection() override;
// If the constructor that uses a MockHelper has been used then this method
// will advance the time of the MockClock.
@@ -324,7 +325,7 @@
QuicConnection::ProcessUdpPacket(self_address, peer_address, packet);
}
- virtual bool OnProtocolVersionMismatch(QuicVersion version) override {
+ bool OnProtocolVersionMismatch(QuicVersion version) override {
return false;
}
@@ -355,7 +356,7 @@
class MockSession : public QuicSession {
public:
explicit MockSession(QuicConnection* connection);
- virtual ~MockSession();
+ ~MockSession() override;
MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
MOCK_METHOD0(GetCryptoStream, QuicCryptoStream*());
@@ -388,14 +389,14 @@
class TestSession : public QuicSession {
public:
TestSession(QuicConnection* connection, const QuicConfig& config);
- virtual ~TestSession();
+ ~TestSession() override;
MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*());
void SetCryptoStream(QuicCryptoStream* stream);
- virtual QuicCryptoStream* GetCryptoStream() override;
+ QuicCryptoStream* GetCryptoStream() override;
private:
QuicCryptoStream* crypto_stream_;
@@ -406,7 +407,7 @@
class TestClientSession : public QuicClientSessionBase {
public:
TestClientSession(QuicConnection* connection, const QuicConfig& config);
- virtual ~TestClientSession();
+ ~TestClientSession() override;
// QuicClientSessionBase
MOCK_METHOD1(OnProofValid,
@@ -420,7 +421,7 @@
void SetCryptoStream(QuicCryptoStream* stream);
- virtual QuicCryptoStream* GetCryptoStream() override;
+ QuicCryptoStream* GetCryptoStream() override;
private:
QuicCryptoStream* crypto_stream_;
@@ -431,7 +432,7 @@
class MockPacketWriter : public QuicPacketWriter {
public:
MockPacketWriter();
- virtual ~MockPacketWriter();
+ ~MockPacketWriter() override;
MOCK_METHOD4(WritePacket,
WriteResult(const char* buffer,
@@ -449,7 +450,7 @@
class MockSendAlgorithm : public SendAlgorithmInterface {
public:
MockSendAlgorithm();
- virtual ~MockSendAlgorithm();
+ ~MockSendAlgorithm() override;
MOCK_METHOD3(SetFromConfig, void(const QuicConfig& config,
bool is_server,
@@ -482,6 +483,7 @@
MOCK_CONST_METHOD0(InRecovery, bool());
MOCK_CONST_METHOD0(GetSlowStartThreshold, QuicByteCount());
MOCK_CONST_METHOD0(GetCongestionControlType, CongestionControlType());
+ MOCK_METHOD1(ResumeConnectionState, void(const CachedNetworkParameters&));
private:
DISALLOW_COPY_AND_ASSIGN(MockSendAlgorithm);
@@ -490,7 +492,7 @@
class MockLossAlgorithm : public LossDetectionInterface {
public:
MockLossAlgorithm();
- virtual ~MockLossAlgorithm();
+ ~MockLossAlgorithm() override;
MOCK_CONST_METHOD0(GetLossDetectionType, LossDetectionType());
MOCK_METHOD4(DetectLostPackets,
@@ -520,7 +522,7 @@
class MockEntropyCalculator : public TestEntropyCalculator {
public:
MockEntropyCalculator();
- virtual ~MockEntropyCalculator();
+ ~MockEntropyCalculator() override;
MOCK_CONST_METHOD1(
EntropyHash,
@@ -542,7 +544,7 @@
protected:
// Object is ref counted.
- virtual ~MockAckNotifierDelegate();
+ ~MockAckNotifierDelegate() override;
private:
DISALLOW_COPY_AND_ASSIGN(MockAckNotifierDelegate);
@@ -552,7 +554,7 @@
public QuicSentPacketManager::NetworkChangeVisitor {
public:
MockNetworkChangeVisitor();
- virtual ~MockNetworkChangeVisitor();
+ ~MockNetworkChangeVisitor() override;
MOCK_METHOD0(OnCongestionWindowChange, void());