summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/net.gyp7
-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
-rw-r--r--net/tools/quic/end_to_end_test.cc20
-rw-r--r--net/tools/quic/quic_client.cc9
-rw-r--r--net/tools/quic/quic_client.h18
-rw-r--r--net/tools/quic/quic_client_session.h1
-rw-r--r--net/tools/quic/quic_dispatcher.cc37
-rw-r--r--net/tools/quic/quic_dispatcher.h47
-rw-r--r--net/tools/quic/quic_dispatcher_test.cc103
-rw-r--r--net/tools/quic/quic_epoll_clock.h1
-rw-r--r--net/tools/quic/quic_packet_writer_wrapper.cc50
-rw-r--r--net/tools/quic/quic_packet_writer_wrapper.h51
-rw-r--r--net/tools/quic/quic_server.cc6
-rw-r--r--net/tools/quic/quic_server.h1
-rw-r--r--net/tools/quic/quic_server_session.cc15
-rw-r--r--net/tools/quic/quic_server_session.h14
-rw-r--r--net/tools/quic/quic_server_session_test.cc7
-rw-r--r--net/tools/quic/quic_server_test.cc4
-rw-r--r--net/tools/quic/quic_socket_utils.cc1
-rw-r--r--net/tools/quic/quic_spdy_client_stream.h1
-rw-r--r--net/tools/quic/quic_spdy_server_stream.h1
-rw-r--r--net/tools/quic/quic_time_wait_list_manager.cc7
-rw-r--r--net/tools/quic/quic_time_wait_list_manager.h11
-rw-r--r--net/tools/quic/quic_time_wait_list_manager_test.cc17
-rw-r--r--net/tools/quic/test_tools/mock_quic_dispatcher.cc6
-rw-r--r--net/tools/quic/test_tools/mock_quic_dispatcher.h2
-rw-r--r--net/tools/quic/test_tools/packet_dropping_test_writer.cc20
-rw-r--r--net/tools/quic/test_tools/packet_dropping_test_writer.h11
-rw-r--r--net/tools/quic/test_tools/quic_dispatcher_peer.cc12
-rw-r--r--net/tools/quic/test_tools/quic_dispatcher_peer.h10
-rw-r--r--net/tools/quic/test_tools/quic_test_client.cc76
-rw-r--r--net/tools/quic/test_tools/quic_test_client.h14
-rw-r--r--net/tools/quic/test_tools/quic_test_utils.cc4
-rw-r--r--net/tools/quic/test_tools/quic_test_utils.h7
90 files changed, 1188 insertions, 621 deletions
diff --git a/net/net.gyp b/net/net.gyp
index 5782b7a..4e362539 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -913,6 +913,8 @@
'quic/quic_time.h',
'quic/quic_utils.cc',
'quic/quic_utils.h',
+ 'quic/quic_write_blocked_list.cc',
+ 'quic/quic_write_blocked_list.h',
'quic/reliable_quic_stream.cc',
'quic/reliable_quic_stream.h',
'quic/spdy_utils.cc',
@@ -1865,8 +1867,6 @@
'quic/test_tools/quic_test_packet_maker.h',
'quic/test_tools/quic_test_utils.cc',
'quic/test_tools/quic_test_utils.h',
- 'quic/test_tools/quic_test_writer.cc',
- 'quic/test_tools/quic_test_writer.h',
'quic/test_tools/reliable_quic_stream_peer.cc',
'quic/test_tools/reliable_quic_stream_peer.h',
'quic/test_tools/simple_quic_framer.cc',
@@ -1906,6 +1906,7 @@
'quic/quic_stream_sequencer_test.cc',
'quic/quic_time_test.cc',
'quic/quic_utils_test.cc',
+ 'quic/quic_write_blocked_list_test.cc',
'quic/reliable_quic_stream_test.cc',
'server/http_server_response_info_unittest.cc',
'server/http_server_unittest.cc',
@@ -2906,6 +2907,8 @@
'tools/quic/quic_epoll_connection_helper.h',
'tools/quic/quic_in_memory_cache.cc',
'tools/quic/quic_in_memory_cache.h',
+ 'tools/quic/quic_packet_writer_wrapper.cc',
+ 'tools/quic/quic_packet_writer_wrapper.h',
'tools/quic/quic_server.cc',
'tools/quic/quic_server.h',
'tools/quic/quic_server_session.cc',
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"
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 70f0325..437aa991 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -6,6 +6,7 @@
#include <string>
#include <vector>
+#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/strings/string_number_conversions.h"
@@ -21,10 +22,10 @@
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_session_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/quic/test_tools/quic_test_writer.h"
#include "net/quic/test_tools/reliable_quic_stream_peer.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/quic_packet_writer_wrapper.h"
#include "net/tools/quic/quic_server.h"
#include "net/tools/quic/quic_socket_utils.h"
#include "net/tools/quic/quic_spdy_client_stream.h"
@@ -42,7 +43,6 @@ using base::StringPiece;
using base::WaitableEvent;
using net::test::QuicConnectionPeer;
using net::test::QuicSessionPeer;
-using net::test::QuicTestWriter;
using net::test::ReliableQuicStreamPeer;
using net::tools::test::PacketDroppingTestWriter;
using net::tools::test::QuicDispatcherPeer;
@@ -179,7 +179,7 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
QuicInMemoryCachePeer::ResetForTests();
}
- virtual QuicTestClient* CreateQuicClient(QuicTestWriter* writer) {
+ virtual QuicTestClient* CreateQuicClient(QuicPacketWriterWrapper* writer) {
QuicTestClient* client = new QuicTestClient(server_address_,
server_hostname_,
false, // not secure
@@ -204,8 +204,8 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
}
virtual void SetUp() {
- // The ownership of these gets transferred to the QuicTestWriter and
- // QuicDispatcher when Initialize() is executed.
+ // The ownership of these gets transferred to the QuicPacketWriterWrapper
+ // and QuicDispatcher when Initialize() is executed.
client_writer_ = new PacketDroppingTestWriter();
server_writer_ = new PacketDroppingTestWriter();
}
@@ -816,7 +816,7 @@ TEST_P(EndToEndTest, StreamCancelErrorTest) {
}
}
-class WrongAddressWriter : public QuicTestWriter {
+class WrongAddressWriter : public QuicPacketWriterWrapper {
public:
WrongAddressWriter() {
IPAddressNumber ip;
@@ -825,12 +825,14 @@ class WrongAddressWriter : public QuicTestWriter {
}
virtual WriteResult WritePacket(
- const char* buffer, size_t buf_len,
+ const char* buffer,
+ size_t buf_len,
const IPAddressNumber& real_self_address,
const IPEndPoint& peer_address,
QuicBlockedWriterInterface* blocked_writer) OVERRIDE {
- return writer()->WritePacket(buffer, buf_len, self_address_.address(),
- peer_address, blocked_writer);
+ // Use wrong address!
+ return QuicPacketWriterWrapper::WritePacket(
+ buffer, buf_len, self_address_.address(), peer_address, blocked_writer);
}
virtual bool IsWriteBlockedDataBuffered() const OVERRIDE {
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc
index df7a493..56648ad 100644
--- a/net/tools/quic/quic_client.cc
+++ b/net/tools/quic/quic_client.cc
@@ -247,12 +247,17 @@ void QuicClient::OnEvent(int fd, EpollEvent* event) {
}
void QuicClient::OnClose(QuicDataStream* stream) {
+ QuicSpdyClientStream* client_stream =
+ static_cast<QuicSpdyClientStream*>(stream);
+ if (response_listener_.get() != NULL) {
+ response_listener_->OnCompleteResponse(
+ stream->id(), client_stream->headers(), client_stream->data());
+ }
+
if (!print_response_) {
return;
}
- QuicSpdyClientStream* client_stream =
- static_cast<QuicSpdyClientStream*>(stream);
const BalsaHeaders& headers = client_stream->headers();
printf("%s\n", headers.first_line().as_string().c_str());
for (BalsaHeaders::const_header_lines_iterator i =
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h
index 5e03882..0b8efe8 100644
--- a/net/tools/quic/quic_client.h
+++ b/net/tools/quic/quic_client.h
@@ -10,6 +10,7 @@
#include <string>
+#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/ip_endpoint.h"
@@ -36,6 +37,15 @@ class QuicClientPeer;
class QuicClient : public EpollCallbackInterface,
public QuicDataStream::Visitor {
public:
+ class ResponseListener {
+ public:
+ ResponseListener() {}
+ virtual ~ResponseListener() {}
+ virtual void OnCompleteResponse(QuicStreamId id,
+ const BalsaHeaders& response_headers,
+ const string& response_body) = 0;
+ };
+
QuicClient(IPEndPoint server_address,
const string& server_hostname,
const QuicVersionVector& supported_versions,
@@ -152,6 +162,11 @@ class QuicClient : public EpollCallbackInterface,
supported_versions_ = versions;
}
+ // Takes ownership of the listener.
+ void set_response_listener(ResponseListener* listener) {
+ response_listener_.reset(listener);
+ }
+
protected:
virtual QuicGuid GenerateGuid();
virtual QuicEpollConnectionHelper* CreateQuicConnectionHelper();
@@ -192,6 +207,9 @@ class QuicClient : public EpollCallbackInterface,
// Helper to be used by created connections.
scoped_ptr<QuicEpollConnectionHelper> helper_;
+ // Listens for full responses.
+ scoped_ptr<ResponseListener> response_listener_;
+
// Writer used to actually send packets to the wire.
scoped_ptr<QuicPacketWriter> writer_;
diff --git a/net/tools/quic/quic_client_session.h b/net/tools/quic/quic_client_session.h
index dcee15e..8330e2d 100644
--- a/net/tools/quic/quic_client_session.h
+++ b/net/tools/quic/quic_client_session.h
@@ -9,6 +9,7 @@
#include <string>
+#include "base/basictypes.h"
#include "net/quic/quic_crypto_client_stream.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_session.h"
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc
index dcb8d6a..e5fecc9 100644
--- a/net/tools/quic/quic_dispatcher.cc
+++ b/net/tools/quic/quic_dispatcher.cc
@@ -12,9 +12,11 @@
#include "net/quic/quic_utils.h"
#include "net/tools/quic/quic_default_packet_writer.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
+#include "net/tools/quic/quic_packet_writer_wrapper.h"
#include "net/tools/quic/quic_socket_utils.h"
namespace net {
+
namespace tools {
using base::StringPiece;
@@ -39,8 +41,7 @@ class DeleteSessionsAlarm : public EpollAlarm {
class QuicDispatcher::QuicFramerVisitor : public QuicFramerVisitorInterface {
public:
explicit QuicFramerVisitor(QuicDispatcher* dispatcher)
- : dispatcher_(dispatcher) {
- }
+ : dispatcher_(dispatcher) {}
// QuicFramerVisitorInterface implementation
virtual void OnPacket() OVERRIDE {}
@@ -123,17 +124,12 @@ class QuicDispatcher::QuicFramerVisitor : public QuicFramerVisitorInterface {
QuicDispatcher::QuicDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
const QuicVersionVector& supported_versions,
- int fd,
EpollServer* epoll_server)
: config_(config),
crypto_config_(crypto_config),
- time_wait_list_manager_(
- new QuicTimeWaitListManager(this, epoll_server, supported_versions)),
delete_sessions_alarm_(new DeleteSessionsAlarm(this)),
epoll_server_(epoll_server),
- fd_(fd),
helper_(new QuicEpollConnectionHelper(epoll_server_)),
- writer_(new QuicDefaultPacketWriter(fd)),
supported_versions_(supported_versions),
current_packet_(NULL),
framer_(supported_versions, /*unused*/ QuicTime::Zero(), true),
@@ -146,9 +142,12 @@ QuicDispatcher::~QuicDispatcher() {
STLDeleteElements(&closed_session_list_);
}
-void QuicDispatcher::set_fd(int fd) {
- fd_ = fd;
- writer_.reset(new QuicDefaultPacketWriter(fd));
+void QuicDispatcher::Initialize(int fd) {
+ DCHECK(writer_ == NULL);
+ writer_.reset(CreateWriterWrapper(CreateWriter(fd)));
+ time_wait_list_manager_.reset(
+ new QuicTimeWaitListManager(writer_.get(), this,
+ epoll_server(), supported_versions()));
}
// TODO(fnk): remove the Writer interface implementation in favor of
@@ -332,6 +331,11 @@ void QuicDispatcher::OnConnectionClosed(QuicGuid guid, QuicErrorCode error) {
CleanUpSession(it);
}
+void QuicDispatcher::OnWriteBlocked(QuicBlockedWriterInterface* writer) {
+ DCHECK(writer_->IsWriteBlocked());
+ write_blocked_list_.insert(make_pair(writer, true));
+}
+
QuicSession* QuicDispatcher::CreateQuicSession(
QuicGuid guid,
const IPEndPoint& server_address,
@@ -343,6 +347,19 @@ QuicSession* QuicDispatcher::CreateQuicSession(
return session;
}
+QuicPacketWriter* QuicDispatcher::CreateWriter(int fd) {
+ return new QuicDefaultPacketWriter(fd);
+}
+
+QuicPacketWriterWrapper* QuicDispatcher::CreateWriterWrapper(
+ QuicPacketWriter* writer) {
+ return new QuicPacketWriterWrapper(writer);
+}
+
+void QuicDispatcher::set_writer(QuicPacketWriter* writer) {
+ writer_->set_writer(writer);
+}
+
bool QuicDispatcher::HandlePacketForTimeWait(
const QuicPacketPublicHeader& header) {
if (header.reset_flag) {
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h
index 1c010ab..47c31d2 100644
--- a/net/tools/quic/quic_dispatcher.h
+++ b/net/tools/quic/quic_dispatcher.h
@@ -10,6 +10,7 @@
#include <list>
+#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/ip_endpoint.h"
@@ -37,11 +38,14 @@ namespace net {
class EpollServer;
class QuicConfig;
+class QuicConnectionHelper;
class QuicCryptoServerConfig;
class QuicSession;
namespace tools {
+class QuicPacketWriterWrapper;
+
namespace test {
class QuicDispatcherPeer;
} // namespace test
@@ -49,7 +53,8 @@ class QuicDispatcherPeer;
class DeleteSessionsAlarm;
class QuicEpollConnectionHelper;
-class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
+class QuicDispatcher : public QuicPacketWriter,
+ public QuicServerSessionVisitor {
public:
// Ideally we'd have a linked_hash_set: the boolean is unused.
typedef linked_hash_map<QuicBlockedWriterInterface*, bool> WriteBlockedList;
@@ -60,10 +65,12 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
QuicDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
const QuicVersionVector& supported_versions,
- int fd,
EpollServer* epoll_server);
+
virtual ~QuicDispatcher();
+ void Initialize(int fd);
+
// QuicPacketWriter
virtual WriteResult WritePacket(
const char* buffer, size_t buf_len,
@@ -89,11 +96,12 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
// Sends ConnectionClose frames to all connected clients.
void Shutdown();
+ // QuicServerSessionVisitor interface implementation:
// Ensure that the closed connection is cleaned up asynchronously.
virtual void OnConnectionClosed(QuicGuid guid, QuicErrorCode error) OVERRIDE;
- // Sets the fd and creates a default packet writer with that fd.
- void set_fd(int fd);
+ // Queues the blocked writer for later resumption.
+ virtual void OnWriteBlocked(QuicBlockedWriterInterface* writer) OVERRIDE;
typedef base::hash_map<QuicGuid, QuicSession*> SessionMap;
@@ -110,8 +118,17 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
WriteBlockedList* write_blocked_list() { return &write_blocked_list_; }
protected:
- const QuicConfig& config_;
- const QuicCryptoServerConfig& crypto_config_;
+ // Instantiates a new low-level packet writer. Caller takes ownership of the
+ // returned object.
+ QuicPacketWriter* CreateWriter(int fd);
+
+ // Instantiates a new top-level writer wrapper. Takes ownership of |writer|.
+ // Caller takes ownership of the returned object.
+ virtual QuicPacketWriterWrapper* CreateWriterWrapper(
+ QuicPacketWriter* writer);
+
+ // Replaces the packet writer with |writer|. Takes ownership of |writer|.
+ void set_writer(QuicPacketWriter* writer);
QuicTimeWaitListManager* time_wait_list_manager() {
return time_wait_list_manager_.get();
@@ -124,7 +141,6 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
return supported_versions_;
}
- protected:
// Called by |framer_visitor_| when the public header has been parsed.
virtual bool OnUnauthenticatedPublicHeader(
const QuicPacketPublicHeader& header);
@@ -140,6 +156,10 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
return *current_packet_;
}
+ const QuicConfig& config() const { return config_; }
+
+ const QuicCryptoServerConfig& crypto_config() const { return crypto_config_; }
+
private:
class QuicFramerVisitor;
friend class net::tools::test::QuicDispatcherPeer;
@@ -154,6 +174,10 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
bool HandlePacketForTimeWait(const QuicPacketPublicHeader& header);
+ const QuicConfig& config_;
+
+ const QuicCryptoServerConfig& crypto_config_;
+
// The list of connections waiting to write.
WriteBlockedList write_blocked_list_;
@@ -170,14 +194,13 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
EpollServer* epoll_server_; // Owned by the server.
- // The connection for client-server communication
- int fd_;
-
// The helper used for all connections.
scoped_ptr<QuicEpollConnectionHelper> helper_;
- // The writer to write to the socket with.
- scoped_ptr<QuicPacketWriter> writer_;
+ // The writer to write to the socket with. We require a writer wrapper to
+ // allow replacing writer implementation without disturbing running
+ // connections.
+ scoped_ptr<QuicPacketWriterWrapper> writer_;
// This vector contains QUIC versions which we currently support.
// This should be ordered such that the highest supported version is the first
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc
index 63400c1..5e4726f 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -12,8 +12,8 @@
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_crypto_stream.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/quic/test_tools/quic_test_writer.h"
#include "net/tools/epoll_server/epoll_server.h"
+#include "net/tools/quic/quic_packet_writer_wrapper.h"
#include "net/tools/quic/quic_time_wait_list_manager.h"
#include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
#include "net/tools/quic/test_tools/quic_test_utils.h"
@@ -23,7 +23,6 @@
using base::StringPiece;
using net::EpollServer;
using net::test::MockSession;
-using net::test::QuicTestWriter;
using net::tools::test::MockConnection;
using std::make_pair;
using testing::_;
@@ -43,7 +42,7 @@ class TestDispatcher : public QuicDispatcher {
explicit TestDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
EpollServer* eps)
- : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), 1, eps) {
+ : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), eps) {
}
MOCK_METHOD3(CreateQuicSession, QuicSession*(
@@ -62,8 +61,8 @@ class MockServerConnection : public MockConnection {
MockServerConnection(QuicGuid guid,
QuicDispatcher* dispatcher)
: MockConnection(guid, true),
- dispatcher_(dispatcher) {
- }
+ dispatcher_(dispatcher) {}
+
void UnregisterOnConnectionClosed() {
LOG(ERROR) << "Unregistering " << guid();
dispatcher_->OnConnectionClosed(guid(), QUIC_NO_ERROR);
@@ -95,6 +94,7 @@ class QuicDispatcherTest : public ::testing::Test {
dispatcher_(config_, crypto_config_, &eps_),
session1_(NULL),
session2_(NULL) {
+ dispatcher_.Initialize(1);
}
virtual ~QuicDispatcherTest() {}
@@ -202,8 +202,9 @@ TEST_F(QuicDispatcherTest, Shutdown) {
class MockTimeWaitListManager : public QuicTimeWaitListManager {
public:
MockTimeWaitListManager(QuicPacketWriter* writer,
+ QuicServerSessionVisitor* visitor,
EpollServer* eps)
- : QuicTimeWaitListManager(writer, eps, QuicSupportedVersions()) {
+ : QuicTimeWaitListManager(writer, visitor, eps, QuicSupportedVersions()) {
}
MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
@@ -215,7 +216,7 @@ class MockTimeWaitListManager : public QuicTimeWaitListManager {
TEST_F(QuicDispatcherTest, TimeWaitListManager) {
MockTimeWaitListManager* time_wait_list_manager =
new MockTimeWaitListManager(
- QuicDispatcherPeer::GetWriter(&dispatcher_), &eps_);
+ QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
// dispatcher takes the ownership of time_wait_list_manager.
QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
time_wait_list_manager);
@@ -257,7 +258,7 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
TEST_F(QuicDispatcherTest, StrayPacketToTimeWaitListManager) {
MockTimeWaitListManager* time_wait_list_manager =
new MockTimeWaitListManager(
- QuicDispatcherPeer::GetWriter(&dispatcher_), &eps_);
+ QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
// dispatcher takes the ownership of time_wait_list_manager.
QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
time_wait_list_manager);
@@ -272,30 +273,31 @@ TEST_F(QuicDispatcherTest, StrayPacketToTimeWaitListManager) {
ProcessPacket(addr, guid, false, "foo");
}
-class BlockingWriter : public QuicTestWriter {
+class BlockingWriter : public QuicPacketWriterWrapper {
public:
BlockingWriter() : write_blocked_(false) {}
virtual bool IsWriteBlocked() const OVERRIDE { return write_blocked_; }
virtual void SetWritable() OVERRIDE { write_blocked_ = false; }
- virtual bool IsWriteBlockedDataBuffered() const OVERRIDE { return false; }
virtual WriteResult WritePacket(
- const char* buffer, size_t buf_len, const IPAddressNumber& self_address,
+ const char* buffer,
+ size_t buf_len,
+ const IPAddressNumber& self_address,
const IPEndPoint& peer_address,
QuicBlockedWriterInterface* blocked_writer) OVERRIDE {
if (write_blocked_) {
return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN);
} else {
- return writer()->WritePacket(buffer, buf_len, self_address, peer_address,
- blocked_writer);
+ return QuicPacketWriterWrapper::WritePacket(
+ buffer, buf_len, self_address, peer_address, blocked_writer);
}
}
bool write_blocked_;
};
-class QuicWriteBlockedListTest : public QuicDispatcherTest {
+class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
public:
virtual void SetUp() {
writer_ = new BlockingWriter;
@@ -323,7 +325,7 @@ class QuicWriteBlockedListTest : public QuicDispatcherTest {
}
bool SetBlocked() {
- writer_->write_blocked_ = true;;
+ writer_->write_blocked_ = true;
return true;
}
@@ -332,12 +334,13 @@ class QuicWriteBlockedListTest : public QuicDispatcherTest {
QuicDispatcher::WriteBlockedList* blocked_list_;
};
-TEST_F(QuicWriteBlockedListTest, BasicOnCanWrite) {
+TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
// No OnCanWrite calls because no connections are blocked.
dispatcher_.OnCanWrite();
- // Register connection 1 for events, and make sure it's nofitied.
- blocked_list_->insert(make_pair(connection1(), true));
+ // Register connection 1 for events, and make sure it's notified.
+ SetBlocked();
+ dispatcher_.OnWriteBlocked(connection1());
EXPECT_CALL(*connection1(), OnCanWrite());
dispatcher_.OnCanWrite();
@@ -346,67 +349,75 @@ TEST_F(QuicWriteBlockedListTest, BasicOnCanWrite) {
EXPECT_FALSE(dispatcher_.OnCanWrite());
}
-TEST_F(QuicWriteBlockedListTest, OnCanWriteOrder) {
+TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
// Make sure we handle events in order.
InSequence s;
- blocked_list_->insert(make_pair(connection1(), true));
- blocked_list_->insert(make_pair(connection2(), true));
+ SetBlocked();
+ dispatcher_.OnWriteBlocked(connection1());
+ dispatcher_.OnWriteBlocked(connection2());
EXPECT_CALL(*connection1(), OnCanWrite());
EXPECT_CALL(*connection2(), OnCanWrite());
dispatcher_.OnCanWrite();
// Check the other ordering.
- blocked_list_->insert(make_pair(connection2(), true));
- blocked_list_->insert(make_pair(connection1(), true));
+ SetBlocked();
+ dispatcher_.OnWriteBlocked(connection2());
+ dispatcher_.OnWriteBlocked(connection1());
EXPECT_CALL(*connection2(), OnCanWrite());
EXPECT_CALL(*connection1(), OnCanWrite());
dispatcher_.OnCanWrite();
}
-TEST_F(QuicWriteBlockedListTest, OnCanWriteRemove) {
+TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
// Add and remove one connction.
- blocked_list_->insert(make_pair(connection1(), true));
+ SetBlocked();
+ dispatcher_.OnWriteBlocked(connection1());
blocked_list_->erase(connection1());
EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
dispatcher_.OnCanWrite();
// Add and remove one connction and make sure it doesn't affect others.
- blocked_list_->insert(make_pair(connection1(), true));
- blocked_list_->insert(make_pair(connection2(), true));
+ SetBlocked();
+ dispatcher_.OnWriteBlocked(connection1());
+ dispatcher_.OnWriteBlocked(connection2());
blocked_list_->erase(connection1());
EXPECT_CALL(*connection2(), OnCanWrite());
dispatcher_.OnCanWrite();
// Add it, remove it, and add it back and make sure things are OK.
- blocked_list_->insert(make_pair(connection1(), true));
+ SetBlocked();
+ dispatcher_.OnWriteBlocked(connection1());
blocked_list_->erase(connection1());
- blocked_list_->insert(make_pair(connection1(), true));
+ dispatcher_.OnWriteBlocked(connection1());
EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
dispatcher_.OnCanWrite();
}
-TEST_F(QuicWriteBlockedListTest, DoubleAdd) {
+TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
// Make sure a double add does not necessitate a double remove.
- blocked_list_->insert(make_pair(connection1(), true));
- blocked_list_->insert(make_pair(connection1(), true));
+ SetBlocked();
+ dispatcher_.OnWriteBlocked(connection1());
+ dispatcher_.OnWriteBlocked(connection1());
blocked_list_->erase(connection1());
EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
dispatcher_.OnCanWrite();
// Make sure a double add does not result in two OnCanWrite calls.
- blocked_list_->insert(make_pair(connection1(), true));
- blocked_list_->insert(make_pair(connection1(), true));
+ SetBlocked();
+ dispatcher_.OnWriteBlocked(connection1());
+ dispatcher_.OnWriteBlocked(connection1());
EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
dispatcher_.OnCanWrite();
}
-TEST_F(QuicWriteBlockedListTest, OnCanWriteHandleBlock) {
+TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlock) {
// Finally make sure if we write block on a write call, we stop calling.
InSequence s;
- blocked_list_->insert(make_pair(connection1(), true));
- blocked_list_->insert(make_pair(connection2(), true));
+ SetBlocked();
+ dispatcher_.OnWriteBlocked(connection1());
+ dispatcher_.OnWriteBlocked(connection2());
EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
- Invoke(this, &QuicWriteBlockedListTest::SetBlocked));
+ Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
dispatcher_.OnCanWrite();
@@ -415,12 +426,13 @@ TEST_F(QuicWriteBlockedListTest, OnCanWriteHandleBlock) {
dispatcher_.OnCanWrite();
}
-TEST_F(QuicWriteBlockedListTest, LimitedWrites) {
+TEST_F(QuicDispatcherWriteBlockedListTest, LimitedWrites) {
// Make sure we call both writers. The first will register for more writing
// but should not be immediately called due to limits.
InSequence s;
- blocked_list_->insert(make_pair(connection1(), true));
- blocked_list_->insert(make_pair(connection2(), true));
+ SetBlocked();
+ dispatcher_.OnWriteBlocked(connection1());
+ dispatcher_.OnWriteBlocked(connection2());
EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(Return(true));
EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(Return(false));
dispatcher_.OnCanWrite();
@@ -430,13 +442,14 @@ TEST_F(QuicWriteBlockedListTest, LimitedWrites) {
dispatcher_.OnCanWrite();
}
-TEST_F(QuicWriteBlockedListTest, TestWriteLimits) {
+TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) {
// Finally make sure if we write block on a write call, we stop calling.
InSequence s;
- blocked_list_->insert(make_pair(connection1(), true));
- blocked_list_->insert(make_pair(connection2(), true));
+ SetBlocked();
+ dispatcher_.OnWriteBlocked(connection1());
+ dispatcher_.OnWriteBlocked(connection2());
EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
- Invoke(this, &QuicWriteBlockedListTest::SetBlocked));
+ Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
dispatcher_.OnCanWrite();
diff --git a/net/tools/quic/quic_epoll_clock.h b/net/tools/quic/quic_epoll_clock.h
index fb21354..76c0c50 100644
--- a/net/tools/quic/quic_epoll_clock.h
+++ b/net/tools/quic/quic_epoll_clock.h
@@ -5,6 +5,7 @@
#ifndef NET_TOOLS_QUIC_QUIC_EPOLL_CLOCK_H_
#define NET_TOOLS_QUIC_QUIC_EPOLL_CLOCK_H_
+#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "net/quic/quic_clock.h"
#include "net/quic/quic_time.h"
diff --git a/net/tools/quic/quic_packet_writer_wrapper.cc b/net/tools/quic/quic_packet_writer_wrapper.cc
new file mode 100644
index 0000000..f45b90c
--- /dev/null
+++ b/net/tools/quic/quic_packet_writer_wrapper.cc
@@ -0,0 +1,50 @@
+// 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/tools/quic/quic_packet_writer_wrapper.h"
+
+#include "net/quic/quic_protocol.h"
+
+namespace net {
+namespace tools {
+
+QuicPacketWriterWrapper::QuicPacketWriterWrapper() {}
+
+QuicPacketWriterWrapper::QuicPacketWriterWrapper(QuicPacketWriter* writer)
+ : writer_(writer) {}
+
+QuicPacketWriterWrapper::~QuicPacketWriterWrapper() {}
+
+WriteResult QuicPacketWriterWrapper::WritePacket(
+ const char* buffer,
+ size_t buf_len,
+ const net::IPAddressNumber& self_address,
+ const net::IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) {
+ return writer_->WritePacket(
+ buffer, buf_len, self_address, peer_address, blocked_writer);
+}
+
+bool QuicPacketWriterWrapper::IsWriteBlockedDataBuffered() const {
+ return writer_->IsWriteBlockedDataBuffered();
+}
+
+bool QuicPacketWriterWrapper::IsWriteBlocked() const {
+ return writer_->IsWriteBlocked();
+}
+
+void QuicPacketWriterWrapper::SetWritable() {
+ writer_->SetWritable();
+}
+
+void QuicPacketWriterWrapper::set_writer(QuicPacketWriter* writer) {
+ writer_.reset(writer);
+}
+
+QuicPacketWriter* QuicPacketWriterWrapper::release_writer() {
+ return writer_.release();
+}
+
+} // namespace tools
+} // namespace net
diff --git a/net/tools/quic/quic_packet_writer_wrapper.h b/net/tools/quic/quic_packet_writer_wrapper.h
new file mode 100644
index 0000000..4a74ce8
--- /dev/null
+++ b/net/tools/quic/quic_packet_writer_wrapper.h
@@ -0,0 +1,51 @@
+// 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_TOOLS_QUIC_QUIC_PACKET_WRITER_WRAPPER_H_
+#define NET_TOOLS_QUIC_QUIC_PACKET_WRITER_WRAPPER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/quic_packet_writer.h"
+
+namespace net {
+
+namespace tools {
+
+// Wraps a writer object to allow dynamically extending functionality. Use
+// cases: replace writer while dispatcher and connections hold on to the
+// wrapper; mix in monitoring in internal server; mix in mocks in unit tests.
+class QuicPacketWriterWrapper : public net::QuicPacketWriter {
+ public:
+ QuicPacketWriterWrapper();
+ explicit QuicPacketWriterWrapper(QuicPacketWriter* writer);
+ virtual ~QuicPacketWriterWrapper();
+
+ // Default implementation of the QuicPacketWriter interface. Passes everything
+ // to |writer_|.
+ virtual WriteResult WritePacket(
+ const char* buffer,
+ size_t buf_len,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) OVERRIDE;
+ virtual bool IsWriteBlockedDataBuffered() const OVERRIDE;
+ virtual bool IsWriteBlocked() const OVERRIDE;
+ virtual void SetWritable() OVERRIDE;
+
+ // Takes ownership of |writer|.
+ void set_writer(QuicPacketWriter* writer);
+
+ // Releases ownership of |writer_|.
+ QuicPacketWriter* release_writer();
+
+ private:
+ scoped_ptr<QuicPacketWriter> writer_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicPacketWriterWrapper);
+};
+
+} // namespace tools
+} // namespace net
+
+#endif // NET_TOOLS_QUIC_QUIC_PACKET_WRITER_WRAPPER_H_
diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc
index 472f2b8..bef78e6 100644
--- a/net/tools/quic/quic_server.cc
+++ b/net/tools/quic/quic_server.cc
@@ -147,9 +147,9 @@ bool QuicServer::Listen(const IPEndPoint& address) {
}
epoll_server_.RegisterFD(fd_, this, kEpollFlags);
- dispatcher_.reset(new QuicDispatcher(config_, crypto_config_,
- supported_versions_,
- fd_, &epoll_server_));
+ dispatcher_.reset(new QuicDispatcher(
+ config_, crypto_config_, supported_versions_, &epoll_server_));
+ dispatcher_->Initialize(fd_);
return true;
}
diff --git a/net/tools/quic/quic_server.h b/net/tools/quic/quic_server.h
index 1c22f11..fefac5d 100644
--- a/net/tools/quic/quic_server.h
+++ b/net/tools/quic/quic_server.h
@@ -8,6 +8,7 @@
#ifndef NET_TOOLS_QUIC_QUIC_SERVER_H_
#define NET_TOOLS_QUIC_QUIC_SERVER_H_
+#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/crypto/quic_crypto_server_config.h"
diff --git a/net/tools/quic/quic_server_session.cc b/net/tools/quic/quic_server_session.cc
index 29fd3165..1d0494c 100644
--- a/net/tools/quic/quic_server_session.cc
+++ b/net/tools/quic/quic_server_session.cc
@@ -15,13 +15,11 @@ namespace tools {
QuicServerSession::QuicServerSession(
const QuicConfig& config,
QuicConnection* connection,
- QuicSessionOwner* owner)
+ QuicServerSessionVisitor* visitor)
: QuicSession(connection, config),
- owner_(owner) {
-}
+ visitor_(visitor) {}
-QuicServerSession::~QuicServerSession() {
-}
+QuicServerSession::~QuicServerSession() {}
void QuicServerSession::InitializeSession(
const QuicCryptoServerConfig& crypto_config) {
@@ -36,7 +34,12 @@ QuicCryptoServerStream* QuicServerSession::CreateQuicCryptoServerStream(
void QuicServerSession::OnConnectionClosed(QuicErrorCode error,
bool from_peer) {
QuicSession::OnConnectionClosed(error, from_peer);
- owner_->OnConnectionClosed(connection()->guid(), error);
+ visitor_->OnConnectionClosed(connection()->guid(), error);
+}
+
+void QuicServerSession::OnWriteBlocked() {
+ QuicSession::OnWriteBlocked();
+ visitor_->OnWriteBlocked(connection());
}
bool QuicServerSession::ShouldCreateIncomingDataStream(QuicStreamId id) {
diff --git a/net/tools/quic/quic_server_session.h b/net/tools/quic/quic_server_session.h
index ff921bb..288cc68 100644
--- a/net/tools/quic/quic_server_session.h
+++ b/net/tools/quic/quic_server_session.h
@@ -10,6 +10,7 @@
#include <set>
#include <vector>
+#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "net/quic/quic_crypto_server_stream.h"
@@ -18,6 +19,7 @@
namespace net {
+class QuicBlockedWriterInterface;
class QuicConfig;
class QuicConnection;
class QuicCryptoServerConfig;
@@ -31,22 +33,24 @@ class QuicServerSessionPeer;
// An interface from the session to the entity owning the session.
// This lets the session notify its owner (the Dispatcher) when the connection
-// is closed.
-class QuicSessionOwner {
+// is closed or blocked.
+class QuicServerSessionVisitor {
public:
- virtual ~QuicSessionOwner() {}
+ virtual ~QuicServerSessionVisitor() {}
virtual void OnConnectionClosed(QuicGuid guid, QuicErrorCode error) = 0;
+ virtual void OnWriteBlocked(QuicBlockedWriterInterface* writer) = 0;
};
class QuicServerSession : public QuicSession {
public:
QuicServerSession(const QuicConfig& config,
QuicConnection *connection,
- QuicSessionOwner* owner);
+ QuicServerSessionVisitor* visitor);
// Override the base class to notify the owner of the connection close.
virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer) OVERRIDE;
+ virtual void OnWriteBlocked() OVERRIDE;
virtual ~QuicServerSession();
@@ -74,7 +78,7 @@ class QuicServerSession : public QuicSession {
friend class test::QuicServerSessionPeer;
scoped_ptr<QuicCryptoServerStream> crypto_stream_;
- QuicSessionOwner* owner_;
+ QuicServerSessionVisitor* visitor_;
DISALLOW_COPY_AND_ASSIGN(QuicServerSession);
};
diff --git a/net/tools/quic/quic_server_session_test.cc b/net/tools/quic/quic_server_session_test.cc
index 2673148..1b2cb3f 100644
--- a/net/tools/quic/quic_server_session_test.cc
+++ b/net/tools/quic/quic_server_session_test.cc
@@ -60,10 +60,9 @@ class TestQuicQuicServerSession : public QuicServerSession {
public:
TestQuicQuicServerSession(const QuicConfig& config,
QuicConnection* connection,
- QuicSessionOwner* owner)
+ QuicServerSessionVisitor* owner)
: QuicServerSession(config, connection, owner),
- close_stream_on_data_(false) {
- }
+ close_stream_on_data_(false) {}
virtual QuicDataStream* CreateIncomingDataStream(
QuicStreamId id) OVERRIDE {
@@ -110,7 +109,7 @@ class QuicServerSessionTest : public ::testing::TestWithParam<QuicVersion> {
QuicDataStreamPeer::SetHeadersDecompressed(stream, true);
}
- StrictMock<MockQuicSessionOwner> owner_;
+ StrictMock<MockQuicServerSessionVisitor> owner_;
StrictMock<MockConnection>* connection_;
QuicConfig config_;
QuicCryptoServerConfig crypto_config_;
diff --git a/net/tools/quic/quic_server_test.cc b/net/tools/quic/quic_server_test.cc
index 23efeb6..833c25f 100644
--- a/net/tools/quic/quic_server_test.cc
+++ b/net/tools/quic/quic_server_test.cc
@@ -21,7 +21,9 @@ class QuicServerDispatchPacketTest : public ::testing::Test {
public:
QuicServerDispatchPacketTest()
: crypto_config_("blah", QuicRandom::GetInstance()),
- dispatcher_(config_, crypto_config_, 1234, &eps_) {}
+ dispatcher_(config_, crypto_config_, &eps_) {
+ dispatcher_.Initialize(1234);
+ }
void DispatchPacket(const QuicEncryptedPacket& packet) {
IPEndPoint client_addr, server_addr;
diff --git a/net/tools/quic/quic_socket_utils.cc b/net/tools/quic/quic_socket_utils.cc
index 87071a6..c51c9ae 100644
--- a/net/tools/quic/quic_socket_utils.cc
+++ b/net/tools/quic/quic_socket_utils.cc
@@ -11,6 +11,7 @@
#include <sys/uio.h>
#include <string>
+#include "base/basictypes.h"
#include "base/logging.h"
#include "net/quic/quic_protocol.h"
diff --git a/net/tools/quic/quic_spdy_client_stream.h b/net/tools/quic/quic_spdy_client_stream.h
index 1e60467..37b0812 100644
--- a/net/tools/quic/quic_spdy_client_stream.h
+++ b/net/tools/quic/quic_spdy_client_stream.h
@@ -8,6 +8,7 @@
#include <sys/types.h>
#include <string>
+#include "base/basictypes.h"
#include "base/strings/string_piece.h"
#include "net/base/io_buffer.h"
#include "net/quic/quic_data_stream.h"
diff --git a/net/tools/quic/quic_spdy_server_stream.h b/net/tools/quic/quic_spdy_server_stream.h
index 574ef76..029e25f 100644
--- a/net/tools/quic/quic_spdy_server_stream.h
+++ b/net/tools/quic/quic_spdy_server_stream.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/basictypes.h"
#include "net/base/io_buffer.h"
#include "net/quic/quic_data_stream.h"
#include "net/quic/quic_protocol.h"
diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc
index d17d721..4708d61 100644
--- a/net/tools/quic/quic_time_wait_list_manager.cc
+++ b/net/tools/quic/quic_time_wait_list_manager.cc
@@ -17,6 +17,7 @@
#include "net/quic/quic_framer.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_utils.h"
+#include "net/tools/quic/quic_server_session.h"
using base::StringPiece;
using std::make_pair;
@@ -93,13 +94,15 @@ class QuicTimeWaitListManager::QueuedPacket {
QuicTimeWaitListManager::QuicTimeWaitListManager(
QuicPacketWriter* writer,
+ QuicServerSessionVisitor* visitor,
EpollServer* epoll_server,
const QuicVersionVector& supported_versions)
: epoll_server_(epoll_server),
kTimeWaitPeriod_(QuicTime::Delta::FromSeconds(kTimeWaitSeconds)),
guid_clean_up_alarm_(new GuidCleanUpAlarm(this)),
clock_(epoll_server_),
- writer_(writer) {
+ writer_(writer),
+ visitor_(visitor) {
SetGuidCleanUpAlarm();
}
@@ -215,6 +218,7 @@ void QuicTimeWaitListManager::SendOrQueuePacket(QueuedPacket* packet) {
bool QuicTimeWaitListManager::WriteToWire(QueuedPacket* queued_packet) {
if (writer_->IsWriteBlocked()) {
+ visitor_->OnWriteBlocked(this);
return false;
}
WriteResult result = writer_->WritePacket(
@@ -226,6 +230,7 @@ bool QuicTimeWaitListManager::WriteToWire(QueuedPacket* queued_packet) {
if (result.status == WRITE_STATUS_BLOCKED) {
// If blocked and unbuffered, return false to retry sending.
DCHECK(writer_->IsWriteBlocked());
+ visitor_->OnWriteBlocked(this);
return writer_->IsWriteBlockedDataBuffered();
} else if (result.status == WRITE_STATUS_ERROR) {
LOG(WARNING) << "Received unknown error while sending reset packet to "
diff --git a/net/tools/quic/quic_time_wait_list_manager.h b/net/tools/quic/quic_time_wait_list_manager.h
index bb1caf2..70a6d0d 100644
--- a/net/tools/quic/quic_time_wait_list_manager.h
+++ b/net/tools/quic/quic_time_wait_list_manager.h
@@ -10,6 +10,7 @@
#include <deque>
+#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
#include "base/strings/string_piece.h"
#include "net/quic/quic_blocked_writer_interface.h"
@@ -23,6 +24,7 @@ namespace net {
namespace tools {
class GuidCleanUpAlarm;
+class QuicServerSessionVisitor;
namespace test {
class QuicTimeWaitListManagerPeer;
@@ -39,8 +41,10 @@ class QuicTimeWaitListManagerPeer;
class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
public:
// writer - the entity that writes to the socket. (Owned by the dispatcher)
+ // visitor - the entity that manages blocked writers. (The dispatcher)
// epoll_server - used to run clean up alarms. (Owned by the dispatcher)
QuicTimeWaitListManager(QuicPacketWriter* writer,
+ QuicServerSessionVisitor* visitor,
EpollServer* epoll_server,
const QuicVersionVector& supported_versions);
virtual ~QuicTimeWaitListManager();
@@ -137,7 +141,7 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
std::deque<QueuedPacket*> pending_packets_queue_;
// Used to schedule alarms to delete old guids which have been in the list for
- // too long. Owned by the dispatcher.
+ // too long.
EpollServer* epoll_server_;
// Time period for which guids should remain in time wait state.
@@ -150,9 +154,12 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
// Clock to efficiently measure approximate time from the epoll server.
QuicEpollClock clock_;
- // Interface that writes given buffer to the socket. Owned by the dispatcher.
+ // Interface that writes given buffer to the socket.
QuicPacketWriter* writer_;
+ // Interface that manages blocked writers.
+ QuicServerSessionVisitor* visitor_;
+
DISALLOW_COPY_AND_ASSIGN(QuicTimeWaitListManager);
};
diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc
index 31cbd41..6e76e96 100644
--- a/net/tools/quic/quic_time_wait_list_manager_test.cc
+++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -41,7 +41,7 @@ namespace test {
class QuicTimeWaitListManagerPeer {
public:
static bool ShouldSendResponse(QuicTimeWaitListManager* manager,
- int received_packet_count) {
+ int received_packet_count) {
return manager->ShouldSendResponse(received_packet_count);
}
@@ -57,14 +57,6 @@ class QuicTimeWaitListManagerPeer {
namespace {
-class TestTimeWaitListManager : public QuicTimeWaitListManager {
- public:
- TestTimeWaitListManager(QuicPacketWriter* writer,
- EpollServer* epoll_server)
- : QuicTimeWaitListManager(writer, epoll_server, QuicSupportedVersions()) {
- }
-};
-
class MockFakeTimeEpollServer : public FakeTimeEpollServer {
public:
MOCK_METHOD2(RegisterAlarm, void(int64 timeout_in_us,
@@ -74,8 +66,8 @@ class MockFakeTimeEpollServer : public FakeTimeEpollServer {
class QuicTimeWaitListManagerTest : public testing::Test {
protected:
QuicTimeWaitListManagerTest()
- : time_wait_list_manager_(
- &writer_, &epoll_server_, QuicSupportedVersions()),
+ : time_wait_list_manager_(&writer_, &visitor_,
+ &epoll_server_, QuicSupportedVersions()),
framer_(QuicSupportedVersions(), QuicTime::Zero(), true),
guid_(45),
writer_is_blocked_(false) {}
@@ -142,6 +134,7 @@ class QuicTimeWaitListManagerTest : public testing::Test {
NiceMock<MockFakeTimeEpollServer> epoll_server_;
StrictMock<MockPacketWriter> writer_;
+ StrictMock<MockQuicServerSessionVisitor> visitor_;
QuicTimeWaitListManager time_wait_list_manager_;
QuicFramer framer_;
QuicGuid guid_;
@@ -307,6 +300,7 @@ TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
.WillOnce(DoAll(
Assign(&writer_is_blocked_, true),
Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN))));
+ EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_));
ProcessPacket(guid, sequence_number);
// 3rd packet. No public reset should be sent;
ProcessPacket(guid, sequence_number);
@@ -321,6 +315,7 @@ TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
ENCRYPTION_NONE, other_guid, other_sequence_number));
EXPECT_CALL(writer_, WritePacket(_, _, _, _, _))
.Times(0);
+ EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_));
ProcessPacket(other_guid, other_sequence_number);
// Now expect all the write blocked public reset packets to be sent again.
diff --git a/net/tools/quic/test_tools/mock_quic_dispatcher.cc b/net/tools/quic/test_tools/mock_quic_dispatcher.cc
index 2d9c1ec..7248909 100644
--- a/net/tools/quic/test_tools/mock_quic_dispatcher.cc
+++ b/net/tools/quic/test_tools/mock_quic_dispatcher.cc
@@ -11,11 +11,9 @@ namespace test {
MockQuicDispatcher::MockQuicDispatcher(
const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
- QuicGuid guid,
EpollServer* eps)
- : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), guid,
- eps) {
-}
+ : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), eps) {}
+
MockQuicDispatcher::~MockQuicDispatcher() {}
} // namespace test
diff --git a/net/tools/quic/test_tools/mock_quic_dispatcher.h b/net/tools/quic/test_tools/mock_quic_dispatcher.h
index 36813c9..a2fec0f 100644
--- a/net/tools/quic/test_tools/mock_quic_dispatcher.h
+++ b/net/tools/quic/test_tools/mock_quic_dispatcher.h
@@ -21,8 +21,8 @@ class MockQuicDispatcher : public QuicDispatcher {
public:
MockQuicDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
- QuicGuid guid,
EpollServer* eps);
+
virtual ~MockQuicDispatcher();
MOCK_METHOD3(ProcessPacket, void(const IPEndPoint& server_address,
diff --git a/net/tools/quic/test_tools/packet_dropping_test_writer.cc b/net/tools/quic/test_tools/packet_dropping_test_writer.cc
index fe26579..0331efd 100644
--- a/net/tools/quic/test_tools/packet_dropping_test_writer.cc
+++ b/net/tools/quic/test_tools/packet_dropping_test_writer.cc
@@ -10,8 +10,6 @@
#include "net/tools/quic/quic_epoll_connection_helper.h"
#include "net/tools/quic/quic_socket_utils.h"
-using net::test::QuicTestWriter;
-
namespace net {
namespace tools {
namespace test {
@@ -64,7 +62,7 @@ PacketDroppingTestWriter::PacketDroppingTestWriter()
simple_random_.set_seed(seed);
}
-PacketDroppingTestWriter::~PacketDroppingTestWriter() { }
+PacketDroppingTestWriter::~PacketDroppingTestWriter() {}
void PacketDroppingTestWriter::SetConnectionHelper(
QuicEpollConnectionHelper* helper) {
@@ -76,7 +74,8 @@ void PacketDroppingTestWriter::SetConnectionHelper(
}
WriteResult PacketDroppingTestWriter::WritePacket(
- const char* buffer, size_t buf_len,
+ const char* buffer,
+ size_t buf_len,
const net::IPAddressNumber& self_address,
const net::IPEndPoint& peer_address,
QuicBlockedWriterInterface* blocked_writer) {
@@ -133,12 +132,8 @@ WriteResult PacketDroppingTestWriter::WritePacket(
return WriteResult(WRITE_STATUS_OK, buf_len);
}
- return writer()->WritePacket(buffer, buf_len, self_address, peer_address,
- blocked_writer);
-}
-
-bool PacketDroppingTestWriter::IsWriteBlockedDataBuffered() const {
- return false;
+ return QuicPacketWriterWrapper::WritePacket(
+ buffer, buf_len, self_address, peer_address, blocked_writer);
}
QuicTime PacketDroppingTestWriter::ReleaseNextPacket() {
@@ -160,8 +155,9 @@ QuicTime PacketDroppingTestWriter::ReleaseNextPacket() {
DVLOG(1) << "Releasing packet. " << (delayed_packets_.size() - 1)
<< " remaining.";
// Grab the next one off the queue and send it.
- writer()->WritePacket(iter->buffer.data(), iter->buffer.length(),
- iter->self_address, iter->peer_address, NULL);
+ QuicPacketWriterWrapper::WritePacket(
+ iter->buffer.data(), iter->buffer.length(),
+ iter->self_address, iter->peer_address, NULL);
DCHECK_GE(cur_buffer_size_, iter->buffer.length());
cur_buffer_size_ -= iter->buffer.length();
delayed_packets_.erase(iter);
diff --git a/net/tools/quic/test_tools/packet_dropping_test_writer.h b/net/tools/quic/test_tools/packet_dropping_test_writer.h
index 2a736e0..8ecaf1f 100644
--- a/net/tools/quic/test_tools/packet_dropping_test_writer.h
+++ b/net/tools/quic/test_tools/packet_dropping_test_writer.h
@@ -7,14 +7,14 @@
#include <list>
+#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "net/quic/quic_alarm.h"
#include "net/quic/quic_blocked_writer_interface.h"
-#include "net/quic/quic_packet_writer.h"
-#include "net/quic/test_tools/quic_test_writer.h"
#include "net/tools/quic/quic_epoll_clock.h"
+#include "net/tools/quic/quic_packet_writer_wrapper.h"
#include "net/tools/quic/test_tools/quic_test_client.h"
#include "net/tools/quic/test_tools/quic_test_utils.h"
@@ -25,7 +25,7 @@ namespace test {
// Simulates a connection that drops packets a configured percentage of the time
// and has a blocked socket a configured percentage of the time. Also provides
// the options to delay packets and reorder packets if delay is enabled.
-class PacketDroppingTestWriter : public net::test::QuicTestWriter {
+class PacketDroppingTestWriter : public QuicPacketWriterWrapper {
public:
PacketDroppingTestWriter();
@@ -35,13 +35,12 @@ class PacketDroppingTestWriter : public net::test::QuicTestWriter {
// QuicPacketWriter methods:
virtual WriteResult WritePacket(
- const char* buffer, size_t buf_len,
+ const char* buffer,
+ size_t buf_len,
const IPAddressNumber& self_address,
const IPEndPoint& peer_address,
QuicBlockedWriterInterface* blocked_writer) OVERRIDE;
- virtual bool IsWriteBlockedDataBuffered() const OVERRIDE;
-
// Writes out any packet which should have been sent by now
// to the contained writer and returns the time
// for the next delayed packet to be written.
diff --git a/net/tools/quic/test_tools/quic_dispatcher_peer.cc b/net/tools/quic/test_tools/quic_dispatcher_peer.cc
index 03324a0..7303175 100644
--- a/net/tools/quic/test_tools/quic_dispatcher_peer.cc
+++ b/net/tools/quic/test_tools/quic_dispatcher_peer.cc
@@ -6,8 +6,7 @@
#include "net/quic/quic_default_packet_writer.h"
#include "net/tools/quic/quic_dispatcher.h"
-
-using net::test::QuicTestWriter;
+#include "net/tools/quic/quic_packet_writer_wrapper.h"
namespace net {
namespace tools {
@@ -22,13 +21,14 @@ void QuicDispatcherPeer::SetTimeWaitListManager(
// static
void QuicDispatcherPeer::UseWriter(QuicDispatcher* dispatcher,
- QuicTestWriter* writer) {
- writer->set_writer(dispatcher->writer_.release());
- dispatcher->writer_.reset(writer);
+ QuicPacketWriterWrapper* writer) {
+ writer->set_writer(dispatcher->writer_->release_writer());
+ dispatcher->writer_->set_writer(writer);
}
// static
-QuicPacketWriter* QuicDispatcherPeer::GetWriter(QuicDispatcher* dispatcher) {
+QuicPacketWriterWrapper* QuicDispatcherPeer::GetWriter(
+ QuicDispatcher* dispatcher) {
return dispatcher->writer_.get();
}
diff --git a/net/tools/quic/test_tools/quic_dispatcher_peer.h b/net/tools/quic/test_tools/quic_dispatcher_peer.h
index 249dcb3..a6b72e0 100644
--- a/net/tools/quic/test_tools/quic_dispatcher_peer.h
+++ b/net/tools/quic/test_tools/quic_dispatcher_peer.h
@@ -5,11 +5,13 @@
#ifndef NET_TOOLS_QUIC_TEST_TOOLS_QUIC_DISPATCHER_PEER_H_
#define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_DISPATCHER_PEER_H_
-#include "net/quic/test_tools/quic_test_writer.h"
#include "net/tools/quic/quic_dispatcher.h"
namespace net {
namespace tools {
+
+class QuicPacketWriterWrapper;
+
namespace test {
class QuicDispatcherPeer {
@@ -18,10 +20,12 @@ class QuicDispatcherPeer {
QuicDispatcher* dispatcher,
QuicTimeWaitListManager* time_wait_list_manager);
+ // Injects |writer| into |dispatcher| beneath the top-level wrapper (to avoid
+ // messing up existing connections).
static void UseWriter(QuicDispatcher* dispatcher,
- net::test::QuicTestWriter* writer);
+ QuicPacketWriterWrapper* writer);
- static QuicPacketWriter* GetWriter(QuicDispatcher* dispatcher);
+ static QuicPacketWriterWrapper* GetWriter(QuicDispatcher* dispatcher);
static QuicEpollConnectionHelper* GetHelper(QuicDispatcher* dispatcher);
};
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index 428acc0..aac75ab 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -13,6 +13,7 @@
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/tools/balsa/balsa_headers.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
+#include "net/tools/quic/quic_packet_writer_wrapper.h"
#include "net/tools/quic/quic_spdy_client_stream.h"
#include "net/tools/quic/test_tools/http_message_test_utils.h"
#include "net/tools/quic/test_tools/quic_client_peer.h"
@@ -20,7 +21,6 @@
using base::StringPiece;
using net::test::QuicConnectionPeer;
-using net::test::QuicTestWriter;
using std::string;
using std::vector;
@@ -96,33 +96,31 @@ BalsaHeaders* MungeHeaders(const BalsaHeaders* const_headers,
}
// A quic client which allows mocking out writes.
-class QuicEpollClient : public QuicClient {
+class MockableQuicClient : public QuicClient {
public:
- typedef QuicClient Super;
-
- QuicEpollClient(IPEndPoint server_address,
- const string& server_hostname,
- const QuicVersionVector& supported_versions)
- : Super(server_address, server_hostname, supported_versions, false),
- override_guid_(0), test_writer_(NULL) {
- }
-
- QuicEpollClient(IPEndPoint server_address,
- const string& server_hostname,
- const QuicConfig& config,
- const QuicVersionVector& supported_versions)
- : Super(server_address, server_hostname, config, supported_versions),
- override_guid_(0), test_writer_(NULL) {
- }
-
- virtual ~QuicEpollClient() {
+ MockableQuicClient(IPEndPoint server_address,
+ const string& server_hostname,
+ const QuicVersionVector& supported_versions)
+ : QuicClient(server_address, server_hostname, supported_versions, false),
+ override_guid_(0),
+ test_writer_(NULL) {}
+
+ MockableQuicClient(IPEndPoint server_address,
+ const string& server_hostname,
+ const QuicConfig& config,
+ const QuicVersionVector& supported_versions)
+ : QuicClient(server_address, server_hostname, config, supported_versions),
+ override_guid_(0),
+ test_writer_(NULL) {}
+
+ virtual ~MockableQuicClient() {
if (connected()) {
Disconnect();
}
}
virtual QuicPacketWriter* CreateQuicPacketWriter() OVERRIDE {
- QuicPacketWriter* writer = Super::CreateQuicPacketWriter();
+ QuicPacketWriter* writer = QuicClient::CreateQuicPacketWriter();
if (!test_writer_) {
return writer;
}
@@ -131,24 +129,22 @@ class QuicEpollClient : public QuicClient {
}
virtual QuicGuid GenerateGuid() OVERRIDE {
- return override_guid_ ? override_guid_ : Super::GenerateGuid();
+ return override_guid_ ? override_guid_ : QuicClient::GenerateGuid();
}
// Takes ownership of writer.
- void UseWriter(QuicTestWriter* writer) { test_writer_ = writer; }
+ void UseWriter(QuicPacketWriterWrapper* writer) { test_writer_ = writer; }
- void UseGuid(QuicGuid guid) {
- override_guid_ = guid;
- }
+ void UseGuid(QuicGuid guid) { override_guid_ = guid; }
private:
QuicGuid override_guid_; // GUID to use, if nonzero
- QuicTestWriter* test_writer_;
+ QuicPacketWriterWrapper* test_writer_;
};
QuicTestClient::QuicTestClient(IPEndPoint address, const string& hostname,
const QuicVersionVector& supported_versions)
- : client_(new QuicEpollClient(address, hostname, supported_versions)) {
+ : client_(new MockableQuicClient(address, hostname, supported_versions)) {
Initialize(address, hostname, true);
}
@@ -156,7 +152,7 @@ QuicTestClient::QuicTestClient(IPEndPoint address,
const string& hostname,
bool secure,
const QuicVersionVector& supported_versions)
- : client_(new QuicEpollClient(address, hostname, supported_versions)) {
+ : client_(new MockableQuicClient(address, hostname, supported_versions)) {
Initialize(address, hostname, secure);
}
@@ -165,8 +161,8 @@ QuicTestClient::QuicTestClient(IPEndPoint address,
bool secure,
const QuicConfig& config,
const QuicVersionVector& supported_versions)
- : client_(new QuicEpollClient(address, hostname, config,
- supported_versions)) {
+ : client_(new MockableQuicClient(
+ address, hostname, config, supported_versions)) {
Initialize(address, hostname, secure);
}
@@ -237,6 +233,10 @@ ssize_t QuicTestClient::SendData(string data, bool last_data) {
return data.length();
}
+QuicPacketCreator::Options* QuicTestClient::options() {
+ return client_->options();
+}
+
string QuicTestClient::SendCustomSynchronousRequest(
const HTTPMessage& message) {
SendMessage(message);
@@ -274,6 +274,12 @@ QuicSpdyClientStream* QuicTestClient::GetOrCreateStream() {
return stream_;
}
+QuicErrorCode QuicTestClient::connection_error() {
+ return client()->session()->error();
+}
+
+QuicClient* QuicTestClient::client() { return client_.get(); }
+
const string& QuicTestClient::cert_common_name() const {
return reinterpret_cast<RecordingProofVerifier*>(proof_verifier_)
->common_name();
@@ -435,17 +441,17 @@ void QuicTestClient::OnClose(QuicDataStream* stream) {
stream_ = NULL;
}
-void QuicTestClient::UseWriter(QuicTestWriter* writer) {
- reinterpret_cast<QuicEpollClient*>(client_.get())->UseWriter(writer);
+void QuicTestClient::UseWriter(QuicPacketWriterWrapper* writer) {
+ client_->UseWriter(writer);
}
void QuicTestClient::UseGuid(QuicGuid guid) {
DCHECK(!connected());
- reinterpret_cast<QuicEpollClient*>(client_.get())->UseGuid(guid);
+ client_->UseGuid(guid);
}
void QuicTestClient::WaitForWriteToFlush() {
- while (connected() && client()->session()->HasQueuedData()) {
+ while (connected() && client()->session()->HasDataToWrite()) {
client_->WaitForEvents();
}
}
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h
index 9792f66..b750cbff 100644
--- a/net/tools/quic/test_tools/quic_test_client.h
+++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -12,7 +12,6 @@
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
#include "net/quic/quic_protocol.h"
-#include "net/quic/test_tools/quic_test_writer.h"
#include "net/tools/quic/quic_client.h"
namespace net {
@@ -21,9 +20,12 @@ class ProofVerifier;
namespace tools {
+class QuicPacketWriterWrapper;
+
namespace test {
class HTTPMessage;
+class MockableQuicClient;
// A toy QUIC client used for testing.
class QuicTestClient : public QuicDataStream::Visitor {
@@ -58,7 +60,7 @@ class QuicTestClient : public QuicDataStream::Visitor {
// Wraps data in a quic packet and sends it.
ssize_t SendData(string data, bool last_data);
- QuicPacketCreator::Options* options() { return client_->options(); }
+ QuicPacketCreator::Options* options();
void WaitForResponse();
@@ -86,7 +88,7 @@ class QuicTestClient : public QuicDataStream::Visitor {
// Configures client_ to take ownership of and use the writer.
// Must be called before initial connect.
- void UseWriter(net::test::QuicTestWriter* writer);
+ void UseWriter(QuicPacketWriterWrapper* writer);
// If the given GUID is nonzero, configures client_ to use a specific GUID
// instead of a random one.
void UseGuid(QuicGuid guid);
@@ -95,9 +97,9 @@ class QuicTestClient : public QuicDataStream::Visitor {
QuicSpdyClientStream* GetOrCreateStream();
QuicRstStreamErrorCode stream_error() { return stream_error_; }
- QuicErrorCode connection_error() { return client()->session()->error(); }
+ QuicErrorCode connection_error();
- QuicClient* client() { return client_.get(); }
+ QuicClient* client();
// cert_common_name returns the common name value of the server's certificate,
// or the empty string if no certificate was presented.
@@ -120,7 +122,7 @@ class QuicTestClient : public QuicDataStream::Visitor {
IPEndPoint server_address_;
IPEndPoint client_address_;
- scoped_ptr<QuicClient> client_; // The actual client
+ scoped_ptr<MockableQuicClient> client_; // The actual client
QuicSpdyClientStream* stream_;
QuicRstStreamErrorCode stream_error_;
diff --git a/net/tools/quic/test_tools/quic_test_utils.cc b/net/tools/quic/test_tools/quic_test_utils.cc
index 2d013c3..9b82b9d 100644
--- a/net/tools/quic/test_tools/quic_test_utils.cc
+++ b/net/tools/quic/test_tools/quic_test_utils.cc
@@ -96,10 +96,10 @@ MockPacketWriter::MockPacketWriter() {
MockPacketWriter::~MockPacketWriter() {
}
-MockQuicSessionOwner::MockQuicSessionOwner() {
+MockQuicServerSessionVisitor::MockQuicServerSessionVisitor() {
}
-MockQuicSessionOwner::~MockQuicSessionOwner() {
+MockQuicServerSessionVisitor::~MockQuicServerSessionVisitor() {
}
bool TestDecompressorVisitor::OnDecompressedData(StringPiece data) {
diff --git a/net/tools/quic/test_tools/quic_test_utils.h b/net/tools/quic/test_tools/quic_test_utils.h
index a263747..af46b77 100644
--- a/net/tools/quic/test_tools/quic_test_utils.h
+++ b/net/tools/quic/test_tools/quic_test_utils.h
@@ -128,11 +128,12 @@ class MockPacketWriter : public QuicPacketWriter {
MOCK_METHOD0(SetWritable, void());
};
-class MockQuicSessionOwner : public QuicSessionOwner {
+class MockQuicServerSessionVisitor : public QuicServerSessionVisitor {
public:
- MockQuicSessionOwner();
- virtual ~MockQuicSessionOwner();
+ MockQuicServerSessionVisitor();
+ virtual ~MockQuicServerSessionVisitor();
MOCK_METHOD2(OnConnectionClosed, void(QuicGuid guid, QuicErrorCode error));
+ MOCK_METHOD1(OnWriteBlocked, void(QuicBlockedWriterInterface* writer));
};
class TestDecompressorVisitor : public QuicSpdyDecompressor::Visitor {