summaryrefslogtreecommitdiffstats
path: root/net/quic
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-16 15:58:14 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-16 15:58:14 +0000
commit9f0dcd4e2bff29c194036a4fad568d6c71f31000 (patch)
treec8ff26dc0c2be5a17e92d34aec6bac3220459572 /net/quic
parent4be22f47f675ac89d6aafcbc88f9d391d9a82e03 (diff)
downloadchromium_src-9f0dcd4e2bff29c194036a4fad568d6c71f31000.zip
chromium_src-9f0dcd4e2bff29c194036a4fad568d6c71f31000.tar.gz
chromium_src-9f0dcd4e2bff29c194036a4fad568d6c71f31000.tar.bz2
Land Recent QUIC Changes.
Eliminate separate boolean tracking socket writeability in QuicConnection; query the writer instead. This CL tries to minimize behavior changes, so no actual bugfixes. Connection will now check writer's status instead of its local flag, so it will refuse to write sooner. Merge internal change: 59603011 https://codereview.chromium.org/138843003/ Change QUIC's SendAlgorithmInterface to have a separate UpdateRtt method instead of passing it in with every acked packet. This fixes a bug where the RTT was not being updated when retransmitted packets were acked and one where a very large RTT could be used when packets are acked before being sent. Merge internal change: 59572874 https://codereview.chromium.org/138843003/ Break out of the loop in QuicSession::OnCanWrite if the QuicConnection is congestion control blocked. This fixes a weird form of starvation among same-priority streams caused by streams often ending up in the same order in the WriteBlockedList before and after QuicSession::OnCanWrite. Stop iterating through QUIC write blocked streams if the connection is congestion-control blocked to avoid starvation of same-priority streams. Not flag protected. Merge internal change: 59513911 https://codereview.chromium.org/139103002/ Fix a bug where the packet was put into unacked packets when it was serialized and acked before being sent. This was only ever seen on Chrome with very short RTTs. Merge internal change: 59408566 https://codereview.chromium.org/133683010/ WriteBlockedList for QUIC that prioritizes Crypto and Headers streams over data streams. Not flag protected. Merge internal change: 59400238 https://codereview.chromium.org/137893008/ Create an interface for explicit notification of Dispatcher about blocked writers; port TimeWaitListManager to the new interface. Merge internal change: 59396227 https://codereview.chromium.org/138503006/ Remove WritePacket() from internal server's QuicDispatcher; Integrating internal changes to clean up QuicDispatcher. Merge internal change: 59346874 https://codereview.chromium.org/131743007/ Reset QUIC's retransmission counters whenever a new packet is acked which updates the RTT estimate. Previously the counters were only done when the left edge was acked, which could cause excessive backoff when the connection was making progress. Merge internal change: 59292726 https://codereview.chromium.org/138273004/ Implement QuicPacketWriterWrapper. This lets us replace or embellish the low-level writer without disturbing connections that keep a pointer to the top level. Merge internal change: 59287995 https://codereview.chromium.org/138273004/ Use basictypes.h consistenly in QUIC code instead of macros.h and/or integral_types.h Simply refactoring includes. Sync'ed with internal source code for include of basictypes.h. Merge internal change: 59287325 https://codereview.chromium.org/136853005/ Use the right priority when marking QUIC streams write blocked via QuicFdWrapper::SetReady. Not flag protected. Used NULL instead of nullptr. Fixed QuicReliableClientStreamTests to pass. Activated the QuicReliableClientStream in the QuicSession so that session's MarkWriteBlocked knows about the stream. Merge internal change: 59263642 https://codereview.chromium.org/136523005/ R=rch@chromium.org Review URL: https://codereview.chromium.org/131743009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245204 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/quic')
-rw-r--r--net/quic/congestion_control/fix_rate_sender.cc19
-rw-r--r--net/quic/congestion_control/fix_rate_sender.h4
-rw-r--r--net/quic/congestion_control/fix_rate_test.cc14
-rw-r--r--net/quic/congestion_control/inter_arrival_sender.cc37
-rw-r--r--net/quic/congestion_control/inter_arrival_sender.h4
-rw-r--r--net/quic/congestion_control/inter_arrival_sender_test.cc11
-rw-r--r--net/quic/congestion_control/pacing_sender.cc9
-rw-r--r--net/quic/congestion_control/pacing_sender.h4
-rw-r--r--net/quic/congestion_control/send_algorithm_interface.h6
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender.cc7
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender.h5
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender_test.cc20
-rw-r--r--net/quic/crypto/crypto_server_test.cc1
-rw-r--r--net/quic/crypto/curve25519_key_exchange.cc1
-rw-r--r--net/quic/crypto/local_strike_register_client.h1
-rw-r--r--net/quic/crypto/strike_register_client.h1
-rw-r--r--net/quic/quic_client_session.h2
-rw-r--r--net/quic/quic_connection.cc122
-rw-r--r--net/quic/quic_connection.h31
-rw-r--r--net/quic/quic_connection_helper.h1
-rw-r--r--net/quic/quic_connection_test.cc234
-rw-r--r--net/quic/quic_crypto_stream.h1
-rw-r--r--net/quic/quic_data_stream.cc2
-rw-r--r--net/quic/quic_data_stream.h2
-rw-r--r--net/quic/quic_data_stream_test.cc3
-rw-r--r--net/quic/quic_fec_group.cc1
-rw-r--r--net/quic/quic_fec_group_test.cc1
-rw-r--r--net/quic/quic_framer_test.cc3
-rw-r--r--net/quic/quic_http_stream_test.cc8
-rw-r--r--net/quic/quic_packet_creator.cc1
-rw-r--r--net/quic/quic_packet_generator.cc1
-rw-r--r--net/quic/quic_packet_writer.h4
-rw-r--r--net/quic/quic_reliable_client_stream.cc4
-rw-r--r--net/quic/quic_reliable_client_stream_test.cc44
-rw-r--r--net/quic/quic_sent_packet_manager.cc51
-rw-r--r--net/quic/quic_sent_packet_manager_test.cc92
-rw-r--r--net/quic/quic_session.cc31
-rw-r--r--net/quic/quic_session.h8
-rw-r--r--net/quic/quic_session_test.cc77
-rw-r--r--net/quic/quic_stream_sequencer_test.cc1
-rw-r--r--net/quic/quic_utils.cc7
-rw-r--r--net/quic/quic_write_blocked_list.cc21
-rw-r--r--net/quic/quic_write_blocked_list.h90
-rw-r--r--net/quic/quic_write_blocked_list_test.cc106
-rw-r--r--net/quic/reliable_quic_stream.cc2
-rw-r--r--net/quic/reliable_quic_stream.h1
-rw-r--r--net/quic/reliable_quic_stream_test.cc3
-rw-r--r--net/quic/test_tools/crypto_test_utils.h1
-rw-r--r--net/quic/test_tools/quic_connection_peer.cc20
-rw-r--r--net/quic/test_tools/quic_connection_peer.h13
-rw-r--r--net/quic/test_tools/quic_data_stream_peer.h1
-rw-r--r--net/quic/test_tools/quic_session_peer.cc2
-rw-r--r--net/quic/test_tools/quic_session_peer.h5
-rw-r--r--net/quic/test_tools/quic_test_utils.h8
-rw-r--r--net/quic/test_tools/quic_test_writer.cc31
-rw-r--r--net/quic/test_tools/quic_test_writer.h37
-rw-r--r--net/quic/test_tools/simple_quic_framer.h1
57 files changed, 788 insertions, 430 deletions
diff --git a/net/quic/congestion_control/fix_rate_sender.cc b/net/quic/congestion_control/fix_rate_sender.cc
index e9c219bd..9e198e9 100644
--- a/net/quic/congestion_control/fix_rate_sender.cc
+++ b/net/quic/congestion_control/fix_rate_sender.cc
@@ -58,16 +58,8 @@ void FixRateSender::OnIncomingQuicCongestionFeedbackFrame(
void FixRateSender::OnPacketAcked(
QuicPacketSequenceNumber /*acked_sequence_number*/,
- QuicByteCount bytes_acked,
- QuicTime::Delta rtt) {
- // RTT can't be negative.
- DCHECK_LE(0, rtt.ToMicroseconds());
-
+ QuicByteCount bytes_acked) {
data_in_flight_ -= bytes_acked;
- if (rtt.IsInfinite()) {
- return;
- }
- latest_rtt_ = rtt;
}
void FixRateSender::OnPacketLost(QuicPacketSequenceNumber /*sequence_number*/,
@@ -127,6 +119,15 @@ QuicBandwidth FixRateSender::BandwidthEstimate() const {
return bitrate_;
}
+void FixRateSender::UpdateRtt(QuicTime::Delta rtt_sample) {
+ // RTT can't be negative.
+ DCHECK_LE(0, rtt_sample.ToMicroseconds());
+ if (rtt_sample.IsInfinite()) {
+ return;
+ }
+ latest_rtt_ = rtt_sample;
+}
+
QuicTime::Delta FixRateSender::SmoothedRtt() const {
// TODO(satyamshekhar): Calculate and return smoothed rtt.
return latest_rtt_;
diff --git a/net/quic/congestion_control/fix_rate_sender.h b/net/quic/congestion_control/fix_rate_sender.h
index 0ce8016..688cf3a 100644
--- a/net/quic/congestion_control/fix_rate_sender.h
+++ b/net/quic/congestion_control/fix_rate_sender.h
@@ -31,8 +31,7 @@ class NET_EXPORT_PRIVATE FixRateSender : public SendAlgorithmInterface {
QuicTime feedback_receive_time,
const SentPacketsMap& sent_packets) OVERRIDE;
virtual void OnPacketAcked(QuicPacketSequenceNumber acked_sequence_number,
- QuicByteCount acked_bytes,
- QuicTime::Delta rtt) OVERRIDE;
+ QuicByteCount acked_bytes) OVERRIDE;
virtual void OnPacketLost(QuicPacketSequenceNumber sequence_number,
QuicTime ack_receive_time) OVERRIDE;
virtual bool OnPacketSent(
@@ -50,6 +49,7 @@ class NET_EXPORT_PRIVATE FixRateSender : public SendAlgorithmInterface {
HasRetransmittableData has_retransmittable_data,
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;
diff --git a/net/quic/congestion_control/fix_rate_test.cc b/net/quic/congestion_control/fix_rate_test.cc
index 752d37f..70cbb96 100644
--- a/net/quic/congestion_control/fix_rate_test.cc
+++ b/net/quic/congestion_control/fix_rate_test.cc
@@ -29,14 +29,12 @@ class FixRateReceiverPeer : public FixRateReceiver {
class FixRateTest : public ::testing::Test {
protected:
FixRateTest()
- : rtt_(QuicTime::Delta::FromMilliseconds(30)),
- sender_(new FixRateSender(&clock_)),
+ : sender_(new FixRateSender(&clock_)),
receiver_(new FixRateReceiverPeer()),
start_(clock_.Now()) {
// Make sure clock does not start at 0.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2));
}
- const QuicTime::Delta rtt_;
MockClock clock_;
SendAlgorithmInterface::SentPacketsMap unused_packet_map_;
scoped_ptr<FixRateSender> sender_;
@@ -78,9 +76,9 @@ TEST_F(FixRateTest, SenderAPI) {
EXPECT_EQ(QuicTime::Delta::Infinite(), sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE));
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
- sender_->OnPacketAcked(1, kDefaultMaxPacketSize, rtt_);
- sender_->OnPacketAcked(2, kDefaultMaxPacketSize, rtt_);
- sender_->OnPacketAcked(3, 600, rtt_);
+ sender_->OnPacketAcked(1, kDefaultMaxPacketSize);
+ sender_->OnPacketAcked(2, kDefaultMaxPacketSize);
+ sender_->OnPacketAcked(3, 600);
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
}
@@ -110,8 +108,8 @@ TEST_F(FixRateTest, FixRatePacing) {
QuicTime::Delta advance_time = sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE);
clock_.AdvanceTime(advance_time);
- sender_->OnPacketAcked(sequence_number - 1, packet_size, rtt_);
- sender_->OnPacketAcked(sequence_number - 2, packet_size, rtt_);
+ sender_->OnPacketAcked(sequence_number - 1, packet_size);
+ sender_->OnPacketAcked(sequence_number - 2, packet_size);
acc_advance_time = acc_advance_time.Add(advance_time);
}
EXPECT_EQ(num_packets * packet_size * 1000000 / bitrate.ToBytesPerSecond(),
diff --git a/net/quic/congestion_control/inter_arrival_sender.cc b/net/quic/congestion_control/inter_arrival_sender.cc
index 1b86b63..b0698ac 100644
--- a/net/quic/congestion_control/inter_arrival_sender.cc
+++ b/net/quic/congestion_control/inter_arrival_sender.cc
@@ -216,27 +216,10 @@ bool InterArrivalSender::ProbingPhase(QuicTime feedback_receive_time) {
void InterArrivalSender::OnPacketAcked(
QuicPacketSequenceNumber /*acked_sequence_number*/,
- QuicByteCount acked_bytes,
- QuicTime::Delta rtt) {
- // RTT can't be negative.
- DCHECK_LE(0, rtt.ToMicroseconds());
-
+ QuicByteCount acked_bytes) {
if (probing_) {
probe_->OnAcknowledgedPacket(acked_bytes);
}
-
- 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_);
}
void InterArrivalSender::OnPacketLost(
@@ -337,6 +320,24 @@ QuicBandwidth InterArrivalSender::BandwidthEstimate() const {
return current_bandwidth_;
}
+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);
diff --git a/net/quic/congestion_control/inter_arrival_sender.h b/net/quic/congestion_control/inter_arrival_sender.h
index ac1c262..7760cef 100644
--- a/net/quic/congestion_control/inter_arrival_sender.h
+++ b/net/quic/congestion_control/inter_arrival_sender.h
@@ -39,8 +39,7 @@ class NET_EXPORT_PRIVATE InterArrivalSender : public SendAlgorithmInterface {
QuicTime feedback_receive_time,
const SentPacketsMap& sent_packets) OVERRIDE;
virtual void OnPacketAcked(QuicPacketSequenceNumber acked_sequence_number,
- QuicByteCount acked_bytes,
- QuicTime::Delta rtt) OVERRIDE;
+ QuicByteCount acked_bytes) OVERRIDE;
virtual void OnPacketLost(QuicPacketSequenceNumber sequence_number,
QuicTime ack_receive_time) OVERRIDE;
virtual bool OnPacketSent(
@@ -58,6 +57,7 @@ class NET_EXPORT_PRIVATE InterArrivalSender : public SendAlgorithmInterface {
HasRetransmittableData has_retransmittable_data,
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;
diff --git a/net/quic/congestion_control/inter_arrival_sender_test.cc b/net/quic/congestion_control/inter_arrival_sender_test.cc
index ff83b48..61655dd 100644
--- a/net/quic/congestion_control/inter_arrival_sender_test.cc
+++ b/net/quic/congestion_control/inter_arrival_sender_test.cc
@@ -18,8 +18,7 @@ namespace test {
class InterArrivalSenderTest : public ::testing::Test {
protected:
InterArrivalSenderTest()
- : rtt_(QuicTime::Delta::FromMilliseconds(60)),
- one_ms_(QuicTime::Delta::FromMilliseconds(1)),
+ : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
one_s_(QuicTime::Delta::FromMilliseconds(1000)),
nine_ms_(QuicTime::Delta::FromMilliseconds(9)),
send_start_time_(send_clock_.Now()),
@@ -54,7 +53,7 @@ class InterArrivalSenderTest : public ::testing::Test {
void AckNPackets(int n) {
for (int i = 0; i < n; ++i) {
sender_.OnPacketAcked(
- acked_sequence_number_++, kDefaultMaxPacketSize, rtt_);
+ acked_sequence_number_++, kDefaultMaxPacketSize);
}
}
@@ -106,7 +105,6 @@ class InterArrivalSenderTest : public ::testing::Test {
return send_clock_.ApproximateNow().Subtract(send_start_time_);
}
- const QuicTime::Delta rtt_;
const QuicTime::Delta one_ms_;
const QuicTime::Delta one_s_;
const QuicTime::Delta nine_ms_;
@@ -504,6 +502,7 @@ TEST_F(InterArrivalSenderTest, MinBitrateDueToDelay) {
}
TEST_F(InterArrivalSenderTest, MinBitrateDueToLoss) {
+ sender_.UpdateRtt(QuicTime::Delta::FromMilliseconds(60));
QuicBandwidth expected_min_bitrate = QuicBandwidth::FromKBitsPerSecond(10);
QuicCongestionFeedbackFrame feedback;
// At startup make sure we can send.
@@ -541,7 +540,7 @@ TEST_F(InterArrivalSenderTest, MinBitrateDueToLoss) {
EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
sender_.OnPacketLost(acked_sequence_number_ - 1, send_clock_.Now());
- sender_.OnPacketAcked(acked_sequence_number_, kDefaultMaxPacketSize, rtt_);
+ sender_.OnPacketAcked(acked_sequence_number_, kDefaultMaxPacketSize);
acked_sequence_number_ += 2; // Create a loss by not acking both packets.
SendFeedbackMessageNPackets(2, nine_ms_, nine_ms_);
}
@@ -556,7 +555,7 @@ TEST_F(InterArrivalSenderTest, MinBitrateDueToLoss) {
EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
sender_.OnPacketLost(acked_sequence_number_ - 1, send_clock_.Now());
- sender_.OnPacketAcked(acked_sequence_number_, kDefaultMaxPacketSize, rtt_);
+ sender_.OnPacketAcked(acked_sequence_number_, kDefaultMaxPacketSize);
acked_sequence_number_ += 2; // Create a loss by not acking both packets.
SendFeedbackMessageNPackets(2, nine_ms_, nine_ms_);
diff --git a/net/quic/congestion_control/pacing_sender.cc b/net/quic/congestion_control/pacing_sender.cc
index cbd2d12..8d346ab 100644
--- a/net/quic/congestion_control/pacing_sender.cc
+++ b/net/quic/congestion_control/pacing_sender.cc
@@ -36,9 +36,8 @@ void PacingSender::OnIncomingQuicCongestionFeedbackFrame(
void PacingSender::OnPacketAcked(
QuicPacketSequenceNumber acked_sequence_number,
- QuicByteCount acked_bytes,
- QuicTime::Delta rtt) {
- sender_->OnPacketAcked(acked_sequence_number, acked_bytes, rtt);
+ QuicByteCount acked_bytes) {
+ sender_->OnPacketAcked(acked_sequence_number, acked_bytes);
}
void PacingSender::OnPacketLost(QuicPacketSequenceNumber sequence_number,
@@ -123,6 +122,10 @@ QuicBandwidth PacingSender::BandwidthEstimate() const {
return sender_->BandwidthEstimate();
}
+void PacingSender::UpdateRtt(QuicTime::Delta rtt_sample) {
+ sender_->UpdateRtt(rtt_sample);
+}
+
QuicTime::Delta PacingSender::SmoothedRtt() const {
return sender_->SmoothedRtt();
}
diff --git a/net/quic/congestion_control/pacing_sender.h b/net/quic/congestion_control/pacing_sender.h
index 621c7c6..c8ffe0b 100644
--- a/net/quic/congestion_control/pacing_sender.h
+++ b/net/quic/congestion_control/pacing_sender.h
@@ -37,8 +37,7 @@ class NET_EXPORT_PRIVATE PacingSender : public SendAlgorithmInterface {
QuicTime feedback_receive_time,
const SendAlgorithmInterface::SentPacketsMap& sent_packets) OVERRIDE;
virtual void OnPacketAcked(QuicPacketSequenceNumber acked_sequence_number,
- QuicByteCount acked_bytes,
- QuicTime::Delta rtt) OVERRIDE;
+ QuicByteCount acked_bytes) OVERRIDE;
virtual void OnPacketLost(QuicPacketSequenceNumber sequence_number,
QuicTime ack_receive_time) OVERRIDE;
virtual bool OnPacketSent(QuicTime sent_time,
@@ -55,6 +54,7 @@ class NET_EXPORT_PRIVATE PacingSender : public SendAlgorithmInterface {
HasRetransmittableData has_retransmittable_data,
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;
diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h
index 35460da..df63bba 100644
--- a/net/quic/congestion_control/send_algorithm_interface.h
+++ b/net/quic/congestion_control/send_algorithm_interface.h
@@ -63,8 +63,7 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
// Called for each received ACK, with sequence number from remote peer.
virtual void OnPacketAcked(QuicPacketSequenceNumber acked_sequence_number,
- QuicByteCount acked_bytes,
- QuicTime::Delta rtt) = 0;
+ QuicByteCount acked_bytes) = 0;
// Indicates a loss event of one packet. |sequence_number| is the
// sequence number of the lost packet.
@@ -101,6 +100,9 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
// Returns 0 when it does not have an estimate.
virtual QuicBandwidth BandwidthEstimate() const = 0;
+ // Updates the smoothed RTT based on a new sample.
+ virtual void UpdateRtt(QuicTime::Delta rtt_sample) = 0;
+
// TODO(satyamshekhar): Monitor MinRtt.
virtual QuicTime::Delta SmoothedRtt() const = 0;
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc
index 1c4a655..5e6e3e3 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -89,15 +89,12 @@ void TcpCubicSender::OnIncomingQuicCongestionFeedbackFrame(
}
void TcpCubicSender::OnPacketAcked(
- QuicPacketSequenceNumber acked_sequence_number,
- QuicByteCount acked_bytes,
- QuicTime::Delta rtt) {
+ QuicPacketSequenceNumber acked_sequence_number, QuicByteCount acked_bytes) {
DCHECK_GE(bytes_in_flight_, acked_bytes);
bytes_in_flight_ -= acked_bytes;
largest_acked_sequence_number_ = max(acked_sequence_number,
largest_acked_sequence_number_);
CongestionAvoidance(acked_sequence_number);
- AckAccounting(rtt);
if (end_sequence_number_ == acked_sequence_number) {
DVLOG(1) << "Start update end sequence number @" << acked_sequence_number;
update_end_sequence_number_ = true;
@@ -286,7 +283,7 @@ void TcpCubicSender::OnRetransmissionTimeout(bool packets_retransmitted) {
}
}
-void TcpCubicSender::AckAccounting(QuicTime::Delta rtt) {
+void TcpCubicSender::UpdateRtt(QuicTime::Delta rtt) {
if (rtt.IsInfinite() || rtt.IsZero()) {
DVLOG(1) << "Ignoring rtt, because it's "
<< (rtt.IsZero() ? "Zero" : "Infinite");
diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h
index fcb370d..0554428 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.h
+++ b/net/quic/congestion_control/tcp_cubic_sender.h
@@ -43,8 +43,7 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
QuicTime feedback_receive_time,
const SentPacketsMap& sent_packets) OVERRIDE;
virtual void OnPacketAcked(QuicPacketSequenceNumber acked_sequence_number,
- QuicByteCount acked_bytes,
- QuicTime::Delta rtt) OVERRIDE;
+ QuicByteCount acked_bytes) OVERRIDE;
virtual void OnPacketLost(QuicPacketSequenceNumber largest_loss,
QuicTime ack_receive_time) OVERRIDE;
virtual bool OnPacketSent(QuicTime sent_time,
@@ -61,6 +60,7 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
HasRetransmittableData has_retransmittable_data,
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;
@@ -72,7 +72,6 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
QuicByteCount AvailableSendWindow();
QuicByteCount SendWindow();
void Reset();
- void AckAccounting(QuicTime::Delta rtt);
void CongestionAvoidance(QuicPacketSequenceNumber ack);
bool IsCwndLimited() const;
void OnTimeOut();
diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc
index c76040a..f17dda7 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -35,14 +35,12 @@ class TcpCubicSenderPeer : public TcpCubicSender {
using TcpCubicSender::AvailableSendWindow;
using TcpCubicSender::SendWindow;
- using TcpCubicSender::AckAccounting;
};
class TcpCubicSenderTest : public ::testing::Test {
protected:
TcpCubicSenderTest()
- : rtt_(QuicTime::Delta::FromMilliseconds(60)),
- one_ms_(QuicTime::Delta::FromMilliseconds(1)),
+ : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
sender_(new TcpCubicSenderPeer(&clock_, true,
kDefaultMaxCongestionWindowTCP)),
receiver_(new TcpReceiver()),
@@ -67,12 +65,12 @@ class TcpCubicSenderTest : public ::testing::Test {
void AckNPackets(int n) {
for (int i = 0; i < n; ++i) {
acked_sequence_number_++;
- sender_->OnPacketAcked(acked_sequence_number_, kDefaultTCPMSS, rtt_);
+ sender_->UpdateRtt(QuicTime::Delta::FromMilliseconds(60));
+ sender_->OnPacketAcked(acked_sequence_number_, kDefaultTCPMSS);
}
clock_.AdvanceTime(one_ms_); // 1 millisecond.
}
- const QuicTime::Delta rtt_;
const QuicTime::Delta one_ms_;
MockClock clock_;
SendAlgorithmInterface::SentPacketsMap not_used_;
@@ -158,12 +156,8 @@ TEST_F(TcpCubicSenderTest, SlowStartAckTrain) {
kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAck);
EXPECT_EQ(expected_send_window, sender_->SendWindow());
EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
- // We should now have fallen out of slow start.
- SendAvailableSendWindow();
- AckNPackets(2);
- expected_send_window += kDefaultTCPMSS;
- EXPECT_EQ(expected_send_window, sender_->SendWindow());
+ // We should now have fallen out of slow start.
// Testing Reno phase.
// We should need 141(65*2+1+10) ACK:ed packets before increasing window by
// one.
@@ -261,7 +255,7 @@ TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
const int64 kDeviationMs = 3;
EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay());
- sender_->AckAccounting(QuicTime::Delta::FromMilliseconds(kRttMs));
+ sender_->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
@@ -272,9 +266,9 @@ TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
for (int i = 0; i < 100; ++i) {
// Run to make sure that we converge.
- sender_->AckAccounting(
+ sender_->UpdateRtt(
QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs));
- sender_->AckAccounting(
+ sender_->UpdateRtt(
QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs));
}
expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4);
diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc
index 07c3ea4..1d32093 100644
--- a/net/quic/crypto/crypto_server_test.cc
+++ b/net/quic/crypto/crypto_server_test.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/basictypes.h"
#include "base/strings/string_number_conversions.h"
#include "crypto/secure_hash.h"
#include "net/quic/crypto/crypto_utils.h"
diff --git a/net/quic/crypto/curve25519_key_exchange.cc b/net/quic/crypto/curve25519_key_exchange.cc
index 3b888045..8ed95aa 100644
--- a/net/quic/crypto/curve25519_key_exchange.cc
+++ b/net/quic/crypto/curve25519_key_exchange.cc
@@ -4,6 +4,7 @@
#include "net/quic/crypto/curve25519_key_exchange.h"
+#include "base/basictypes.h"
#include "base/logging.h"
#include "crypto/curve25519.h"
#include "net/quic/crypto/quic_random.h"
diff --git a/net/quic/crypto/local_strike_register_client.h b/net/quic/crypto/local_strike_register_client.h
index abd610b..fe8ae93 100644
--- a/net/quic/crypto/local_strike_register_client.h
+++ b/net/quic/crypto/local_strike_register_client.h
@@ -5,6 +5,7 @@
#ifndef NET_QUIC_CRYPTO_LOCAL_STRIKE_REGISTER_CLIENT_H_
#define NET_QUIC_CRYPTO_LOCAL_STRIKE_REGISTER_CLIENT_H_
+#include "base/basictypes.h"
#include "base/strings/string_piece.h"
#include "base/synchronization/lock.h"
#include "net/base/net_export.h"
diff --git a/net/quic/crypto/strike_register_client.h b/net/quic/crypto/strike_register_client.h
index 3555e85..e37827a 100644
--- a/net/quic/crypto/strike_register_client.h
+++ b/net/quic/crypto/strike_register_client.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/basictypes.h"
#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
#include "net/quic/quic_time.h"
diff --git a/net/quic/quic_client_session.h b/net/quic/quic_client_session.h
index 943c206..ebc7092 100644
--- a/net/quic/quic_client_session.h
+++ b/net/quic/quic_client_session.h
@@ -12,12 +12,14 @@
#include <string>
+#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/completion_callback.h"
#include "net/proxy/proxy_server.h"
#include "net/quic/quic_connection_logger.h"
#include "net/quic/quic_crypto_client_stream.h"
+#include "net/quic/quic_protocol.h"
#include "net/quic/quic_reliable_client_stream.h"
#include "net/quic/quic_session.h"
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 51991be..479373e 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -166,7 +166,6 @@ QuicConnection::QuicConnection(QuicGuid guid,
peer_address_(address),
largest_seen_packet_with_ack_(0),
pending_version_negotiation_packet_(false),
- write_blocked_(false),
received_packet_manager_(kTCP),
ack_alarm_(helper->CreateAlarm(new AckAlarm(this))),
retransmission_alarm_(helper->CreateAlarm(new RetransmissionAlarm(this))),
@@ -772,9 +771,6 @@ void QuicConnection::SendVersionNegotiationPacket() {
WriteResult result =
writer_->WritePacket(version_packet->data(), version_packet->length(),
self_address().address(), peer_address(), this);
- if (result.status == WRITE_STATUS_BLOCKED) {
- write_blocked_ = true;
- }
if (result.status == WRITE_STATUS_OK ||
(result.status == WRITE_STATUS_BLOCKED &&
writer_->IsWriteBlockedDataBuffered())) {
@@ -881,21 +877,9 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
}
bool QuicConnection::OnCanWrite() {
- write_blocked_ = false;
- return DoWrite();
-}
-
-bool QuicConnection::WriteIfNotBlocked() {
- if (write_blocked_) {
- return false;
- }
- return DoWrite();
-}
+ DCHECK(!writer_->IsWriteBlocked());
-bool QuicConnection::DoWrite() {
- DCHECK(!write_blocked_);
WriteQueuedPackets();
-
WritePendingRetransmissions();
IsHandshake pending_handshake = visitor_->HasPendingHandshake() ?
@@ -925,7 +909,13 @@ bool QuicConnection::DoWrite() {
}
}
- return !write_blocked_;
+ return !writer_->IsWriteBlocked();
+}
+
+void QuicConnection::WriteIfNotBlocked() {
+ if (!writer_->IsWriteBlocked()) {
+ OnCanWrite();
+ }
}
bool QuicConnection::ProcessValidatedPacket() {
@@ -946,15 +936,16 @@ bool QuicConnection::ProcessValidatedPacket() {
return true;
}
-bool QuicConnection::WriteQueuedPackets() {
- DCHECK(!write_blocked_);
+void QuicConnection::WriteQueuedPackets() {
+ DCHECK(!writer_->IsWriteBlocked());
if (pending_version_negotiation_packet_) {
SendVersionNegotiationPacket();
}
QueuedPacketList::iterator packet_iterator = queued_packets_.begin();
- while (!write_blocked_ && packet_iterator != queued_packets_.end()) {
+ while (!writer_->IsWriteBlocked() &&
+ packet_iterator != queued_packets_.end()) {
if (WritePacket(packet_iterator->encryption_level,
packet_iterator->sequence_number,
packet_iterator->packet,
@@ -962,15 +953,14 @@ bool QuicConnection::WriteQueuedPackets() {
packet_iterator->retransmittable,
packet_iterator->handshake,
packet_iterator->forced)) {
+ delete packet_iterator->packet;
packet_iterator = queued_packets_.erase(packet_iterator);
} else {
// Continue, because some queued packets may still be writable.
- // This can happen if a retransmit send fail.
+ // This can happen if a retransmit send fails.
++packet_iterator;
}
}
-
- return !write_blocked_;
}
void QuicConnection::WritePendingRetransmissions() {
@@ -1035,7 +1025,7 @@ bool QuicConnection::ShouldGeneratePacket(
bool QuicConnection::CanWrite(TransmissionType transmission_type,
HasRetransmittableData retransmittable,
IsHandshake handshake) {
- if (write_blocked_) {
+ if (writer_->IsWriteBlocked()) {
return false;
}
@@ -1073,16 +1063,13 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
IsHandshake handshake,
Force forced) {
if (ShouldDiscardPacket(level, sequence_number, retransmittable)) {
- delete packet;
return true;
}
- // If we're write blocked, we know we can't write.
- if (write_blocked_) {
- return false;
- }
-
- // If we are not forced and we can't write, then simply return false;
+ // If the writer is blocked, we must not write. However, if the packet is
+ // forced (i.e., it's the ConnectionClose packet), we still need to encrypt it
+ // and hand it off to TimeWaitListManager.
+ // We check nonforced packets here and forced after encryption.
if (forced == NO_FORCE &&
!CanWrite(transmission_type, retransmittable, handshake)) {
return false;
@@ -1098,20 +1085,29 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
sequence_number_of_last_inorder_packet_ = sequence_number;
}
- scoped_ptr<QuicEncryptedPacket> encrypted(
- framer_.EncryptPacket(level, sequence_number, *packet));
- if (encrypted.get() == NULL) {
+ QuicEncryptedPacket* encrypted =
+ framer_.EncryptPacket(level, sequence_number, *packet);
+ if (encrypted == NULL) {
LOG(DFATAL) << ENDPOINT << "Failed to encrypt packet number "
<< sequence_number;
+ // CloseConnection does not send close packet, so no infinite loop here.
CloseConnection(QUIC_ENCRYPTION_FAILURE, false);
return false;
}
- // If it's the ConnectionClose packet, the only FORCED frame type,
- // clone a copy for resending later by the TimeWaitListManager.
- if (forced == FORCE) {
+ // Forced packets are eventually owned by TimeWaitListManager; nonforced are
+ // deleted at the end of this call.
+ scoped_ptr<QuicEncryptedPacket> encrypted_deleter;
+ if (forced == NO_FORCE) {
+ encrypted_deleter.reset(encrypted);
+ } else { // forced == FORCE
DCHECK(connection_close_packet_.get() == NULL);
- connection_close_packet_.reset(encrypted->Clone());
+ connection_close_packet_.reset(encrypted);
+ // This assures we won't try to write *forced* packets when blocked.
+ // Return true to stop processing.
+ if (writer_->IsWriteBlocked()) {
+ return true;
+ }
}
if (encrypted->length() > options()->max_packet_length) {
@@ -1153,16 +1149,11 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
debug_visitor_->OnPacketSent(sequence_number, level, *encrypted, result);
}
if (result.status == WRITE_STATUS_BLOCKED) {
- // TODO(satyashekhar): It might be more efficient (fewer system calls), if
- // all connections share this variable i.e this becomes a part of
- // PacketWriterInterface.
- write_blocked_ = true;
// If the socket buffers the the data, then the packet should not
// be queued and sent again, which would result in an unnecessary
// duplicate packet being sent. The helper must call OnPacketSent
// when the packet is actually sent.
if (writer_->IsWriteBlockedDataBuffered()) {
- delete packet;
return true;
}
pending_write_.reset();
@@ -1170,7 +1161,6 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
}
if (OnPacketSent(result)) {
- delete packet;
return true;
}
return false;
@@ -1196,19 +1186,15 @@ bool QuicConnection::ShouldDiscardPacket(
return true;
}
- if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
- if (!sent_packet_manager_.IsUnacked(sequence_number)) {
- // This is a crazy edge case, but if we retransmit a packet,
- // (but have to queue it for some reason) then receive an ack
- // for the previous transmission (but not the retransmission)
- // then receive a truncated ACK which causes us to raise the
- // high water mark, all before we're able to send the packet
- // then we can simply drop it.
- DVLOG(1) << ENDPOINT << "Dropping packet: " << sequence_number
- << " since it has already been acked.";
- return true;
- }
+ // If the packet has been discarded before sending, don't send it.
+ // This occurs if a packet gets serialized, queued, then discarded.
+ if (!sent_packet_manager_.IsUnacked(sequence_number)) {
+ DVLOG(1) << ENDPOINT << "Dropping packet before sending: "
+ << sequence_number << " since it has already been discarded.";
+ return true;
+ }
+ if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
if (sent_packet_manager_.IsPreviousTransmission(sequence_number)) {
// If somehow we have already retransmitted this packet *before*
// we actually send it for the first time (I think this is probably
@@ -1322,6 +1308,7 @@ bool QuicConnection::SendOrQueuePacket(EncryptionLevel level,
packet.entropy_hash);
if (WritePacket(level, packet.sequence_number, packet.packet,
transmission_type, retransmittable, handshake, forced)) {
+ delete packet.packet;
return true;
}
queued_packets_.push_back(QueuedPacket(packet.sequence_number, packet.packet,
@@ -1491,9 +1478,9 @@ void QuicConnection::SendConnectionClose(QuicErrorCode error) {
void QuicConnection::SendConnectionCloseWithDetails(QuicErrorCode error,
const string& details) {
- if (!write_blocked_) {
- SendConnectionClosePacket(error, details);
- }
+ // If we're write blocked, WritePacket() will not send, but will capture the
+ // serialized packet.
+ SendConnectionClosePacket(error, details);
CloseConnection(error, false);
}
@@ -1566,6 +1553,21 @@ bool QuicConnection::HasQueuedData() const {
!queued_packets_.empty() || packet_generator_.HasQueuedFrames();
}
+bool QuicConnection::CanWriteStreamData() {
+ if (HasQueuedData()) {
+ return false;
+ }
+
+ IsHandshake pending_handshake = visitor_->HasPendingHandshake() ?
+ IS_HANDSHAKE : NOT_HANDSHAKE;
+ // Sending queued packets may have caused the socket to become write blocked,
+ // or the congestion manager to prohibit sending. If we've sent everything
+ // we had queued and we're still not blocked, let the visitor know it can
+ // write more.
+ return ShouldGeneratePacket(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA,
+ pending_handshake);
+}
+
void QuicConnection::SetIdleNetworkTimeout(QuicTime::Delta timeout) {
if (timeout < idle_network_timeout_) {
idle_network_timeout_ = timeout;
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 9a71201..4aa5129 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -75,8 +75,10 @@ class NET_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// Called when the connection is closed either locally by the framer, or
// remotely by the peer.
- virtual void OnConnectionClosed(QuicErrorCode error,
- bool from_peer) = 0;
+ virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer) = 0;
+
+ // Called when the connection failed to write because the socket was blocked.
+ virtual void OnWriteBlocked() = 0;
// Called once a specific QUIC version is agreed by both endpoints.
virtual void OnSuccessfulVersionNegotiation(const QuicVersion& version) = 0;
@@ -249,9 +251,8 @@ class NET_EXPORT_PRIVATE QuicConnection
// Called when a packet has been finally sent to the network.
bool OnPacketSent(WriteResult result);
- // If the socket is not blocked, this allows queued writes to happen. Returns
- // false if the socket has become blocked.
- bool WriteIfNotBlocked();
+ // If the socket is not blocked, writes queued packets.
+ void WriteIfNotBlocked();
// Do any work which logically would be done in OnPacket but can not be
// safely done until the packet is validated. Returns true if the packet
@@ -339,6 +340,11 @@ class NET_EXPORT_PRIVATE QuicConnection
// does nothing if there are no pending frames.
void Flush();
+ // Returns true if the underlying UDP socket is writable, there is
+ // no queued data and the connection is not congestion-control
+ // blocked.
+ bool CanWriteStreamData();
+
// Returns true if the connection has queued packets or frames.
bool HasQueuedData() const;
@@ -411,8 +417,8 @@ class NET_EXPORT_PRIVATE QuicConnection
// Send a packet to the peer using encryption |level|. If |sequence_number|
// is present in the |retransmission_map_|, then contents of this packet will
// be retransmitted with a new sequence number if it's not acked by the peer.
- // Deletes |packet| via WritePacket call or transfers ownership to
- // QueuedPacket, ultimately deleted via WritePacket. Updates the
+ // Deletes |packet| if WritePacket call succeeds, or transfers ownership to
+ // QueuedPacket, ultimately deleted in WriteQueuedPackets. Updates the
// entropy map corresponding to |sequence_number| using |entropy_hash|.
// |transmission_type| and |retransmittable| are supplied to the congestion
// manager, and when |forced| is true, it bypasses the congestion manager.
@@ -425,7 +431,7 @@ class NET_EXPORT_PRIVATE QuicConnection
// of helper. Returns true on successful write, false otherwise. However,
// behavior is undefined if connection is not established or broken. In any
// circumstances, a return value of true implies that |packet| has been
- // deleted and should not be accessed. If |sequence_number| is present in
+ // transmitted and may be destroyed. If |sequence_number| is present in
// |retransmission_map_| it also sets up retransmission of the given packet
// in case of successful write. If |force| is FORCE, then the packet will be
// sent immediately and the send scheduler will not be consulted.
@@ -532,10 +538,6 @@ class NET_EXPORT_PRIVATE QuicConnection
// Clears any accumulated frames from the last received packet.
void ClearLastFrames();
- // Called from OnCanWrite and WriteIfNotBlocked to write queued packets.
- // Returns false if the socket has become blocked.
- bool DoWrite();
-
// 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|.
@@ -550,7 +552,7 @@ class NET_EXPORT_PRIVATE QuicConnection
// Writes as many queued packets as possible. The connection must not be
// blocked when this is called.
- bool WriteQueuedPackets();
+ void WriteQueuedPackets();
// Writes as many pending retransmissions as possible.
void WritePendingRetransmissions();
@@ -640,9 +642,6 @@ class NET_EXPORT_PRIVATE QuicConnection
// Contains the connection close packet if the connection has been closed.
scoped_ptr<QuicEncryptedPacket> connection_close_packet_;
- // True when the socket becomes unwritable.
- bool write_blocked_;
-
FecGroupMap group_map_;
QuicReceivedPacketManager received_packet_manager_;
diff --git a/net/quic/quic_connection_helper.h b/net/quic/quic_connection_helper.h
index 3354656..fa866f2 100644
--- a/net/quic/quic_connection_helper.h
+++ b/net/quic/quic_connection_helper.h
@@ -12,6 +12,7 @@
#include <set>
+#include "base/basictypes.h"
#include "base/memory/weak_ptr.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/quic_protocol.h"
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 3487cd0..6ad02c7 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -274,6 +274,7 @@ class TestPacketWriter : public QuicPacketWriter {
TestPacketWriter()
: last_packet_size_(0),
write_blocked_(false),
+ block_next_write_(false),
is_write_blocked_data_buffered_(false),
is_server_(true),
final_bytes_of_last_packet_(0),
@@ -282,7 +283,7 @@ class TestPacketWriter : public QuicPacketWriter {
packets_write_attempts_(0) {
}
- // QuicPacketWriter
+ // QuicPacketWriter interface
virtual WriteResult WritePacket(
const char* buffer, size_t buf_len,
const IPAddressNumber& self_address,
@@ -304,6 +305,10 @@ class TestPacketWriter : public QuicPacketWriter {
visitor_.Reset();
framer.set_visitor(&visitor_);
EXPECT_TRUE(framer.ProcessPacket(packet));
+ if (block_next_write_) {
+ write_blocked_ = true;
+ block_next_write_ = false;
+ }
if (IsWriteBlocked()) {
return WriteResult(WRITE_STATUS_BLOCKED, -1);
}
@@ -319,7 +324,7 @@ class TestPacketWriter : public QuicPacketWriter {
virtual void SetWritable() OVERRIDE { write_blocked_ = false; }
- void SetWriteBlocked() { write_blocked_ = true; }
+ void BlockNextWrite() { block_next_write_ = true; }
// Resets the visitor's state by clearing out the headers and frames.
void Reset() {
@@ -375,6 +380,7 @@ class TestPacketWriter : public QuicPacketWriter {
FramerVisitorCapturingFrames visitor_;
size_t last_packet_size_;
bool write_blocked_;
+ bool block_next_write_;
bool is_write_blocked_data_buffered_;
bool is_server_;
uint32 final_bytes_of_last_packet_;
@@ -824,6 +830,17 @@ class QuicConnectionTest : public ::testing::TestWithParam<bool> {
}
}
+ void TriggerConnectionClose() {
+ // Send an erroneous packet to close the connection.
+ EXPECT_CALL(visitor_,
+ OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
+ // Call ProcessDataPacket rather than ProcessPacket, as we should not get a
+ // packet call to the visitor.
+ ProcessDataPacket(6000, 0, !kEntropyFlag);
+ EXPECT_FALSE(
+ QuicConnectionPeer::GetConnectionClosePacket(&connection_) == NULL);
+ }
+
QuicGuid guid_;
QuicFramer framer_;
QuicPacketCreator creator_;
@@ -944,10 +961,13 @@ TEST_F(QuicConnectionTest, PacketsOutOfOrderWithAdditionsAndLeastAwaiting) {
}
TEST_F(QuicConnectionTest, RejectPacketTooFarOut) {
+ EXPECT_CALL(visitor_,
+ OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
// Call ProcessDataPacket rather than ProcessPacket, as we should not get a
// packet call to the visitor.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
ProcessDataPacket(6000, 0, !kEntropyFlag);
+ EXPECT_FALSE(
+ QuicConnectionPeer::GetConnectionClosePacket(&connection_) == NULL);
}
TEST_F(QuicConnectionTest, TruncatedAck) {
@@ -964,7 +984,8 @@ TEST_F(QuicConnectionTest, TruncatedAck) {
}
EXPECT_CALL(entropy_calculator_,
EntropyHash(511)).WillOnce(testing::Return(0));
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(256);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(256);
EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
ProcessAckPacket(&frame);
@@ -978,7 +999,8 @@ TEST_F(QuicConnectionTest, TruncatedAck) {
AckPacket(192, &frame);
// Removing one missing packet allows us to ack 192 and one more range.
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(2);
EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
ProcessAckPacket(&frame);
@@ -1040,6 +1062,7 @@ TEST_F(QuicConnectionTest, AckReceiptCausesAckSend) {
QuicAckFrame frame = InitAckFrame(original, 1);
NackPacket(original, &frame);
// First nack triggers early retransmit.
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
QuicPacketSequenceNumber retransmission;
EXPECT_CALL(*send_algorithm_,
OnPacketSent(_, _, packet_size - kQuicVersionSize,
@@ -1050,7 +1073,8 @@ TEST_F(QuicConnectionTest, AckReceiptCausesAckSend) {
QuicAckFrame frame2 = InitAckFrame(retransmission, 1);
NackPacket(original, &frame2);
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _));
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _));
ProcessAckPacket(&frame2);
// Now if the peer sends an ack which still reports the retransmitted packet
@@ -1099,7 +1123,8 @@ TEST_F(QuicConnectionTest, LargestObservedLower) {
SendStreamDataToPeer(1, "foo", 0, !kFin, NULL);
SendStreamDataToPeer(1, "bar", 3, !kFin, NULL);
SendStreamDataToPeer(1, "eep", 6, !kFin, NULL);
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(2);
// Start out saying the largest observed is 2.
QuicAckFrame frame1 = InitAckFrame(1, 0);
@@ -1233,7 +1258,8 @@ TEST_F(QuicConnectionTest, SendingDifferentSequenceNumberLengthsUnackedDelta) {
TEST_F(QuicConnectionTest, BasicSending) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(6);
+// EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+// EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(6);
QuicPacketSequenceNumber last_packet;
SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1
EXPECT_EQ(1u, last_packet);
@@ -1249,6 +1275,9 @@ TEST_F(QuicConnectionTest, BasicSending) {
SendAckPacketToPeer(); // Packet 5
EXPECT_EQ(1u, last_ack()->sent_info.least_unacked);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(3);
+
// Peer acks up to packet 3.
QuicAckFrame frame = InitAckFrame(3, 0);
ProcessAckPacket(&frame);
@@ -1258,6 +1287,9 @@ TEST_F(QuicConnectionTest, BasicSending) {
// ack for 4.
EXPECT_EQ(4u, last_ack()->sent_info.least_unacked);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(3);
+
// Peer acks up to packet 4, the last packet.
QuicAckFrame frame2 = InitAckFrame(6, 0);
ProcessAckPacket(&frame2); // Acks don't instigate acks.
@@ -1309,7 +1341,7 @@ TEST_F(QuicConnectionTest, FECQueueing) {
connection_.options()->max_packets_per_fec_group = 2;
EXPECT_EQ(0u, connection_.NumQueuedPackets());
- writer_->SetWriteBlocked();
+ writer_->BlockNextWrite();
const string payload(payload_length, 'a');
connection_.SendStreamDataWithString(1, payload, 0, !kFin, NULL);
EXPECT_FALSE(creator_.ShouldSendFec(true));
@@ -1351,7 +1383,8 @@ TEST_F(QuicConnectionTest, DontAbandonAckedFEC) {
// received, it would cause the covered packet to be acked as well.
NackPacket(1, &ack_fec);
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(1);
ProcessAckPacket(&ack_fec);
clock_.AdvanceTime(DefaultRetransmissionTime());
@@ -1381,7 +1414,8 @@ TEST_F(QuicConnectionTest, AbandonAllFEC) {
NackPacket(4, &ack_fec);
// Lose the first FEC packet and ack the three data packets.
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(3);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(3);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _));
EXPECT_CALL(*send_algorithm_, OnPacketLost(2, _));
ProcessAckPacket(&ack_fec);
@@ -1577,7 +1611,7 @@ TEST_F(QuicConnectionTest, FramePackingSendvQueued) {
// Try to send two stream frames in 1 packet by using writev.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _));
- writer_->SetWriteBlocked();
+ writer_->BlockNextWrite();
char data[] = "ABCD";
IOVector data_iov;
data_iov.AppendNoCoalesce(data, 2);
@@ -1587,11 +1621,6 @@ TEST_F(QuicConnectionTest, FramePackingSendvQueued) {
EXPECT_EQ(1u, connection_.NumQueuedPackets());
EXPECT_TRUE(connection_.HasQueuedData());
- // Attempt to send all packets, but since we're actually still
- // blocked, they should all remain queued.
- EXPECT_FALSE(connection_.OnCanWrite());
- EXPECT_EQ(1u, connection_.NumQueuedPackets());
-
// Unblock the writes and actually send.
writer_->SetWritable();
EXPECT_TRUE(connection_.OnCanWrite());
@@ -1643,7 +1672,8 @@ TEST_F(QuicConnectionTest, OnCanWrite) {
}
TEST_F(QuicConnectionTest, RetransmitOnNack) {
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _));
EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _)).Times(1);
QuicPacketSequenceNumber last_packet;
@@ -1667,6 +1697,8 @@ TEST_F(QuicConnectionTest, RetransmitOnNack) {
QuicAckFrame nack_two = InitAckFrame(3, 0);
NackPacket(2, &nack_two);
// The third nack should trigger a retransmission.
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _));
EXPECT_CALL(*send_algorithm_,
OnPacketSent(_, _, second_packet_size - kQuicVersionSize,
NACK_RETRANSMISSION, _)).Times(1);
@@ -1674,7 +1706,8 @@ TEST_F(QuicConnectionTest, RetransmitOnNack) {
}
TEST_F(QuicConnectionTest, DiscardRetransmit) {
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _));
EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _)).Times(1);
QuicPacketSequenceNumber last_packet;
@@ -1697,7 +1730,9 @@ TEST_F(QuicConnectionTest, DiscardRetransmit) {
NackPacket(2, &nack_two);
// The first nack should trigger a fast retransmission, but we'll be
// write blocked, so the packet will be queued.
- writer_->SetWriteBlocked();
+ writer_->BlockNextWrite();
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _));
ProcessAckPacket(&nack_two);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -1731,6 +1766,7 @@ TEST_F(QuicConnectionTest, RetransmitNackedLargestObserved) {
QuicAckFrame frame = InitAckFrame(1, largest_observed);
NackPacket(largest_observed, &frame);
// The first nack should retransmit the largest observed packet.
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
EXPECT_CALL(*send_algorithm_,
OnPacketSent(_, _, packet_size - kQuicVersionSize,
NACK_RETRANSMISSION, _));
@@ -1744,7 +1780,7 @@ TEST_F(QuicConnectionTest, QueueAfterTwoRTOs) {
}
// Block the congestion window and ensure they're queued.
- writer_->SetWriteBlocked();
+ writer_->BlockNextWrite();
clock_.AdvanceTime(DefaultRetransmissionTime());
// Only one packet should be retransmitted.
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
@@ -1763,9 +1799,9 @@ TEST_F(QuicConnectionTest, QueueAfterTwoRTOs) {
}
TEST_F(QuicConnectionTest, WriteBlockedThenSent) {
- writer_->SetWriteBlocked();
-
+ writer_->BlockNextWrite();
writer_->set_is_write_blocked_data_buffered(true);
+
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
@@ -1774,21 +1810,68 @@ TEST_F(QuicConnectionTest, WriteBlockedThenSent) {
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
}
-TEST_F(QuicConnectionTest, ResumptionAlarmThenWriteBlocked) {
- // Set the send and resumption alarm, then block the connection.
+TEST_F(QuicConnectionTest, WriteBlockedAckedThenSent) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ writer_->BlockNextWrite();
+
+ writer_->set_is_write_blocked_data_buffered(true);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
+ EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
+
+ // Ack the sent packet before the callback returns, which happens in
+ // rare circumstances with write blocked sockets.
+ QuicAckFrame ack = InitAckFrame(1, 0);
+ ProcessAckPacket(&ack);
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+ connection_.OnPacketSent(WriteResult(WRITE_STATUS_OK, 0));
+ EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
+}
+
+TEST_F(QuicConnectionTest, RetransmitWriteBlockedAckedOriginalThenSent) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+
+ writer_->BlockNextWrite();
+ writer_->set_is_write_blocked_data_buffered(true);
+
+ // Simulate the retransmission alarm firing.
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _));
+ clock_.AdvanceTime(DefaultRetransmissionTime());
+ connection_.GetRetransmissionAlarm()->Fire();
+
+ // Ack the sent packet before the callback returns, which happens in
+ // rare circumstances with write blocked sockets.
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ QuicAckFrame ack = InitAckFrame(1, 0);
+ ProcessAckPacket(&ack);
+
+ connection_.OnPacketSent(WriteResult(WRITE_STATUS_OK, 0));
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+}
+
+TEST_F(QuicConnectionTest, ResumptionAlarmWhenWriteBlocked) {
+ // Block the connection.
+ writer_->BlockNextWrite();
+ connection_.SendStreamDataWithString(3, "foo", 0, !kFin, NULL);
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+ EXPECT_TRUE(writer_->IsWriteBlocked());
+
+ // Set the send and resumption alarms. Fire the alarms and ensure they don't
+ // attempt to write.
connection_.GetResumeWritesAlarm()->Set(clock_.ApproximateNow());
connection_.GetSendAlarm()->Set(clock_.ApproximateNow());
- QuicConnectionPeer::SetIsWriteBlocked(&connection_, true);
-
- // Fire the alarms and ensure the connection is still write blocked.
connection_.GetResumeWritesAlarm()->Fire();
connection_.GetSendAlarm()->Fire();
- EXPECT_TRUE(QuicConnectionPeer::IsWriteBlocked(&connection_));
+ EXPECT_TRUE(writer_->IsWriteBlocked());
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
}
TEST_F(QuicConnectionTest, LimitPacketsPerNack) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(15, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(15, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(4);
int offset = 0;
// Send packets 1 to 15.
@@ -1816,7 +1899,6 @@ TEST_F(QuicConnectionTest, LimitPacketsPerNack) {
// Test sending multiple acks from the connection to the session.
TEST_F(QuicConnectionTest, MultipleAcks) {
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(6);
QuicPacketSequenceNumber last_packet;
SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1
EXPECT_EQ(1u, last_packet);
@@ -1831,18 +1913,23 @@ TEST_F(QuicConnectionTest, MultipleAcks) {
EXPECT_EQ(6u, last_packet);
// Client will ack packets 1, 2, [!3], 4, 5.
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(4);
QuicAckFrame frame1 = InitAckFrame(5, 0);
NackPacket(3, &frame1);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessAckPacket(&frame1);
// Now the client implicitly acks 3, and explicitly acks 6.
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(2);
QuicAckFrame frame2 = InitAckFrame(6, 0);
ProcessAckPacket(&frame2);
}
TEST_F(QuicConnectionTest, DontLatchUnackedPacket) {
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(1);
SendStreamDataToPeer(1, "foo", 0, !kFin, NULL); // Packet 1;
// From now on, we send acks, so the send algorithm won't save them.
ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
@@ -2145,6 +2232,7 @@ TEST_F(QuicConnectionTest, RetransmissionCountCalculation) {
EXPECT_TRUE(QuicConnectionPeer::IsRetransmission(
&connection_, rto_sequence_number));
// Once by explicit nack.
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_)).Times(3);
EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1);
EXPECT_CALL(*send_algorithm_,
OnPacketAbandoned(rto_sequence_number, _)).Times(1);
@@ -2172,7 +2260,7 @@ TEST_F(QuicConnectionTest, RetransmissionCountCalculation) {
}
TEST_F(QuicConnectionTest, SetRTOAfterWritingToSocket) {
- writer_->SetWriteBlocked();
+ writer_->BlockNextWrite();
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
// Make sure that RTO is not started when the packet is queued.
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
@@ -2195,7 +2283,8 @@ TEST_F(QuicConnectionTest, DelayRTOWithAckReceipt) {
// Advance the time right before the RTO, then receive an ack for the first
// packet to delay the RTO.
clock_.AdvanceTime(DefaultRetransmissionTime());
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(1);
QuicAckFrame ack = InitAckFrame(1, 0);
ProcessAckPacket(&ack);
EXPECT_TRUE(retransmission_alarm->IsSet());
@@ -2222,15 +2311,10 @@ TEST_F(QuicConnectionTest, DelayRTOWithAckReceipt) {
TEST_F(QuicConnectionTest, TestQueued) {
EXPECT_EQ(0u, connection_.NumQueuedPackets());
- writer_->SetWriteBlocked();
+ writer_->BlockNextWrite();
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
- // Attempt to send all packets, but since we're actually still
- // blocked, they should all remain queued.
- EXPECT_FALSE(connection_.OnCanWrite());
- EXPECT_EQ(1u, connection_.NumQueuedPackets());
-
// Unblock the writes and actually send.
writer_->SetWritable();
EXPECT_TRUE(connection_.OnCanWrite());
@@ -2382,7 +2466,7 @@ TEST_F(QuicConnectionTest, SendSchedulerForce) {
TEST_F(QuicConnectionTest, SendSchedulerEAGAIN) {
QuicPacket* packet = ConstructDataPacket(1, 0, !kEntropyFlag);
- writer_->SetWriteBlocked();
+ writer_->BlockNextWrite();
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::Zero()));
@@ -2633,7 +2717,7 @@ TEST_F(QuicConnectionTest, DontSendDelayedAckOnOutgoingCryptoPacket) {
TEST_F(QuicConnectionTest, NoAckForClose) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(1);
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(0);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(0);
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, true));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
ProcessClosePacket(2, 0);
@@ -2857,11 +2941,10 @@ TEST_F(QuicConnectionTest, ServerSendsVersionNegotiationPacketSocketBlocked) {
framer_.set_version(QuicVersionMax());
connection_.set_is_server(true);
- writer_->SetWriteBlocked();
+ writer_->BlockNextWrite();
connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
EXPECT_EQ(0u, writer_->last_packet_size());
EXPECT_TRUE(connection_.HasQueuedData());
- EXPECT_TRUE(QuicConnectionPeer::IsWriteBlocked(&connection_));
writer_->SetWritable();
connection_.OnCanWrite();
@@ -2902,12 +2985,11 @@ TEST_F(QuicConnectionTest,
framer_.set_version(QuicVersionMax());
connection_.set_is_server(true);
- writer_->SetWriteBlocked();
+ writer_->BlockNextWrite();
writer_->set_is_write_blocked_data_buffered(true);
connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
EXPECT_EQ(0u, writer_->last_packet_size());
EXPECT_FALSE(connection_.HasQueuedData());
- EXPECT_TRUE(QuicConnectionPeer::IsWriteBlocked(&connection_));
}
TEST_F(QuicConnectionTest, ClientHandlesVersionNegotiation) {
@@ -3007,7 +3089,8 @@ TEST_F(QuicConnectionTest, CheckSendStats) {
NackPacket(3, &nack_three);
NackPacket(1, &nack_three);
QuicFrame frame(&nack_three);
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1);
EXPECT_CALL(visitor_, OnCanWrite()).Times(4).WillRepeatedly(Return(true));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -3136,41 +3219,32 @@ TEST_F(QuicConnectionTest, SelectMutualVersion) {
EXPECT_FALSE(connection_.SelectMutualVersion(unsupported_version));
}
-TEST_F(QuicConnectionTest, ConnectionCloseWhenNotWriteBlocked) {
- writer_->SetWritable(); // Already default.
+TEST_F(QuicConnectionTest, ConnectionCloseWhenWritable) {
+ EXPECT_FALSE(writer_->IsWriteBlocked());
- // Send a packet (but write will not block).
+ // Send a packet.
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_EQ(1u, writer_->packets_write_attempts());
- // Send an erroneous packet to close the connection.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
- ProcessDataPacket(6000, 0, !kEntropyFlag);
+ TriggerConnectionClose();
EXPECT_EQ(2u, writer_->packets_write_attempts());
}
-TEST_F(QuicConnectionTest, ConnectionCloseWhenWriteBlocked) {
- EXPECT_EQ(0u, connection_.NumQueuedPackets());
- writer_->SetWriteBlocked();
+TEST_F(QuicConnectionTest, ConnectionCloseGettingWriteBlocked) {
+ writer_->BlockNextWrite();
+ TriggerConnectionClose();
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+ EXPECT_TRUE(writer_->IsWriteBlocked());
+}
- // Send a packet to so that write will really block.
+TEST_F(QuicConnectionTest, ConnectionCloseWhenWriteBlocked) {
+ writer_->BlockNextWrite();
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
EXPECT_EQ(1u, writer_->packets_write_attempts());
-
- // Send an erroneous packet to close the connection.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
- ProcessDataPacket(6000, 0, !kEntropyFlag);
- EXPECT_EQ(1u, writer_->packets_write_attempts());
-}
-
-TEST_F(QuicConnectionTest, ConnectionCloseWhenNothingPending) {
- writer_->SetWriteBlocked();
-
- // Send an erroneous packet to close the connection.
- EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
- ProcessDataPacket(6000, 0, !kEntropyFlag);
+ EXPECT_TRUE(writer_->IsWriteBlocked());
+ TriggerConnectionClose();
EXPECT_EQ(1u, writer_->packets_write_attempts());
}
@@ -3179,13 +3253,14 @@ TEST_F(QuicConnectionTest, AckNotifierTriggerCallback) {
// Create a delegate which we expect to be called.
scoped_refptr<MockAckNotifierDelegate> delegate(new MockAckNotifierDelegate);
- EXPECT_CALL(*delegate, OnAckNotification()).Times(1);;
+ EXPECT_CALL(*delegate, OnAckNotification()).Times(1);
// Send some data, which will register the delegate to be notified.
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, delegate.get());
// Process an ACK from the server which should trigger the callback.
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(1);
QuicAckFrame frame = InitAckFrame(1, 0);
ProcessAckPacket(&frame);
}
@@ -3195,9 +3270,10 @@ TEST_F(QuicConnectionTest, AckNotifierFailToTriggerCallback) {
// Create a delegate which we don't expect to be called.
scoped_refptr<MockAckNotifierDelegate> delegate(new MockAckNotifierDelegate);
- EXPECT_CALL(*delegate, OnAckNotification()).Times(0);;
+ EXPECT_CALL(*delegate, OnAckNotification()).Times(0);
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(2);
// Send some data, which will register the delegate to be notified. This will
// not be ACKed and so the delegate should never be called.
@@ -3221,10 +3297,11 @@ TEST_F(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) {
// Create a delegate which we expect to be called.
scoped_refptr<MockAckNotifierDelegate> delegate(new MockAckNotifierDelegate);
- EXPECT_CALL(*delegate, OnAckNotification()).Times(1);;
+ EXPECT_CALL(*delegate, OnAckNotification()).Times(1);
// In total expect ACKs for all 4 packets.
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(4);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(4);
// Send four packets, and register to be notified on ACK of packet 2.
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
@@ -3254,10 +3331,11 @@ TEST_F(QuicConnectionTest, AckNotifierCallbackAfterFECRecovery) {
// Create a delegate which we expect to be called.
scoped_refptr<MockAckNotifierDelegate> delegate(new MockAckNotifierDelegate);
- EXPECT_CALL(*delegate, OnAckNotification()).Times(1);;
+ EXPECT_CALL(*delegate, OnAckNotification()).Times(1);
// Expect ACKs for 1 packet.
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(1);
// Send one packet, and register to be notified on ACK.
connection_.SendStreamDataWithString(1, "foo", 0, !kFin, delegate.get());
diff --git a/net/quic/quic_crypto_stream.h b/net/quic/quic_crypto_stream.h
index a082d50..b29580b 100644
--- a/net/quic/quic_crypto_stream.h
+++ b/net/quic/quic_crypto_stream.h
@@ -5,6 +5,7 @@
#ifndef NET_QUIC_QUIC_CRYPTO_STREAM_H_
#define NET_QUIC_QUIC_CRYPTO_STREAM_H_
+#include "base/basictypes.h"
#include "net/quic/crypto/crypto_framer.h"
#include "net/quic/crypto/crypto_utils.h"
#include "net/quic/quic_config.h"
diff --git a/net/quic/quic_data_stream.cc b/net/quic/quic_data_stream.cc
index 0e450f1..a537d81 100644
--- a/net/quic/quic_data_stream.cc
+++ b/net/quic/quic_data_stream.cc
@@ -7,7 +7,7 @@
#include "base/logging.h"
#include "net/quic/quic_session.h"
#include "net/quic/quic_spdy_decompressor.h"
-#include "net/spdy/write_blocked_list.h"
+#include "net/quic/quic_write_blocked_list.h"
using base::StringPiece;
using std::min;
diff --git a/net/quic/quic_data_stream.h b/net/quic/quic_data_stream.h
index 9e8c10e..ce4ac4f 100644
--- a/net/quic/quic_data_stream.h
+++ b/net/quic/quic_data_stream.h
@@ -13,10 +13,12 @@
#include <list>
+#include "base/basictypes.h"
#include "base/strings/string_piece.h"
#include "net/base/iovec.h"
#include "net/base/net_export.h"
#include "net/quic/quic_ack_notifier.h"
+#include "net/quic/quic_protocol.h"
#include "net/quic/quic_spdy_compressor.h"
#include "net/quic/quic_spdy_decompressor.h"
#include "net/quic/quic_stream_sequencer.h"
diff --git a/net/quic/quic_data_stream_test.cc b/net/quic/quic_data_stream_test.cc
index 25144f8..e767a46 100644
--- a/net/quic/quic_data_stream_test.cc
+++ b/net/quic/quic_data_stream_test.cc
@@ -9,6 +9,7 @@
#include "net/quic/quic_spdy_compressor.h"
#include "net/quic/quic_spdy_decompressor.h"
#include "net/quic/quic_utils.h"
+#include "net/quic/quic_write_blocked_list.h"
#include "net/quic/spdy_utils.h"
#include "net/quic/test_tools/quic_session_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
@@ -119,7 +120,7 @@ class QuicDataStreamTest : public ::testing::TestWithParam<QuicVersion> {
scoped_ptr<QuicSpdyCompressor> compressor_;
scoped_ptr<QuicSpdyDecompressor> decompressor_;
SpdyHeaderBlock headers_;
- WriteBlockedList<QuicStreamId>* write_blocked_list_;
+ QuicWriteBlockedList* write_blocked_list_;
};
INSTANTIATE_TEST_CASE_P(Tests, QuicDataStreamTest,
diff --git a/net/quic/quic_fec_group.cc b/net/quic/quic_fec_group.cc
index 4be4810..8e37044 100644
--- a/net/quic/quic_fec_group.cc
+++ b/net/quic/quic_fec_group.cc
@@ -6,6 +6,7 @@
#include <limits>
+#include "base/basictypes.h"
#include "base/logging.h"
using base::StringPiece;
diff --git a/net/quic/quic_fec_group_test.cc b/net/quic/quic_fec_group_test.cc
index 3de40b1..02ed5c9 100644
--- a/net/quic/quic_fec_group_test.cc
+++ b/net/quic/quic_fec_group_test.cc
@@ -5,6 +5,7 @@
#include <algorithm>
#include <vector>
+#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "net/quic/quic_fec_group.h"
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc
index 7f07b96..b1ceb49 100644
--- a/net/quic/quic_framer_test.cc
+++ b/net/quic/quic_framer_test.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "net/quic/quic_framer.h"
+
#include <algorithm>
#include <map>
#include <string>
@@ -14,7 +16,6 @@
#include "base/stl_util.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
-#include "net/quic/quic_framer.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_utils.h"
#include "net/quic/test_tools/quic_framer_peer.h"
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 22ed3b8..a49d6bb 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -22,6 +22,7 @@
#include "net/quic/quic_default_packet_writer.h"
#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_reliable_client_stream.h"
+#include "net/quic/quic_write_blocked_list.h"
#include "net/quic/spdy_utils.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
@@ -35,7 +36,6 @@
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_http_utils.h"
#include "net/spdy/spdy_protocol.h"
-#include "net/spdy/write_blocked_list.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -662,7 +662,7 @@ TEST_P(QuicHttpStreamTest, Priority) {
QuicReliableClientStream* reliable_stream =
QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
DCHECK(reliable_stream);
- DCHECK_EQ(static_cast<QuicPriority>(kHighestPriority),
+ DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
reliable_stream->EffectivePriority());
EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
@@ -709,13 +709,13 @@ TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
DCHECK(reliable_stream);
QuicReliableClientStream::Delegate* delegate = reliable_stream->GetDelegate();
DCHECK(delegate);
- DCHECK_EQ(static_cast<QuicPriority>(kHighestPriority),
+ DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
reliable_stream->EffectivePriority());
// Set Delegate to NULL and make sure EffectivePriority returns highest
// priority.
reliable_stream->SetDelegate(NULL);
- DCHECK_EQ(static_cast<QuicPriority>(kHighestPriority),
+ DCHECK_EQ(QuicWriteBlockedList::kHighestPriority,
reliable_stream->EffectivePriority());
reliable_stream->SetDelegate(delegate);
}
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc
index cb37cc2..2ac8747 100644
--- a/net/quic/quic_packet_creator.cc
+++ b/net/quic/quic_packet_creator.cc
@@ -4,6 +4,7 @@
#include "net/quic/quic_packet_creator.h"
+#include "base/basictypes.h"
#include "base/logging.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_ack_notifier.h"
diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc
index 3785f7d..4c65734 100644
--- a/net/quic/quic_packet_generator.cc
+++ b/net/quic/quic_packet_generator.cc
@@ -4,6 +4,7 @@
#include "net/quic/quic_packet_generator.h"
+#include "base/basictypes.h"
#include "base/logging.h"
#include "net/quic/quic_fec_group.h"
#include "net/quic/quic_utils.h"
diff --git a/net/quic/quic_packet_writer.h b/net/quic/quic_packet_writer.h
index fbea660..a4b26d6c 100644
--- a/net/quic/quic_packet_writer.h
+++ b/net/quic/quic_packet_writer.h
@@ -26,8 +26,8 @@ class NET_EXPORT_PRIVATE QuicPacketWriter {
// and error_code is populated.
virtual WriteResult WritePacket(
const char* buffer, size_t buf_len,
- const net::IPAddressNumber& self_address,
- const net::IPEndPoint& peer_address,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address,
QuicBlockedWriterInterface* blocked_writer) = 0;
// Returns true if the writer buffers and subsequently rewrites data
diff --git a/net/quic/quic_reliable_client_stream.cc b/net/quic/quic_reliable_client_stream.cc
index af12b8b..996a5c5 100644
--- a/net/quic/quic_reliable_client_stream.cc
+++ b/net/quic/quic_reliable_client_stream.cc
@@ -7,7 +7,7 @@
#include "base/callback_helpers.h"
#include "net/base/net_errors.h"
#include "net/quic/quic_session.h"
-#include "net/spdy/write_blocked_list.h"
+#include "net/quic/quic_write_blocked_list.h"
namespace net {
@@ -59,7 +59,7 @@ QuicPriority QuicReliableClientStream::EffectivePriority() const {
if (delegate_ && delegate_->HasSendHeadersComplete()) {
return QuicDataStream::EffectivePriority();
}
- return kHighestPriority;
+ return QuicWriteBlockedList::kHighestPriority;
}
int QuicReliableClientStream::WriteStreamData(
diff --git a/net/quic/quic_reliable_client_stream_test.cc b/net/quic/quic_reliable_client_stream_test.cc
index 79579e4..b01d0fd 100644
--- a/net/quic/quic_reliable_client_stream_test.cc
+++ b/net/quic/quic_reliable_client_stream_test.cc
@@ -12,6 +12,7 @@
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
+using testing::AnyNumber;
using testing::Return;
using testing::StrEq;
using testing::_;
@@ -41,9 +42,10 @@ class QuicReliableClientStreamTest
: public ::testing::TestWithParam<QuicVersion> {
public:
QuicReliableClientStreamTest()
- : session_(new MockConnection(false, SupportedVersions(GetParam()))),
- stream_(kStreamId, &session_, BoundNetLog()) {
- stream_.SetDelegate(&delegate_);
+ : session_(new MockConnection(false, SupportedVersions(GetParam()))) {
+ stream_ = new QuicReliableClientStream(kStreamId, &session_, BoundNetLog());
+ session_.ActivateStream(stream_);
+ stream_->SetDelegate(&delegate_);
}
void InitializeHeaders() {
@@ -78,7 +80,7 @@ class QuicReliableClientStreamTest
testing::StrictMock<MockDelegate> delegate_;
MockSession session_;
- QuicReliableClientStream stream_;
+ QuicReliableClientStream* stream_;
QuicCryptoClientConfig crypto_config_;
SpdyHeaderBlock headers_;
};
@@ -94,21 +96,21 @@ TEST_P(QuicReliableClientStreamTest, OnFinRead) {
uncompressed_headers.size()));
QuicStreamOffset offset = 0;
if (GetParam() > QUIC_VERSION_12) {
- stream_.OnStreamHeaders(uncompressed_headers);
- stream_.OnStreamHeadersComplete(false, uncompressed_headers.length());
+ stream_->OnStreamHeaders(uncompressed_headers);
+ stream_->OnStreamHeadersComplete(false, uncompressed_headers.length());
} else {
QuicSpdyCompressor compressor;
string compressed_headers = compressor.CompressHeaders(headers_);
QuicStreamFrame frame1(kStreamId, false, 0,
MakeIOVector(compressed_headers));
- stream_.OnStreamFrame(frame1);
+ stream_->OnStreamFrame(frame1);
offset = compressed_headers.length();
}
IOVector iov;
QuicStreamFrame frame2(kStreamId, true, offset, iov);
EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR));
- stream_.OnStreamFrame(frame2);
+ stream_->OnStreamFrame(frame2);
}
TEST_P(QuicReliableClientStreamTest, ProcessData) {
@@ -116,7 +118,7 @@ TEST_P(QuicReliableClientStreamTest, ProcessData) {
EXPECT_CALL(delegate_, OnDataReceived(StrEq(data), arraysize(data)));
EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR));
- EXPECT_EQ(arraysize(data), stream_.ProcessData(data, arraysize(data)));
+ EXPECT_EQ(arraysize(data), stream_->ProcessData(data, arraysize(data)));
}
TEST_P(QuicReliableClientStreamTest, ProcessDataWithError) {
@@ -127,14 +129,14 @@ TEST_P(QuicReliableClientStreamTest, ProcessDataWithError) {
EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR));
- EXPECT_EQ(0u, stream_.ProcessData(data, arraysize(data)));
+ EXPECT_EQ(0u, stream_->ProcessData(data, arraysize(data)));
}
TEST_P(QuicReliableClientStreamTest, OnError) {
EXPECT_CALL(delegate_, OnError(ERR_INTERNET_DISCONNECTED));
- stream_.OnError(ERR_INTERNET_DISCONNECTED);
- EXPECT_FALSE(stream_.GetDelegate());
+ stream_->OnError(ERR_INTERNET_DISCONNECTED);
+ EXPECT_FALSE(stream_->GetDelegate());
}
TEST_P(QuicReliableClientStreamTest, WriteStreamData) {
@@ -144,33 +146,33 @@ TEST_P(QuicReliableClientStreamTest, WriteStreamData) {
const size_t kDataLen = arraysize(kData1);
// All data written.
- EXPECT_CALL(session_, WritevData(stream_.id(), _, _, _, _, _)).WillOnce(
+ EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _)).WillOnce(
Return(QuicConsumedData(kDataLen, true)));
TestCompletionCallback callback;
- EXPECT_EQ(OK, stream_.WriteStreamData(base::StringPiece(kData1, kDataLen),
- true, callback.callback()));
+ EXPECT_EQ(OK, stream_->WriteStreamData(base::StringPiece(kData1, kDataLen),
+ true, callback.callback()));
}
TEST_P(QuicReliableClientStreamTest, WriteStreamDataAsync) {
- EXPECT_CALL(delegate_, HasSendHeadersComplete());
+ EXPECT_CALL(delegate_, HasSendHeadersComplete()).Times(AnyNumber());
EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR));
const char kData1[] = "hello world";
const size_t kDataLen = arraysize(kData1);
// No data written.
- EXPECT_CALL(session_, WritevData(stream_.id(), _, _, _, _, _)).WillOnce(
+ EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _)).WillOnce(
Return(QuicConsumedData(0, false)));
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- stream_.WriteStreamData(base::StringPiece(kData1, kDataLen),
- true, callback.callback()));
+ stream_->WriteStreamData(base::StringPiece(kData1, kDataLen),
+ true, callback.callback()));
ASSERT_FALSE(callback.have_result());
// All data written.
- EXPECT_CALL(session_, WritevData(stream_.id(), _, _, _, _, _)).WillOnce(
+ EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _)).WillOnce(
Return(QuicConsumedData(kDataLen, true)));
- stream_.OnCanWrite();
+ stream_->OnCanWrite();
ASSERT_TRUE(callback.have_result());
EXPECT_EQ(OK, callback.WaitForResult());
}
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc
index af9a507a..8208004 100644
--- a/net/quic/quic_sent_packet_manager.cc
+++ b/net/quic/quic_sent_packet_manager.cc
@@ -104,6 +104,7 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
<< "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_);
}
if (config.congestion_control() == kPACE) {
MaybeEnablePacing();
@@ -181,19 +182,17 @@ void QuicSentPacketManager::OnRetransmittedPacket(
bool QuicSentPacketManager::OnIncomingAck(
const ReceivedPacketInfo& received_info, QuicTime ack_receive_time) {
- // Determine if the least unacked sequence number is being acked.
- QuicPacketSequenceNumber least_unacked_sent_before =
- GetLeastUnackedSentPacket();
- // TODO(ianswett): Consider a non-TCP metric for determining the connection
- // is making progress, since QUIC has out of order delivery.
- bool new_least_unacked = !IsAwaitingPacket(received_info,
- least_unacked_sent_before);
-
+ // We rely on delta_time_largest_observed to compute an RTT estimate, so
+ // we only update rtt when the largest observed gets acked.
+ bool largest_observed_acked =
+ ContainsKey(unacked_packets_, received_info.largest_observed);
MaybeUpdateRTT(received_info, ack_receive_time);
HandleAckForSentPackets(received_info);
MaybeRetransmitOnAckFrame(received_info, ack_receive_time);
- if (new_least_unacked) {
+ // Anytime we are making forward progress and have a new RTT estimate, reset
+ // the backoff counters.
+ if (largest_observed_acked) {
// Reset all retransmit counters any time a new packet is acked.
consecutive_rto_count_ = 0;
consecutive_tlp_count_ = 0;
@@ -304,15 +303,9 @@ void QuicSentPacketManager::RetransmitUnackedPackets(
unacked_it != unacked_packets_.end(); ++unacked_it) {
const RetransmittableFrames* frames =
unacked_it->second.retransmittable_frames;
- if (frames == NULL) {
- continue;
- }
if (retransmission_type == ALL_PACKETS ||
- frames->encryption_level() == ENCRYPTION_INITIAL) {
- // TODO(satyamshekhar): Think about congestion control here.
- // Specifically, about the retransmission count of packets being sent
- // proactively to achieve 0 (minimal) RTT.
- if (unacked_it->second.retransmittable_frames) {
+ (frames != NULL && frames->encryption_level() == ENCRYPTION_INITIAL)) {
+ if (frames) {
OnPacketAbandoned(unacked_it);
MarkForRetransmission(unacked_it->first, NACK_RETRANSMISSION);
} else {
@@ -398,7 +391,7 @@ QuicSentPacketManager::MarkPacketHandled(
if (it->second.pending) {
size_t bytes_sent = packet_history_map_[sequence_number]->bytes_sent();
if (received_by_peer == RECEIVED_BY_PEER) {
- send_algorithm_->OnPacketAcked(sequence_number, bytes_sent, rtt_sample_);
+ send_algorithm_->OnPacketAcked(sequence_number, bytes_sent);
} else {
// It's been abandoned.
send_algorithm_->OnPacketAbandoned(sequence_number, bytes_sent);
@@ -550,18 +543,13 @@ bool QuicSentPacketManager::OnPacketSent(
TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data) {
DCHECK_LT(0u, sequence_number);
- // In some edge cases, on some platforms (such as Windows), it is possible
- // that we were write-blocked when we tried to send a packet, and then decided
- // not to send the packet (such as when the encryption key changes, and we
- // "discard" the unsent packet). In that rare case, we may indeed
- // asynchronously (later) send the packet, calling this method, but the
- // sequence number may already be erased from unacked_packets_ map. In that
- // case, we can just return false since the packet will not be tracked for
- // retransmission.
- if (!ContainsKey(unacked_packets_, sequence_number))
- return false;
- DCHECK(!unacked_packets_[sequence_number].pending);
UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
+ // In rare circumstances, the packet could be serialized, sent, and then acked
+ // before OnPacketSent is called.
+ if (it == unacked_packets_.end()) {
+ return false;
+ }
+ DCHECK(!it->second.pending);
// Only track packets the send algorithm wants us to track.
if (!send_algorithm_->OnPacketSent(sent_time, sequence_number, bytes,
@@ -805,6 +793,10 @@ void QuicSentPacketManager::MaybeUpdateRTT(
if (transmission_info == NULL) {
return;
}
+ // Don't update the RTT if it hasn't been sent.
+ if (transmission_info->sent_time == QuicTime::Zero()) {
+ return;
+ }
QuicTime::Delta send_delta =
ack_receive_time.Subtract(transmission_info->sent_time);
@@ -817,6 +809,7 @@ void QuicSentPacketManager::MaybeUpdateRTT(
// approximation until we get a better estimate.
rtt_sample_ = send_delta;
}
+ send_algorithm_->UpdateRtt(rtt_sample_);
}
QuicTime::Delta QuicSentPacketManager::TimeUntilSend(
diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc
index b0e861d..14ab403 100644
--- a/net/quic/quic_sent_packet_manager_test.cc
+++ b/net/quic/quic_sent_packet_manager_test.cc
@@ -32,6 +32,8 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
QuicSentPacketManagerPeer::SetSendAlgorithm(&manager_, send_algorithm_);
// Disable tail loss probes for most tests.
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 0);
+ // Advance the time 1s so the send times are never QuicTime::Zero.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000));
}
~QuicSentPacketManagerTest() {
@@ -242,12 +244,15 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
SendDataPacket(1);
RetransmitPacket(1, 2);
+ QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(15);
+ clock_.AdvanceTime(rtt);
// Ack 1 but not 2.
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _, _));
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(rtt));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _));
ReceivedPacketInfo received_info;
received_info.largest_observed = 1;
- EXPECT_TRUE(manager_.OnIncomingAck(received_info, QuicTime::Zero()));
+ EXPECT_TRUE(manager_.OnIncomingAck(received_info, clock_.ApproximateNow()));
// 2 remains unacked, but no packets have retransmittable data.
QuicPacketSequenceNumber unacked[] = { 2 };
@@ -267,31 +272,39 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
.WillOnce(Return(true));
manager_.OnPacketSent(2, clock_.ApproximateNow(), 1000,
NACK_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(15);
+ clock_.AdvanceTime(rtt);
// First, ACK packet 1 which makes packet 2 non-retransmittable.
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _, _));
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(rtt));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _));
ReceivedPacketInfo received_info;
received_info.largest_observed = 1;
- EXPECT_TRUE(manager_.OnIncomingAck(received_info, QuicTime::Zero()));
+ EXPECT_TRUE(manager_.OnIncomingAck(received_info, clock_.ApproximateNow()));
SendDataPacket(3);
SendDataPacket(4);
SendDataPacket(5);
+ clock_.AdvanceTime(rtt);
+
// Next, NACK packet 2 three times.
received_info.largest_observed = 3;
received_info.missing_packets.insert(2);
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(3, _, _));
- EXPECT_TRUE(manager_.OnIncomingAck(received_info, QuicTime::Zero()));
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(rtt));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(3, _));
+ EXPECT_TRUE(manager_.OnIncomingAck(received_info, clock_.ApproximateNow()));
received_info.largest_observed = 4;
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(4, _, _));
- EXPECT_TRUE(manager_.OnIncomingAck(received_info, QuicTime::Zero()));
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(rtt));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(4, _));
+ EXPECT_TRUE(manager_.OnIncomingAck(received_info, clock_.ApproximateNow()));
received_info.largest_observed = 5;
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(5, _, _));
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(rtt));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(5, _));
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _));
EXPECT_CALL(*send_algorithm_, OnPacketLost(2, _));
- EXPECT_TRUE(manager_.OnIncomingAck(received_info, QuicTime::Zero()));
+ EXPECT_TRUE(manager_.OnIncomingAck(received_info, clock_.ApproximateNow()));
// No packets remain unacked.
VerifyUnackedPackets(NULL, 0);
@@ -317,7 +330,8 @@ TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckPreviousBeforeSend) {
// send algorithm is not informed that it has been ACK'd.
ReceivedPacketInfo received_info;
received_info.largest_observed = 1;
- EXPECT_TRUE(manager_.OnIncomingAck(received_info, QuicTime::Zero()));
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(QuicTime::Delta::Zero()));
+ EXPECT_TRUE(manager_.OnIncomingAck(received_info, clock_.ApproximateNow()));
// Since 2 was marked for retransmit, when 1 is acked, 2 is discarded.
VerifyUnackedPackets(NULL, 0);
@@ -333,12 +347,15 @@ TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
SendDataPacket(1);
RetransmitPacket(1, 2);
RetransmitPacket(2, 3);
+ QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(15);
+ clock_.AdvanceTime(rtt);
// Ack 1 but not 2 or 3.
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _, _));
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(rtt));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(1, _));
ReceivedPacketInfo received_info;
received_info.largest_observed = 1;
- manager_.OnIncomingAck(received_info, QuicTime::Zero());
+ manager_.OnIncomingAck(received_info, clock_.ApproximateNow());
// 3 remains unacked, but no packets have retransmittable data.
QuicPacketSequenceNumber unacked[] = { 3 };
@@ -643,7 +660,8 @@ TEST_F(QuicSentPacketManagerTest, NackRetransmit1Packet) {
received_info.missing_packets.insert(1);
for (QuicPacketSequenceNumber i = 1; i <= 3; ++i) {
received_info.largest_observed = i + 1;
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(i + 1, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(i + 1, _)).Times(1);
if (i == 3) {
EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
@@ -671,7 +689,8 @@ TEST_F(QuicSentPacketManagerTest, NackRetransmit1PacketWith1StretchAck) {
QuicTime::Delta::FromMilliseconds(5);
received_info.missing_packets.insert(1);
received_info.largest_observed = kNumSentPackets;
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(3);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(3);
EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
manager_.OnIncomingAck(received_info, clock_.Now());
@@ -696,7 +715,8 @@ TEST_F(QuicSentPacketManagerTest, NackRetransmit1PacketSingleAck) {
received_info.missing_packets.insert(2);
received_info.missing_packets.insert(3);
received_info.largest_observed = 4;
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(4, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(4, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
manager_.OnIncomingAck(received_info, clock_.Now());
@@ -718,7 +738,8 @@ TEST_F(QuicSentPacketManagerTest, EarlyRetransmit1Packet) {
QuicTime::Delta::FromMilliseconds(5);
received_info.missing_packets.insert(1);
received_info.largest_observed = kNumSentPackets;
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(kNumSentPackets, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(kNumSentPackets, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
manager_.OnIncomingAck(received_info, clock_.Now());
@@ -744,7 +765,8 @@ TEST_F(QuicSentPacketManagerTest, DontEarlyRetransmitPacket) {
received_info.missing_packets.insert(3);
received_info.missing_packets.insert(4);
received_info.largest_observed = kNumSentPackets;
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(5, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(5, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
manager_.OnIncomingAck(received_info, clock_.Now());
@@ -768,8 +790,9 @@ TEST_F(QuicSentPacketManagerTest, NackRetransmit2Packets) {
for (size_t i = 1; i < kNumSentPackets; ++i) {
received_info.missing_packets.insert(i);
}
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
EXPECT_CALL(*send_algorithm_,
- OnPacketAcked(kNumSentPackets, _, _)).Times(1);
+ OnPacketAcked(kNumSentPackets, _)).Times(1);
EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
manager_.OnIncomingAck(received_info, clock_.Now());
@@ -839,8 +862,9 @@ TEST_F(QuicSentPacketManagerTest, NackTwiceThenAck) {
received_info.largest_observed = i + 1;
received_info.delta_time_largest_observed =
QuicTime::Delta::FromMilliseconds(5);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
EXPECT_CALL(*send_algorithm_,
- OnPacketAcked(_, _, _)).Times(i == 3 ? 2 : 1);
+ OnPacketAcked(_, _)).Times(i == 3 ? 2 : 1);
manager_.OnIncomingAck(received_info, clock_.Now());
EXPECT_FALSE(manager_.HasPendingRetransmissions());
// The nack count remains at 2 when the packet is acked.
@@ -855,8 +879,9 @@ TEST_F(QuicSentPacketManagerTest, Rtt) {
SendDataPacket(sequence_number);
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(expected_rtt));
EXPECT_CALL(*send_algorithm_,
- OnPacketAcked(sequence_number, _, expected_rtt)).Times(1);
+ OnPacketAcked(sequence_number, _)).Times(1);
ReceivedPacketInfo received_info;
received_info.largest_observed = sequence_number;
received_info.delta_time_largest_observed =
@@ -874,8 +899,9 @@ TEST_F(QuicSentPacketManagerTest, RttWithInvalidDelta) {
SendDataPacket(sequence_number);
clock_.AdvanceTime(expected_rtt);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(expected_rtt));
EXPECT_CALL(*send_algorithm_,
- OnPacketAcked(sequence_number, _, expected_rtt)).Times(1);
+ OnPacketAcked(sequence_number, _)).Times(1);
ReceivedPacketInfo received_info;
received_info.largest_observed = sequence_number;
received_info.delta_time_largest_observed =
@@ -892,8 +918,9 @@ TEST_F(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
SendDataPacket(sequence_number);
clock_.AdvanceTime(expected_rtt);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(expected_rtt));
EXPECT_CALL(*send_algorithm_,
- OnPacketAcked(sequence_number, _, expected_rtt)).Times(1);
+ OnPacketAcked(sequence_number, _)).Times(1);
ReceivedPacketInfo received_info;
received_info.largest_observed = sequence_number;
received_info.delta_time_largest_observed = QuicTime::Delta::Infinite();
@@ -909,7 +936,8 @@ TEST_F(QuicSentPacketManagerTest, RttZeroDelta) {
SendDataPacket(sequence_number);
clock_.AdvanceTime(expected_rtt);
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(sequence_number, _, expected_rtt))
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(expected_rtt));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(sequence_number, _))
.Times(1);
ReceivedPacketInfo received_info;
received_info.largest_observed = sequence_number;
@@ -937,7 +965,8 @@ TEST_F(QuicSentPacketManagerTest, TailLossProbeTimeout) {
// Ack the third and ensure the first two are considered lost, but they were
// already abandoned, so that won't occur again.
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(3, _, _));
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(3, _));
EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
ReceivedPacketInfo received_info;
@@ -1007,7 +1036,8 @@ TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
// Now ack the two crypto packets and the speculatively encrypted request,
// and ensure the first four crypto packets get abandoned, but not lost.
- EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(5);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _)).Times(5);
ReceivedPacketInfo received_info;
received_info.largest_observed = 9;
received_info.missing_packets.insert(1);
@@ -1155,6 +1185,16 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeRTO) {
// The delay should double the second time.
expected_time = clock_.Now().Add(expected_rto_delay).Add(expected_rto_delay);
EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
+
+ // Ack a packet and ensure the RTO goes back to the original value.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 2;
+ received_info.missing_packets.insert(1);
+ EXPECT_CALL(*send_algorithm_, UpdateRtt(_));
+ manager_.OnIncomingAck(received_info, clock_.ApproximateNow());
+
+ expected_time = clock_.Now().Add(expected_rto_delay);
+ EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
}
TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index 5ac6a9d..9be3a3b 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -64,12 +64,16 @@ class VisitorShim : public QuicConnectionVisitorInterface {
session_->OnConfigNegotiated();
}
- virtual void OnConnectionClosed(QuicErrorCode error,
- bool from_peer) OVERRIDE {
+ virtual void OnConnectionClosed(
+ QuicErrorCode error, bool from_peer) OVERRIDE {
session_->OnConnectionClosed(error, from_peer);
// The session will go away, so don't bother with cleanup.
}
+ virtual void OnWriteBlocked() OVERRIDE {
+ session_->OnWriteBlocked();
+ }
+
virtual bool HasPendingHandshake() const OVERRIDE {
return session_->HasPendingHandshake();
}
@@ -269,16 +273,14 @@ bool QuicSession::OnCanWrite() {
// may be modifying the list as we loop.
int remaining_writes = write_blocked_streams_.NumBlockedStreams();
- while (!connection_->HasQueuedData() &&
- remaining_writes > 0) {
+ while (remaining_writes > 0 && connection_->CanWriteStreamData()) {
DCHECK(write_blocked_streams_.HasWriteBlockedStreams());
if (!write_blocked_streams_.HasWriteBlockedStreams()) {
LOG(DFATAL) << "WriteBlockedStream is missing";
connection_->CloseConnection(QUIC_INTERNAL_ERROR, false);
return true; // We have no write blocked streams.
}
- int index = write_blocked_streams_.GetHighestPriorityWriteBlockedList();
- QuicStreamId stream_id = write_blocked_streams_.PopFront(index);
+ QuicStreamId stream_id = write_blocked_streams_.PopFront();
if (stream_id == kCryptoStreamId) {
has_pending_handshake_ = false; // We just popped it.
}
@@ -588,6 +590,17 @@ size_t QuicSession::GetNumOpenStreams() const {
}
void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) {
+#ifndef NDEBUG
+ ReliableQuicStream* stream = GetStream(id);
+ if (stream != NULL) {
+ LOG_IF(DFATAL, priority != stream->EffectivePriority())
+ << "Priorities do not match. Got: " << priority
+ << " Expected: " << stream->EffectivePriority();
+ } else {
+ LOG(DFATAL) << "Marking unknown stream " << id << " blocked.";
+ }
+#endif
+
if (id == kCryptoStreamId) {
DCHECK(!has_pending_handshake_);
has_pending_handshake_ = true;
@@ -596,11 +609,11 @@ void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) {
// kHighestPriority.
priority = kHighestPriority;
}
- write_blocked_streams_.PushBack(id, priority);
+ write_blocked_streams_.PushBack(id, priority, connection()->version());
}
-bool QuicSession::HasQueuedData() const {
- return write_blocked_streams_.NumBlockedStreams() ||
+bool QuicSession::HasDataToWrite() const {
+ return write_blocked_streams_.HasWriteBlockedStreams() ||
connection_->HasQueuedData();
}
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h
index a071587..a8ed206 100644
--- a/net/quic/quic_session.h
+++ b/net/quic/quic_session.h
@@ -21,8 +21,8 @@
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_spdy_compressor.h"
#include "net/quic/quic_spdy_decompressor.h"
+#include "net/quic/quic_write_blocked_list.h"
#include "net/quic/reliable_quic_stream.h"
-#include "net/spdy/write_blocked_list.h"
namespace net {
@@ -65,10 +65,10 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
virtual void OnRstStream(const QuicRstStreamFrame& frame) OVERRIDE;
virtual void OnGoAway(const QuicGoAwayFrame& frame) OVERRIDE;
virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer) OVERRIDE;
+ virtual void OnWriteBlocked() OVERRIDE {}
virtual void OnSuccessfulVersionNegotiation(
const QuicVersion& version) OVERRIDE {}
virtual void OnConfigNegotiated() OVERRIDE;
- // Not needed for HTTP.
virtual bool OnCanWrite() OVERRIDE;
virtual bool HasPendingHandshake() const OVERRIDE;
@@ -171,7 +171,7 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// Returns true if the session has data to be sent, either queued in the
// connection, or in a write-blocked stream.
- bool HasQueuedData() const;
+ bool HasDataToWrite() const;
// Marks that |stream_id| is blocked waiting to decompress the
// headers identified by |decompression_id|.
@@ -303,7 +303,7 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
base::hash_set<QuicStreamId> implicitly_created_streams_;
// A list of streams which need to write more data.
- WriteBlockedList<QuicStreamId> write_blocked_streams_;
+ QuicWriteBlockedList write_blocked_streams_;
// A map of headers waiting to be compressed, and the streams
// they are associated with.
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc
index 9d4acbf..2d362fd 100644
--- a/net/quic/quic_session_test.cc
+++ b/net/quic/quic_session_test.cc
@@ -7,7 +7,9 @@
#include <set>
#include <vector>
+#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
+#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/quic_crypto_stream.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/reliable_quic_stream.h"
@@ -26,13 +28,15 @@ using std::vector;
using testing::_;
using testing::InSequence;
using testing::InvokeWithoutArgs;
+using testing::Return;
using testing::StrictMock;
namespace net {
namespace test {
namespace {
-const QuicPriority kSomeMiddlePriority = 2;
+const QuicPriority kHighestPriority = 0;
+const QuicPriority kSomeMiddlePriority = 3;
class TestCryptoStream : public QuicCryptoStream {
public:
@@ -279,6 +283,32 @@ TEST_P(QuicSessionTest, DecompressionError) {
}
}
+TEST_P(QuicSessionTest, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
+ TestStream* stream2 = session_.CreateOutgoingDataStream();
+ // Close the stream.
+ stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
+ // TODO(rtenneti): enable when chromium supports EXPECT_DEBUG_DFATAL.
+ /*
+ QuicStreamId kClosedStreamId = stream2->id();
+ EXPECT_DEBUG_DFATAL(
+ session_.MarkWriteBlocked(kClosedStreamId, kSomeMiddlePriority),
+ "Marking unknown stream 2 blocked.");
+ */
+}
+
+TEST_P(QuicSessionTest, DebugDFatalIfMarkWriteBlockedCalledWithWrongPriority) {
+ const QuicPriority kDifferentPriority = 0;
+
+ TestStream* stream2 = session_.CreateOutgoingDataStream();
+ EXPECT_NE(kDifferentPriority, stream2->EffectivePriority());
+ // TODO(rtenneti): enable when chromium supports EXPECT_DEBUG_DFATAL.
+ /*
+ EXPECT_DEBUG_DFATAL(
+ session_.MarkWriteBlocked(stream2->id(), kDifferentPriority),
+ "Priorities do not match. Got: 0 Expected: 3");
+ */
+}
+
TEST_P(QuicSessionTest, OnCanWrite) {
TestStream* stream2 = session_.CreateOutgoingDataStream();
TestStream* stream4 = session_.CreateOutgoingDataStream();
@@ -299,6 +329,49 @@ TEST_P(QuicSessionTest, OnCanWrite) {
EXPECT_FALSE(session_.OnCanWrite());
}
+TEST_P(QuicSessionTest, OnCanWriteCongestionControlBlocks) {
+ InSequence s;
+
+ // Drive congestion control manually.
+ MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
+ QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
+
+ TestStream* stream2 = session_.CreateOutgoingDataStream();
+ TestStream* stream4 = session_.CreateOutgoingDataStream();
+ TestStream* stream6 = session_.CreateOutgoingDataStream();
+
+ session_.MarkWriteBlocked(stream2->id(), kSomeMiddlePriority);
+ session_.MarkWriteBlocked(stream6->id(), kSomeMiddlePriority);
+ session_.MarkWriteBlocked(stream4->id(), kSomeMiddlePriority);
+
+ StreamBlocker stream2_blocker(&session_, stream2->id());
+ EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _, _)).WillOnce(Return(
+ QuicTime::Delta::Zero()));
+ EXPECT_CALL(*stream2, OnCanWrite());
+ EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _, _)).WillOnce(Return(
+ QuicTime::Delta::Zero()));
+ EXPECT_CALL(*stream6, OnCanWrite());
+ EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _, _)).WillOnce(Return(
+ QuicTime::Delta::Infinite()));
+ // stream4->OnCanWrite is not called.
+
+ // TODO(avd) change return value to 'true', since the connection
+ // can't write because it is congestion control blocked.
+ EXPECT_FALSE(session_.OnCanWrite());
+
+ // Still congestion-control blocked.
+ EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _, _)).WillOnce(Return(
+ QuicTime::Delta::Infinite()));
+ EXPECT_FALSE(session_.OnCanWrite());
+
+ // stream4->OnCanWrite is called once the connection stops being
+ // congestion-control blocked.
+ EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _, _)).WillOnce(Return(
+ QuicTime::Delta::Zero()));
+ EXPECT_CALL(*stream4, OnCanWrite());
+ EXPECT_TRUE(session_.OnCanWrite());
+}
+
TEST_P(QuicSessionTest, BufferedHandshake) {
EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
@@ -314,7 +387,7 @@ TEST_P(QuicSessionTest, BufferedHandshake) {
EXPECT_FALSE(session_.HasPendingHandshake());
// Blocking (due to buffering of) the Crypto stream is detected.
- session_.MarkWriteBlocked(kCryptoStreamId, kSomeMiddlePriority);
+ session_.MarkWriteBlocked(kCryptoStreamId, kHighestPriority);
EXPECT_TRUE(session_.HasPendingHandshake());
TestStream* stream4 = session_.CreateOutgoingDataStream();
diff --git a/net/quic/quic_stream_sequencer_test.cc b/net/quic/quic_stream_sequencer_test.cc
index cc21176..51b3487 100644
--- a/net/quic/quic_stream_sequencer_test.cc
+++ b/net/quic/quic_stream_sequencer_test.cc
@@ -7,6 +7,7 @@
#include <utility>
#include <vector>
+#include "base/logging.h"
#include "base/rand_util.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/reliable_quic_stream.h"
diff --git a/net/quic/quic_utils.cc b/net/quic/quic_utils.cc
index a2662c5..30ce560 100644
--- a/net/quic/quic_utils.cc
+++ b/net/quic/quic_utils.cc
@@ -8,11 +8,12 @@
#include <algorithm>
+#include "base/basictypes.h"
#include "base/logging.h"
#include "base/port.h"
#include "base/strings/stringprintf.h"
#include "base/strings/string_number_conversions.h"
-#include "net/spdy/write_blocked_list.h"
+#include "net/quic/quic_write_blocked_list.h"
using base::StringPiece;
using std::string;
@@ -285,12 +286,12 @@ string QuicUtils::StringToHexASCIIDump(StringPiece in_buffer) {
// static
QuicPriority QuicUtils::LowestPriority() {
- return static_cast<QuicPriority>(kLowestPriority);
+ return QuicWriteBlockedList::kLowestPriority;
}
// static
QuicPriority QuicUtils::HighestPriority() {
- return static_cast<QuicPriority>(kHighestPriority);
+ return QuicWriteBlockedList::kHighestPriority;
}
} // namespace net
diff --git a/net/quic/quic_write_blocked_list.cc b/net/quic/quic_write_blocked_list.cc
new file mode 100644
index 0000000..cdca06f
--- /dev/null
+++ b/net/quic/quic_write_blocked_list.cc
@@ -0,0 +1,21 @@
+// 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/quic_write_blocked_list.h"
+
+namespace net {
+
+const QuicPriority QuicWriteBlockedList::kHighestPriority =
+ static_cast<QuicPriority>(net::kHighestPriority);
+const QuicPriority QuicWriteBlockedList::kLowestPriority =
+ static_cast<QuicPriority>(net::kLowestPriority);
+
+QuicWriteBlockedList::QuicWriteBlockedList()
+ : crypto_stream_blocked_(false),
+ headers_stream_blocked_(false) {
+}
+
+QuicWriteBlockedList::~QuicWriteBlockedList() {}
+
+} // namespace net
diff --git a/net/quic/quic_write_blocked_list.h b/net/quic/quic_write_blocked_list.h
new file mode 100644
index 0000000..3848b08
--- /dev/null
+++ b/net/quic/quic_write_blocked_list.h
@@ -0,0 +1,90 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef NET_QUIC_QUIC_WRITE_BLOCKED_LIST_H_
+#define NET_QUIC_QUIC_WRITE_BLOCKED_LIST_H_
+
+#include "net/base/net_export.h"
+#include "net/quic/quic_protocol.h"
+#include "net/spdy/write_blocked_list.h"
+
+namespace net {
+
+// Keeps tracks of the QUIC streams that have data to write, sorted by
+// priority. QUIC stream priority order is:
+// Crypto stream > Headers stream > Data streams by requested priority.
+class NET_EXPORT_PRIVATE QuicWriteBlockedList {
+ private:
+ typedef WriteBlockedList<QuicStreamId> QuicWriteBlockedListBase;
+
+ public:
+ static const QuicPriority kHighestPriority;
+ static const QuicPriority kLowestPriority;
+
+ QuicWriteBlockedList();
+ ~QuicWriteBlockedList();
+
+ bool HasWriteBlockedStreams() const {
+ return crypto_stream_blocked_ ||
+ headers_stream_blocked_ ||
+ base_write_blocked_list_.HasWriteBlockedStreams();
+ }
+
+ size_t NumBlockedStreams() const {
+ size_t num_blocked = base_write_blocked_list_.NumBlockedStreams();
+ if (crypto_stream_blocked_) {
+ ++num_blocked;
+ }
+ if (headers_stream_blocked_) {
+ ++num_blocked;
+ }
+
+ return num_blocked;
+ }
+
+ QuicStreamId PopFront() {
+ if (crypto_stream_blocked_) {
+ crypto_stream_blocked_ = false;
+ return kCryptoStreamId;
+ } else if (headers_stream_blocked_) {
+ headers_stream_blocked_ = false;
+ return kHeadersStreamId;
+ } else {
+ SpdyPriority priority =
+ base_write_blocked_list_.GetHighestPriorityWriteBlockedList();
+ return base_write_blocked_list_.PopFront(priority);
+ }
+ }
+
+ // TODO(avd) Remove version argument when QUIC_VERSION_12 is deprecated.
+ void PushBack(QuicStreamId stream_id,
+ QuicPriority priority,
+ QuicVersion version) {
+ if (stream_id == kCryptoStreamId) {
+ DCHECK_EQ(kHighestPriority, priority);
+ // TODO(avd) Add DCHECK(!crypto_stream_blocked_)
+ crypto_stream_blocked_ = true;
+ } else if (version > QUIC_VERSION_12 &&
+ stream_id == kHeadersStreamId) {
+ DCHECK_EQ(kHighestPriority, priority);
+ // TODO(avd) Add DCHECK(!headers_stream_blocked_);
+ headers_stream_blocked_ = true;
+ } else {
+ base_write_blocked_list_.PushBack(
+ stream_id, static_cast<SpdyPriority>(priority));
+ }
+ }
+
+ private:
+ QuicWriteBlockedListBase base_write_blocked_list_;
+ bool crypto_stream_blocked_;
+ bool headers_stream_blocked_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicWriteBlockedList);
+};
+
+} // namespace net
+
+
+#endif // NET_QUIC_QUIC_WRITE_BLOCKED_LIST_H_
diff --git a/net/quic/quic_write_blocked_list_test.cc b/net/quic/quic_write_blocked_list_test.cc
new file mode 100644
index 0000000..541e01f
--- /dev/null
+++ b/net/quic/quic_write_blocked_list_test.cc
@@ -0,0 +1,106 @@
+// 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/quic_write_blocked_list.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+TEST(QuicWriteBlockedListTest, PriorityOrder) {
+ QuicWriteBlockedList write_blocked_list;
+
+ // Mark streams blocked in roughly reverse priority order, and
+ // verify that streams are sorted.
+ write_blocked_list.PushBack(40,
+ QuicWriteBlockedList::kLowestPriority,
+ QUIC_VERSION_13);
+ write_blocked_list.PushBack(23,
+ QuicWriteBlockedList::kHighestPriority,
+ QUIC_VERSION_13);
+ write_blocked_list.PushBack(17,
+ QuicWriteBlockedList::kHighestPriority,
+ QUIC_VERSION_13);
+ write_blocked_list.PushBack(kHeadersStreamId,
+ QuicWriteBlockedList::kHighestPriority,
+ QUIC_VERSION_13);
+ write_blocked_list.PushBack(kCryptoStreamId,
+ QuicWriteBlockedList::kHighestPriority,
+ QUIC_VERSION_13);
+
+ EXPECT_EQ(5u, write_blocked_list.NumBlockedStreams());
+ EXPECT_TRUE(write_blocked_list.HasWriteBlockedStreams());
+ // The Crypto stream is highest priority.
+ EXPECT_EQ(kCryptoStreamId, write_blocked_list.PopFront());
+ // Followed by the Headers stream.
+ EXPECT_EQ(kHeadersStreamId, write_blocked_list.PopFront());
+ // Streams with same priority are popped in the order they were inserted.
+ EXPECT_EQ(23u, write_blocked_list.PopFront());
+ EXPECT_EQ(17u, write_blocked_list.PopFront());
+ // Low priority stream appears last.
+ EXPECT_EQ(40u, write_blocked_list.PopFront());
+
+ EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
+ EXPECT_FALSE(write_blocked_list.HasWriteBlockedStreams());
+}
+
+TEST(QuicWriteBlockedListTest, CryptoStream) {
+ QuicWriteBlockedList write_blocked_list;
+ write_blocked_list.PushBack(kCryptoStreamId,
+ QuicWriteBlockedList::kHighestPriority,
+ QUIC_VERSION_13);
+
+ EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams());
+ EXPECT_TRUE(write_blocked_list.HasWriteBlockedStreams());
+ EXPECT_EQ(kCryptoStreamId, write_blocked_list.PopFront());
+ EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
+ EXPECT_FALSE(write_blocked_list.HasWriteBlockedStreams());
+}
+
+TEST(QuicWriteBlockedListTest, HeadersStream) {
+ QuicWriteBlockedList write_blocked_list;
+ write_blocked_list.PushBack(kHeadersStreamId,
+ QuicWriteBlockedList::kHighestPriority,
+ QUIC_VERSION_13);
+
+ EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams());
+ EXPECT_TRUE(write_blocked_list.HasWriteBlockedStreams());
+ EXPECT_EQ(kHeadersStreamId, write_blocked_list.PopFront());
+ EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
+ EXPECT_FALSE(write_blocked_list.HasWriteBlockedStreams());
+}
+
+TEST(QuicWriteBlockedListTest, NoHeadersStreamInVersion12) {
+ for (int idx = 0; idx < 2; ++idx) {
+ QuicVersion version = ((idx == 0) ? QUIC_VERSION_13 : QUIC_VERSION_12);
+ QuicWriteBlockedList write_blocked_list;
+ write_blocked_list.PushBack(5,
+ QuicWriteBlockedList::kHighestPriority,
+ version);
+ write_blocked_list.PushBack(kHeadersStreamId,
+ QuicWriteBlockedList::kHighestPriority,
+ version);
+
+ EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
+ EXPECT_TRUE(write_blocked_list.HasWriteBlockedStreams());
+ if (version > QUIC_VERSION_12) {
+ // In newer QUIC versions, there is a headers stream which is
+ // higher priority than data streams.
+ EXPECT_EQ(kHeadersStreamId, write_blocked_list.PopFront());
+ EXPECT_EQ(5u, write_blocked_list.PopFront());
+ } else {
+ // In older QUIC versions, there is no reserved headers stream id.
+ EXPECT_EQ(5u, write_blocked_list.PopFront());
+ EXPECT_EQ(kHeadersStreamId, write_blocked_list.PopFront());
+ }
+ EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
+ EXPECT_FALSE(write_blocked_list.HasWriteBlockedStreams());
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc
index a04dc75..fc11f0b 100644
--- a/net/quic/reliable_quic_stream.cc
+++ b/net/quic/reliable_quic_stream.cc
@@ -7,7 +7,7 @@
#include "base/logging.h"
#include "net/quic/quic_session.h"
#include "net/quic/quic_spdy_decompressor.h"
-#include "net/spdy/write_blocked_list.h"
+#include "net/quic/quic_write_blocked_list.h"
using base::StringPiece;
using std::min;
diff --git a/net/quic/reliable_quic_stream.h b/net/quic/reliable_quic_stream.h
index e29005d..822baeb 100644
--- a/net/quic/reliable_quic_stream.h
+++ b/net/quic/reliable_quic_stream.h
@@ -11,6 +11,7 @@
#include <list>
+#include "base/basictypes.h"
#include "base/strings/string_piece.h"
#include "net/base/iovec.h"
#include "net/base/net_export.h"
diff --git a/net/quic/reliable_quic_stream_test.cc b/net/quic/reliable_quic_stream_test.cc
index 7e82f53..ce352a7 100644
--- a/net/quic/reliable_quic_stream_test.cc
+++ b/net/quic/reliable_quic_stream_test.cc
@@ -9,6 +9,7 @@
#include "net/quic/quic_spdy_compressor.h"
#include "net/quic/quic_spdy_decompressor.h"
#include "net/quic/quic_utils.h"
+#include "net/quic/quic_write_blocked_list.h"
#include "net/quic/spdy_utils.h"
#include "net/quic/test_tools/quic_session_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
@@ -117,7 +118,7 @@ class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> {
scoped_ptr<QuicSpdyCompressor> compressor_;
scoped_ptr<QuicSpdyDecompressor> decompressor_;
SpdyHeaderBlock headers_;
- WriteBlockedList<QuicStreamId>* write_blocked_list_;
+ QuicWriteBlockedList* write_blocked_list_;
};
TEST_F(ReliableQuicStreamTest, WriteAllData) {
diff --git a/net/quic/test_tools/crypto_test_utils.h b/net/quic/test_tools/crypto_test_utils.h
index 60674a9..65ba9ee 100644
--- a/net/quic/test_tools/crypto_test_utils.h
+++ b/net/quic/test_tools/crypto_test_utils.h
@@ -10,6 +10,7 @@
#include <utility>
#include <vector>
+#include "base/basictypes.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "net/quic/crypto/crypto_framer.h"
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc
index a7dcca5..83b3884 100644
--- a/net/quic/test_tools/quic_connection_peer.cc
+++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -12,7 +12,6 @@
#include "net/quic/quic_received_packet_manager.h"
#include "net/quic/test_tools/quic_framer_peer.h"
#include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
-#include "net/quic/test_tools/quic_test_writer.h"
namespace net {
namespace test {
@@ -116,17 +115,6 @@ QuicPacketEntropyHash QuicConnectionPeer::ReceivedEntropyHash(
}
// static
-bool QuicConnectionPeer::IsWriteBlocked(QuicConnection* connection) {
- return connection->write_blocked_;
-}
-
-// static
-void QuicConnectionPeer::SetIsWriteBlocked(QuicConnection* connection,
- bool write_blocked) {
- connection->write_blocked_ = write_blocked;
-}
-
-// static
bool QuicConnectionPeer::IsServer(QuicConnection* connection) {
return connection->is_server_;
}
@@ -207,7 +195,7 @@ QuicPacketWriter* QuicConnectionPeer::GetWriter(QuicConnection* connection) {
// static
void QuicConnectionPeer::SetWriter(QuicConnection* connection,
- QuicTestWriter* writer) {
+ QuicPacketWriter* writer) {
connection->writer_ = writer;
}
@@ -216,5 +204,11 @@ void QuicConnectionPeer::CloseConnection(QuicConnection* connection) {
connection->connected_ = false;
}
+// static
+QuicEncryptedPacket* QuicConnectionPeer::GetConnectionClosePacket(
+ QuicConnection* connection) {
+ return connection->connection_close_packet_.get();
+}
+
} // namespace test
} // namespace net
diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h
index 5b75b77..dc675a2 100644
--- a/net/quic/test_tools/quic_connection_peer.h
+++ b/net/quic/test_tools/quic_connection_peer.h
@@ -18,6 +18,7 @@ class QuicAlarm;
class QuicConnection;
class QuicConnectionHelperInterface;
class QuicConnectionVisitorInterface;
+class QuicEncryptedPacket;
class QuicFecGroup;
class QuicFramer;
class QuicPacketCreator;
@@ -29,8 +30,6 @@ class SendAlgorithmInterface;
namespace test {
-class QuicTestWriter;
-
// Peer to make public a number of otherwise private QuicConnection methods.
class QuicConnectionPeer {
public:
@@ -77,10 +76,6 @@ class QuicConnectionPeer {
QuicConnection* connection,
QuicPacketSequenceNumber sequence_number);
- static bool IsWriteBlocked(QuicConnection* connection);
-
- static void SetIsWriteBlocked(QuicConnection* connection, bool write_blocked);
-
static bool IsServer(QuicConnection* connection);
static void SetIsServer(QuicConnection* connection, bool is_server);
@@ -107,8 +102,10 @@ class QuicConnectionPeer {
static QuicAlarm* GetTimeoutAlarm(QuicConnection* connection);
static QuicPacketWriter* GetWriter(QuicConnection* connection);
- static void SetWriter(QuicConnection* connection, QuicTestWriter* writer);
+ static void SetWriter(QuicConnection* connection, QuicPacketWriter* writer);
static void CloseConnection(QuicConnection* connection);
+ static QuicEncryptedPacket* GetConnectionClosePacket(
+ QuicConnection* connection);
private:
DISALLOW_COPY_AND_ASSIGN(QuicConnectionPeer);
@@ -118,4 +115,4 @@ class QuicConnectionPeer {
} // namespace net
-#endif // NET_QUIC_TEST_TOOLS_QUIC_TEST_PEER_H_
+#endif // NET_QUIC_TEST_TOOLS_QUIC_CONNECTION_PEER_H_
diff --git a/net/quic/test_tools/quic_data_stream_peer.h b/net/quic/test_tools/quic_data_stream_peer.h
index bfaf826..914b87d 100644
--- a/net/quic/test_tools/quic_data_stream_peer.h
+++ b/net/quic/test_tools/quic_data_stream_peer.h
@@ -6,7 +6,6 @@
#define NET_QUIC_TEST_TOOLS_QUIC_DATA_STREAM_PEER_H_
#include "base/basictypes.h"
-#include "net/quic/quic_protocol.h"
namespace net {
diff --git a/net/quic/test_tools/quic_session_peer.cc b/net/quic/test_tools/quic_session_peer.cc
index 4cb38ca..080643b 100644
--- a/net/quic/test_tools/quic_session_peer.cc
+++ b/net/quic/test_tools/quic_session_peer.cc
@@ -27,7 +27,7 @@ QuicHeadersStream* QuicSessionPeer::GetHeadersStream(QuicSession* session) {
}
// static
-WriteBlockedList<QuicStreamId>* QuicSessionPeer::GetWriteblockedStreams(
+QuicWriteBlockedList* QuicSessionPeer::GetWriteblockedStreams(
QuicSession* session) {
return &session->write_blocked_streams_;
}
diff --git a/net/quic/test_tools/quic_session_peer.h b/net/quic/test_tools/quic_session_peer.h
index e432f9d..d8f1c75 100644
--- a/net/quic/test_tools/quic_session_peer.h
+++ b/net/quic/test_tools/quic_session_peer.h
@@ -6,7 +6,7 @@
#define NET_QUIC_TEST_TOOLS_QUIC_SESSION_PEER_H_
#include "net/quic/quic_protocol.h"
-#include "net/spdy/write_blocked_list.h"
+#include "net/quic/quic_write_blocked_list.h"
namespace net {
@@ -21,8 +21,7 @@ class QuicSessionPeer {
static void SetNextStreamId(QuicSession* session, QuicStreamId id);
static void SetMaxOpenStreams(QuicSession* session, uint32 max_streams);
static QuicHeadersStream* GetHeadersStream(QuicSession* session);
- static WriteBlockedList<QuicStreamId>* GetWriteblockedStreams(
- QuicSession* session);
+ static QuicWriteBlockedList* GetWriteblockedStreams(QuicSession* session);
static QuicDataStream* GetIncomingDataStream(QuicSession* session,
QuicStreamId stream_id);
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index 188adad..bc1e151 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -226,6 +226,7 @@ class MockConnectionVisitor : public QuicConnectionVisitorInterface {
MOCK_METHOD1(OnRstStream, void(const QuicRstStreamFrame& frame));
MOCK_METHOD1(OnGoAway, void(const QuicGoAwayFrame& frame));
MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
+ MOCK_METHOD0(OnWriteBlocked, void());
MOCK_METHOD0(OnCanWrite, bool());
MOCK_CONST_METHOD0(HasPendingHandshake, bool());
MOCK_METHOD1(OnSuccessfulVersionNegotiation,
@@ -353,6 +354,8 @@ class MockSession : public QuicSession {
MOCK_METHOD0(IsHandshakeComplete, bool());
MOCK_METHOD0(IsCryptoHandshakeConfirmed, bool());
+ using QuicSession::ActivateStream;
+
private:
DISALLOW_COPY_AND_ASSIGN(MockSession);
};
@@ -401,8 +404,8 @@ class MockSendAlgorithm : public SendAlgorithmInterface {
void(const QuicCongestionFeedbackFrame&,
QuicTime feedback_receive_time,
const SentPacketsMap&));
- MOCK_METHOD3(OnPacketAcked,
- void(QuicPacketSequenceNumber, QuicByteCount, QuicTime::Delta));
+ MOCK_METHOD2(OnPacketAcked,
+ void(QuicPacketSequenceNumber, QuicByteCount));
MOCK_METHOD2(OnPacketLost, void(QuicPacketSequenceNumber, QuicTime));
MOCK_METHOD5(OnPacketSent,
bool(QuicTime sent_time, QuicPacketSequenceNumber, QuicByteCount,
@@ -414,6 +417,7 @@ class MockSendAlgorithm : public SendAlgorithmInterface {
HasRetransmittableData,
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());
diff --git a/net/quic/test_tools/quic_test_writer.cc b/net/quic/test_tools/quic_test_writer.cc
deleted file mode 100644
index a1cd786..0000000
--- a/net/quic/test_tools/quic_test_writer.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 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/test_tools/quic_test_writer.h"
-
-namespace net {
-namespace test {
-
-QuicTestWriter::QuicTestWriter() {}
-
-QuicTestWriter::~QuicTestWriter() {}
-
-bool QuicTestWriter::IsWriteBlocked() const {
- return writer_->IsWriteBlocked();
-}
-
-void QuicTestWriter::SetWritable() {
- writer_->SetWritable();
-}
-
-QuicPacketWriter* QuicTestWriter::writer() {
- return writer_.get();
-}
-
-void QuicTestWriter::set_writer(QuicPacketWriter* writer) {
- writer_.reset(writer);
-}
-
-} // namespace test
-} // namespace net
diff --git a/net/quic/test_tools/quic_test_writer.h b/net/quic/test_tools/quic_test_writer.h
deleted file mode 100644
index 1fa655c..0000000
--- a/net/quic/test_tools/quic_test_writer.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_QUIC_TEST_TOOLS_QUIC_TEST_WRITER_H_
-#define NET_QUIC_TEST_TOOLS_QUIC_TEST_WRITER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "net/quic/quic_packet_writer.h"
-
-namespace net {
-namespace test {
-
-// Allows setting a writer for a QuicConnection, to allow
-// fine-grained control of writes.
-class QuicTestWriter : public QuicPacketWriter {
- public:
- QuicTestWriter();
- virtual ~QuicTestWriter();
-
- virtual bool IsWriteBlocked() const OVERRIDE;
- virtual void SetWritable() OVERRIDE;
-
- // Takes ownership of |writer|.
- void set_writer(QuicPacketWriter* writer);
-
- protected:
- QuicPacketWriter* writer();
-
- private:
- scoped_ptr<QuicPacketWriter> writer_;
-};
-
-} // namespace test
-} // namespace net
-
-#endif // NET_QUIC_TEST_TOOLS_QUIC_TEST_WRITER_H_
diff --git a/net/quic/test_tools/simple_quic_framer.h b/net/quic/test_tools/simple_quic_framer.h
index 3a112e1..fe742ca 100644
--- a/net/quic/test_tools/simple_quic_framer.h
+++ b/net/quic/test_tools/simple_quic_framer.h
@@ -7,6 +7,7 @@
#include <vector>
+#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_protocol.h"