summaryrefslogtreecommitdiffstats
path: root/net/quic
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-18 05:43:20 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-18 05:43:20 +0000
commitc995c57ac3cbf7c29c56dd4aba5ab8d1ed54c73f (patch)
treeefdaf02c88a1809609cb65488c75e27f31bb3cf2 /net/quic
parent736337679a839a57b9a39e2c0677d52a44e31dc6 (diff)
downloadchromium_src-c995c57ac3cbf7c29c56dd4aba5ab8d1ed54c73f.zip
chromium_src-c995c57ac3cbf7c29c56dd4aba5ab8d1ed54c73f.tar.gz
chromium_src-c995c57ac3cbf7c29c56dd4aba5ab8d1ed54c73f.tar.bz2
Cleaning up constructors for QuicData, QuicPacket and QuicEncryptedPacket to not take unnamed bool values.
Merge internal change: 41194576 Simplify the interface between the QuicConnection and the congestion control system. Add a QuicCongestionManager to wrap the the SendScheduler and ReceiptMetricsCollector in a single class for all congestion-related functionality. (Narrows the SendScheduler-specific interface to just those methods called by the QuicConnection.) This is a minor cleanup in advance of moving the RTO management out of QuicConnection (since it is algorithm specific). Merge internal change: 41188949 Refactor SendStreamData to frame one StreamFrame at once and send it, instea d of framing and serializing multiple in DataToStream. Merge internal change: 41155771 Expand the 48 bit on-the-wire packet sequence number into the full 64 bit se quence number. Merge internal change: 41147680 Enable encryption of private flags. Merge internal change: 41147034 Splitting flags into private and public and implementing framing for both. Merge internal change: 41145985 Add a zero length padding frame. Merge internal change: 41141396 Remove "support" for PDUs Merge internal change: 41133537 Remove the Clear method from QuicPacketCreator options, and explicitly initialize all field in the constructor. Merge internal change: 41128100 Cleanup from chrome cl 11820003 Merge internal change: 41118012 Refactor to pull out connection close so that connection can be closed without sending connection close frame. Merge internal change: 41026182 Keep a bool to check if a QuicPacket is an FEC packet instead of taking whol e packet flag as an input to the constructor. Merge internal change: 41026127 Remove default constructors for QuicTime and QuicTime::Delta and used static Zero() methods instead to make it clear what value is being used. One annoying side-effect is this means that maps which have these objects as keys can't not be accessed with []. Thankfully, this is not a huge problem. (It only affects us in one place). But I can add the default constructors back to support this use case, if necessary. (I'd prefer not to since I think Zero() is more clear, but can go either way). Merge internal change: 40993340 Replace boolean literals with named constants ini QuicConnection::SendPacket() calls. Merge internal change: 40991762 Consistently use Retransmit/Retransmission (instead of Resend) when talking about sending QUIC data a second time (in a new packet). Merge internal change: 40988697 Move the logic for RTO timeout handling from the Helper to the QuicConnection. Merge internal change: 40980852 Fixing a bug where a non-existant frame corresponding to an FEC was being deleted. Merge internal change: 40883214 Change the QUIC FEC group number from an ad-hoc id to the sequence number of the first packet in the group. Over the wire, however, send a 1 byte delta from the sequence number of the current packet to the sequence number of the first protected packet in the group. Merge internal change: 40881017 TBR=jar@chromium.org Review URL: https://chromiumcodereview.appspot.com/11959039 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177612 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/quic')
-rw-r--r--net/quic/congestion_control/cubic.cc10
-rw-r--r--net/quic/congestion_control/fix_rate_sender.cc8
-rw-r--r--net/quic/congestion_control/fix_rate_sender.h4
-rw-r--r--net/quic/congestion_control/fix_rate_test.cc4
-rw-r--r--net/quic/congestion_control/hybrid_slow_start.cc7
-rw-r--r--net/quic/congestion_control/leaky_bucket.cc1
-rw-r--r--net/quic/congestion_control/paced_sender_test.cc3
-rw-r--r--net/quic/congestion_control/quic_congestion_manager.cc54
-rw-r--r--net/quic/congestion_control/quic_congestion_manager.h80
-rw-r--r--net/quic/congestion_control/quic_receipt_metrics_collector.h15
-rw-r--r--net/quic/congestion_control/quic_receipt_metrics_collector_test.cc2
-rw-r--r--net/quic/congestion_control/quic_send_scheduler.cc10
-rw-r--r--net/quic/congestion_control/quic_send_scheduler.h16
-rw-r--r--net/quic/congestion_control/quic_send_scheduler_test.cc4
-rw-r--r--net/quic/congestion_control/send_algorithm_interface.h4
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender.cc21
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender.h4
-rw-r--r--net/quic/congestion_control/tcp_receiver_test.cc2
-rw-r--r--net/quic/crypto/crypto_protocol.cc7
-rw-r--r--net/quic/quic_connection.cc253
-rw-r--r--net/quic/quic_connection.h103
-rw-r--r--net/quic/quic_connection_helper.cc66
-rw-r--r--net/quic/quic_connection_helper.h15
-rw-r--r--net/quic/quic_connection_helper_test.cc37
-rw-r--r--net/quic/quic_connection_test.cc108
-rw-r--r--net/quic/quic_data_writer.cc5
-rw-r--r--net/quic/quic_data_writer.h2
-rw-r--r--net/quic/quic_fec_group.cc8
-rw-r--r--net/quic/quic_fec_group.h6
-rw-r--r--net/quic/quic_fec_group_test.cc8
-rw-r--r--net/quic/quic_framer.cc252
-rw-r--r--net/quic/quic_framer.h27
-rw-r--r--net/quic/quic_framer_test.cc603
-rw-r--r--net/quic/quic_http_stream_test.cc7
-rw-r--r--net/quic/quic_packet_creator.cc162
-rw-r--r--net/quic/quic_packet_creator.h54
-rw-r--r--net/quic/quic_packet_creator_test.cc239
-rw-r--r--net/quic/quic_protocol.cc4
-rw-r--r--net/quic/quic_protocol.h146
-rw-r--r--net/quic/quic_session.cc7
-rw-r--r--net/quic/quic_session.h6
-rw-r--r--net/quic/quic_stream_factory_test.cc15
-rw-r--r--net/quic/quic_time.cc13
-rw-r--r--net/quic/quic_time.h13
-rw-r--r--net/quic/quic_time_test.cc9
-rw-r--r--net/quic/reliable_quic_stream.cc5
-rw-r--r--net/quic/test_tools/mock_clock.cc6
-rw-r--r--net/quic/test_tools/quic_connection_peer.cc11
-rw-r--r--net/quic/test_tools/quic_connection_peer.h3
-rw-r--r--net/quic/test_tools/quic_test_utils.cc14
-rw-r--r--net/quic/test_tools/quic_test_utils.h10
51 files changed, 1535 insertions, 938 deletions
diff --git a/net/quic/congestion_control/cubic.cc b/net/quic/congestion_control/cubic.cc
index 6ea46bd..c1faeb3 100644
--- a/net/quic/congestion_control/cubic.cc
+++ b/net/quic/congestion_control/cubic.cc
@@ -70,7 +70,9 @@ const uint32 cube_root_table[] = {
} // namespace
Cubic::Cubic(const QuicClock* clock)
- : clock_(clock) {
+ : clock_(clock),
+ epoch_(QuicTime::Zero()),
+ last_update_time_(QuicTime::Zero()) {
Reset();
}
@@ -103,8 +105,8 @@ uint32 Cubic::CubeRoot(uint64 a) {
}
void Cubic::Reset() {
- epoch_ = QuicTime(); // Reset time.
- last_update_time_ = QuicTime(); // Reset time.
+ epoch_ = QuicTime::Zero(); // Reset time.
+ last_update_time_ = QuicTime::Zero(); // Reset time.
last_congestion_window_ = 0;
last_max_congestion_window_ = 0;
acked_packets_count_ = 0;
@@ -124,7 +126,7 @@ QuicTcpCongestionWindow Cubic::CongestionWindowAfterPacketLoss(
} else {
last_max_congestion_window_ = current_congestion_window;
}
- epoch_ = QuicTime(); // Reset time.
+ epoch_ = QuicTime::Zero(); // Reset time.
return (current_congestion_window * kBeta) >> 10;
}
diff --git a/net/quic/congestion_control/fix_rate_sender.cc b/net/quic/congestion_control/fix_rate_sender.cc
index fc9b6c7..46ca0b5 100644
--- a/net/quic/congestion_control/fix_rate_sender.cc
+++ b/net/quic/congestion_control/fix_rate_sender.cc
@@ -51,21 +51,21 @@ void FixRateSender::OnIncomingLoss(int /*number_of_lost_packets*/) {
void FixRateSender::SentPacket(QuicPacketSequenceNumber /*sequence_number*/,
size_t bytes,
- bool retransmit) {
+ bool is_retransmission) {
fix_rate_leaky_bucket_.Add(bytes);
paced_sender_.SentPacket(bytes);
- if (!retransmit) {
+ if (!is_retransmission) {
bytes_in_flight_ += bytes;
}
}
-QuicTime::Delta FixRateSender::TimeUntilSend(bool /*retransmit*/) {
+QuicTime::Delta FixRateSender::TimeUntilSend(bool /*is_retransmission*/) {
if (CongestionWindow() > fix_rate_leaky_bucket_.BytesPending()) {
if (CongestionWindow() <= bytes_in_flight_) {
// We need an ack before we send more.
return QuicTime::Delta::Infinite();
}
- QuicTime::Delta zero_time;
+ QuicTime::Delta zero_time(QuicTime::Delta::Zero());
return paced_sender_.TimeUntilSend(zero_time);
}
QuicTime::Delta time_remaining = fix_rate_leaky_bucket_.TimeRemaining();
diff --git a/net/quic/congestion_control/fix_rate_sender.h b/net/quic/congestion_control/fix_rate_sender.h
index c81581c..146ea23 100644
--- a/net/quic/congestion_control/fix_rate_sender.h
+++ b/net/quic/congestion_control/fix_rate_sender.h
@@ -31,8 +31,8 @@ class NET_EXPORT_PRIVATE FixRateSender : public SendAlgorithmInterface {
virtual void OnIncomingLoss(int number_of_lost_packets) OVERRIDE;
virtual void SentPacket(QuicPacketSequenceNumber equence_number,
size_t bytes,
- bool retransmit) OVERRIDE;
- virtual QuicTime::Delta TimeUntilSend(bool retransmit) OVERRIDE;
+ bool is_retransmission) OVERRIDE;
+ virtual QuicTime::Delta TimeUntilSend(bool is_retransmission) OVERRIDE;
virtual size_t AvailableCongestionWindow() OVERRIDE;
virtual int BandwidthEstimate() OVERRIDE;
// End implementation of SendAlgorithmInterface.
diff --git a/net/quic/congestion_control/fix_rate_test.cc b/net/quic/congestion_control/fix_rate_test.cc
index 5edabb0..6cb4956 100644
--- a/net/quic/congestion_control/fix_rate_test.cc
+++ b/net/quic/congestion_control/fix_rate_test.cc
@@ -34,7 +34,7 @@ class FixRateTest : public ::testing::Test {
TEST_F(FixRateTest, ReceiverAPI) {
QuicCongestionFeedbackFrame feedback;
- QuicTime timestamp;
+ QuicTime timestamp(QuicTime::Zero());
receiver_->SetBitrate(300000); // Bytes per second.
receiver_->RecordIncomingPacket(1, 1, timestamp, false);
ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
@@ -75,7 +75,7 @@ TEST_F(FixRateTest, FixRatePacing) {
receiver_->SetBitrate(240000); // Bytes per second.
ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback);
- QuicTime acc_advance_time;
+ QuicTime acc_advance_time(QuicTime::Zero());
QuicPacketSequenceNumber sequence_number = 0;
for (int i = 0; i < num_packets; i += 2) {
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
diff --git a/net/quic/congestion_control/hybrid_slow_start.cc b/net/quic/congestion_control/hybrid_slow_start.cc
index dcd2e4a5..cbdd1bb 100644
--- a/net/quic/congestion_control/hybrid_slow_start.cc
+++ b/net/quic/congestion_control/hybrid_slow_start.cc
@@ -19,8 +19,11 @@ HybridSlowStart::HybridSlowStart(const QuicClock* clock)
started_(false),
found_ack_train_(false),
found_delay_(false),
+ round_start_(QuicTime::Zero()),
end_sequence_number_(0),
- sample_count_(0) {
+ last_time_(QuicTime::Zero()),
+ sample_count_(0),
+ current_rtt_(QuicTime::Delta::Zero()) {
}
void HybridSlowStart::Restart() {
@@ -32,7 +35,7 @@ void HybridSlowStart::Reset(QuicPacketSequenceNumber end_sequence_number) {
DLOG(INFO) << "Reset hybrid slow start @" << end_sequence_number;
round_start_ = last_time_ = clock_->Now();
end_sequence_number_ = end_sequence_number;
- current_rtt_ = QuicTime::Delta(); // Reset to 0.
+ current_rtt_ = QuicTime::Delta::Zero();
sample_count_ = 0;
started_ = true;
}
diff --git a/net/quic/congestion_control/leaky_bucket.cc b/net/quic/congestion_control/leaky_bucket.cc
index d3dd513..60ec7a6 100644
--- a/net/quic/congestion_control/leaky_bucket.cc
+++ b/net/quic/congestion_control/leaky_bucket.cc
@@ -11,6 +11,7 @@ namespace net {
LeakyBucket::LeakyBucket(const QuicClock* clock, int bytes_per_second)
: clock_(clock),
bytes_(0),
+ time_last_updated_(QuicTime::Zero()),
draining_rate_bytes_per_s_(bytes_per_second) {
}
diff --git a/net/quic/congestion_control/paced_sender_test.cc b/net/quic/congestion_control/paced_sender_test.cc
index c49f654..e93261b 100644
--- a/net/quic/congestion_control/paced_sender_test.cc
+++ b/net/quic/congestion_control/paced_sender_test.cc
@@ -18,7 +18,8 @@ const int kHundredKBytesPerS = 100000;
class PacedSenderTest : public ::testing::Test {
protected:
PacedSenderTest()
- : paced_sender_(new PacedSender(&clock_, kHundredKBytesPerS)) {
+ : zero_time_(QuicTime::Delta::Zero()),
+ paced_sender_(new PacedSender(&clock_, kHundredKBytesPerS)) {
}
const QuicTime::Delta zero_time_;
diff --git a/net/quic/congestion_control/quic_congestion_manager.cc b/net/quic/congestion_control/quic_congestion_manager.cc
new file mode 100644
index 0000000..8e300bb
--- /dev/null
+++ b/net/quic/congestion_control/quic_congestion_manager.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/congestion_control/quic_congestion_manager.h"
+
+#include "net/quic/congestion_control/quic_receipt_metrics_collector.h"
+#include "net/quic/congestion_control/quic_send_scheduler.h"
+
+namespace net {
+
+QuicCongestionManager::QuicCongestionManager(
+ const QuicClock* clock,
+ CongestionFeedbackType type)
+ : collector_(new QuicReceiptMetricsCollector(clock, type)),
+ scheduler_(new QuicSendScheduler(clock, type)) {
+}
+
+QuicCongestionManager::~QuicCongestionManager() {
+}
+
+void QuicCongestionManager::SentPacket(QuicPacketSequenceNumber sequence_number,
+ size_t bytes,
+ bool is_retransmission) {
+ scheduler_->SentPacket(sequence_number, bytes, is_retransmission);
+}
+
+void QuicCongestionManager::OnIncomingQuicCongestionFeedbackFrame(
+ const QuicCongestionFeedbackFrame& frame) {
+ scheduler_->OnIncomingQuicCongestionFeedbackFrame(frame);
+}
+
+void QuicCongestionManager::OnIncomingAckFrame(const QuicAckFrame& frame) {
+ scheduler_->OnIncomingAckFrame(frame);
+}
+
+QuicTime::Delta QuicCongestionManager::TimeUntilSend(bool is_retransmission) {
+ return scheduler_->TimeUntilSend(is_retransmission);
+}
+
+bool QuicCongestionManager::GenerateCongestionFeedback(
+ QuicCongestionFeedbackFrame* feedback) {
+ return collector_->GenerateCongestionFeedback(feedback);
+}
+
+void QuicCongestionManager::RecordIncomingPacket(
+ size_t bytes,
+ QuicPacketSequenceNumber sequence_number,
+ QuicTime timestamp,
+ bool revived) {
+ collector_->RecordIncomingPacket(bytes, sequence_number, timestamp, revived);
+}
+
+} // namespace net
diff --git a/net/quic/congestion_control/quic_congestion_manager.h b/net/quic/congestion_control/quic_congestion_manager.h
new file mode 100644
index 0000000..9402213
--- /dev/null
+++ b/net/quic/congestion_control/quic_congestion_manager.h
@@ -0,0 +1,80 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This is the interface from the QuicConnection into the QUIC
+// congestion control code. It wraps the QuicSendScheduler and
+// QuicReceiptMetricsCollector and provides a single interface
+// for consumers.
+
+#ifndef NET_QUIC_CONGESTION_CONTROL_QUIC_CONGESTION_MANAGER_H_
+#define NET_QUIC_CONGESTION_CONTROL_QUIC_CONGESTION_MANAGER_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/quic_protocol.h"
+
+namespace net {
+
+namespace test {
+class QuicConnectionPeer;
+} // namespace test
+
+class QuicClock;
+class QuicReceiptMetricsCollector;
+class QuicSendScheduler;
+
+class QuicCongestionManager {
+ public:
+ QuicCongestionManager(const QuicClock* clock,
+ CongestionFeedbackType congestion_type);
+ virtual ~QuicCongestionManager();
+
+ // Called when we have received an ack frame from peer.
+ virtual void OnIncomingAckFrame(const QuicAckFrame& frame);
+
+ // Called when a congestion feedback frame is received from peer.
+ virtual void OnIncomingQuicCongestionFeedbackFrame(
+ const QuicCongestionFeedbackFrame& frame);
+
+ // Called when we have sent bytes to the peer. This informs the manager both
+ // the number of bytes sent and if they were retransmitted.
+ virtual void SentPacket(QuicPacketSequenceNumber sequence_number,
+ size_t bytes,
+ bool is_retransmission);
+
+ // Calculate the time until we can send the next packet to the wire.
+ // Note 1: When kUnknownWaitTime is returned, there is no need to poll
+ // TimeUntilSend again until we receive an OnIncomingAckFrame event.
+ // Note 2: Send algorithms may or may not use |retransmit| in their
+ // calculations.
+ virtual QuicTime::Delta TimeUntilSend(bool is_retransmission);
+
+ // Should be called before sending an ACK packet, to decide if we need
+ // to attach a QuicCongestionFeedbackFrame block.
+ // Returns false if no QuicCongestionFeedbackFrame block is needed.
+ // Otherwise fills in feedback and returns true.
+ virtual bool GenerateCongestionFeedback(
+ QuicCongestionFeedbackFrame* feedback);
+
+ // Should be called for each incoming packet.
+ // bytes: the packet size in bytes including IP headers.
+ // sequence_number: the unique sequence number from the QUIC packet header.
+ // timestamp: the arrival time of the packet.
+ // revived: true if the packet was lost and then recovered with help of a
+ // FEC packet.
+ virtual void RecordIncomingPacket(size_t bytes,
+ QuicPacketSequenceNumber sequence_number,
+ QuicTime timestamp,
+ bool revived);
+
+ private:
+ friend class test::QuicConnectionPeer;
+
+ scoped_ptr<QuicReceiptMetricsCollector> collector_;
+ scoped_ptr<QuicSendScheduler> scheduler_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CONGESTION_CONTROL_QUIC_CONGESTION_MANAGER_H_
diff --git a/net/quic/congestion_control/quic_receipt_metrics_collector.h b/net/quic/congestion_control/quic_receipt_metrics_collector.h
index dbd3c3c..d985cff 100644
--- a/net/quic/congestion_control/quic_receipt_metrics_collector.h
+++ b/net/quic/congestion_control/quic_receipt_metrics_collector.h
@@ -27,19 +27,18 @@ class NET_EXPORT_PRIVATE QuicReceiptMetricsCollector {
virtual ~QuicReceiptMetricsCollector();
- // Should be called for each ACK packet to decide if we need to attach a
- // QuicCongestionFeedbackFrame block.
+ // Should be called before sending an ACK packet, to decide if we need
+ // to attach a QuicCongestionFeedbackFrame block.
// Returns false if no QuicCongestionFeedbackFrame block is needed.
- // Otherwise fills in feedback and return true.
+ // Otherwise fills in feedback and returns true.
virtual bool GenerateCongestionFeedback(
QuicCongestionFeedbackFrame* feedback);
// Should be called for each incoming packet.
- // bytes: is the packet size in bytes including IP headers.
- // sequence_number: is the unique sequence number from the QUIC packet header.
- // timestamp: is the sent timestamp from the QUIC packet header.
- // TODO(pwestin) which type should we use for timestamp?
- // revived: is set if the packet is lost and then recovered with help of a
+ // bytes: the packet size in bytes including IP headers.
+ // sequence_number: the unique sequence number from the QUIC packet header.
+ // timestamp: the arrival time of the packet.
+ // revived: true if the packet was lost and then recovered with help of a
// FEC packet.
virtual void RecordIncomingPacket(size_t bytes,
QuicPacketSequenceNumber sequence_number,
diff --git a/net/quic/congestion_control/quic_receipt_metrics_collector_test.cc b/net/quic/congestion_control/quic_receipt_metrics_collector_test.cc
index 52f661c..891fcba 100644
--- a/net/quic/congestion_control/quic_receipt_metrics_collector_test.cc
+++ b/net/quic/congestion_control/quic_receipt_metrics_collector_test.cc
@@ -24,7 +24,7 @@ class QuicReceiptMetricsCollectorTest : public ::testing::Test {
TEST_F(QuicReceiptMetricsCollectorTest, FixedRateReceiverAPI) {
SetUpCongestionType(kFixRate);
QuicCongestionFeedbackFrame feedback;
- QuicTime timestamp;
+ QuicTime timestamp(QuicTime::Zero());
receiver_->RecordIncomingPacket(1, 1, timestamp, false);
ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
EXPECT_EQ(kFixRate, feedback.type);
diff --git a/net/quic/congestion_control/quic_send_scheduler.cc b/net/quic/congestion_control/quic_send_scheduler.cc
index 7b30ee0..ba18c96 100644
--- a/net/quic/congestion_control/quic_send_scheduler.cc
+++ b/net/quic/congestion_control/quic_send_scheduler.cc
@@ -67,11 +67,11 @@ int QuicSendScheduler::UpdatePacketHistory() {
void QuicSendScheduler::SentPacket(QuicPacketSequenceNumber sequence_number,
size_t bytes,
- bool retransmit) {
+ bool is_retransmission) {
int bucket = UpdatePacketHistory();
packet_history_[bucket] += bytes;
- send_algorithm_->SentPacket(sequence_number, bytes, retransmit);
- if (!retransmit) {
+ send_algorithm_->SentPacket(sequence_number, bytes, is_retransmission);
+ if (!is_retransmission) {
pending_packets_[sequence_number] =
new PendingPacket(bytes, clock_->Now());
}
@@ -125,8 +125,8 @@ void QuicSendScheduler::OnIncomingAckFrame(const QuicAckFrame& ack_frame) {
}
}
-QuicTime::Delta QuicSendScheduler::TimeUntilSend(bool retransmit) {
- return send_algorithm_->TimeUntilSend(retransmit);
+QuicTime::Delta QuicSendScheduler::TimeUntilSend(bool is_retransmission) {
+ return send_algorithm_->TimeUntilSend(is_retransmission);
}
size_t QuicSendScheduler::AvailableCongestionWindow() {
diff --git a/net/quic/congestion_control/quic_send_scheduler.h b/net/quic/congestion_control/quic_send_scheduler.h
index 66324ae..c5f1c83 100644
--- a/net/quic/congestion_control/quic_send_scheduler.h
+++ b/net/quic/congestion_control/quic_send_scheduler.h
@@ -54,25 +54,25 @@ class NET_EXPORT_PRIVATE QuicSendScheduler {
CongestionFeedbackType congestion_type);
virtual ~QuicSendScheduler();
- // Called when we have received an ack frame from remote peer.
- virtual void OnIncomingAckFrame(const QuicAckFrame& ack_frame);
+ // Called when we have received an ack frame from peer.
+ virtual void OnIncomingAckFrame(const QuicAckFrame& frame);
- // Called when we have received an congestion feedback frame from remote peer.
+ // Called when a congestion feedback frame is received from peer.
virtual void OnIncomingQuicCongestionFeedbackFrame(
- const QuicCongestionFeedbackFrame& congestion_feedback_frame);
+ const QuicCongestionFeedbackFrame& frame);
- // Inform that we sent x bytest to the wire, and if that was a retransmission.
- // Note: this function must be called for every packet sent to the wire.
+ // Called when we have sent bytes to the peer. This informs the manager both
+ // the number of bytes sent and if they were retransmitted.
virtual void SentPacket(QuicPacketSequenceNumber sequence_number,
size_t bytes,
- bool retransmit);
+ bool is_retransmission);
// Calculate the time until we can send the next packet to the wire.
// Note 1: When kUnknownWaitTime is returned, there is no need to poll
// TimeUntilSend again until we receive an OnIncomingAckFrame event.
// Note 2: Send algorithms may or may not use |retransmit| in their
// calculations.
- virtual QuicTime::Delta TimeUntilSend(bool retransmit);
+ virtual QuicTime::Delta TimeUntilSend(bool is_retransmission);
// Returns the current available congestion window in bytes, the number of
// bytes that can be sent now.
diff --git a/net/quic/congestion_control/quic_send_scheduler_test.cc b/net/quic/congestion_control/quic_send_scheduler_test.cc
index f28a6db..a59c0e7 100644
--- a/net/quic/congestion_control/quic_send_scheduler_test.cc
+++ b/net/quic/congestion_control/quic_send_scheduler_test.cc
@@ -54,7 +54,7 @@ TEST_F(QuicSendSchedulerTest, FixedRatePacing) {
feedback.fix_rate.bitrate_in_bytes_per_second = 100000;
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback);
- QuicTime acc_advance_time;
+ QuicTime acc_advance_time(QuicTime::Zero());
for (int i = 1; i <= 100; ++i) {
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
@@ -174,7 +174,7 @@ TEST_F(QuicSendSchedulerTest, Pacing) {
feedback.fix_rate.bitrate_in_bytes_per_second = 1000000;
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback);
- QuicTime acc_advance_time;
+ QuicTime acc_advance_time(QuicTime::Zero());
for (int i = 1; i <= 100;) {
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
EXPECT_EQ(kMaxPacketSize * 2, sender_->AvailableCongestionWindow());
diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h
index 5590d49..63aef3a 100644
--- a/net/quic/congestion_control/send_algorithm_interface.h
+++ b/net/quic/congestion_control/send_algorithm_interface.h
@@ -39,12 +39,12 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
// Note: this function must be called for every packet sent to the wire.
virtual void SentPacket(QuicPacketSequenceNumber sequence_number,
size_t bytes,
- bool retransmit) = 0;
+ bool is_retransmission) = 0;
// Calculate the time until we can send the next packet.
// Usage: When this returns 0, CongestionWindow returns the number of bytes
// of the congestion window.
- virtual QuicTime::Delta TimeUntilSend(bool retransmit) = 0;
+ virtual QuicTime::Delta TimeUntilSend(bool is_retransmission) = 0;
// The current available congestion window in bytes.
virtual size_t AvailableCongestionWindow() = 0;
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc
index 7aab66c..001fff5 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -30,7 +30,7 @@ TcpCubicSender::TcpCubicSender(const QuicClock* clock, bool reno)
end_sequence_number_(0),
congestion_window_(kInitialCongestionWindow),
slowstart_threshold_(kMaxCongestionWindow),
- delay_min_() {
+ delay_min_(QuicTime::Delta::Zero()) {
}
void TcpCubicSender::OnIncomingQuicCongestionFeedbackFrame(
@@ -81,11 +81,12 @@ void TcpCubicSender::OnIncomingLoss(int /*number_of_lost_packets*/) {
}
void TcpCubicSender::SentPacket(QuicPacketSequenceNumber sequence_number,
- size_t bytes, bool retransmit) {
- if (!retransmit) {
+ size_t bytes,
+ bool is_retransmission) {
+ if (!is_retransmission) {
bytes_in_flight_ += bytes;
}
- if (!retransmit && update_end_sequence_number_) {
+ if (!is_retransmission && update_end_sequence_number_) {
end_sequence_number_ = sequence_number;
if (AvailableCongestionWindow() == 0) {
update_end_sequence_number_ = false;
@@ -94,15 +95,15 @@ void TcpCubicSender::SentPacket(QuicPacketSequenceNumber sequence_number,
}
}
-QuicTime::Delta TcpCubicSender::TimeUntilSend(bool retransmit) {
- if (retransmit) {
- // For TCP we can always send a retransmit immediately.
- return QuicTime::Delta();
+QuicTime::Delta TcpCubicSender::TimeUntilSend(bool is_retransmission) {
+ if (is_retransmission) {
+ // For TCP we can always send a retransmission immediately.
+ return QuicTime::Delta::Zero();
}
if (AvailableCongestionWindow() == 0) {
return QuicTime::Delta::Infinite();
}
- return QuicTime::Delta();
+ return QuicTime::Delta::Zero();
}
size_t TcpCubicSender::AvailableCongestionWindow() {
@@ -126,7 +127,7 @@ int TcpCubicSender::BandwidthEstimate() {
}
void TcpCubicSender::Reset() {
- delay_min_ = QuicTime::Delta(); // Reset to 0.
+ delay_min_ = QuicTime::Delta::Zero();
hybrid_slow_start_.Restart();
}
diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h
index bb2fe06..628ff56 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.h
+++ b/net/quic/congestion_control/tcp_cubic_sender.h
@@ -33,8 +33,8 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
virtual void OnIncomingLoss(int number_of_lost_packets) OVERRIDE;
virtual void SentPacket(QuicPacketSequenceNumber sequence_number,
size_t bytes,
- bool retransmit) OVERRIDE;
- virtual QuicTime::Delta TimeUntilSend(bool retransmit) OVERRIDE;
+ bool is_retransmission) OVERRIDE;
+ virtual QuicTime::Delta TimeUntilSend(bool is_retransmission) OVERRIDE;
virtual size_t AvailableCongestionWindow() OVERRIDE;
virtual int BandwidthEstimate() OVERRIDE;
// End implementation of SendAlgorithmInterface.
diff --git a/net/quic/congestion_control/tcp_receiver_test.cc b/net/quic/congestion_control/tcp_receiver_test.cc
index 6fb2a82..1d4a2bb 100644
--- a/net/quic/congestion_control/tcp_receiver_test.cc
+++ b/net/quic/congestion_control/tcp_receiver_test.cc
@@ -21,7 +21,7 @@ class QuicTcpReceiverTest : public ::testing::Test {
TEST_F(QuicTcpReceiverTest, SimpleReceiver) {
QuicCongestionFeedbackFrame feedback;
- QuicTime timestamp;
+ QuicTime timestamp(QuicTime::Zero());
receiver_->RecordIncomingPacket(1, 1, timestamp, false);
ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
EXPECT_EQ(kTCP, feedback.type);
diff --git a/net/quic/crypto/crypto_protocol.cc b/net/quic/crypto/crypto_protocol.cc
index 993a4d2..e9220ec 100644
--- a/net/quic/crypto/crypto_protocol.cc
+++ b/net/quic/crypto/crypto_protocol.cc
@@ -9,7 +9,10 @@ namespace net {
CryptoHandshakeMessage::CryptoHandshakeMessage() {}
CryptoHandshakeMessage::~CryptoHandshakeMessage() {}
-QuicClientCryptoConfig::QuicClientCryptoConfig() : version(0) {
+QuicClientCryptoConfig::QuicClientCryptoConfig()
+ : version(0),
+ idle_connection_state_lifetime(QuicTime::Delta::Zero()),
+ keepalive_timeout(QuicTime::Delta::Zero()) {
}
QuicClientCryptoConfig::~QuicClientCryptoConfig() {}
@@ -36,7 +39,7 @@ void QuicClientCryptoConfig::SetDefaults() {
idle_connection_state_lifetime = QuicTime::Delta::FromMilliseconds(300000);
// Keepalive timeout.
- keepalive_timeout = QuicTime::Delta(); // Don't send keepalive probes.
+ keepalive_timeout = QuicTime::Delta::Zero(); // Don't send keepalive probes.
}
} // namespace net
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index debc017..bf09e91 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -27,6 +27,8 @@ namespace net {
// TODO(pwestin): kDefaultTimeoutUs is in int64.
int32 kNegotiatedTimeoutUs = kDefaultTimeoutUs;
+namespace {
+
// The largest gap in packets we'll accept without closing the connection.
// This will likely have to be tuned.
const QuicPacketSequenceNumber kMaxPacketGap = 5000;
@@ -35,29 +37,37 @@ const QuicPacketSequenceNumber kMaxPacketGap = 5000;
// without exceeding kMaxPacketSize.
const QuicPacketSequenceNumber kMaxUnackedPackets = 192u;
-// The amount of time we wait before resending a packet.
-const int64 kDefaultResendTimeMs = 500;
-
// We want to make sure if we get a large nack packet, we don't queue up too
// many packets at once. 10 is arbitrary.
-const int kMaxResendPerAck = 10;
+const int kMaxRetransmissionsPerAck = 10;
-// TCP resends after 2 nacks. We allow for a third in case of out-of-order
+// TCP retransmits after 2 nacks. We allow for a third in case of out-of-order
// delivery.
-// TODO(ianswett): Change to match TCP's rule of resending once an ack at least
-// 3 sequence numbers larger arrives.
-const int kNumberOfNacksBeforeResend = 3;
+// TODO(ianswett): Change to match TCP's rule of retransmitting once an ack
+// at least 3 sequence numbers larger arrives.
+const int kNumberOfNacksBeforeRetransmission = 3;
// The maxiumum number of packets we'd like to queue. We may end up queueing
// more in the case of many control frames.
// 6 is arbitrary.
const int kMaxPacketsToSerializeAtOnce = 6;
+// Limit the number of packets we send per retransmission-alarm so we
+// eventually cede. 10 is arbitrary.
+const int kMaxPacketsPerRetransmissionAlarm = 10;
+
+// Named constants for SendPacket options.
+const bool kForce = true;
+const bool kShouldRetransmit = true;
+const bool kIsRetransmission = true;
+
bool Near(QuicPacketSequenceNumber a, QuicPacketSequenceNumber b) {
QuicPacketSequenceNumber delta = (a > b) ? a - b : b - a;
return delta <= kMaxPacketGap;
}
+} // namespace
+
QuicConnection::UnackedPacket::UnackedPacket(QuicFrames unacked_frames)
: frames(unacked_frames),
number_nacks(0) {
@@ -87,16 +97,15 @@ QuicConnection::QuicConnection(QuicGuid guid,
largest_seen_packet_with_ack_(0),
peer_largest_observed_packet_(0),
peer_least_packet_awaiting_ack_(0),
+ handling_retransmission_timeout_(false),
write_blocked_(false),
packet_creator_(guid_, &framer_),
timeout_(QuicTime::Delta::FromMicroseconds(kDefaultTimeoutUs)),
time_of_last_packet_(clock_->Now()),
- collector_(new QuicReceiptMetricsCollector(clock_, kTCP)),
- scheduler_(new QuicSendScheduler(clock_, kTCP)),
+ congestion_manager_(clock_, kTCP),
connected_(true),
received_truncated_ack_(false),
send_ack_in_response_to_packet_(false) {
- options()->max_num_packets = kMaxPacketsToSerializeAtOnce;
helper_->SetConnection(this);
helper_->SetTimeoutAlarm(timeout_);
framer_.set_visitor(this);
@@ -128,6 +137,9 @@ QuicConnection::~QuicConnection() {
void QuicConnection::DeleteEnclosedFrame(QuicFrame* frame) {
switch (frame->type) {
+ case PADDING_FRAME:
+ delete frame->padding_frame;
+ break;
case STREAM_FRAME:
delete frame->stream_frame;
break;
@@ -143,7 +155,6 @@ void QuicConnection::DeleteEnclosedFrame(QuicFrame* frame) {
case CONNECTION_CLOSE_FRAME:
delete frame->connection_close_frame;
break;
- case PDU_FRAME: // Fall through.
case NUM_FRAME_TYPES:
DCHECK(false) << "Cannot delete type: " << frame->type;
}
@@ -152,12 +163,12 @@ void QuicConnection::DeleteEnclosedFrame(QuicFrame* frame) {
void QuicConnection::DeleteUnackedPacket(UnackedPacket* unacked) {
for (QuicFrames::iterator it = unacked->frames.begin();
it != unacked->frames.end(); ++it) {
- DCHECK(ShouldResend(*it));
+ DCHECK(ShouldRetransmit(*it));
DeleteEnclosedFrame(&(*it));
}
}
-bool QuicConnection::ShouldResend(const QuicFrame& frame) {
+bool QuicConnection::ShouldRetransmit(const QuicFrame& frame) {
return frame.type != ACK_FRAME && frame.type != CONGESTION_FEEDBACK_FRAME;
}
@@ -188,7 +199,7 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
}
// If this packet has already been seen, or that the sender
- // has told us will not be resent, then stop processing the packet.
+ // has told us will not be retransmitted, then stop processing the packet.
if (!outgoing_ack_.received_info.IsAwaitingPacket(
header.packet_sequence_number)) {
return false;
@@ -199,7 +210,7 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
}
void QuicConnection::OnFecProtectedPayload(StringPiece payload) {
- DCHECK_NE(0, last_header_.fec_group);
+ DCHECK_NE(0u, last_header_.fec_group);
QuicFecGroup* group = GetFecGroup();
group->Update(last_header_, payload);
}
@@ -227,14 +238,14 @@ void QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
UpdatePacketInformationReceivedByPeer(incoming_ack);
UpdatePacketInformationSentByPeer(incoming_ack);
- scheduler_->OnIncomingAckFrame(incoming_ack);
+ congestion_manager_.OnIncomingAckFrame(incoming_ack);
// Now the we have received an ack, we might be able to send queued packets.
if (queued_packets_.empty()) {
return;
}
- QuicTime::Delta delay = scheduler_->TimeUntilSend(false);
+ QuicTime::Delta delay = congestion_manager_.TimeUntilSend(false);
if (delay.IsZero()) {
helper_->UnregisterSendAlarmIfRegistered();
if (!write_blocked_) {
@@ -247,7 +258,7 @@ void QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
void QuicConnection::OnCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback) {
- scheduler_->OnIncomingQuicCongestionFeedbackFrame(feedback);
+ congestion_manager_.OnIncomingQuicCongestionFeedbackFrame(feedback);
}
bool QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
@@ -309,7 +320,7 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
packet_creator_.sequence_number() + 1,
peer_largest_observed_packet_ + 1);
- int resent_packets = 0;
+ int retransmitted_packets = 0;
// Go through the packets we have not received an ack for and see if this
// incoming_ack shows they've been seen by the peer.
@@ -323,7 +334,8 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
// always sending packets with new sequence numbers. I believe it may
// only be relevant for the first crypto connect packet, which doesn't
// get a new packet sequence number.
- // The acked packet might be queued (if a resend had been attempted).
+ // The acked packet might be queued (if a retransmission had been
+ // attempted).
for (QueuedPacketList::iterator q = queued_packets_.begin();
q != queued_packets_.end(); ++q) {
if (q->sequence_number == it->first) {
@@ -338,7 +350,7 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
++it;
unacked_packets_.erase(it_tmp);
} else {
- // This is a packet which we planned on resending and has not been
+ // This is a packet which we planned on retransmitting and has not been
// seen at the time of this ack being sent out. See if it's our new
// lowest unacked packet.
DVLOG(1) << "still missing " << it->first;
@@ -347,24 +359,24 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
}
// Determine if this packet is being explicitly nacked and, if so, if it
- // is worth resending.
- QuicPacketSequenceNumber resend_number = 0;
+ // is worth retransmitting.
+ QuicPacketSequenceNumber retransmission_number = 0;
if (it->first < peer_largest_observed_packet_) {
// The peer got packets after this sequence number. This is an explicit
// nack.
++(it->second->number_nacks);
- if (it->second->number_nacks >= kNumberOfNacksBeforeResend &&
- resent_packets < kMaxResendPerAck) {
- resend_number = it->first;
+ if (it->second->number_nacks >= kNumberOfNacksBeforeRetransmission &&
+ retransmitted_packets < kMaxRetransmissionsPerAck) {
+ retransmission_number = it->first;
}
}
++it;
- if (resend_number > 0) {
- ++resent_packets;
- DVLOG(1) << "Trying to resend packet " << resend_number
+ if (retransmission_number > 0) {
+ ++retransmitted_packets;
+ DVLOG(1) << "Trying to retransmit packet " << retransmission_number
<< " as it has been nacked 3 or more times.";
- MaybeResendPacket(resend_number);
+ MaybeRetransmitPacket(retransmission_number);
}
}
}
@@ -376,7 +388,7 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
void QuicConnection::SetLeastUnacked(QuicPacketSequenceNumber lowest_unacked) {
// If we've gotten an ack for the lowest packet we were waiting on,
- // update that and the list of packets we advertise we will not resend.
+ // update that and the list of packets we advertise we will not retransmit.
if (lowest_unacked > outgoing_ack_.sent_info.least_unacked) {
outgoing_ack_.sent_info.least_unacked = lowest_unacked;
}
@@ -412,7 +424,7 @@ void QuicConnection::UpdatePacketInformationSentByPeer(
}
void QuicConnection::OnFecData(const QuicFecData& fec) {
- DCHECK_NE(0, last_header_.fec_group);
+ DCHECK_NE(0u, last_header_.fec_group);
QuicFecGroup* group = GetFecGroup();
group->UpdateFec(last_header_.packet_sequence_number, fec);
}
@@ -427,16 +439,15 @@ void QuicConnection::OnConnectionCloseFrame(
const QuicConnectionCloseFrame& frame) {
DLOG(INFO) << "Connection closed with error "
<< QuicUtils::ErrorToString(frame.error_code);
- connected_ = false;
- visitor_->ConnectionClose(frame.error_code, true);
+ CloseConnection(frame.error_code, true);
}
void QuicConnection::OnPacketComplete() {
if (!last_packet_revived_) {
DLOG(INFO) << "Got packet " << last_header_.packet_sequence_number
<< " with " << last_stream_frames_.size()
- << " stream frames for " << last_header_.guid;
- collector_->RecordIncomingPacket(last_size_,
+ << " stream frames for " << last_header_.public_header.guid;
+ congestion_manager_.RecordIncomingPacket(last_size_,
last_header_.packet_sequence_number,
clock_->Now(),
last_packet_revived_);
@@ -461,8 +472,7 @@ void QuicConnection::MaybeSendAckInResponseToPacket() {
} else if (!last_stream_frames_.empty()) {
// TODO(alyssar) this case should really be "if the packet contained any
// non-ack frame", rather than "if the packet contained a stream frame"
- helper_->SetAckAlarm(
- QuicTime::Delta::FromMicroseconds(kDefaultResendTimeMs));
+ helper_->SetAckAlarm(DefaultRetransmissionTime());
}
send_ack_in_response_to_packet_ = !send_ack_in_response_to_packet_;
}
@@ -471,46 +481,37 @@ QuicConsumedData QuicConnection::SendStreamData(
QuicStreamId id,
StringPiece data,
QuicStreamOffset offset,
- bool fin,
- QuicPacketSequenceNumber* last_packet) {
+ bool fin) {
size_t total_bytes_consumed = 0;
bool fin_consumed = false;
+ packet_creator_.MaybeStartFEC();
while (queued_packets_.empty()) {
- vector<PacketPair> packets;
QuicFrames frames;
size_t bytes_consumed =
- packet_creator_.DataToStream(id, data, offset, fin, &packets, &frames);
+ packet_creator_.CreateStreamFrame(id, data, offset, fin, &frames);
total_bytes_consumed += bytes_consumed;
offset += bytes_consumed;
fin_consumed = fin && bytes_consumed == data.size();
data.remove_prefix(bytes_consumed);
- DCHECK_LT(0u, packets.size());
-
- for (size_t i = 0; i < packets.size(); ++i) {
- // Resend is false for FEC packets.
- bool should_resend = !packets[i].second->IsFecPacket();
- SendPacket(packets[i].first,
- packets[i].second,
- should_resend,
- false,
- false);
- if (should_resend) {
- QuicFrames unacked_frames;
- unacked_frames.push_back(frames[i]);
- UnackedPacket* unacked = new UnackedPacket(
- unacked_frames, frames[i].stream_frame->data.as_string());
- // Ensure the string piece points to the owned copy of the data.
- unacked->frames[0].stream_frame->data = StringPiece(unacked->data);
- unacked_packets_.insert(make_pair(packets[i].first, unacked));
- } else {
- DeleteEnclosedFrame(&frames[i]);
- }
- }
- if (last_packet != NULL) {
- *last_packet = packets[packets.size() - 1].first;
+ PacketPair pair = packet_creator_.SerializeAllFrames(frames);
+ // TODO(ianswett): Restore packet reordering.
+ SendPacket(pair.first, pair.second, kShouldRetransmit, !kForce,
+ !kIsRetransmission);
+ UnackedPacket* unacked = new UnackedPacket(
+ frames, frames[0].stream_frame->data.as_string());
+ // Ensure the string piece points to the owned copy of the data.
+ unacked->frames[0].stream_frame->data = StringPiece(unacked->data);
+ unacked_packets_.insert(make_pair(pair.first, unacked));
+
+ if (packet_creator_.ShouldSendFec(data.size() == 0)) {
+ PacketPair fec_pair = packet_creator_.SerializeFec();
+ // Never resend FEC packets.
+ SendPacket(fec_pair.first, fec_pair.second, !kShouldRetransmit, !kForce,
+ !kIsRetransmission);
}
+
if (data.size() == 0) {
// We're done writing the data. Exit the loop.
// We don't make this a precondition beacuse we could have 0 bytes of data
@@ -561,7 +562,7 @@ bool QuicConnection::OnCanWrite() {
// We're not write blocked, but some stream didn't write out all of its
// bytes. Register for 'immediate' resumption so we'll keep writing after
// other quic connections have had a chance to use the socket.
- helper_->SetSendAlarm(QuicTime::Delta());
+ helper_->SetSendAlarm(QuicTime::Delta::Zero());
}
}
@@ -581,11 +582,12 @@ bool QuicConnection::WriteData() {
size_t num_serialized;
PacketPair pair = packet_creator_.SerializeFrames(
queued_control_frames_, &num_serialized);
- // If any serialized frames need to be resent, add them to unacked_packets.
+ // If any serialized frames need to be retransmitted, add them to
+ // unacked_packets.
QuicFrames unacked_frames;
for (QuicFrames::const_iterator iter = queued_control_frames_.begin();
iter != queued_control_frames_.begin() + num_serialized; ++iter) {
- if (ShouldResend(*iter)) {
+ if (ShouldRetransmit(*iter)) {
unacked_frames.push_back(*iter);
}
}
@@ -612,7 +614,8 @@ bool QuicConnection::WriteData() {
num_queued_packets = queued_packets_.size();
QueuedPacket p = queued_packets_.front();
queued_packets_.pop_front();
- SendPacket(p.sequence_number, p.packet, p.resend, false, p.retransmit);
+ SendPacket(p.sequence_number, p.packet, p.should_retransmit, !kForce,
+ p.is_retransmission);
}
return !write_blocked_;
@@ -624,7 +627,7 @@ void QuicConnection::RecordPacketReceived(const QuicPacketHeader& header) {
outgoing_ack_.received_info.RecordReceived(sequence_number);
}
-bool QuicConnection::MaybeResendPacketForRTO(
+bool QuicConnection::MaybeRetransmitPacketForRTO(
QuicPacketSequenceNumber sequence_number) {
// If the packet hasn't been acked and we're getting truncated acks, ignore
// any RTO for packets larger than the peer's largest observed packet; it may
@@ -635,12 +638,12 @@ bool QuicConnection::MaybeResendPacketForRTO(
ContainsKey(unacked_packets_, sequence_number)) {
return false;
} else {
- MaybeResendPacket(sequence_number);
+ MaybeRetransmitPacket(sequence_number);
return true;
}
}
-void QuicConnection::MaybeResendPacket(
+void QuicConnection::MaybeRetransmitPacket(
QuicPacketSequenceNumber sequence_number) {
UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
@@ -648,30 +651,31 @@ void QuicConnection::MaybeResendPacket(
UnackedPacket* unacked = it->second;
// TODO(ianswett): Never change the sequence number of the connect packet.
unacked_packets_.erase(it);
- // Re-packetize the frames with a new sequence number for resend.
- // Resent data packets do not use FEC, even when it's enabled.
+ // Re-packetize the frames with a new sequence number for retransmission.
+ // Retransmitted data packets do not use FEC, even when it's enabled.
PacketPair packetpair = packet_creator_.SerializeAllFrames(unacked->frames);
- DVLOG(1) << "Resending unacked packet " << sequence_number << " as "
+ DVLOG(1) << "Retransmitting unacked packet " << sequence_number << " as "
<< packetpair.first;
unacked_packets_.insert(make_pair(packetpair.first, unacked));
// Make sure if this was our least unacked packet, that we update our
// outgoing ack. If this wasn't the least unacked, this is a no-op.
UpdateLeastUnacked(sequence_number);
- SendPacket(packetpair.first, packetpair.second, true, false, true);
+ SendPacket(packetpair.first, packetpair.second, kShouldRetransmit,
+ !kForce, kIsRetransmission);
} else {
DVLOG(2) << "alarm fired for " << sequence_number
<< " but it has been acked";
}
}
-bool QuicConnection::CanWrite(bool is_retransmit) {
+bool QuicConnection::CanWrite(bool is_retransmission) {
// TODO(ianswett): If the packet is a retransmit, the current send alarm may
// be too long.
if (write_blocked_ || helper_->IsSendAlarmSet()) {
return false;
}
- QuicTime::Delta delay = scheduler_->TimeUntilSend(is_retransmit);
+ QuicTime::Delta delay = congestion_manager_.TimeUntilSend(is_retransmission);
// If the scheduler requires a delay, then we can not send this packet now.
if (!delay.IsZero() && !delay.IsInfinite()) {
// TODO(pwestin): we need to handle delay.IsInfinite() seperately.
@@ -683,21 +687,31 @@ bool QuicConnection::CanWrite(bool is_retransmit) {
bool QuicConnection::SendPacket(QuicPacketSequenceNumber sequence_number,
QuicPacket* packet,
- bool should_resend,
+ bool should_retransmit,
bool force,
- bool is_retransmit) {
+ bool is_retransmission) {
// If this packet is being forced, don't bother checking to see if we should
// write, just write.
if (!force) {
// If we can't write, then simply queue the packet.
- if (!CanWrite(is_retransmit)) {
+ if (!CanWrite(is_retransmission)) {
queued_packets_.push_back(
- QueuedPacket(sequence_number, packet, should_resend, is_retransmit));
+ QueuedPacket(sequence_number, packet, should_retransmit,
+ is_retransmission));
return false;
}
}
- if (should_resend) {
- helper_->SetResendAlarm(sequence_number, DefaultResendTime());
+ if (should_retransmit) {
+ // Do not set the retransmisson alarm if we're already handling the
+ // retransmission alarm because the retransmission alarm will be reset when
+ // OnRetransmissionTimeout completes.
+ if (!handling_retransmission_timeout_) {
+ helper_->SetRetransmissionAlarm(DefaultRetransmissionTime());
+ }
+ retransmission_timeouts_.push_back(
+ make_pair(sequence_number, clock_->Now().Add(
+ DefaultRetransmissionTime())));
+
// The second case should never happen in the real world, but does here
// because we sometimes send out of order to validate corner cases.
if (outgoing_ack_.sent_info.least_unacked == 0 ||
@@ -709,7 +723,8 @@ bool QuicConnection::SendPacket(QuicPacketSequenceNumber sequence_number,
scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(*packet));
int error;
DLOG(INFO) << "Sending packet : "
- << (should_resend ? "data bearing " : " ack only ")
+ << (packet->is_fec_packet() ? "FEC " :
+ (should_retransmit ? "data bearing " : " ack only "))
<< "packet " << sequence_number;
DCHECK(encrypted->length() <= kMaxPacketSize)
<< "Packet " << sequence_number << " will not be read; too large: "
@@ -724,7 +739,8 @@ bool QuicConnection::SendPacket(QuicPacketSequenceNumber sequence_number,
// UDP sockets.
/*
queued_packets_.push_front(
- QueuedPacket(sequence_number, packet, should_resend, is_retransmit));
+ QueuedPacket(sequence_number, packet, should_retransmit,
+ is_retransmission));
*/
return false;
}
@@ -734,7 +750,8 @@ bool QuicConnection::SendPacket(QuicPacketSequenceNumber sequence_number,
time_of_last_packet_ = clock_->Now();
DVLOG(1) << "last packet: " << time_of_last_packet_.ToMicroseconds();
- scheduler_->SentPacket(sequence_number, packet->length(), is_retransmit);
+ congestion_manager_.SentPacket(sequence_number, packet->length(),
+ is_retransmission);
delete packet;
return true;
}
@@ -753,7 +770,7 @@ void QuicConnection::SendAck() {
if (!ContainsKey(unacked_packets_, outgoing_ack_.sent_info.least_unacked)) {
// At some point, all packets were acked, and we set least_unacked to a
- // packet we will not resend. Make sure we update it.
+ // packet we will not retransmit. Make sure we update it.
UpdateLeastUnacked(outgoing_ack_.sent_info.least_unacked);
}
@@ -761,7 +778,8 @@ void QuicConnection::SendAck() {
should_send_ack_ = true;
- if (collector_->GenerateCongestionFeedback(&outgoing_congestion_feedback_)) {
+ if (congestion_manager_.GenerateCongestionFeedback(
+ &outgoing_congestion_feedback_)) {
DVLOG(1) << "Sending feedback " << outgoing_congestion_feedback_;
should_send_congestion_feedback_ = true;
}
@@ -771,6 +789,46 @@ void QuicConnection::SendAck() {
}
}
+QuicTime QuicConnection::OnRetransmissionTimeout() {
+ // This guards against registering the alarm later than we should.
+ //
+ // If we have packet A and B in the list and we call
+ // MaybeRetransmitPacketForRTO on A, that may trigger a call to
+ // SetRetransmissionAlarm if A is retransmitted as C. In that case we
+ // don't want to register the alarm under SetRetransmissionAlarm; we
+ // want to set it to the RTO of B when we return from this function.
+ handling_retransmission_timeout_ = true;
+
+ for (int i = 0; i < kMaxPacketsPerRetransmissionAlarm; ++i) {
+ if (retransmission_timeouts_.empty() ||
+ retransmission_timeouts_.front().second > clock_->Now()) {
+ break;
+ }
+ if (!MaybeRetransmitPacketForRTO(retransmission_timeouts_.front().first)) {
+ DLOG(INFO) << "MaybeRetransmitPacketForRTO failed: "
+ << "adding an extra delay.";
+ // This implicitly delays the RTO for all subsequent packets, since
+ // MaybeRetransmitPacketForRTO will return false for all packets with
+ // a larger sequence number anyway.
+ retransmission_timeouts_.front().second =
+ retransmission_timeouts_.front().second.Add(
+ DefaultRetransmissionTime());
+ break;
+ }
+ retransmission_timeouts_.pop_front();
+ }
+
+ handling_retransmission_timeout_ = false;
+
+ if (retransmission_timeouts_.empty()) {
+ return QuicTime::FromMilliseconds(0);
+ }
+
+ // We have packets remaining. Return the absolute RTO of the oldest packet
+ // on the list.
+ return retransmission_timeouts_.front().second;
+}
+
void QuicConnection::MaybeProcessRevivedPacket() {
QuicFecGroup* group = GetFecGroup();
if (group == NULL || !group->CanRevive()) {
@@ -809,10 +867,17 @@ void QuicConnection::SendConnectionClose(QuicErrorCode error) {
frame.ack_frame = outgoing_ack_;
PacketPair packetpair = packet_creator_.CloseConnection(&frame);
- // There's no point in resending this: we're closing the connection.
- SendPacket(packetpair.first, packetpair.second, false, true, false);
+ // There's no point in retransmitting this: we're closing the connection.
+ SendPacket(packetpair.first, packetpair.second, !kShouldRetransmit, kForce,
+ !kIsRetransmission);
+ CloseConnection(error, false);
+}
+
+void QuicConnection::CloseConnection(QuicErrorCode error, bool from_peer) {
+ // TODO(satyamshekhar): Ask the dispatcher to delete visitor and hence self
+ // if the visitor will always be deleted by closing the connection.
connected_ = false;
- visitor_->ConnectionClose(error, false);
+ visitor_->ConnectionClose(error, from_peer);
}
void QuicConnection::CloseFecGroupsBefore(
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 1e3bf81..6515e01 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -22,6 +22,7 @@
#include "base/hash_tables.h"
#include "net/base/ip_endpoint.h"
+#include "net/quic/congestion_control/quic_congestion_manager.h"
#include "net/quic/quic_fec_group.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
@@ -34,8 +35,6 @@ class QuicConnection;
class QuicEncrypter;
class QuicFecGroup;
class QuicRandom;
-class QuicReceiptMetricsCollector;
-class QuicSendScheduler;
namespace test {
class QuicConnectionPeer;
@@ -93,12 +92,12 @@ class NET_EXPORT_PRIVATE QuicConnectionHelperInterface {
virtual int WritePacketToWire(const QuicEncryptedPacket& packet,
int* error) = 0;
- // Sets up an alarm to resend the packet with the given sequence number if we
- // haven't gotten an ack in the expected time frame. Implementations must
- // invoke MaybeResendPacketForRTO when the alarm fires. Implementations must
- // also handle the case where |this| is deleted before the alarm fires.
- virtual void SetResendAlarm(QuicPacketSequenceNumber sequence_number,
- QuicTime::Delta delay) = 0;
+ // Sets up an alarm to retransmit a packet if we haven't received an ack
+ // in the expected time frame. Implementations must invoke
+ // OnRetransmissionAlarm when the alarm fires. Implementations must also
+ // handle the case where |this| is deleted before the alarm fires. If the
+ // alarm is already set, this call is a no-op.
+ virtual void SetRetransmissionAlarm(QuicTime::Delta delay) = 0;
// Sets an alarm to send packets after |delay_in_us|. Implementations must
// invoke OnCanWrite when the alarm fires. Implementations must also
@@ -146,15 +145,17 @@ class NET_EXPORT_PRIVATE QuicConnection : public QuicFramerVisitorInterface {
QuicConsumedData SendStreamData(QuicStreamId id,
base::StringPiece data,
QuicStreamOffset offset,
- bool fin,
- QuicPacketSequenceNumber* last_packet);
+ bool fin);
+
// Send a stream reset frame to the peer.
virtual void SendRstStream(QuicStreamId id,
QuicErrorCode error,
QuicStreamOffset offset);
- // Sends a connection close frame to the peer, and notifies the visitor of
- // the close.
+ // Sends a connection close frame to the peer, and closes the connection by
+ // calling CloseConnection(notifying the visitor as it does so).
virtual void SendConnectionClose(QuicErrorCode error);
+ // Notifies the visitor of the close and marks the connection as disconnected.
+ void CloseConnection(QuicErrorCode error, bool from_peer);
// Processes an incoming UDP packet (consisting of a QuicEncryptedPacket) from
// the peer. If processing this packet permits a packet to be revived from
@@ -197,14 +198,14 @@ class NET_EXPORT_PRIVATE QuicConnection : public QuicFramerVisitorInterface {
// Updates the internal state concerning which packets have been acked.
void RecordPacketReceived(const QuicPacketHeader& header);
- // Called by a ResendAlarm when the timer goes off. If the peer appears to be
- // sending truncated acks, this returns false to indicate failure, otherwise
- // it calls MaybeResendPacket and returns true.
- bool MaybeResendPacketForRTO(QuicPacketSequenceNumber sequence_number);
+ // Called by a RetransmissionAlarm when the timer goes off. If the peer
+ // appears to be sending truncated acks, this returns false to indicate
+ // failure, otherwise it calls MaybeRetransmitPacket and returns true.
+ bool MaybeRetransmitPacketForRTO(QuicPacketSequenceNumber sequence_number);
- // Called to resend a packet, in the case a packet was sufficiently nacked by
- // the peer, or not acked within the time out window.
- void MaybeResendPacket(QuicPacketSequenceNumber sequence_number);
+ // Called to retransmit a packet, in the case a packet was sufficiently
+ // nacked by the peer, or not acked within the time out window.
+ void MaybeRetransmitPacket(QuicPacketSequenceNumber sequence_number);
QuicPacketCreator::Options* options() { return packet_creator_.options(); }
@@ -229,19 +230,23 @@ class NET_EXPORT_PRIVATE QuicConnection : public QuicFramerVisitorInterface {
// Sets up a packet with an QuicAckFrame and sends it out.
void SendAck();
+ // Called when an RTO fires. Returns the time when this alarm
+ // should next fire, or 0 if no retransmission alarm should be set.
+ QuicTime OnRetransmissionTimeout();
+
protected:
- // Send a packet to the peer. If should_resend is true, this packet contains
- // data, and contents will be resent with a new sequence number if we don't
- // get an ack. If force is true, then the packet will be sent immediately and
- // the send scheduler will not be consulted. If is_retransmit is true, this
- // packet is being retransmitted with a new sequence number. Always takes
- // ownership of packet.
+ // Send a packet to the peer. If should_retransmit is true, this packet
+ // contains data, and contents will be retransmitted with a new sequence
+ // number if we don't get an ack. If force is true, then the packet will
+ // be sent immediately and the send scheduler will not be consulted. If
+ // is_retransmission is true, this packet is being retransmitted with a new
+ // sequence number. Always takes ownership of packet.
// TODO(wtc): none of the callers check the return value.
virtual bool SendPacket(QuicPacketSequenceNumber number,
QuicPacket* packet,
- bool should_resend,
+ bool should_retransmit,
bool force,
- bool is_retransmit);
+ bool is_retransmission);
// Make sure an ack we got from our peer is sane.
bool ValidateAckFrame(const QuicAckFrame& incoming_ack);
@@ -272,18 +277,18 @@ class NET_EXPORT_PRIVATE QuicConnection : public QuicFramerVisitorInterface {
struct QueuedPacket {
QueuedPacket(QuicPacketSequenceNumber sequence_number,
QuicPacket* packet,
- bool resend,
- bool retransmit)
+ bool should_retransmit,
+ bool is_retransmission)
: sequence_number(sequence_number),
packet(packet),
- resend(resend),
- retransmit(retransmit) {
+ should_retransmit(should_retransmit),
+ is_retransmission(is_retransmission) {
}
QuicPacketSequenceNumber sequence_number;
QuicPacket* packet;
- bool resend;
- bool retransmit;
+ bool should_retransmit;
+ bool is_retransmission;
};
struct UnackedPacket {
@@ -301,17 +306,19 @@ class NET_EXPORT_PRIVATE QuicConnection : public QuicFramerVisitorInterface {
typedef base::hash_map<QuicPacketSequenceNumber,
UnackedPacket*> UnackedPacketMap;
typedef std::map<QuicFecGroupNumber, QuicFecGroup*> FecGroupMap;
+ typedef std::list<std::pair<QuicPacketSequenceNumber, QuicTime> >
+ RetransmissionTimeouts;
- // The amount of time we wait before resending a packet.
- static const QuicTime::Delta DefaultResendTime() {
+ // The amount of time we wait before retransmitting a packet.
+ static const QuicTime::Delta DefaultRetransmissionTime() {
return QuicTime::Delta::FromMilliseconds(500);
}
static void DeleteUnackedPacket(UnackedPacket* unacked);
- static bool ShouldResend(const QuicFrame& frame);
+ static bool ShouldRetransmit(const QuicFrame& frame);
// Checks if a packet can be written now, and sets the timer if necessary.
- bool CanWrite(bool is_retransmit);
+ bool CanWrite(bool is_retransmission);
// Writes as much queued data as possible. The connection must not be
// blocked when this is called.
@@ -356,13 +363,24 @@ class NET_EXPORT_PRIVATE QuicConnection : public QuicFramerVisitorInterface {
QuicPacketSequenceNumber peer_largest_observed_packet_;
QuicPacketSequenceNumber peer_least_packet_awaiting_ack_;
- // When new packets are created which may be resent, they are added
+ // When new packets are created which may be retransmitted, they are added
// to this map, which contains owning pointers to the contained frames.
UnackedPacketMap unacked_packets_;
+ // List of packets that we might need to retransmission, and the time at
+ // which we should retransmission them. This is currently a FIFO queue which
+ // means we will never fire an RTO for packet 2 if we are waiting to fire
+ // the RTO for packet 1. This logic is likely suboptimal but it will
+ // change when it moves to the SendScheduler so it is fine for now.
+ RetransmissionTimeouts retransmission_timeouts_;
+
+ // True while OnRetransmissionTimeout is running to prevent
+ // SetRetransmissionAlarm from being called erroneously.
+ bool handling_retransmission_timeout_;
+
// When packets could not be sent because the socket was not writable,
// they are added to this list. All corresponding frames are in
- // unacked_packets_ if they are to be resent.
+ // unacked_packets_ if they are to be retransmitted.
QueuedPacketList queued_packets_;
// Pending control frames, besides the ack and congestion control frames.
@@ -383,10 +401,9 @@ class NET_EXPORT_PRIVATE QuicConnection : public QuicFramerVisitorInterface {
// The time that we got or tried to send a packet for this connection.
QuicTime time_of_last_packet_;
- scoped_ptr<QuicReceiptMetricsCollector> collector_;
-
- // Scheduler which drives packet send rate.
- scoped_ptr<QuicSendScheduler> scheduler_;
+ // Congestion manager which controls the rate the connection sends packets
+ // as well as collecting and generating congestion feedback.
+ QuicCongestionManager congestion_manager_;
// True by default. False if we've received or sent an explicit connection
// close.
diff --git a/net/quic/quic_connection_helper.cc b/net/quic/quic_connection_helper.cc
index b53646db..18fd69d 100644
--- a/net/quic/quic_connection_helper.cc
+++ b/net/quic/quic_connection_helper.cc
@@ -15,13 +15,6 @@
namespace net {
-// Limit the number of packets we send per resend-alarm so we eventually cede.
-// 10 is arbitrary.
-const size_t kMaxPacketsPerResendAlarm = 10;
-
-// The time to wait if an RTO alarm fires but is ignored due to truncated acks.
-const int kExtraRTODelayUs = 500 * 1000;
-
QuicConnectionHelper::QuicConnectionHelper(base::TaskRunner* task_runner,
const QuicClock* clock,
QuicRandom* random_generator,
@@ -33,10 +26,10 @@ QuicConnectionHelper::QuicConnectionHelper(base::TaskRunner* task_runner,
random_generator_(random_generator),
send_alarm_registered_(false),
timeout_alarm_registered_(false),
- resend_alarm_registered_(false),
- resend_alarm_running_(false),
+ retransmission_alarm_registered_(false),
+ retransmission_alarm_running_(false),
ack_alarm_registered_(false),
- ack_alarm_time_(QuicTime()) {
+ ack_alarm_time_(QuicTime::Zero()) {
}
QuicConnectionHelper::~QuicConnectionHelper() {
@@ -78,19 +71,14 @@ int QuicConnectionHelper::WritePacketToWire(
return rv;
}
-void QuicConnectionHelper::SetResendAlarm(
- QuicPacketSequenceNumber sequence_number,
- QuicTime::Delta delay) {
- if (!resend_alarm_registered_ &&
- !resend_alarm_running_) {
- resend_alarm_registered_ = true;
+void QuicConnectionHelper::SetRetransmissionAlarm(QuicTime::Delta delay) {
+ if (!retransmission_alarm_registered_) {
task_runner_->PostDelayedTask(
FROM_HERE,
- base::Bind(&QuicConnectionHelper::OnResendAlarm,
+ base::Bind(&QuicConnectionHelper::OnRetransmissionAlarm,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMicroseconds(delay.ToMicroseconds()));
}
- resend_times_[sequence_number] = clock_->Now().Add(delay);
}
void QuicConnectionHelper::SetAckAlarm(QuicTime::Delta delay) {
@@ -106,7 +94,7 @@ void QuicConnectionHelper::SetAckAlarm(QuicTime::Delta delay) {
}
void QuicConnectionHelper::ClearAckAlarm() {
- ack_alarm_time_ = QuicTime();
+ ack_alarm_time_ = QuicTime::Zero();
}
void QuicConnectionHelper::SetSendAlarm(QuicTime::Delta delay) {
@@ -149,41 +137,11 @@ void QuicConnectionHelper::GetPeerAddress(IPEndPoint* peer_address) {
socket_->GetPeerAddress(peer_address);
}
-void QuicConnectionHelper::OnResendAlarm() {
- // This guards against registering the alarm later than we should.
- //
- // If we have packet A and B in the list and we call MaybeResendPacketForRTO
- // on A, that may trigger a call to SetResendAlarm if A is resent as C. In
- // that case we don't want to register the alarm under SetResendAlarm; we
- // want to set it to the RTO of B at the end of this method.
- resend_alarm_registered_ = false;
- resend_alarm_running_ = true;
-
- for (size_t i = 0; i < kMaxPacketsPerResendAlarm; ++i) {
- if (resend_times_.empty() ||
- resend_times_.begin()->second > clock_->Now()) {
- break;
- }
- QuicPacketSequenceNumber sequence_number = resend_times_.begin()->first;
- if (!connection_->MaybeResendPacketForRTO(sequence_number)) {
- DLOG(INFO) << "MaybeResendPacketForRTO failed: adding an extra delay.";
- SetResendAlarm(sequence_number,
- QuicTime::Delta::FromMicroseconds(kExtraRTODelayUs));
- break;
- }
- resend_times_.erase(sequence_number);
- }
-
- // Nothing from here on does external calls.
- resend_alarm_running_ = false;
- if (resend_times_.empty()) {
- return;
+void QuicConnectionHelper::OnRetransmissionAlarm() {
+ QuicTime when = connection_->OnRetransmissionTimeout();
+ if (!when.IsInitialized()) {
+ SetRetransmissionAlarm(clock_->Now().Subtract(when));
}
-
- // We have packet remaining. Reschedule for the RTO of the oldest packet
- // on the list.
- SetResendAlarm(resend_times_.begin()->first,
- resend_times_.begin()->second.Subtract(clock_->Now()));
}
void QuicConnectionHelper::OnSendAlarm() {
@@ -211,7 +169,7 @@ void QuicConnectionHelper::OnAckAlarm() {
return;
}
- ack_alarm_time_ = QuicTime();
+ ack_alarm_time_ = QuicTime::Zero();
connection_->SendAck();
}
diff --git a/net/quic/quic_connection_helper.h b/net/quic/quic_connection_helper.h
index 994ab54..a119371 100644
--- a/net/quic/quic_connection_helper.h
+++ b/net/quic/quic_connection_helper.h
@@ -47,8 +47,7 @@ class NET_EXPORT_PRIVATE QuicConnectionHelper
virtual QuicRandom* GetRandomGenerator() OVERRIDE;
virtual int WritePacketToWire(const QuicEncryptedPacket& packet,
int* error) OVERRIDE;
- virtual void SetResendAlarm(QuicPacketSequenceNumber sequence_number,
- QuicTime::Delta delay) OVERRIDE;
+ virtual void SetRetransmissionAlarm(QuicTime::Delta delay) OVERRIDE;
virtual void SetSendAlarm(QuicTime::Delta delay) OVERRIDE;
virtual void SetTimeoutAlarm(QuicTime::Delta delay) OVERRIDE;
virtual bool IsSendAlarmSet() OVERRIDE;
@@ -66,8 +65,8 @@ class NET_EXPORT_PRIVATE QuicConnectionHelper
// An alarm is scheduled for each data-bearing packet as it is sent out.
// When the alarm goes off, the connection checks to see if the packet has
- // been acked, and resends if it has not.
- void OnResendAlarm();
+ // been acked, and retransmits if it has not.
+ void OnRetransmissionAlarm();
// An alarm that is scheduled when the sent scheduler requires a
// a delay before sending packets and fires when the packet may be sent.
void OnSendAlarm();
@@ -86,12 +85,12 @@ class NET_EXPORT_PRIVATE QuicConnectionHelper
QuicRandom* random_generator_;
bool send_alarm_registered_;
bool timeout_alarm_registered_;
- bool resend_alarm_registered_;
- bool resend_alarm_running_;
+ bool retransmission_alarm_registered_;
+ bool retransmission_alarm_running_;
bool ack_alarm_registered_;
QuicTime ack_alarm_time_;
- // Times that packets should be resent.
- std::map<QuicPacketSequenceNumber, QuicTime> resend_times_;
+ // Times that packets should be retransmitted.
+ std::map<QuicPacketSequenceNumber, QuicTime> retransmission_times_;
DISALLOW_COPY_AND_ASSIGN(QuicConnectionHelper);
};
diff --git a/net/quic/quic_connection_helper_test.cc b/net/quic/quic_connection_helper_test.cc
index 67b073e..7bd6ff8 100644
--- a/net/quic/quic_connection_helper_test.cc
+++ b/net/quic/quic_connection_helper_test.cc
@@ -101,7 +101,7 @@ class QuicConnectionHelperTest : public ::testing::Test {
&random_generator_, socket));
scheduler_ = new testing::StrictMock<MockScheduler>();
EXPECT_CALL(*scheduler_, TimeUntilSend(_)).
- WillRepeatedly(testing::Return(QuicTime::Delta()));
+ WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
connection_.reset(new TestConnection(guid_, IPEndPoint(), helper_.get()));
connection_->set_visitor(&visitor_);
connection_->SetScheduler(scheduler_);
@@ -161,9 +161,10 @@ class QuicConnectionHelperTest : public ::testing::Test {
private:
void InitializeHeader(QuicPacketSequenceNumber sequence_number) {
- header_.guid = guid_;
+ header_.public_header.guid = guid_;
+ header_.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
header_.packet_sequence_number = sequence_number;
- header_.flags = PACKET_FLAGS_NONE;
+ header_.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header_.fec_group = 0;
}
@@ -199,12 +200,12 @@ TEST_F(QuicConnectionHelperTest, IsSendAlarmSet) {
}
TEST_F(QuicConnectionHelperTest, SetSendAlarm) {
- helper_->SetSendAlarm(QuicTime::Delta());
+ helper_->SetSendAlarm(QuicTime::Delta::Zero());
EXPECT_TRUE(helper_->IsSendAlarmSet());
}
TEST_F(QuicConnectionHelperTest, UnregisterSendAlarmIfRegistered) {
- helper_->SetSendAlarm(QuicTime::Delta());
+ helper_->SetSendAlarm(QuicTime::Delta::Zero());
helper_->UnregisterSendAlarmIfRegistered() ;
EXPECT_FALSE(helper_->IsSendAlarmSet());
}
@@ -226,7 +227,7 @@ TEST_F(QuicConnectionHelperTest, SetAckAlarm) {
EXPECT_CALL(*scheduler_, SentPacket(1, _, false));
runner_->RunNextTask();
- EXPECT_EQ(QuicTime().Add(delta), clock_.Now());
+ EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
}
TEST_F(QuicConnectionHelperTest, ClearAckAlarm) {
@@ -242,7 +243,7 @@ TEST_F(QuicConnectionHelperTest, ClearAckAlarm) {
// When the AckAlarm actually fires, no ack will be sent.
runner_->RunNextTask();
- EXPECT_EQ(QuicTime().Add(delta), clock_.Now());
+ EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
}
TEST_F(QuicConnectionHelperTest, ResetAckAlarm) {
@@ -263,32 +264,34 @@ TEST_F(QuicConnectionHelperTest, ResetAckAlarm) {
// The task will execute at delta1, but will not send and ack,
// but it will reschedule itself for delta2
runner_->RunNextTask();
- EXPECT_EQ(QuicTime().Add(delta1), clock_.Now());
+ EXPECT_EQ(QuicTime::Zero().Add(delta1), clock_.Now());
// Verify that the ack alarm task has been re-posted.
ASSERT_EQ(2u, runner_->GetPostedTasks().size());
EXPECT_CALL(*scheduler_, SentPacket(1, _, false));
runner_->RunNextTask();
- EXPECT_EQ(QuicTime().Add(delta2), clock_.Now());
+ EXPECT_EQ(QuicTime::Zero().Add(delta2), clock_.Now());
}
-TEST_F(QuicConnectionHelperTest, TestResend) {
+TEST_F(QuicConnectionHelperTest, TestRetransmission) {
AddWrite(SYNCHRONOUS, ConstructDataPacket(1));
AddWrite(SYNCHRONOUS, ConstructDataPacket(2));
Initialize();
- QuicTime::Delta kDefaultResendTime = QuicTime::Delta::FromMilliseconds(500);
+ QuicTime::Delta kDefaultRetransmissionTime =
+ QuicTime::Delta::FromMilliseconds(500);
QuicTime start = clock_.Now();
EXPECT_CALL(*scheduler_, SentPacket(1, _, false));
// Send a packet.
- connection_->SendStreamData(1, kData, 0, false, NULL);
+ connection_->SendStreamData(1, kData, 0, false);
EXPECT_CALL(*scheduler_, SentPacket(2, _, true));
- // Since no ack was received, the resend alarm will fire and resend it.
+ // Since no ack was received, the retransmission alarm will fire and
+ // retransmit it.
runner_->RunNextTask();
- EXPECT_EQ(kDefaultResendTime, clock_.Now().Subtract(start));
+ EXPECT_EQ(kDefaultRetransmissionTime, clock_.Now().Subtract(start));
EXPECT_TRUE(AtEof());
}
@@ -347,7 +350,7 @@ TEST_F(QuicConnectionHelperTest, TimeoutAfterSend) {
EXPECT_EQ(5000u, clock_.Now().ToMicroseconds());
EXPECT_CALL(*scheduler_, SentPacket(1, _, false));
- // Send an ack so we don't set the resend alarm.
+ // Send an ack so we don't set the retransmission alarm.
connection_->SendAck();
// The original alarm will fire. We should not time out because we had a
@@ -374,14 +377,14 @@ TEST_F(QuicConnectionHelperTest, SendSchedulerDelayThenSend) {
EXPECT_CALL(*scheduler_, TimeUntilSend(false)).WillOnce(testing::Return(
QuicTime::Delta::FromMicroseconds(1)));
- connection_->SendStreamData(1, kData, 0, false, NULL);
+ connection_->SendStreamData(1, kData, 0, false);
EXPECT_CALL(*scheduler_, SentPacket(1, _, false));
EXPECT_EQ(1u, connection_->NumQueuedPackets());
// Advance the clock to fire the alarm, and configure the scheduler
// to permit the packet to be sent.
EXPECT_CALL(*scheduler_, TimeUntilSend(false)).WillOnce(testing::Return(
- QuicTime::Delta()));
+ QuicTime::Delta::Zero()));
EXPECT_CALL(visitor_, OnCanWrite()).WillOnce(testing::Return(true));
runner_->RunNextTask();
EXPECT_EQ(0u, connection_->NumQueuedPackets());
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 4f0bf6e..3e80dc9 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -64,6 +64,9 @@ class TestConnectionHelper : public QuicConnectionHelperInterface {
TestConnectionHelper(MockClock* clock, MockRandom* random_generator)
: clock_(clock),
random_generator_(random_generator),
+ retransmission_alarm_(QuicTime::Zero()),
+ send_alarm_(QuicTime::Zero()),
+ timeout_alarm_(QuicTime::Zero()),
blocked_(false) {
}
@@ -100,9 +103,8 @@ class TestConnectionHelper : public QuicConnectionHelperInterface {
return packet.length();
}
- virtual void SetResendAlarm(QuicPacketSequenceNumber sequence_number,
- QuicTime::Delta delay) {
- resend_alarms_[sequence_number] = clock_->Now().Add(delay);
+ virtual void SetRetransmissionAlarm(QuicTime::Delta delay) {
+ retransmission_alarm_ = clock_->Now().Add(delay);
}
virtual void SetSendAlarm(QuicTime::Delta delay) {
@@ -118,14 +120,14 @@ class TestConnectionHelper : public QuicConnectionHelperInterface {
}
virtual void UnregisterSendAlarmIfRegistered() {
- send_alarm_ = QuicTime();
+ send_alarm_ = QuicTime::Zero();
}
virtual void SetAckAlarm(QuicTime::Delta delay) {}
virtual void ClearAckAlarm() {}
- const map<QuicPacketSequenceNumber, QuicTime>& resend_alarms() const {
- return resend_alarms_;
+ QuicTime retransmission_alarm() const {
+ return retransmission_alarm_;
}
QuicTime timeout_alarm() const { return timeout_alarm_; }
@@ -141,7 +143,7 @@ class TestConnectionHelper : public QuicConnectionHelperInterface {
private:
MockClock* clock_;
MockRandom* random_generator_;
- map<QuicPacketSequenceNumber, QuicTime> resend_alarms_;
+ QuicTime retransmission_alarm_;
QuicTime send_alarm_;
QuicTime timeout_alarm_;
QuicPacketHeader header_;
@@ -174,11 +176,11 @@ class TestConnection : public QuicConnection {
bool SendPacket(QuicPacketSequenceNumber sequence_number,
QuicPacket* packet,
- bool should_resend,
+ bool should_retransmit,
bool force,
- bool is_retransmit) {
+ bool is_retransmission) {
return QuicConnection::SendPacket(
- sequence_number, packet, should_resend, force, is_retransmit);
+ sequence_number, packet, should_retransmit, force, is_retransmission);
}
private:
@@ -202,7 +204,7 @@ class QuicConnectionTest : public ::testing::Test {
// Simplify tests by not sending feedback unless specifically configured.
SetFeedback(NULL);
EXPECT_CALL(*scheduler_, TimeUntilSend(_)).WillRepeatedly(Return(
- QuicTime::Delta()));
+ QuicTime::Delta::Zero()));
EXPECT_CALL(*collector_,
RecordIncomingPacket(_, _, _, _)).Times(AnyNumber());
EXPECT_CALL(*scheduler_, SentPacket(_, _, _)).Times(AnyNumber());
@@ -262,13 +264,13 @@ class QuicConnectionTest : public ::testing::Test {
// redundancy.
scoped_ptr<QuicPacket> data_packet(ConstructDataPacket(number, 1));
- header_.guid = guid_;
+ header_.public_header.guid = guid_;
+ header_.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header_.private_flags = PACKET_PRIVATE_FLAGS_FEC;
header_.packet_sequence_number = number;
- header_.flags = PACKET_FLAGS_FEC;
- header_.fec_group = 1;
+ header_.fec_group = min_protected_packet;
QuicFecData fec_data;
- fec_data.min_protected_packet_sequence_number = min_protected_packet;
- fec_data.fec_group = 1;
+ fec_data.fec_group = header_.fec_group;
// Since all data packets in this test have the same payload, the
// redundancy is either equal to that payload or the xor of that payload
// with itself, depending on the number of packets.
@@ -291,7 +293,11 @@ class QuicConnectionTest : public ::testing::Test {
QuicStreamOffset offset, bool fin,
QuicPacketSequenceNumber* last_packet) {
EXPECT_CALL(*scheduler_, SentPacket(_, _, _));
- connection_.SendStreamData(id, data, offset, fin, last_packet);
+ connection_.SendStreamData(id, data, offset, fin);
+ if (last_packet != NULL) {
+ *last_packet =
+ QuicConnectionPeer::GetPacketCreator(&connection_)->sequence_number();
+ }
EXPECT_CALL(*scheduler_, SentPacket(_, _, _)).Times(AnyNumber());
}
@@ -321,9 +327,10 @@ class QuicConnectionTest : public ::testing::Test {
QuicPacket* ConstructDataPacket(QuicPacketSequenceNumber number,
QuicFecGroupNumber fec_group) {
- header_.guid = guid_;
+ header_.public_header.guid = guid_;
+ header_.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header_.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header_.packet_sequence_number = number;
- header_.flags = PACKET_FLAGS_NONE;
header_.fec_group = fec_group;
QuicFrames frames;
@@ -602,7 +609,7 @@ TEST_F(QuicConnectionTest, BasicSending) {
EXPECT_EQ(9u, last_ack()->sent_info.least_unacked);
}
-TEST_F(QuicConnectionTest, ResendOnNack) {
+TEST_F(QuicConnectionTest, RetransmitOnNack) {
QuicPacketSequenceNumber last_packet;
SendStreamDataToPeer(1, "foo", 0, false, &last_packet); // Packet 1
SendStreamDataToPeer(1, "foos", 3, false, &last_packet); // Packet 2
@@ -612,8 +619,8 @@ TEST_F(QuicConnectionTest, ResendOnNack) {
expected_acks.insert(1);
EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks)));
- // Client acks one but not two or three. Right now we only resend on explicit
- // nack, so it should not trigger resend.
+ // Client acks one but not two or three. Right now we only retransmit on
+ // explicit nack, so it should not trigger a retransimission.
QuicAckFrame ack_one(1, 0);
ProcessAckPacket(&ack_one);
ProcessAckPacket(&ack_one);
@@ -630,8 +637,8 @@ TEST_F(QuicConnectionTest, ResendOnNack) {
ProcessAckPacket(&nack_two);
ProcessAckPacket(&nack_two);
- // The third nack should trigger resend.
- EXPECT_CALL(*scheduler_, SentPacket(_, 37, true)).Times(1);
+ // The third nack should trigger a retransimission.
+ EXPECT_CALL(*scheduler_, SentPacket(_, 38, true)).Times(1);
ProcessAckPacket(&nack_two);
}
@@ -658,11 +665,11 @@ TEST_F(QuicConnectionTest, LimitPacketsPerNack) {
// The second call will trigger an ack.
EXPECT_CALL(*scheduler_, SentPacket(_, _, _)).Times(1);
ProcessAckPacket(&nack);
- // The third call should trigger resending 10 packets.
+ // The third call should trigger retransmitting 10 packets.
EXPECT_CALL(*scheduler_, SentPacket(_, _, _)).Times(10);
ProcessAckPacket(&nack);
- // The fourth call should trigger resending the 11th packet and an ack.
+ // The fourth call should trigger retransmitting the 11th packet and an ack.
EXPECT_CALL(*scheduler_, SentPacket(_, _, _)).Times(2);
ProcessAckPacket(&nack);
}
@@ -764,26 +771,25 @@ TEST_F(QuicConnectionTest, ReviveMissingPacketAfterDataPackets) {
ProcessFecProtectedPacket(5, true);
}
-TEST_F(QuicConnectionTest, TestResend) {
+TEST_F(QuicConnectionTest, TestRetransmit) {
// TODO(rch): make this work
// FLAGS_fake_packet_loss_percentage = 100;
- const QuicTime::Delta kDefaultResendTime =
+ const QuicTime::Delta kDefaultRetransmissionTime =
QuicTime::Delta::FromMilliseconds(500);
- QuicTime default_resend_time = clock_.Now().Add(kDefaultResendTime);
+ QuicTime default_retransmission_time = clock_.Now().Add(
+ kDefaultRetransmissionTime);
QuicAckFrame* outgoing_ack = QuicConnectionPeer::GetOutgoingAck(&connection_);
SendStreamDataToPeer(1, "foo", 0, false, NULL);
EXPECT_EQ(1u, outgoing_ack->sent_info.least_unacked);
EXPECT_EQ(1u, last_header()->packet_sequence_number);
- EXPECT_EQ(1u, helper_->resend_alarms().size());
- EXPECT_EQ(default_resend_time,
- helper_->resend_alarms().find(1)->second);
- // Simulate the resend alarm firing
- clock_.AdvanceTime(kDefaultResendTime);
+ EXPECT_EQ(default_retransmission_time, helper_->retransmission_alarm());
+ // Simulate the retransimission alarm firing
+ clock_.AdvanceTime(kDefaultRetransmissionTime);
EXPECT_CALL(*scheduler_, SentPacket(_, _, _));
- connection_.MaybeResendPacket(1);
+ connection_.MaybeRetransmitPacket(1);
EXPECT_EQ(2u, last_header()->packet_sequence_number);
EXPECT_EQ(2u, outgoing_ack->sent_info.least_unacked);
}
@@ -792,7 +798,7 @@ TEST_F(QuicConnectionTest, TestResend) {
TEST_F(QuicConnectionTest, DISABLED_TestQueued) {
EXPECT_EQ(0u, connection_.NumQueuedPackets());
helper_->set_blocked(true);
- connection_.SendStreamData(1, "foo", 0, false, NULL);
+ connection_.SendStreamData(1, "foo", 0, false);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
// Attempt to send all packets, but since we're actually still
@@ -876,7 +882,7 @@ TEST_F(QuicConnectionTest, TimeoutAfterSend) {
// When we send a packet, the timeout will change to 5000 + kDefaultTimeout.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
- // Send an ack so we don't set the resend alarm.
+ // Send an ack so we don't set the retransimission alarm.
SendAckPacketToPeer();
EXPECT_EQ(default_timeout, helper_->timeout_alarm());
@@ -900,12 +906,12 @@ TEST_F(QuicConnectionTest, TimeoutAfterSend) {
EXPECT_FALSE(connection_.connected());
}
-// TODO(ianswett): Add scheduler tests when resend is false.
+// TODO(ianswett): Add scheduler tests when should_retransmit is false.
TEST_F(QuicConnectionTest, SendScheduler) {
// Test that if we send a packet without delay, it is not queued.
QuicPacket* packet = ConstructDataPacket(1, 0);
EXPECT_CALL(*scheduler_, TimeUntilSend(false)).WillOnce(testing::Return(
- QuicTime::Delta()));
+ QuicTime::Delta::Zero()));
EXPECT_CALL(*scheduler_, SentPacket(_, _, _));
connection_.SendPacket(1, packet, true, false, false);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
@@ -935,7 +941,7 @@ TEST_F(QuicConnectionTest, DISABLED_SendSchedulerEAGAIN) {
QuicPacket* packet = ConstructDataPacket(1, 0);
helper_->set_blocked(true);
EXPECT_CALL(*scheduler_, TimeUntilSend(false)).WillOnce(testing::Return(
- QuicTime::Delta()));
+ QuicTime::Delta::Zero()));
EXPECT_CALL(*scheduler_, SentPacket(1, _, _)).Times(0);
connection_.SendPacket(1, packet, true, false, false);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -952,7 +958,7 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenSend) {
// Advance the clock to fire the alarm, and configure the scheduler
// to permit the packet to be sent.
EXPECT_CALL(*scheduler_, TimeUntilSend(false)).WillOnce(testing::Return(
- QuicTime::Delta()));
+ QuicTime::Delta::Zero()));
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(1));
EXPECT_CALL(*scheduler_, SentPacket(_, _, _));
EXPECT_CALL(visitor_, OnCanWrite());
@@ -971,7 +977,7 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenRetransmit) {
// Advance the clock to fire the alarm, and configure the scheduler
// to permit the packet to be sent.
EXPECT_CALL(*scheduler_, TimeUntilSend(true)).WillOnce(testing::Return(
- QuicTime::Delta()));
+ QuicTime::Delta::Zero()));
// Ensure the scheduler is notified this is a retransmit.
EXPECT_CALL(*scheduler_, SentPacket(1, _, true));
@@ -1001,11 +1007,11 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenAckAndSend) {
connection_.SendPacket(1, packet, true, false, false);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
- // Now send non-retransmitting information, that we're not going to resend 3.
- // The far end should stop waiting for it.
+ // Now send non-retransmitting information, that we're not going to
+ // retransmit 3. The far end should stop waiting for it.
QuicAckFrame frame(0, 1);
EXPECT_CALL(*scheduler_, TimeUntilSend(false)).WillRepeatedly(testing::Return(
- QuicTime::Delta()));
+ QuicTime::Delta::Zero()));
EXPECT_CALL(*scheduler_, SentPacket(_, _, _));
EXPECT_CALL(visitor_, OnCanWrite());
ProcessAckPacket(&frame);
@@ -1022,8 +1028,8 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenAckAndHold) {
connection_.SendPacket(1, packet, true, false, false);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
- // Now send non-resending information, that we're not going to resend 3.
- // The far end should stop waiting for it.
+ // Now send non-retransmitting information, that we're not going to
+ // retransmit 3. The far end should stop waiting for it.
QuicAckFrame frame(0, 1);
EXPECT_CALL(*scheduler_, TimeUntilSend(false)).WillOnce(testing::Return(
QuicTime::Delta::FromMicroseconds(1)));
@@ -1055,9 +1061,9 @@ TEST_F(QuicConnectionTest, TestQueueLimitsOnSendStreamData) {
// Queue the first packet.
EXPECT_CALL(*scheduler_, TimeUntilSend(false)).WillOnce(testing::Return(
QuicTime::Delta::FromMicroseconds(10)));
- EXPECT_EQ(6u, connection_.SendStreamData(
- 1, "EnoughDataToQueue", 0, false, NULL).bytes_consumed);
- EXPECT_EQ(6u, connection_.NumQueuedPackets());
+ EXPECT_EQ(1u, connection_.SendStreamData(
+ 1, "EnoughDataToQueue", 0, false).bytes_consumed);
+ EXPECT_EQ(1u, connection_.NumQueuedPackets());
}
TEST_F(QuicConnectionTest, LoopThroughSendingPackets) {
@@ -1069,7 +1075,7 @@ TEST_F(QuicConnectionTest, LoopThroughSendingPackets) {
// Queue the first packet.
EXPECT_CALL(*scheduler_, SentPacket(_, _, _)).Times(17);
EXPECT_EQ(17u, connection_.SendStreamData(
- 1, "EnoughDataToQueue", 0, false, NULL).bytes_consumed);
+ 1, "EnoughDataToQueue", 0, false).bytes_consumed);
}
} // namespace
diff --git a/net/quic/quic_data_writer.cc b/net/quic/quic_data_writer.cc
index c4f7552..3bbad4e 100644
--- a/net/quic/quic_data_writer.cc
+++ b/net/quic/quic_data_writer.cc
@@ -98,6 +98,11 @@ bool QuicDataWriter::WriteBytes(const void* data, size_t data_len) {
return true;
}
+void QuicDataWriter::WritePadding() {
+ memset(buffer_ + length_, 0x00, capacity_ - length_);
+ length_ = capacity_;
+}
+
bool QuicDataWriter::WriteUInt8ToOffset(uint8 value, size_t offset) {
DCHECK_LT(offset, capacity_);
int latched_length = length_;
diff --git a/net/quic/quic_data_writer.h b/net/quic/quic_data_writer.h
index 3ca4fa3..f80e905 100644
--- a/net/quic/quic_data_writer.h
+++ b/net/quic/quic_data_writer.h
@@ -46,6 +46,8 @@ class NET_EXPORT_PRIVATE QuicDataWriter {
bool WriteUInt128(uint128 value);
bool WriteStringPiece16(base::StringPiece val);
bool WriteBytes(const void* data, size_t data_len);
+ // Fills the remaining buffer with null characters.
+ void WritePadding();
// Methods for editing the payload at a specific offset, where the
// offset must be within the writer's capacity.
diff --git a/net/quic/quic_fec_group.cc b/net/quic/quic_fec_group.cc
index c678787..2a2695d 100644
--- a/net/quic/quic_fec_group.cc
+++ b/net/quic/quic_fec_group.cc
@@ -26,6 +26,10 @@ QuicFecGroup::QuicFecGroup()
QuicFecGroup::~QuicFecGroup() {}
+size_t QuicFecGroup::GroupSize() const {
+ return max_protected_packet_ - min_protected_packet_ + 1;
+}
+
bool QuicFecGroup::Update(const QuicPacketHeader& header,
StringPiece decrypted_payload) {
if (received_packets_.count(header.packet_sequence_number) != 0) {
@@ -54,7 +58,7 @@ bool QuicFecGroup::UpdateFec(
}
set<QuicPacketSequenceNumber>::const_iterator it = received_packets_.begin();
while (it != received_packets_.end()) {
- if ((*it < fec.min_protected_packet_sequence_number) ||
+ if ((*it < fec.fec_group) ||
(*it >= fec_packet_sequence_number)) {
DLOG(ERROR) << "FEC group does not cover received packet: " << *it;
return false;
@@ -64,7 +68,7 @@ bool QuicFecGroup::UpdateFec(
if (!UpdateParity(fec.redundancy)) {
return false;
}
- min_protected_packet_ = fec.min_protected_packet_sequence_number;
+ min_protected_packet_ = fec.fec_group;
max_protected_packet_ = fec_packet_sequence_number - 1;
return true;
}
diff --git a/net/quic/quic_fec_group.h b/net/quic/quic_fec_group.h
index 63a3253..67cba64 100644
--- a/net/quic/quic_fec_group.h
+++ b/net/quic/quic_fec_group.h
@@ -21,6 +21,12 @@ class NET_EXPORT_PRIVATE QuicFecGroup {
QuicFecGroup();
~QuicFecGroup();
+ QuicPacketSequenceNumber min_protected_packet() const {
+ return min_protected_packet_;
+ }
+
+ size_t GroupSize() const;
+
// Updates the FEC group based on the delivery of a data packet.
// Returns false if this packet has already been seen, true otherwise.
bool Update(const QuicPacketHeader& header,
diff --git a/net/quic/quic_fec_group_test.cc b/net/quic/quic_fec_group_test.cc
index a53942f..4e4dd20 100644
--- a/net/quic/quic_fec_group_test.cc
+++ b/net/quic/quic_fec_group_test.cc
@@ -53,7 +53,7 @@ class QuicFecGroupTest : public ::testing::Test {
if (packet == lost_packet) {
ASSERT_FALSE(group.IsFinished());
QuicFecData fec;
- fec.min_protected_packet_sequence_number = 0;
+ fec.fec_group = 0;
fec.redundancy = StringPiece(redundancy.get(), strlen(kData[0]));
ASSERT_TRUE(group.UpdateFec(num_packets, fec));
} else {
@@ -79,7 +79,7 @@ class QuicFecGroupTest : public ::testing::Test {
ASSERT_FALSE(group.IsFinished());
// Attempt to revive the missing packet.
QuicFecData fec;
- fec.min_protected_packet_sequence_number = 0;
+ fec.fec_group = 0;
fec.redundancy = StringPiece(redundancy.get(), strlen(kData[0]));
ASSERT_TRUE(group.UpdateFec(num_packets, fec));
@@ -134,7 +134,7 @@ TEST_F(QuicFecGroupTest, UpdateFecIfReceivedPacketIsNotCovered) {
group.Update(header, data1);
QuicFecData fec;
- fec.min_protected_packet_sequence_number = 1;
+ fec.fec_group = 1;
fec.redundancy = redundancy;
ASSERT_FALSE(group.UpdateFec(2, fec));
@@ -182,7 +182,7 @@ TEST_F(QuicFecGroupTest, ProtectsPacketsBeforeWithSeveralPackets) {
TEST_F(QuicFecGroupTest, ProtectsPacketsBeforeWithFecData) {
QuicFecData fec;
- fec.min_protected_packet_sequence_number = 2;
+ fec.fec_group = 2;
fec.redundancy = kData[0];
QuicFecGroup group;
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index cae0b85..2c359ed 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -12,17 +12,41 @@
#include "net/quic/quic_utils.h"
using base::StringPiece;
+using std::make_pair;
using std::map;
using std::numeric_limits;
namespace net {
-bool kQuicAllowOversizedPacketsForTest = false;
+namespace {
+
+// Mask to select the lowest 48 bits of a sequence number.
+const QuicPacketSequenceNumber kSequenceNumberMask =
+ GG_UINT64_C(0x0000FFFFFFFFFFFF);
+
+// Returns the absolute value of the difference between |a| and |b|.
+QuicPacketSequenceNumber Delta(QuicPacketSequenceNumber a,
+ QuicPacketSequenceNumber b) {
+ // Since these are unsigned numbers, we can't just return abs(a - b)
+ if (a < b) {
+ return b - a;
+ }
+ return a - b;
+}
+
+QuicPacketSequenceNumber ClosestTo(QuicPacketSequenceNumber target,
+ QuicPacketSequenceNumber a,
+ QuicPacketSequenceNumber b) {
+ return (Delta(target, a) < Delta(target, b)) ? a : b;
+}
+
+} // namespace
QuicFramer::QuicFramer(QuicDecrypter* decrypter, QuicEncrypter* encrypter)
: visitor_(NULL),
fec_builder_(NULL),
error_(QUIC_NO_ERROR),
+ last_sequence_number_(0),
decrypter_(decrypter),
encrypter_(encrypter) {
}
@@ -59,6 +83,14 @@ QuicPacket* QuicFramer::ConstructMaxFrameDataPacket(
len += 1; // frame count
bool truncating = false;
for (size_t i = 0; i < frames.size(); ++i) {
+ if (frames[i].type == PADDING_FRAME) {
+ // PADDING implies end of packet so make sure we don't have
+ // more frames on the list.
+ DCHECK_EQ(i, frames.size() - 1);
+ len = max_plaintext_size;
+ *num_consumed = i + 1;
+ break;
+ }
size_t frame_len = 1; // Space for the 8 bit type.
frame_len += ComputeFramePayloadLength(frames[i]);
if (len + frame_len > max_plaintext_size) {
@@ -104,15 +136,15 @@ QuicPacket* QuicFramer::ConstructMaxFrameDataPacket(
}
switch (frame.type) {
+ case PADDING_FRAME:
+ writer.WritePadding();
+ break;
case STREAM_FRAME:
if (!AppendStreamFramePayload(*frame.stream_frame,
&writer)) {
return NULL;
}
break;
- case PDU_FRAME:
- RaiseError(QUIC_INVALID_FRAME_DATA);
- return NULL;
case ACK_FRAME:
if (!AppendAckFramePayload(*frame.ack_frame, &writer)) {
return NULL;
@@ -143,8 +175,8 @@ QuicPacket* QuicFramer::ConstructMaxFrameDataPacket(
}
DCHECK(truncating || len == writer.length());
- QuicPacket* packet = new QuicPacket(writer.take(), len, true,
- PACKET_FLAGS_NONE);
+ QuicPacket* packet = QuicPacket::NewDataPacket(writer.take(), len, true);
+
if (fec_builder_) {
fec_builder_->OnBuiltFecProtectedPayload(header,
packet->FecProtectedData());
@@ -155,10 +187,7 @@ QuicPacket* QuicFramer::ConstructMaxFrameDataPacket(
QuicPacket* QuicFramer::ConstructFecPacket(const QuicPacketHeader& header,
const QuicFecData& fec) {
- // Compute the length of the packet. We use "magic numbers" here because
- // sizeof(member_) is not necessairly the same as sizeof(member_wire_format).
size_t len = kPacketHeaderSize;
- len += 6; // first protected packet sequence number
len += fec.redundancy.length();
QuicDataWriter writer(len);
@@ -167,33 +196,51 @@ QuicPacket* QuicFramer::ConstructFecPacket(const QuicPacketHeader& header,
return NULL;
}
- if (!writer.WriteUInt48(fec.min_protected_packet_sequence_number)) {
- return NULL;
- }
-
if (!writer.WriteBytes(fec.redundancy.data(), fec.redundancy.length())) {
return NULL;
}
- return new QuicPacket(writer.take(), len, true, PACKET_FLAGS_FEC);
+ return QuicPacket::NewFecPacket(writer.take(), len, true);
}
+// TODO(satyamshekhar): Framer doesn't need addresses. Get rid of them.
bool QuicFramer::ProcessPacket(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
const QuicEncryptedPacket& packet) {
DCHECK(!reader_.get());
reader_.reset(new QuicDataReader(packet.data(), packet.length()));
+
+ // First parse the public header.
+ QuicPacketPublicHeader public_header;
+ if (!ProcessPublicHeader(&public_header)) {
+ DLOG(WARNING) << "Unable to process header.";
+ reader_.reset(NULL);
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
+
+ if (!ProcessDataPacket(public_header, self_address, peer_address, packet)) {
+ reader_.reset(NULL);
+ return false;
+ };
+
+ reader_.reset(NULL);
+ return true;
+}
+
+bool QuicFramer::ProcessDataPacket(
+ const QuicPacketPublicHeader& public_header,
+ const IPEndPoint& self_address,
+ const IPEndPoint& peer_address,
+ const QuicEncryptedPacket& packet) {
visitor_->OnPacket(self_address, peer_address);
- // First parse the packet header.
- QuicPacketHeader header;
+ QuicPacketHeader header(public_header);
if (!ProcessPacketHeader(&header, packet)) {
- DLOG(WARNING) << "Unable to process header.";
+ DLOG(WARNING) << "Unable to process data packet header.";
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
if (!visitor_->OnPacketHeader(header)) {
- reader_.reset(NULL);
return true;
}
@@ -203,7 +250,7 @@ bool QuicFramer::ProcessPacket(const IPEndPoint& self_address,
}
// Handle the payload.
- if ((header.flags & PACKET_FLAGS_FEC) == 0) {
+ if ((header.private_flags & PACKET_PRIVATE_FLAGS_FEC) == 0) {
if (header.fec_group != 0) {
StringPiece payload = reader_->PeekRemainingPayload();
visitor_->OnFecProtectedPayload(payload);
@@ -216,18 +263,11 @@ bool QuicFramer::ProcessPacket(const IPEndPoint& self_address,
} else {
QuicFecData fec_data;
fec_data.fec_group = header.fec_group;
- if (!reader_->ReadUInt48(
- &fec_data.min_protected_packet_sequence_number)) {
- set_detailed_error("Unable to read first protected packet.");
- return RaiseError(QUIC_INVALID_FEC_DATA);
- }
-
fec_data.redundancy = reader_->ReadRemainingPayload();
visitor_->OnFecData(fec_data);
}
visitor_->OnPacketComplete();
- reader_.reset(NULL);
return true;
}
@@ -258,69 +298,140 @@ bool QuicFramer::ProcessRevivedPacket(const QuicPacketHeader& header,
bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header,
QuicDataWriter* writer) {
- if (!writer->WriteUInt64(header.guid)) {
+ if (!writer->WriteUInt64(header.public_header.guid)) {
+ return false;
+ }
+
+ uint8 flags =static_cast<uint8>(header.public_header.flags);
+ if (!writer->WriteBytes(&flags, 1)) {
return false;
}
- if (!writer->WriteUInt48(header.packet_sequence_number)) {
+ if (!AppendPacketSequenceNumber(header.packet_sequence_number, writer)) {
return false;
}
- uint8 flags = static_cast<uint8>(header.flags);
+ flags = static_cast<uint8>(header.private_flags);
if (!writer->WriteBytes(&flags, 1)) {
return false;
}
- if (!writer->WriteBytes(&header.fec_group, 1)) {
+ // Offset from the current packet sequence number to the first fec
+ // protected packet, or kNoFecOffset to signal no FEC protection.
+ uint8 first_fec_protected_packet_offset = kNoFecOffset;
+
+ // The FEC group number is the sequence number of the first fec
+ // protected packet, or 0 if this packet is not protected.
+ if (header.fec_group != 0) {
+ DCHECK_GE(header.packet_sequence_number, header.fec_group);
+ DCHECK_GT(255u, header.packet_sequence_number - header.fec_group);
+ first_fec_protected_packet_offset =
+ header.packet_sequence_number - header.fec_group;
+ }
+ if (!writer->WriteBytes(&first_fec_protected_packet_offset, 1)) {
return false;
}
return true;
}
-bool QuicFramer::ProcessPacketHeader(QuicPacketHeader* header,
- const QuicEncryptedPacket& packet) {
- if (!reader_->ReadUInt64(&header->guid)) {
+QuicPacketSequenceNumber QuicFramer::CalculatePacketSequenceNumberFromWire(
+ QuicPacketSequenceNumber packet_sequence_number) const {
+ // The new sequence number might have wrapped to the next epoc, or
+ // it might have reverse wrapped to the previous epoch, or it might
+ // remain in the same epoch. Select the sequence number closest to the
+ // previous sequence number.
+ QuicPacketSequenceNumber epoch = last_sequence_number_ & ~kSequenceNumberMask;
+ QuicPacketSequenceNumber prev_epoch = epoch - (GG_UINT64_C(1) << 48);
+ QuicPacketSequenceNumber next_epoch = epoch + (GG_UINT64_C(1) << 48);
+
+ return ClosestTo(last_sequence_number_,
+ epoch + packet_sequence_number,
+ ClosestTo(last_sequence_number_,
+ prev_epoch + packet_sequence_number,
+ next_epoch + packet_sequence_number));
+}
+
+bool QuicFramer::ProcessPublicHeader(QuicPacketPublicHeader* public_header) {
+ if (!reader_->ReadUInt64(&public_header->guid)) {
set_detailed_error("Unable to read GUID.");
return false;
}
- if (!reader_->ReadUInt48(&header->packet_sequence_number)) {
+ uint8 public_flags;
+ if (!reader_->ReadBytes(&public_flags, 1)) {
+ set_detailed_error("Unable to read public flags.");
+ return false;
+ }
+
+ if (public_flags > PACKET_PUBLIC_FLAGS_MAX) {
+ set_detailed_error("Illegal flags value.");
+ return false;
+ }
+
+ public_header->flags = static_cast<QuicPacketPublicFlags>(public_flags);
+ return true;
+}
+
+bool QuicFramer::ProcessPacketHeader(
+ QuicPacketHeader* header,
+ const QuicEncryptedPacket& packet) {
+ if (!ProcessPacketSequenceNumber(&header->packet_sequence_number)) {
set_detailed_error("Unable to read sequence number.");
return false;
}
+
if (header->packet_sequence_number == 0u) {
set_detailed_error("Packet sequence numbers cannot be 0.");
return false;
}
- unsigned char flags;
- if (!reader_->ReadBytes(&flags, 1)) {
- set_detailed_error("Unable to read flags.");
+ if (!DecryptPayload(packet)) {
+ DLOG(WARNING) << "Unable to decrypt payload.";
+ return RaiseError(QUIC_DECRYPTION_FAILURE);
+ }
+
+ uint8 private_flags;
+ if (!reader_->ReadBytes(&private_flags, 1)) {
+ set_detailed_error("Unable to read private flags.");
return false;
}
- if (flags > PACKET_FLAGS_MAX) {
- set_detailed_error("Illegal flags value.");
+ if (private_flags > PACKET_PRIVATE_FLAGS_MAX) {
+ set_detailed_error("Illegal private flags value.");
return false;
}
- header->flags = static_cast<QuicPacketFlags>(flags);
+ header->private_flags = static_cast<QuicPacketPrivateFlags>(private_flags);
- if (!DecryptPayload(packet)) {
- DLOG(WARNING) << "Unable to decrypt payload.";
- return RaiseError(QUIC_DECRYPTION_FAILURE);
+ uint8 first_fec_protected_packet_offset;
+ if (!reader_->ReadBytes(&first_fec_protected_packet_offset, 1)) {
+ set_detailed_error("Unable to read first fec protected packet offset.");
+ return false;
}
+ header->fec_group = first_fec_protected_packet_offset == kNoFecOffset ? 0 :
+ header->packet_sequence_number - first_fec_protected_packet_offset;
+
+ // Set the last sequence number after we have decrypted the packet
+ // so we are confident is not attacker controlled.
+ last_sequence_number_ = header->packet_sequence_number;
+ return true;
+}
- if (!reader_->ReadBytes(&header->fec_group, 1)) {
- set_detailed_error("Unable to read fec group.");
+bool QuicFramer::ProcessPacketSequenceNumber(
+ QuicPacketSequenceNumber* sequence_number) {
+ QuicPacketSequenceNumber wire_sequence_number;
+ if (!reader_->ReadUInt48(&wire_sequence_number)) {
return false;
}
+ *sequence_number =
+ CalculatePacketSequenceNumberFromWire(wire_sequence_number);
return true;
}
bool QuicFramer::ProcessFrameData() {
+ // TODO(ianswett): remove frame_count
uint8 frame_count;
if (!reader_->ReadBytes(&frame_count, 1)) {
set_detailed_error("Unable to read frame count.");
@@ -334,16 +445,14 @@ bool QuicFramer::ProcessFrameData() {
return RaiseError(QUIC_INVALID_FRAME_DATA);
}
switch (frame_type) {
+ case PADDING_FRAME:
+ // We're done with the packet
+ return true;
case STREAM_FRAME:
if (!ProcessStreamFrame()) {
return RaiseError(QUIC_INVALID_FRAME_DATA);
}
break;
- case PDU_FRAME:
- if (!ProcessPDUFrame()) {
- return RaiseError(QUIC_INVALID_FRAME_DATA);
- }
- break;
case ACK_FRAME: {
QuicAckFrame frame;
if (!ProcessAckFrame(&frame)) {
@@ -410,10 +519,6 @@ bool QuicFramer::ProcessStreamFrame() {
return true;
}
-bool QuicFramer::ProcessPDUFrame() {
- return false;
-}
-
bool QuicFramer::ProcessAckFrame(QuicAckFrame* frame) {
if (!ProcessSentInfo(&frame->sent_info)) {
return false;
@@ -426,7 +531,7 @@ bool QuicFramer::ProcessAckFrame(QuicAckFrame* frame) {
}
bool QuicFramer::ProcessReceivedInfo(ReceivedPacketInfo* received_info) {
- if (!reader_->ReadUInt48(&received_info->largest_observed)) {
+ if (!ProcessPacketSequenceNumber(&received_info->largest_observed)) {
set_detailed_error("Unable to read largest observed.");
return false;
}
@@ -439,7 +544,7 @@ bool QuicFramer::ProcessReceivedInfo(ReceivedPacketInfo* received_info) {
for (int i = 0; i < num_missing_packets; ++i) {
QuicPacketSequenceNumber sequence_number;
- if (!reader_->ReadUInt48(&sequence_number)) {
+ if (!ProcessPacketSequenceNumber(&sequence_number)) {
set_detailed_error("Unable to read sequence number in missing packets.");
return false;
}
@@ -450,7 +555,7 @@ bool QuicFramer::ProcessReceivedInfo(ReceivedPacketInfo* received_info) {
}
bool QuicFramer::ProcessSentInfo(SentPacketInfo* sent_info) {
- if (!reader_->ReadUInt48(&sent_info->least_unacked)) {
+ if (!ProcessPacketSequenceNumber(&sent_info->least_unacked)) {
set_detailed_error("Unable to read least unacked.");
return false;
}
@@ -486,7 +591,7 @@ bool QuicFramer::ProcessQuicCongestionFeedbackFrame(
if (num_received_packets > 0u) {
uint64 smallest_received;
- if (!reader_->ReadUInt48(&smallest_received)) {
+ if (!ProcessPacketSequenceNumber(&smallest_received)) {
set_detailed_error("Unable to read smallest received.");
return false;
}
@@ -497,8 +602,9 @@ bool QuicFramer::ProcessQuicCongestionFeedbackFrame(
return false;
}
- inter_arrival->received_packet_times[smallest_received] =
- QuicTime::FromMicroseconds(time_received_us);
+ inter_arrival->received_packet_times.insert(
+ make_pair(smallest_received,
+ QuicTime::FromMicroseconds(time_received_us)));
for (int i = 0; i < num_received_packets - 1; ++i) {
uint16 sequence_delta;
@@ -515,8 +621,9 @@ bool QuicFramer::ProcessQuicCongestionFeedbackFrame(
return false;
}
QuicPacketSequenceNumber packet = smallest_received + sequence_delta;
- inter_arrival->received_packet_times[packet] =
- QuicTime::FromMicroseconds(time_received_us + time_delta_us);
+ inter_arrival->received_packet_times.insert(
+ make_pair(packet, QuicTime::FromMicroseconds(time_received_us +
+ time_delta_us)));
}
}
break;
@@ -655,9 +762,6 @@ size_t QuicFramer::ComputeFramePayloadLength(const QuicFrame& frame) {
len += 2; // space for the 16 bit length
len += frame.stream_frame->data.size();
break;
- case PDU_FRAME:
- DLOG(INFO) << "PDU_FRAME not yet supported";
- break; // Need to support this eventually :>
case ACK_FRAME: {
const QuicAckFrame& ack = *frame.ack_frame;
len += 6; // largest observed packet sequence number
@@ -720,6 +824,12 @@ size_t QuicFramer::ComputeFramePayloadLength(const QuicFrame& frame) {
return len;
}
+bool QuicFramer::AppendPacketSequenceNumber(
+ QuicPacketSequenceNumber packet_sequence_number,
+ QuicDataWriter* writer) {
+ return writer->WriteUInt48(packet_sequence_number & kSequenceNumberMask);
+}
+
bool QuicFramer::AppendStreamFramePayload(
const QuicStreamFrame& frame,
QuicDataWriter* writer) {
@@ -763,12 +873,13 @@ QuicPacketSequenceNumber QuicFramer::CalculateLargestObserved(
bool QuicFramer::AppendAckFramePayload(
const QuicAckFrame& frame,
QuicDataWriter* writer) {
- if (!writer->WriteUInt48(frame.sent_info.least_unacked)) {
+ if (!AppendPacketSequenceNumber(frame.sent_info.least_unacked, writer)) {
return false;
}
size_t largest_observed_offset = writer->length();
- if (!writer->WriteUInt48(frame.received_info.largest_observed)) {
+ if (!AppendPacketSequenceNumber(frame.received_info.largest_observed,
+ writer)) {
return false;
}
@@ -783,11 +894,12 @@ bool QuicFramer::AppendAckFramePayload(
SequenceSet::const_iterator it = frame.received_info.missing_packets.begin();
int num_missing_packets_written = 0;
for (; it != frame.received_info.missing_packets.end(); ++it) {
- if (!writer->WriteUInt48(*it)) {
+ if (!AppendPacketSequenceNumber(*it, writer)) {
// We are truncating. Overwrite largest_observed.
QuicPacketSequenceNumber largest_observed =
CalculateLargestObserved(frame.received_info.missing_packets, --it);
- writer->WriteUInt48ToOffset(largest_observed, largest_observed_offset);
+ writer->WriteUInt48ToOffset(largest_observed & kSequenceNumberMask,
+ largest_observed_offset);
writer->WriteUInt8ToOffset(num_missing_packets_written,
num_missing_packets_offset);
return true;
@@ -831,7 +943,7 @@ bool QuicFramer::AppendQuicCongestionFeedbackFramePayload(
inter_arrival.received_packet_times.begin();
QuicPacketSequenceNumber lowest_sequence = it->first;
- if (!writer->WriteUInt48(lowest_sequence)) {
+ if (!AppendPacketSequenceNumber(lowest_sequence, writer)) {
return false;
}
diff --git a/net/quic/quic_framer.h b/net/quic/quic_framer.h
index f749e29..81c944a 100644
--- a/net/quic/quic_framer.h
+++ b/net/quic/quic_framer.h
@@ -18,6 +18,10 @@
namespace net {
+namespace test {
+class QuicFramerPeer;
+} // namespace test
+
class QuicDataReader;
class QuicDataWriter;
class QuicDecrypter;
@@ -164,15 +168,24 @@ class NET_EXPORT_PRIVATE QuicFramer {
const std::string& detailed_error() { return detailed_error_; }
private:
+ friend class test::QuicFramerPeer;
+
+ bool ProcessDataPacket(const QuicPacketPublicHeader& public_header,
+ const IPEndPoint& self_address,
+ const IPEndPoint& peer_address,
+ const QuicEncryptedPacket& packet);
+
bool WritePacketHeader(const QuicPacketHeader& header,
- QuicDataWriter* builder);
+ QuicDataWriter* writer);
+
+ bool ProcessPublicHeader(QuicPacketPublicHeader* header);
bool ProcessPacketHeader(QuicPacketHeader* header,
const QuicEncryptedPacket& packet);
+ bool ProcessPacketSequenceNumber(QuicPacketSequenceNumber* sequence_number);
bool ProcessFrameData();
bool ProcessStreamFrame();
- bool ProcessPDUFrame();
bool ProcessAckFrame(QuicAckFrame* frame);
bool ProcessReceivedInfo(ReceivedPacketInfo* received_info);
bool ProcessSentInfo(SentPacketInfo* sent_info);
@@ -183,9 +196,18 @@ class NET_EXPORT_PRIVATE QuicFramer {
bool DecryptPayload(const QuicEncryptedPacket& packet);
+ // Returns the full packet sequence number from the truncated
+ // wire format version and the last seen packet sequence number.
+ QuicPacketSequenceNumber CalculatePacketSequenceNumberFromWire(
+ QuicPacketSequenceNumber packet_sequence_number) const;
+
// Computes the wire size in bytes of the payload of |frame|.
size_t ComputeFramePayloadLength(const QuicFrame& frame);
+ bool AppendPacketSequenceNumber(
+ QuicPacketSequenceNumber packet_sequence_number,
+ QuicDataWriter* writer);
+
bool AppendStreamFramePayload(const QuicStreamFrame& frame,
QuicDataWriter* builder);
bool AppendAckFramePayload(const QuicAckFrame& frame,
@@ -213,6 +235,7 @@ class NET_EXPORT_PRIVATE QuicFramer {
QuicFramerVisitorInterface* visitor_;
QuicFecBuilderInterface* fec_builder_;
QuicErrorCode error_;
+ QuicPacketSequenceNumber last_sequence_number_;
// Buffer containing decrypted payload data during parsing.
scoped_ptr<QuicData> decrypted_;
// Decrypter used to decrypt packets during parsing.
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc
index 2b8832c..6b10890 100644
--- a/net/quic/quic_framer_test.cc
+++ b/net/quic/quic_framer_test.cc
@@ -19,6 +19,7 @@
using base::hash_set;
using base::StringPiece;
+using std::make_pair;
using std::map;
using std::string;
using std::vector;
@@ -26,6 +27,24 @@ using std::vector;
namespace net {
namespace test {
+const QuicPacketSequenceNumber kEpoch = GG_UINT64_C(1) << 48;
+const QuicPacketSequenceNumber kMask = kEpoch - 1;
+
+class QuicFramerPeer {
+ public:
+ static QuicPacketSequenceNumber CalculatePacketSequenceNumberFromWire(
+ QuicFramer* framer,
+ QuicPacketSequenceNumber packet_sequence_number) {
+ return framer->CalculatePacketSequenceNumberFromWire(
+ packet_sequence_number);
+ }
+ static void SetLastSequenceNumber(
+ QuicFramer* framer,
+ QuicPacketSequenceNumber packet_sequence_number) {
+ framer->last_sequence_number_ = packet_sequence_number;
+ }
+};
+
class TestEncrypter : public QuicEncrypter {
public:
virtual ~TestEncrypter() {}
@@ -232,6 +251,19 @@ class QuicFramerTest : public ::testing::Test {
EXPECT_EQ(keys, ack->received_info.largest_observed);
}
+ void CheckCalculatePacketSequenceNumber(
+ QuicPacketSequenceNumber expected_sequence_number,
+ QuicPacketSequenceNumber last_sequence_number) {
+ QuicPacketSequenceNumber wire_sequence_number =
+ expected_sequence_number & kMask;
+ QuicFramerPeer::SetLastSequenceNumber(&framer_, last_sequence_number);
+ EXPECT_EQ(expected_sequence_number,
+ QuicFramerPeer::CalculatePacketSequenceNumberFromWire(
+ &framer_, wire_sequence_number))
+ << "last_sequence_number: " << last_sequence_number
+ << "wire_sequence_number: " << wire_sequence_number;
+ }
+
test::TestEncrypter* encrypter_;
test::TestDecrypter* decrypter_;
QuicFramer framer_;
@@ -240,6 +272,105 @@ class QuicFramerTest : public ::testing::Test {
IPEndPoint peer_address_;
};
+TEST_F(QuicFramerTest, CalculatePacketSequenceNumberFromWireNearEpochStart) {
+ // A few quick manual sanity checks
+ CheckCalculatePacketSequenceNumber(GG_UINT64_C(1), GG_UINT64_C(0));
+ CheckCalculatePacketSequenceNumber(kEpoch + 1, kMask);
+ CheckCalculatePacketSequenceNumber(kEpoch, kMask);
+
+ // Cases where the last number was close to the start of the range
+ for (uint64 last = 0; last < 10; last++) {
+ // Small numbers should not wrap (even if they're out of order).
+ for (uint64 j = 0; j < 10; j++) {
+ CheckCalculatePacketSequenceNumber(j, last);
+ }
+
+ // Large numbers should not wrap either (because we're near 0 already).
+ for (uint64 j = 0; j < 10; j++) {
+ CheckCalculatePacketSequenceNumber(kEpoch - 1 - j, last);
+ }
+ }
+}
+
+TEST_F(QuicFramerTest, CalculatePacketSequenceNumberFromWireNearEpochEnd) {
+ // Cases where the last number was close to the end of the range
+ for (uint64 i = 0; i < 10; i++) {
+ QuicPacketSequenceNumber last = kEpoch - i;
+
+ // Small numbers should wrap.
+ for (uint64 j = 0; j < 10; j++) {
+ CheckCalculatePacketSequenceNumber(kEpoch + j, last);
+ }
+
+ // Large numbers should not (even if they're out of order).
+ for (uint64 j = 0; j < 10; j++) {
+ CheckCalculatePacketSequenceNumber(kEpoch - 1 - j, last);
+ }
+ }
+}
+
+// Next check where we're in a non-zero epoch to verify we handle
+// reverse wrapping, too.
+TEST_F(QuicFramerTest, CalculatePacketSequenceNumberFromWireNearPrevEpoch) {
+ const uint64 prev_epoch = 1 * kEpoch;
+ const uint64 cur_epoch = 2 * kEpoch;
+ // Cases where the last number was close to the start of the range
+ for (uint64 i = 0; i < 10; i++) {
+ uint64 last = cur_epoch + i;
+ // Small number should not wrap (even if they're out of order).
+ for (uint64 j = 0; j < 10; j++) {
+ CheckCalculatePacketSequenceNumber(cur_epoch + j, last);
+ }
+
+ // But large numbers should reverse wrap.
+ for (uint64 j = 0; j < 10; j++) {
+ uint64 num = kEpoch - 1 - j;
+ CheckCalculatePacketSequenceNumber(prev_epoch + num, last);
+ }
+ }
+}
+
+TEST_F(QuicFramerTest, CalculatePacketSequenceNumberFromWireNearNextEpoch) {
+ const uint64 cur_epoch = 2 * kEpoch;
+ const uint64 next_epoch = 3 * kEpoch;
+ // Cases where the last number was close to the end of the range
+ for (uint64 i = 0; i < 10; i++) {
+ QuicPacketSequenceNumber last = next_epoch - 1 - i;
+
+ // Small numbers should wrap.
+ for (uint64 j = 0; j < 10; j++) {
+ CheckCalculatePacketSequenceNumber(next_epoch + j, last);
+ }
+
+ // but large numbers should not (even if they're out of order).
+ for (uint64 j = 0; j < 10; j++) {
+ uint64 num = kEpoch - 1 - j;
+ CheckCalculatePacketSequenceNumber(cur_epoch + num, last);
+ }
+ }
+}
+
+TEST_F(QuicFramerTest, CalculatePacketSequenceNumberFromWireNearNextMax) {
+ const uint64 max_number = std::numeric_limits<uint64>::max();
+ const uint64 max_epoch = max_number & ~kMask;
+
+ // Cases where the last number was close to the end of the range
+ for (uint64 i = 0; i < 10; i++) {
+ QuicPacketSequenceNumber last = max_number - i;
+
+ // Small numbers should not wrap (because they have nowhere to go.
+ for (uint64 j = 0; j < 10; j++) {
+ CheckCalculatePacketSequenceNumber(max_epoch + j, last);
+ }
+
+ // Large numbers should not wrap either.
+ for (uint64 j = 0; j < 10; j++) {
+ uint64 num = kEpoch - 1 - j;
+ CheckCalculatePacketSequenceNumber(max_epoch + num, last);
+ }
+ }
+}
+
TEST_F(QuicFramerTest, EmptyPacket) {
char packet[] = { 0x00 };
QuicEncryptedPacket encrypted(packet, 0, false);
@@ -252,13 +383,15 @@ TEST_F(QuicFramerTest, LargePacket) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
};
@@ -270,7 +403,8 @@ TEST_F(QuicFramerTest, LargePacket) {
ASSERT_TRUE(visitor_.header_.get());
// Make sure we've parsed the packet header, so we can send an error.
- EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), visitor_.header_->guid);
+ EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210),
+ visitor_.header_->public_header.guid);
// Make sure the correct error is propogated.
EXPECT_EQ(QUIC_PACKET_TOO_LARGE, framer_.error());
}
@@ -280,59 +414,121 @@ TEST_F(QuicFramerTest, PacketHeader) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
};
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(self_address_, peer_address_, encrypted));
-
EXPECT_EQ(QUIC_INVALID_FRAME_DATA, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), visitor_.header_->guid);
+ EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210),
+ visitor_.header_->public_header.guid);
+ EXPECT_EQ(0x00, visitor_.header_->public_header.flags);
+ EXPECT_EQ(0x00, visitor_.header_->private_flags);
EXPECT_EQ(GG_UINT64_C(0x123456789ABC),
visitor_.header_->packet_sequence_number);
- EXPECT_EQ(0x00, visitor_.header_->flags);
- EXPECT_EQ(0x00, visitor_.header_->fec_group);
+ EXPECT_EQ(0x00u, visitor_.header_->fec_group);
// Now test framing boundaries
- for (int i = 0; i < 16; ++i) {
+ for (size_t i = 0; i < kPacketHeaderSize; ++i) {
string expected_error;
- if (i < 8) {
+ if (i < kPublicFlagsOffset) {
expected_error = "Unable to read GUID.";
- } else if (i < 14) {
+ } else if (i < kSequenceNumberOffset) {
+ expected_error = "Unable to read public flags.";
+ } else if (i < kPrivateFlagsOffset) {
expected_error = "Unable to read sequence number.";
- } else if (i < 15) {
- expected_error = "Unable to read flags.";
- } else if (i < 16) {
- expected_error = "Unable to read fec group.";
+ } else if (i < kFecGroupOffset) {
+ expected_error = "Unable to read private flags.";
+ } else {
+ expected_error = "Unable to read first fec protected packet offset.";
}
CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER);
}
}
-TEST_F(QuicFramerTest, StreamFrame) {
+TEST_F(QuicFramerTest, PaddingFrame) {
unsigned char packet[] = {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
+ // private flags
0x00,
- // fec group
+ // first fec protected packet offset
+ 0xFF,
+
+ // frame count
+ 0x01,
+ // frame type (padding frame)
0x00,
+ // Ignored data (which in this case is a stream frame)
+ 0x01,
+ 0x04, 0x03, 0x02, 0x01,
+ 0x01,
+ 0x54, 0x76, 0x10, 0x32,
+ 0xDC, 0xFE, 0x98, 0xBA,
+ 0x0c, 0x00,
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ };
+
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(self_address_, peer_address_, encrypted));
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ ASSERT_EQ(peer_address_, visitor_.peer_address_);
+ ASSERT_EQ(self_address_, visitor_.self_address_);
+
+ ASSERT_EQ(0u, visitor_.stream_frames_.size());
+ EXPECT_EQ(0u, visitor_.ack_frames_.size());
+
+ // Now test framing boundaries
+ for (size_t i = 0; i < 2; ++i) {
+ string expected_error;
+ if (i < 1) {
+ expected_error = "Unable to read frame count.";
+ } else if (i < 2) {
+ expected_error = "Unable to read frame type.";
+ }
+ CheckProcessingFails(packet, i + kPacketHeaderSize, expected_error,
+ QUIC_INVALID_FRAME_DATA);
+ }
+}
+
+TEST_F(QuicFramerTest, StreamFrame) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // public flags
+ 0x00,
+ // packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags
+ 0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
// frame type (stream frame)
- 0x00,
+ 0x01,
// stream id
0x04, 0x03, 0x02, 0x01,
// fin
@@ -394,18 +590,20 @@ TEST_F(QuicFramerTest, RejectPacket) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
// frame type (stream frame)
- 0x00,
+ 0x01,
// stream id
0x04, 0x03, 0x02, 0x01,
// fin
@@ -438,7 +636,7 @@ TEST_F(QuicFramerTest, RevivedStreamFrame) {
// frame count
0x01,
// frame type (stream frame)
- 0x00,
+ 0x01,
// stream id
0x04, 0x03, 0x02, 0x01,
// fin
@@ -455,9 +653,10 @@ TEST_F(QuicFramerTest, RevivedStreamFrame) {
};
QuicPacketHeader header;
- header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
- header.flags = PACKET_FLAGS_NONE;
header.fec_group = 0;
// Do not encrypt the payload because the revived payload is post-encryption.
@@ -468,12 +667,13 @@ TEST_F(QuicFramerTest, RevivedStreamFrame) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_EQ(1, visitor_.revived_packets_);
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), visitor_.header_->guid);
+ EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210),
+ visitor_.header_->public_header.guid);
+ EXPECT_EQ(0x00, visitor_.header_->public_header.flags);
+ EXPECT_EQ(0x00, visitor_.header_->private_flags);
EXPECT_EQ(GG_UINT64_C(0x123456789ABC),
visitor_.header_->packet_sequence_number);
- EXPECT_EQ(0x00, visitor_.header_->flags);
- EXPECT_EQ(0x00, visitor_.header_->fec_group);
-
+ EXPECT_EQ(0x00u, visitor_.header_->fec_group);
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
@@ -489,18 +689,20 @@ TEST_F(QuicFramerTest, StreamFrameInFecGroup) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x12, 0x34,
- // flags
+ // private flags
0x00,
- // fec group
+ // first fec protected packet offset
0x02,
// frame count
0x01,
// frame type (stream frame)
- 0x00,
+ 0x01,
// stream id
0x04, 0x03, 0x02, 0x01,
// fin
@@ -522,7 +724,8 @@ TEST_F(QuicFramerTest, StreamFrameInFecGroup) {
EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_EQ(2, visitor_.header_->fec_group);
+ EXPECT_EQ(GG_UINT64_C(0x341256789ABA),
+ visitor_.header_->fec_group);
EXPECT_EQ(string(AsChars(packet) + kStartOfFecProtectedData,
arraysize(packet) - kStartOfFecProtectedData),
visitor_.fec_protected_payload_);
@@ -542,13 +745,15 @@ TEST_F(QuicFramerTest, AckFrame) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -609,13 +814,15 @@ TEST_F(QuicFramerTest, CongestionFeedbackFrameTCP) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -669,13 +876,15 @@ TEST_F(QuicFramerTest, CongestionFeedbackFrameInterArrival) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -768,13 +977,15 @@ TEST_F(QuicFramerTest, CongestionFeedbackFrameFixRate) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -824,13 +1035,15 @@ TEST_F(QuicFramerTest, CongestionFeedbackFrameInvalidFeedback) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -851,13 +1064,15 @@ TEST_F(QuicFramerTest, RstStreamFrame) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -916,14 +1131,15 @@ TEST_F(QuicFramerTest, ConnectionCloseFrame) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
+ // private flags
0x00,
- // fec group
- 0x00,
-
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -1001,17 +1217,16 @@ TEST_F(QuicFramerTest, FecPacket) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags (FEC)
+ // private flags (FEC)
0x01,
- // fec group
+ // first fec protected packet offset
0x01,
- // first protected packet
- 0xBB, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
// redundancy
'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h',
@@ -1030,16 +1245,61 @@ TEST_F(QuicFramerTest, FecPacket) {
EXPECT_EQ(0u, visitor_.ack_frames_.size());
ASSERT_EQ(1, visitor_.fec_count_);
const QuicFecData& fec_data = *visitor_.fec_data_[0];
- EXPECT_EQ(GG_UINT64_C(0x0123456789ABB),
- fec_data.min_protected_packet_sequence_number);
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABB), fec_data.fec_group);
EXPECT_EQ("abcdefghijklmnop", fec_data.redundancy);
}
-TEST_F(QuicFramerTest, ConstructStreamFramePacket) {
+TEST_F(QuicFramerTest, ConstructPaddingFramePacket) {
QuicPacketHeader header;
- header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
- header.flags = PACKET_FLAGS_NONE;
+ header.fec_group = 0;
+
+ QuicPaddingFrame padding_frame;
+
+ QuicFrames frames;
+ frames.push_back(QuicFrame(&padding_frame));
+
+ unsigned char packet[kMaxPacketSize] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // public flags
+ 0x00,
+ // packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags
+ 0x00,
+ // first fec protected packet offset
+ 0xFF,
+
+ // frame count
+ 0x01,
+ // frame type (padding frame)
+ 0x00,
+ };
+
+ // unsigned char packet[kMaxPacketSize];
+ memset(packet + kPacketHeaderSize + 1, 0x00,
+ kMaxPacketSize - kPacketHeaderSize - 1);
+
+ scoped_ptr<QuicPacket> data(framer_.ConstructFrameDataPacket(header, frames));
+ ASSERT_TRUE(data != NULL);
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+}
+
+TEST_F(QuicFramerTest, ConstructStreamFramePacket) {
+ QuicPacketHeader header;
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
+ header.packet_sequence_number = GG_UINT64_C(0x77123456789ABC);
header.fec_group = 0;
QuicStreamFrame stream_frame;
@@ -1055,18 +1315,20 @@ TEST_F(QuicFramerTest, ConstructStreamFramePacket) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
// frame type (stream frame)
- 0x00,
+ 0x01,
// stream id
0x04, 0x03, 0x02, 0x01,
// fin
@@ -1092,15 +1354,17 @@ TEST_F(QuicFramerTest, ConstructStreamFramePacket) {
TEST_F(QuicFramerTest, ConstructAckFramePacket) {
QuicPacketHeader header;
- header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
- header.flags = PACKET_FLAGS_NONE;
header.fec_group = 0;
QuicAckFrame ack_frame;
- ack_frame.received_info.largest_observed = GG_UINT64_C(0x0123456789ABF);
- ack_frame.received_info.missing_packets.insert(GG_UINT64_C(0x0123456789ABE));
- ack_frame.sent_info.least_unacked = GG_UINT64_C(0x0123456789AA0);
+ ack_frame.received_info.largest_observed = GG_UINT64_C(0x770123456789ABF);
+ ack_frame.received_info.missing_packets.insert(
+ GG_UINT64_C(0x770123456789ABE));
+ ack_frame.sent_info.least_unacked = GG_UINT64_C(0x770123456789AA0);
QuicFrames frames;
frames.push_back(QuicFrame(&ack_frame));
@@ -1109,13 +1373,15 @@ TEST_F(QuicFramerTest, ConstructAckFramePacket) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -1144,9 +1410,10 @@ TEST_F(QuicFramerTest, ConstructAckFramePacket) {
TEST_F(QuicFramerTest, ConstructCongestionFeedbackFramePacketTCP) {
QuicPacketHeader header;
- header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
- header.flags = PACKET_FLAGS_NONE;
header.fec_group = 0;
QuicCongestionFeedbackFrame congestion_feedback_frame;
@@ -1161,13 +1428,15 @@ TEST_F(QuicFramerTest, ConstructCongestionFeedbackFramePacketTCP) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -1191,22 +1460,24 @@ TEST_F(QuicFramerTest, ConstructCongestionFeedbackFramePacketTCP) {
TEST_F(QuicFramerTest, ConstructCongestionFeedbackFramePacketInterArrival) {
QuicPacketHeader header;
- header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
- header.flags = PACKET_FLAGS_NONE;
header.fec_group = 0;
QuicCongestionFeedbackFrame frame;
frame.type = kInterArrival;
- frame.inter_arrival.accumulated_number_of_lost_packets
- = 0x0302;
- frame.inter_arrival.received_packet_times[GG_UINT64_C(0x0123456789ABA)] =
- QuicTime::FromMicroseconds(GG_UINT64_C(0x07E1D2C3B4A59687));
- frame.inter_arrival.received_packet_times[GG_UINT64_C(0x0123456789ABB)] =
- QuicTime::FromMicroseconds(GG_UINT64_C(0x07E1D2C3B4A59688));
- frame.inter_arrival.received_packet_times[GG_UINT64_C(0x0123456789ABD)] =
- QuicTime::FromMicroseconds(GG_UINT64_C(0x07E1D2C3B4A59689));
-
+ frame.inter_arrival.accumulated_number_of_lost_packets = 0x0302;
+ frame.inter_arrival.received_packet_times.insert(
+ make_pair(GG_UINT64_C(0x0123456789ABA),
+ QuicTime::FromMicroseconds(GG_UINT64_C(0x07E1D2C3B4A59687))));
+ frame.inter_arrival.received_packet_times.insert(
+ make_pair(GG_UINT64_C(0x0123456789ABB),
+ QuicTime::FromMicroseconds(GG_UINT64_C(0x07E1D2C3B4A59688))));
+ frame.inter_arrival.received_packet_times.insert(
+ make_pair(GG_UINT64_C(0x0123456789ABD),
+ QuicTime::FromMicroseconds(GG_UINT64_C(0x07E1D2C3B4A59689))));
QuicFrames frames;
frames.push_back(QuicFrame(&frame));
@@ -1214,13 +1485,15 @@ TEST_F(QuicFramerTest, ConstructCongestionFeedbackFramePacketInterArrival) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -1258,9 +1531,10 @@ TEST_F(QuicFramerTest, ConstructCongestionFeedbackFramePacketInterArrival) {
TEST_F(QuicFramerTest, ConstructCongestionFeedbackFramePacketFixRate) {
QuicPacketHeader header;
- header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
- header.flags = PACKET_FLAGS_NONE;
header.fec_group = 0;
QuicCongestionFeedbackFrame congestion_feedback_frame;
@@ -1275,13 +1549,15 @@ TEST_F(QuicFramerTest, ConstructCongestionFeedbackFramePacketFixRate) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -1303,9 +1579,10 @@ TEST_F(QuicFramerTest, ConstructCongestionFeedbackFramePacketFixRate) {
TEST_F(QuicFramerTest, ConstructCongestionFeedbackFramePacketInvalidFeedback) {
QuicPacketHeader header;
- header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
- header.flags = PACKET_FLAGS_NONE;
header.fec_group = 0;
QuicCongestionFeedbackFrame congestion_feedback_frame;
@@ -1321,9 +1598,10 @@ TEST_F(QuicFramerTest, ConstructCongestionFeedbackFramePacketInvalidFeedback) {
TEST_F(QuicFramerTest, ConstructRstFramePacket) {
QuicPacketHeader header;
- header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
- header.flags = PACKET_FLAGS_NONE;
header.fec_group = 0;
QuicRstStreamFrame rst_frame;
@@ -1336,13 +1614,15 @@ TEST_F(QuicFramerTest, ConstructRstFramePacket) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -1377,9 +1657,10 @@ TEST_F(QuicFramerTest, ConstructRstFramePacket) {
TEST_F(QuicFramerTest, ConstructCloseFramePacket) {
QuicPacketHeader header;
- header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
- header.flags = PACKET_FLAGS_NONE;
header.fec_group = 0;
QuicConnectionCloseFrame close_frame;
@@ -1398,13 +1679,15 @@ TEST_F(QuicFramerTest, ConstructCloseFramePacket) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
- 0x00,
- // fec group
+ // private flags
0x00,
+ // first fec protected packet offset
+ 0xFF,
// frame count
0x01,
@@ -1444,31 +1727,30 @@ TEST_F(QuicFramerTest, ConstructCloseFramePacket) {
TEST_F(QuicFramerTest, ConstructFecPacket) {
QuicPacketHeader header;
- header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_FEC;
header.packet_sequence_number = (GG_UINT64_C(0x123456789ABC));
- header.flags = PACKET_FLAGS_FEC;
- header.fec_group = 1;
+ header.fec_group = GG_UINT64_C(0x123456789ABB);;
QuicFecData fec_data;
fec_data.fec_group = 1;
- fec_data.min_protected_packet_sequence_number =
- GG_UINT64_C(0x123456789ABB);
fec_data.redundancy = "abcdefghijklmnop";
unsigned char packet[] = {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
+ // private flags
0x01,
- // fec group
+ // first fec protected packet offset
0x01,
- // first protected packet
- 0xBB, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+
// redundancy
'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h',
@@ -1489,16 +1771,16 @@ TEST_F(QuicFramerTest, EncryptPacket) {
// guid
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
- // packet id
+ // public flags
+ 0x00,
+ // packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // flags
+ // private flags
0x01,
- // fec group
+ // first fec protected packet offset
0x01,
- // first protected packet
- 0xBB, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+
// redundancy
'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h',
@@ -1506,8 +1788,9 @@ TEST_F(QuicFramerTest, EncryptPacket) {
'm', 'n', 'o', 'p',
};
- QuicPacket raw(AsChars(packet), arraysize(packet), false, PACKET_FLAGS_NONE);
- scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(raw));
+ scoped_ptr<QuicPacket> raw(
+ QuicPacket::NewDataPacket(AsChars(packet), arraysize(packet), false));
+ scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(*raw));
ASSERT_TRUE(encrypted.get() != NULL);
EXPECT_TRUE(CheckEncryption(StringPiece(AsChars(packet), arraysize(packet))));
@@ -1534,11 +1817,13 @@ TEST_F(QuicFramerTest, DISABLED_CalculateLargestReceived) {
EXPECT_EQ(4u, QuicFramer::CalculateLargestObserved(missing, missing.find(2)));
}
-TEST_F(QuicFramerTest, Truncation) {
+// TODO(rch) enable after landing the revised truncation CL.
+TEST_F(QuicFramerTest, DISABLED_Truncation) {
QuicPacketHeader header;
- header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
- header.flags = PACKET_FLAGS_NONE;
header.fec_group = 0;
QuicConnectionCloseFrame close_frame;
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 58a0e83..fd53f85 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -162,7 +162,7 @@ class QuicHttpStreamTest : public ::testing::Test {
scheduler_ = new MockScheduler();
collector_ = new TestCollector(NULL);
EXPECT_CALL(*scheduler_, TimeUntilSend(_)).
- WillRepeatedly(testing::Return(QuicTime::Delta()));
+ WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
helper_ = new QuicConnectionHelper(runner_.get(), &clock_,
&random_generator_, socket);
connection_ = new TestQuicConnection(guid_, peer_addr_, helper_);
@@ -234,10 +234,11 @@ class QuicHttpStreamTest : public ::testing::Test {
private:
void InitializeHeader(QuicPacketSequenceNumber sequence_number) {
- header_.guid = guid_;
+ header_.public_header.guid = guid_;
+ header_.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
header_.packet_sequence_number = sequence_number;
- header_.flags = PACKET_FLAGS_NONE;
header_.fec_group = 0;
+ header_.private_flags = PACKET_PRIVATE_FLAGS_NONE;
}
QuicEncryptedPacket* ConstructPacket(const QuicPacketHeader& header,
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc
index 769434d..cd79bbb 100644
--- a/net/quic/quic_packet_creator.cc
+++ b/net/quic/quic_packet_creator.cc
@@ -19,7 +19,7 @@ QuicPacketCreator::QuicPacketCreator(QuicGuid guid, QuicFramer* framer)
: guid_(guid),
framer_(framer),
sequence_number_(0),
- fec_group_number_(1) {
+ fec_group_number_(0) {
framer_->set_fec_builder(this);
}
@@ -27,57 +27,35 @@ QuicPacketCreator::~QuicPacketCreator() {
}
void QuicPacketCreator::OnBuiltFecProtectedPayload(
- const QuicPacketHeader& header,
- StringPiece payload) {
+ const QuicPacketHeader& header, StringPiece payload) {
if (fec_group_.get()) {
fec_group_->Update(header, payload);
}
}
-PacketPair QuicPacketCreator::SerializeAllFrames(const QuicFrames& frames) {
- size_t num_serialized;
- PacketPair pair = SerializeFrames(frames, &num_serialized);
- DCHECK_EQ(frames.size(), num_serialized);
- return pair;
+bool QuicPacketCreator::ShouldSendFec(bool force_close) const {
+ DCHECK(options_.max_packets_per_fec_group == 0 ||
+ (fec_group_.get() != NULL && fec_group_->GroupSize() > 0));
+ return options_.max_packets_per_fec_group > 0 &&
+ ((force_close && fec_group_->GroupSize() > 0) ||
+ fec_group_->GroupSize() >= options_.max_packets_per_fec_group);
}
-PacketPair QuicPacketCreator::SerializeFrames(
- const QuicFrames& frames, size_t* num_serialized) {
- QuicPacketHeader header;
- FillPacketHeader(0, PACKET_FLAGS_NONE, &header);
-
- QuicPacket* packet = framer_->ConstructMaxFrameDataPacket(
- header, frames, num_serialized);
- return make_pair(header.packet_sequence_number, packet);
+void QuicPacketCreator::MaybeStartFEC() {
+ if (options_.max_packets_per_fec_group > 0) {
+ DCHECK(fec_group_.get() == NULL);
+ fec_group_number_ = sequence_number() + 1;
+ fec_group_.reset(new QuicFecGroup());
+ }
}
-size_t QuicPacketCreator::DataToStream(QuicStreamId id,
- StringPiece data,
- QuicStreamOffset offset,
- bool fin,
- vector<PacketPair>* packets,
- QuicFrames* packetized_frames) {
+size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
+ StringPiece data,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicFrames* frames) {
DCHECK_GT(options_.max_packet_length,
QuicUtils::StreamFramePacketOverhead(1));
- DCHECK_LT(0u, options_.max_num_packets);
- QuicPacketHeader header;
-
- QuicPacket* packet = NULL;
- QuicFrames frames;
- QuicFecGroupNumber current_fec_group = 0;
- QuicFecData fec_data;
-
- size_t num_data_packets = options_.max_num_packets;
-
- if (options_.use_fec) {
- DCHECK_LT(1u, options_.max_num_packets);
- --num_data_packets;
- DCHECK(!fec_group_.get());
- fec_group_.reset(new QuicFecGroup);
- current_fec_group = fec_group_number_;
- fec_data.fec_group = current_fec_group;
- fec_data.min_protected_packet_sequence_number = sequence_number_ + 1;
- }
size_t unconsumed_bytes = data.size();
if (data.size() != 0) {
@@ -87,30 +65,18 @@ size_t QuicPacketCreator::DataToStream(QuicStreamId id,
DCHECK_GT(max_frame_len, 0u);
size_t frame_len = min<size_t>(max_frame_len, unconsumed_bytes);
- while (unconsumed_bytes > 0 && num_data_packets > 0) {
- --num_data_packets;
+ if (unconsumed_bytes > 0) {
bool set_fin = false;
- if (unconsumed_bytes <= frame_len) { // last loop
+ if (unconsumed_bytes <= frame_len) { // last frame.
frame_len = min(unconsumed_bytes, frame_len);
set_fin = fin;
}
StringPiece data_frame(data.data() + data.size() - unconsumed_bytes,
- frame_len);
+ frame_len);
+ frames->push_back(QuicFrame(new QuicStreamFrame(
+ id, set_fin, offset, data_frame)));
- QuicStreamFrame* frame = new QuicStreamFrame(
- id, set_fin, offset, data_frame);
- frames.push_back(QuicFrame(frame));
- FillPacketHeader(current_fec_group, PACKET_FLAGS_NONE, &header);
- offset += frame_len;
unconsumed_bytes -= frame_len;
-
- // Produce the data packet (which might fin the stream).
- packet = framer_->ConstructFrameDataPacket(header, frames);
- DCHECK(packet);
- DCHECK_GE(options_.max_packet_length, packet->length());
- packets->push_back(make_pair(header.packet_sequence_number, packet));
- packetized_frames->push_back(frames[0]);
- frames.clear();
}
// If we haven't finished serializing all the data, don't set any final fin.
if (unconsumed_bytes > 0) {
@@ -120,54 +86,51 @@ size_t QuicPacketCreator::DataToStream(QuicStreamId id,
// Create a new packet for the fin, if necessary.
if (fin && data.size() == 0) {
- FillPacketHeader(current_fec_group, PACKET_FLAGS_NONE, &header);
QuicStreamFrame* frame = new QuicStreamFrame(id, true, offset, "");
- frames.push_back(QuicFrame(frame));
- packet = framer_->ConstructFrameDataPacket(header, frames);
- DCHECK(packet);
- DCHECK_GE(options_.max_packet_length, packet->length());
- packets->push_back(make_pair(header.packet_sequence_number, packet));
- packetized_frames->push_back(frames[0]);
- frames.clear();
+ frames->push_back(QuicFrame(frame));
}
- // Create a new FEC packet, if necessary
- if (current_fec_group != 0) {
- FillPacketHeader(current_fec_group, PACKET_FLAGS_FEC, &header);
- fec_data.redundancy = fec_group_->parity();
- QuicPacket* fec_packet = framer_->ConstructFecPacket(header, fec_data);
- DCHECK(fec_packet);
- DCHECK_GE(options_.max_packet_length, packet->length());
- packets->push_back(make_pair(header.packet_sequence_number, fec_packet));
- ++fec_group_number_;
- }
- /*
- if (options_.random_reorder) {
- int32 seed = ACMRandom::HostnamePidTimeSeed();
- ACMRandom random(seed);
- DLOG(INFO) << "Seed " << seed;
-
- vector<PacketPair> tmp_store;
- tmp_store.swap(*packets);
-
- while (tmp_store.size() != 0) {
- int idx = random.Uniform(tmp_store.size());
- packets->push_back(tmp_store[idx]);
- tmp_store.erase(tmp_store.begin() + idx);
- }
- }
- */
- fec_group_.reset(NULL);
- DCHECK(options_.max_num_packets >= packets->size());
-
return data.size() - unconsumed_bytes;
}
+PacketPair QuicPacketCreator::SerializeAllFrames(const QuicFrames& frames) {
+ size_t num_serialized;
+ PacketPair pair = SerializeFrames(frames, &num_serialized);
+ DCHECK_EQ(frames.size(), num_serialized);
+ return pair;
+}
+
+PacketPair QuicPacketCreator::SerializeFrames(const QuicFrames& frames,
+ size_t* num_serialized) {
+ QuicPacketHeader header;
+ FillPacketHeader(fec_group_number_, PACKET_PRIVATE_FLAGS_NONE, &header);
+
+ QuicPacket* packet = framer_->ConstructMaxFrameDataPacket(
+ header, frames, num_serialized);
+ return make_pair(header.packet_sequence_number, packet);
+}
+
+QuicPacketCreator::PacketPair QuicPacketCreator::SerializeFec() {
+ DCHECK_LT(0u, fec_group_->GroupSize());
+ QuicPacketHeader header;
+ FillPacketHeader(fec_group_number_, PACKET_PRIVATE_FLAGS_FEC, &header);
+
+ QuicFecData fec_data;
+ fec_data.fec_group = fec_group_->min_protected_packet();
+ fec_data.redundancy = fec_group_->parity();
+ QuicPacket* packet = framer_->ConstructFecPacket(header, fec_data);
+ fec_group_.reset(NULL);
+ fec_group_number_ = 0;
+ DCHECK(packet);
+ DCHECK_GE(options_.max_packet_length, packet->length());
+ return make_pair(header.packet_sequence_number, packet);
+}
+
QuicPacketCreator::PacketPair QuicPacketCreator::CloseConnection(
QuicConnectionCloseFrame* close_frame) {
QuicPacketHeader header;
- FillPacketHeader(0, PACKET_FLAGS_NONE, &header);
+ FillPacketHeader(0, PACKET_PRIVATE_FLAGS_NONE, &header);
QuicFrames frames;
frames.push_back(QuicFrame(close_frame));
@@ -177,10 +140,11 @@ QuicPacketCreator::PacketPair QuicPacketCreator::CloseConnection(
}
void QuicPacketCreator::FillPacketHeader(QuicFecGroupNumber fec_group,
- QuicPacketFlags flags,
+ QuicPacketPrivateFlags flags,
QuicPacketHeader* header) {
- header->guid = guid_;
- header->flags = flags;
+ header->public_header.guid = guid_;
+ header->public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
+ header->private_flags = flags;
header->packet_sequence_number = ++sequence_number_;
header->fec_group = fec_group;
}
diff --git a/net/quic/quic_packet_creator.h b/net/quic/quic_packet_creator.h
index 4f11348..0fc8176 100644
--- a/net/quic/quic_packet_creator.h
+++ b/net/quic/quic_packet_creator.h
@@ -22,24 +22,17 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
public:
// Options for controlling how packets are created.
struct Options {
- Options() {
- Clear();
- }
- void Clear() {
- memset(this, 0, sizeof(Options));
- max_packet_length = kMaxPacketSize;
- max_num_packets = std::numeric_limits<size_t>::max();
+ Options()
+ : max_packet_length(kMaxPacketSize),
+ random_reorder(false),
+ max_packets_per_fec_group(0) {
}
// TODO(alyssar, rch) max frames/packet
size_t max_packet_length;
- // The maximum number of packets we'd like to serialize.
- // If the data can't be fully serialized, DataToStream will only consume as
- // much data as fits into this many packets.
- size_t max_num_packets;
bool random_reorder; // Inefficient: rewrite if used at scale.
- // TODO(rch) should probably be max packets per group.
- bool use_fec;
+ // 0 indicates fec is disabled.
+ size_t max_packets_per_fec_group;
};
QuicPacketCreator(QuicGuid guid, QuicFramer* framer);
@@ -52,24 +45,33 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
typedef std::pair<QuicPacketSequenceNumber, QuicPacket*> PacketPair;
+ // Checks if it's time to send an FEC packet. |force_close| forces this to
+ // return true if an fec group is open.
+ bool ShouldSendFec(bool force_close) const;
+
+ // Starts a new FEC group with the next serialized packet, if FEC is enabled.
+ void MaybeStartFEC();
+
+ // Converts a raw payload to a frame. Returns the number of bytes consumed
+ // from data. If data is empty and fin is true, the expected behavior is to
+ // consume the fin but return 0.
+ size_t CreateStreamFrame(QuicStreamId id,
+ base::StringPiece data,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicFrames* frames);
+
// Serializes all frames into a single packet. All frames must fit into a
// single packet.
PacketPair SerializeAllFrames(const QuicFrames& frames);
// Serializes as many non-fec frames as can fit into a single packet.
// num_serialized is set to the number of frames serialized into the packet.
- PacketPair SerializeFrames(const QuicFrames& frames, size_t* num_serialized);
-
- // Converts a raw payload to a series of QuicPackets and matching frames in
- // those packets. Returns the number of bytes consumed from data.
- // If data is empty and fin is true, the expected behavior is to consume the
- // fin but return 0.
- size_t DataToStream(QuicStreamId id,
- base::StringPiece data,
- QuicStreamOffset offset,
- bool fin,
- std::vector<PacketPair>* packets,
- QuicFrames* packetized_frames);
+ PacketPair SerializeFrames(const QuicFrames& frames,
+ size_t* num_serialized);
+
+ // Packetize FEC data.
+ PacketPair SerializeFec();
PacketPair CloseConnection(QuicConnectionCloseFrame* close_frame);
@@ -87,7 +89,7 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
private:
void FillPacketHeader(QuicFecGroupNumber fec_group,
- QuicPacketFlags flags,
+ QuicPacketPrivateFlags flags,
QuicPacketHeader* header);
Options options_;
diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc
index d4835b1..d4bdb28 100644
--- a/net/quic/quic_packet_creator_test.cc
+++ b/net/quic/quic_packet_creator_test.cc
@@ -10,10 +10,11 @@
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
+using base::StringPiece;
+using std::string;
+using std::vector;
using testing::InSequence;
using testing::_;
-using std::vector;
-using std::string;
namespace net {
namespace test {
@@ -31,21 +32,16 @@ class QuicPacketCreatorTest : public ::testing::Test {
framer_.set_visitor(&framer_visitor_);
}
~QuicPacketCreatorTest() {
- STLDeleteValues(&packets_);
for (QuicFrames::iterator it = frames_.begin(); it != frames_.end(); ++it) {
QuicConnection::DeleteEnclosedFrame(&(*it));
}
}
- void ProcessPackets() {
- for (size_t i = 0; i < packets_.size(); ++i) {
- scoped_ptr<QuicEncryptedPacket> encrypted(
- framer_.EncryptPacket(*packets_[i].second));
- framer_.ProcessPacket(IPEndPoint(), IPEndPoint(), *encrypted);
- }
+ void ProcessPacket(QuicPacket* packet) {
+ scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(*packet));
+ framer_.ProcessPacket(IPEndPoint(), IPEndPoint(), *encrypted);
}
- vector<QuicPacketCreator::PacketPair> packets_;
QuicFrames frames_;
QuicFramer framer_;
testing::StrictMock<MockFramerVisitor> framer_visitor_;
@@ -56,172 +52,97 @@ class QuicPacketCreatorTest : public ::testing::Test {
QuicPacketCreator utils_;
};
-TEST_F(QuicPacketCreatorTest, DataToStreamBasic) {
- size_t bytes_consumed = utils_.DataToStream(
- id_, data_, 0, true, &packets_, &frames_);
-
- ASSERT_EQ(1u, packets_.size());
- ASSERT_EQ(1u, utils_.sequence_number());
- ASSERT_EQ(data_.size(), bytes_consumed);
-
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket(_, _));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
-
- ProcessPackets();
-}
-
-TEST_F(QuicPacketCreatorTest, DataToStreamFec) {
- utils_.options()->use_fec = true;
- size_t bytes_consumed = utils_.DataToStream(
- id_, data_, 0, true, &packets_, &frames_);
-
- ASSERT_EQ(2u, packets_.size());
- ASSERT_EQ(2u, utils_.sequence_number());
- ASSERT_EQ(data_.size(), bytes_consumed);
-
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket(_, _));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnFecProtectedPayload(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
-
- EXPECT_CALL(framer_visitor_, OnPacket(_, _));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnFecData(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
-
- ProcessPackets();
-}
-
-TEST_F(QuicPacketCreatorTest, DataToStreamFecHandled) {
- utils_.options()->use_fec = true;
- size_t bytes_consumed = utils_.DataToStream(
- id_, data_, 0, true, &packets_, &frames_);
- ASSERT_EQ(data_.size(), bytes_consumed);
-
- ASSERT_EQ(2u, packets_.size());
- ASSERT_EQ(2u, utils_.sequence_number());
-
- QuicFecData fec_data;
- fec_data.fec_group = 1;
- fec_data.min_protected_packet_sequence_number = 1;
- fec_data.redundancy = packets_[0].second->FecProtectedData();
-
- InSequence s;
- // Data packet
- EXPECT_CALL(framer_visitor_, OnPacket(_, _));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnFecProtectedPayload(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
-
- // FEC packet
- EXPECT_CALL(framer_visitor_, OnPacket(_, _));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnFecData(fec_data));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
-
- ProcessPackets();
-
- // Revived data packet
- EXPECT_CALL(framer_visitor_, OnRevivedPacket());
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
-
- QuicPacketHeader header;
- framer_.ProcessRevivedPacket(header, fec_data.redundancy);
-}
-
-TEST_F(QuicPacketCreatorTest, DataToStreamSkipFin) {
- size_t bytes_consumed = utils_.DataToStream(
- id_, data_, 0, false, &packets_, &frames_);
- ASSERT_EQ(data_.size(), bytes_consumed);
-
- ASSERT_EQ(1u, packets_.size());
- ASSERT_EQ(1u, utils_.sequence_number());
-
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket(_, _));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
-
- ProcessPackets();
+TEST_F(QuicPacketCreatorTest, SerializeFrame) {
+ frames_.push_back(QuicFrame(new QuicStreamFrame(
+ 0u, false, 0u, StringPiece(""))));
+ PacketPair pair = utils_.SerializeAllFrames(frames_);
+
+ {
+ InSequence s;
+ EXPECT_CALL(framer_visitor_, OnPacket(_, _));
+ EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
+ EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
+ EXPECT_CALL(framer_visitor_, OnPacketComplete());
+ }
+ ProcessPacket(pair.second);
+ delete pair.second;
}
-TEST_F(QuicPacketCreatorTest, NoData) {
- data_ = "";
-
- size_t bytes_consumed = utils_.DataToStream(
- id_, data_, 0, true, &packets_, &frames_);
- ASSERT_EQ(data_.size(), bytes_consumed);
-
- ASSERT_EQ(1u, packets_.size());
- ASSERT_EQ(1u, utils_.sequence_number());
-
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket(_, _));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
-
- ProcessPackets();
+TEST_F(QuicPacketCreatorTest, SerializeFrames) {
+ frames_.push_back(QuicFrame(new QuicAckFrame(0u, 0u)));
+ frames_.push_back(QuicFrame(new QuicStreamFrame(
+ 0u, false, 0u, StringPiece(""))));
+ frames_.push_back(QuicFrame(new QuicStreamFrame(
+ 0u, true, 0u, StringPiece(""))));
+ PacketPair pair = utils_.SerializeAllFrames(frames_);
+
+ {
+ InSequence s;
+ EXPECT_CALL(framer_visitor_, OnPacket(_, _));
+ EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
+ EXPECT_CALL(framer_visitor_, OnAckFrame(_));
+ EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
+ EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
+ EXPECT_CALL(framer_visitor_, OnPacketComplete());
+ }
+ ProcessPacket(pair.second);
+ delete pair.second;
}
-TEST_F(QuicPacketCreatorTest, MultiplePackets) {
- size_t ciphertext_size = NullEncrypter().GetCiphertextSize(2);
- utils_.options()->max_packet_length =
- ciphertext_size + QuicUtils::StreamFramePacketOverhead(1);
+TEST_F(QuicPacketCreatorTest, SerializeWithFEC) {
+ utils_.options()->max_packets_per_fec_group = 6;
+ utils_.MaybeStartFEC();
+
+ frames_.push_back(QuicFrame(new QuicStreamFrame(
+ 0u, false, 0u, StringPiece(""))));
+ PacketPair pair = utils_.SerializeAllFrames(frames_);
+
+ {
+ InSequence s;
+ EXPECT_CALL(framer_visitor_, OnPacket(_, _));
+ EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
+ EXPECT_CALL(framer_visitor_, OnFecProtectedPayload(_));
+ EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
+ EXPECT_CALL(framer_visitor_, OnPacketComplete());
+ }
+ ProcessPacket(pair.second);
+ delete pair.second;
- size_t bytes_consumed = utils_.DataToStream(
- id_, data_, 0, true, &packets_, &frames_);
- ASSERT_EQ(data_.size(), bytes_consumed);
+ ASSERT_FALSE(utils_.ShouldSendFec(false));
+ ASSERT_TRUE(utils_.ShouldSendFec(true));
- ASSERT_EQ(2u, packets_.size());
- ASSERT_EQ(2u, utils_.sequence_number());
+ pair = utils_.SerializeFec();
+ ASSERT_EQ(2u, pair.first);
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket(_, _));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
-
- EXPECT_CALL(framer_visitor_, OnPacket(_, _));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
-
- ProcessPackets();
+ {
+ InSequence s;
+ EXPECT_CALL(framer_visitor_, OnPacket(_, _));
+ EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
+ EXPECT_CALL(framer_visitor_, OnFecData(_));
+ EXPECT_CALL(framer_visitor_, OnPacketComplete());
+ }
+ ProcessPacket(pair.second);
+ delete pair.second;
}
-TEST_F(QuicPacketCreatorTest, MultiplePacketsWithLimits) {
- const size_t kPayloadBytesPerPacket = 2;
-
- size_t ciphertext_size = NullEncrypter().GetCiphertextSize(
- kPayloadBytesPerPacket);
- utils_.options()->max_packet_length =
- ciphertext_size + QuicUtils::StreamFramePacketOverhead(1);
- utils_.options()->max_num_packets = 1;
-
- size_t bytes_consumed = utils_.DataToStream(
- id_, data_, 0, true, &packets_, &frames_);
- ASSERT_EQ(kPayloadBytesPerPacket, bytes_consumed);
+TEST_F(QuicPacketCreatorTest, CloseConnection) {
+ QuicConnectionCloseFrame frame;
+ frame.error_code = QUIC_NO_ERROR;
+ frame.ack_frame = QuicAckFrame(0u, 0u);
- ASSERT_EQ(1u, packets_.size());
+ PacketPair pair = utils_.CloseConnection(&frame);
+ ASSERT_EQ(1u, pair.first);
ASSERT_EQ(1u, utils_.sequence_number());
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket(_, _));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
+ EXPECT_CALL(framer_visitor_, OnAckFrame(_));
+ EXPECT_CALL(framer_visitor_, OnConnectionCloseFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
- ProcessPackets();
+ ProcessPacket(pair.second);
+ delete pair.second;
}
} // namespace
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index 3d0b4d9..37ba15e4 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -157,10 +157,6 @@ bool QuicFecData::operator==(const QuicFecData& other) const {
if (fec_group != other.fec_group) {
return false;
}
- if (min_protected_packet_sequence_number !=
- other.min_protected_packet_sequence_number) {
- return false;
- }
if (redundancy != other.redundancy) {
return false;
}
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index f2d60a2..a391421 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -32,20 +32,7 @@ typedef uint64 QuicGuid;
typedef uint32 QuicStreamId;
typedef uint64 QuicStreamOffset;
typedef uint64 QuicPacketSequenceNumber;
-typedef uint8 QuicFecGroupNumber;
-
-// A struct for functions which consume data payloads and fins.
-// The first member of the pair indicates bytes consumed.
-// The second member of the pair indicates if an incoming fin was consumed.
-struct QuicConsumedData {
- QuicConsumedData(size_t bytes_consumed, bool fin_consumed)
- : bytes_consumed(bytes_consumed),
- fin_consumed(fin_consumed) {
- }
- size_t bytes_consumed;
- bool fin_consumed;
-};
-
+typedef QuicPacketSequenceNumber QuicFecGroupNumber;
// TODO(rch): Consider Quic specific names for these constants.
const size_t kMaxPacketSize = 1200; // Maximum size in bytes of a QUIC packet.
@@ -53,20 +40,40 @@ const size_t kMaxPacketSize = 1200; // Maximum size in bytes of a QUIC packet.
// Maximum number of open streams per connection.
const size_t kDefaultMaxStreamsPerConnection = 100;
-// Size in bytes of the packet header common across all packets.
-const size_t kPacketHeaderSize = 16;
+// Number of bytes reserved for guid in the packet header.
+const size_t kQuicGuidSize = 8;
+// Number of bytes reserved for public flags in the packet header.
+const size_t kPublicFlagsSize = 1;
+// Number of bytes reserved for sequence number in the packet header.
+const size_t kSequenceNumberSize = 6;
+// Number of bytes reserved for private flags in the packet header.
+const size_t kPrivateFlagsSize = 1;
+// Number of bytes reserved for FEC group in the packet header.
+const size_t kFecGroupSize = 1;
+
+// Size in bytes of the data or fec packet header.
+const size_t kPacketHeaderSize = kQuicGuidSize + kPublicFlagsSize +
+ kPrivateFlagsSize + kSequenceNumberSize + kFecGroupSize;
+
+// Index into the guid offset in the header.
+const size_t kGuidOffset = 0;
+// Index into the flags offset in the header.
+const size_t kPublicFlagsOffset = kQuicGuidSize;
+
+// Index into the sequence number offset in the header.
+const size_t kSequenceNumberOffset = kPublicFlagsOffset + kPublicFlagsSize;
+// Index into the private flags offset in the data packet header.
+const size_t kPrivateFlagsOffset = kSequenceNumberOffset + kSequenceNumberSize;
+// Index into the fec group offset in the header.
+const size_t kFecGroupOffset = kPrivateFlagsOffset + kPrivateFlagsSize;
+
// Index of the first byte in a QUIC packet of FEC protected data.
const size_t kStartOfFecProtectedData = kPacketHeaderSize;
// Index of the first byte in a QUIC packet of encrypted data.
-const size_t kStartOfEncryptedData = kPacketHeaderSize - 1;
+const size_t kStartOfEncryptedData = kPacketHeaderSize - kPrivateFlagsSize -
+ kFecGroupSize;
// Index of the first byte in a QUIC packet which is hashed.
const size_t kStartOfHashData = 0;
-// Index into the sequence number offset in the header.
-const int kSequenceNumberOffset = 8;
-// Index into the flags offset in the header.
-const int kFlagsOffset = 14;
-// Index into the fec group offset in the header.
-const int kFecGroupOffset = 15;
// Size in bytes of all stream frame fields.
const size_t kMinStreamFrameLength = 15;
@@ -78,13 +85,16 @@ const QuicStreamId kMaxStreamIdDelta = 100;
// TODO(rch): ensure that this is not usable by any other streams.
const QuicStreamId kCryptoStreamId = 1;
+// Value which indicates this packet is not FEC protected.
+const uint8 kNoFecOffset = 0xFF;
+
typedef std::pair<QuicPacketSequenceNumber, QuicPacket*> PacketPair;
const int64 kDefaultTimeoutUs = 600000000; // 10 minutes.
enum QuicFrameType {
- STREAM_FRAME = 0,
- PDU_FRAME,
+ PADDING_FRAME = 0,
+ STREAM_FRAME,
ACK_FRAME,
CONGESTION_FEEDBACK_FRAME,
RST_STREAM_FRAME,
@@ -92,11 +102,21 @@ enum QuicFrameType {
NUM_FRAME_TYPES
};
-enum QuicPacketFlags {
- PACKET_FLAGS_NONE = 0,
- PACKET_FLAGS_FEC = 1, // Payload is FEC as opposed to frames.
+enum QuicPacketPublicFlags {
+ PACKET_PUBLIC_FLAGS_NONE = 0,
+ PACKET_PUBLIC_FLAGS_VERSION = 1,
+ PACKET_PUBLIC_FLAGS_RST = 2, // Packet is a public reset packet.
+ PACKET_PUBLIC_FLAGS_MAX = 3 // Both bit set.
+};
+
+enum QuicPacketPrivateFlags {
+ PACKET_PRIVATE_FLAGS_NONE = 0,
+ PACKET_PRIVATE_FLAGS_FEC = 1, // Payload is FEC as opposed to frames.
+ PACKET_PRIVATE_FLAGS_MAX = PACKET_PRIVATE_FLAGS_FEC
+};
- PACKET_FLAGS_MAX = PACKET_FLAGS_FEC
+enum QuicVersion {
+ QUIC_VERSION_1 = 0
};
enum QuicErrorCode {
@@ -161,15 +181,28 @@ enum QuicErrorCode {
};
-struct NET_EXPORT_PRIVATE QuicPacketHeader {
- // Includes the ConnectionHeader and CongestionMonitoredHeader
- // from the design docs, as well as some elements of DecryptedData.
+struct NET_EXPORT_PRIVATE QuicPacketPublicHeader {
+ // Universal header. All QuicPacket headers will have a guid and public flags.
+ // TODO(satyamshekhar): Support versioning as per Protocol Negotiation Doc.
QuicGuid guid;
+ QuicPacketPublicFlags flags;
+};
+
+// Header for Data or FEC packets.
+struct QuicPacketHeader {
+ QuicPacketHeader() {}
+ explicit QuicPacketHeader(const QuicPacketPublicHeader& header)
+ : public_header(header) {}
+ QuicPacketPublicHeader public_header;
+ QuicPacketPrivateFlags private_flags;
QuicPacketSequenceNumber packet_sequence_number;
- QuicPacketFlags flags;
QuicFecGroupNumber fec_group;
};
+// A padding frame contains no payload.
+struct NET_EXPORT_PRIVATE QuicPaddingFrame {
+};
+
struct NET_EXPORT_PRIVATE QuicStreamFrame {
QuicStreamFrame();
QuicStreamFrame(QuicStreamId stream_id,
@@ -308,6 +341,10 @@ struct NET_EXPORT_PRIVATE QuicConnectionCloseFrame {
struct NET_EXPORT_PRIVATE QuicFrame {
QuicFrame() {}
+ explicit QuicFrame(QuicPaddingFrame* padding_frame)
+ : type(PADDING_FRAME),
+ padding_frame(padding_frame) {
+ }
explicit QuicFrame(QuicStreamFrame* stream_frame)
: type(STREAM_FRAME),
stream_frame(stream_frame) {
@@ -331,6 +368,7 @@ struct NET_EXPORT_PRIVATE QuicFrame {
QuicFrameType type;
union {
+ QuicPaddingFrame* padding_frame;
QuicStreamFrame* stream_frame;
QuicAckFrame* ack_frame;
QuicCongestionFeedbackFrame* congestion_feedback_frame;
@@ -346,6 +384,9 @@ struct NET_EXPORT_PRIVATE QuicFecData {
bool operator==(const QuicFecData& other) const;
+ // The FEC group number is also the sequence number of the first
+ // FEC protected packet. The last protected packet's sequence number will
+ // be one less than the sequence number of the FEC packet.
QuicFecGroupNumber fec_group;
QuicPacketSequenceNumber min_protected_packet_sequence_number;
// The last protected packet's sequence number will be one
@@ -388,11 +429,17 @@ class NET_EXPORT_PRIVATE QuicData {
class NET_EXPORT_PRIVATE QuicPacket : public QuicData {
public:
- QuicPacket(
- char* buffer, size_t length, bool owns_buffer, QuicPacketFlags flags)
- : QuicData(buffer, length, owns_buffer),
- buffer_(buffer),
- flags_(flags) { }
+ static QuicPacket* NewDataPacket(char* buffer,
+ size_t length,
+ bool owns_buffer) {
+ return new QuicPacket(buffer, length, owns_buffer, false);
+ }
+
+ static QuicPacket* NewFecPacket(char* buffer,
+ size_t length,
+ bool owns_buffer) {
+ return new QuicPacket(buffer, length, owns_buffer, true);
+ }
base::StringPiece FecProtectedData() const {
return base::StringPiece(data() + kStartOfFecProtectedData,
@@ -408,15 +455,18 @@ class NET_EXPORT_PRIVATE QuicPacket : public QuicData {
length() - kStartOfEncryptedData);
}
- bool IsFecPacket() const {
- return flags_ == PACKET_FLAGS_FEC;
- }
+ bool is_fec_packet() const { return is_fec_packet_; }
char* mutable_data() { return buffer_; }
private:
+ QuicPacket(char* buffer, size_t length, bool owns_buffer, bool is_fec_packet)
+ : QuicData(buffer, length, owns_buffer),
+ buffer_(buffer),
+ is_fec_packet_(is_fec_packet) { }
+
char* buffer_;
- const QuicPacketFlags flags_;
+ const bool is_fec_packet_;
DISALLOW_COPY_AND_ASSIGN(QuicPacket);
};
@@ -437,6 +487,18 @@ class NET_EXPORT_PRIVATE QuicEncryptedPacket : public QuicData {
DISALLOW_COPY_AND_ASSIGN(QuicEncryptedPacket);
};
+// A struct for functions which consume data payloads and fins.
+// The first member of the pair indicates bytes consumed.
+// The second member of the pair indicates if an incoming fin was consumed.
+struct QuicConsumedData {
+ QuicConsumedData(size_t bytes_consumed, bool fin_consumed)
+ : bytes_consumed(bytes_consumed),
+ fin_consumed(fin_consumed) {
+ }
+ size_t bytes_consumed;
+ bool fin_consumed;
+};
+
} // namespace net
#endif // NET_QUIC_QUIC_PROTOCOL_H_
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index 49490f6..f1872d2 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -78,8 +78,9 @@ bool QuicSession::OnPacket(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
const QuicPacketHeader& header,
const vector<QuicStreamFrame>& frames) {
- if (header.guid != connection()->guid()) {
- DLOG(INFO) << "Got packet header for invalid GUID: " << header.guid;
+ if (header.public_header.guid != connection()->guid()) {
+ DLOG(INFO) << "Got packet header for invalid GUID: "
+ << header.public_header.guid;
return false;
}
for (size_t i = 0; i < frames.size(); ++i) {
@@ -151,7 +152,7 @@ QuicConsumedData QuicSession::WriteData(QuicStreamId id,
bool fin) {
// TODO(wtc): type mismatch -- connection_->SendStreamData() returns a
// size_t.
- return connection_->SendStreamData(id, data, offset, fin, NULL);
+ return connection_->SendStreamData(id, data, offset, fin);
}
void QuicSession::SendRstStream(QuicStreamId id,
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h
index 9d9f848..c5c8b265 100644
--- a/net/quic/quic_session.h
+++ b/net/quic/quic_session.h
@@ -50,8 +50,10 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// indicating if the fin bit was consumed. This does not indicate the data
// has been sent on the wire: it may have been turned into a packet and queued
// if the socket was unexpectedly blocked.
- virtual QuicConsumedData WriteData(QuicStreamId id, base::StringPiece data,
- QuicStreamOffset offset, bool fin);
+ virtual QuicConsumedData WriteData(QuicStreamId id,
+ base::StringPiece data,
+ QuicStreamOffset offset,
+ bool fin);
// Called by streams when they want to close the stream in both directions.
void SendRstStream(QuicStreamId id,
QuicErrorCode error,
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index e9162b4..fdae38d 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -50,9 +50,10 @@ class QuicStreamFactoryTest : public ::testing::Test {
QuicPacketSequenceNumber num,
QuicStreamId stream_id) {
QuicPacketHeader header;
- header.guid = 0xDEADBEEF;
+ header.public_header.guid = 0xDEADBEEF;
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
header.packet_sequence_number = num;
- header.flags = PACKET_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.fec_group = 0;
QuicRstStreamFrame rst(stream_id, 0, QUIC_NO_ERROR);
@@ -64,9 +65,10 @@ class QuicStreamFactoryTest : public ::testing::Test {
QuicPacketSequenceNumber largest_received,
QuicPacketSequenceNumber least_unacked) {
QuicPacketHeader header;
- header.guid = 0xDEADBEEF;
+ header.public_header.guid = 0xDEADBEEF;
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
header.packet_sequence_number = 2;
- header.flags = PACKET_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.fec_group = 0;
QuicAckFrame ack(largest_received, least_unacked);
@@ -90,9 +92,10 @@ class QuicStreamFactoryTest : public ::testing::Test {
scoped_ptr<QuicEncryptedPacket> ConstructFeedbackPacket(
QuicPacketSequenceNumber sequence_number) {
QuicPacketHeader header;
- header.guid = 0xDEADBEEF;
+ header.public_header.guid = 0xDEADBEEF;
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
header.packet_sequence_number = sequence_number;
- header.flags = PACKET_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.fec_group = 0;
QuicCongestionFeedbackFrame frame;
diff --git a/net/quic/quic_time.cc b/net/quic/quic_time.cc
index b0d6434..7d3ba66 100644
--- a/net/quic/quic_time.cc
+++ b/net/quic/quic_time.cc
@@ -11,14 +11,14 @@ namespace net {
// Highest number of microseconds that DateTimeOffset can hold.
const int64 kQuicInfiniteTimeUs = GG_INT64_C(0x7fffffffffffffff) / 10;
-QuicTime::Delta::Delta()
- : delta_(base::TimeDelta::FromMicroseconds(0)) {
-}
-
QuicTime::Delta::Delta(base::TimeDelta delta)
: delta_(delta) {
}
+QuicTime::Delta QuicTime::Delta::Zero() {
+ return QuicTime::Delta::FromMicroseconds(0);
+}
+
QuicTime::Delta QuicTime::Delta::Infinite() {
return QuicTime::Delta::FromMicroseconds(kQuicInfiniteTimeUs);
}
@@ -61,8 +61,9 @@ QuicTime::Delta QuicTime::Delta::Subtract(const Delta& delta) const {
delta.ToMicroseconds());
}
-
-QuicTime::QuicTime() {
+// static
+QuicTime QuicTime::Zero() {
+ return QuicTime::FromMilliseconds(0);
}
QuicTime::QuicTime(base::TimeTicks ticks)
diff --git a/net/quic/quic_time.h b/net/quic/quic_time.h
index e5ca02a..a1fb6a3 100644
--- a/net/quic/quic_time.h
+++ b/net/quic/quic_time.h
@@ -23,14 +23,14 @@ class NET_EXPORT_PRIVATE QuicTime {
// time, stored in microsecond resolution.
class NET_EXPORT_PRIVATE Delta {
public:
- // Default constructor initializes to 0.
- Delta();
-
explicit Delta(base::TimeDelta delta);
// Create a object with infinite offset time.
static Delta Infinite();
+ // Create a object with infinite offset time.
+ static Delta Zero();
+
// Converts a number of milliseconds to a time offset.
static Delta FromMilliseconds(int64 ms);
@@ -60,11 +60,12 @@ class NET_EXPORT_PRIVATE QuicTime {
friend class QuicTime;
};
- // Default constructor initializes to time 0.
- QuicTime();
-
explicit QuicTime(base::TimeTicks ticks);
+ // Creates a new QuicTime with an internal value of 0. IsInitialized()
+ // will return true for these times.
+ static QuicTime Zero();
+
// Create a new QuicTime holding the time_ms.
static QuicTime FromMilliseconds(int64 time_ms);
diff --git a/net/quic/quic_time_test.cc b/net/quic/quic_time_test.cc
index 978bc43..5353289 100644
--- a/net/quic/quic_time_test.cc
+++ b/net/quic/quic_time_test.cc
@@ -14,13 +14,14 @@ class QuicTimeDeltaTest : public ::testing::Test {
};
TEST_F(QuicTimeDeltaTest, Zero) {
- EXPECT_TRUE(QuicTime::Delta().IsZero());
+ EXPECT_TRUE(QuicTime::Delta::Zero().IsZero());
+ EXPECT_FALSE(QuicTime::Delta::Zero().IsInfinite());
EXPECT_FALSE(QuicTime::Delta::FromMilliseconds(1).IsZero());
}
TEST_F(QuicTimeDeltaTest, Infinite) {
EXPECT_TRUE(QuicTime::Delta::Infinite().IsInfinite());
- EXPECT_FALSE(QuicTime::Delta().IsInfinite());
+ EXPECT_FALSE(QuicTime::Delta::Zero().IsInfinite());
EXPECT_FALSE(QuicTime::Delta::FromMilliseconds(1).IsInfinite());
}
@@ -34,7 +35,7 @@ TEST_F(QuicTimeDeltaTest, FromTo) {
TEST_F(QuicTimeDeltaTest, Add) {
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2000),
- QuicTime::Delta().Add(QuicTime::Delta::FromMilliseconds(2)));
+ QuicTime::Delta::Zero().Add(QuicTime::Delta::FromMilliseconds(2)));
}
TEST_F(QuicTimeDeltaTest, Subtract) {
@@ -49,7 +50,7 @@ class QuicTimeTest : public ::testing::Test {
};
TEST_F(QuicTimeTest, Initialized) {
- EXPECT_FALSE(QuicTime().IsInitialized());
+ EXPECT_FALSE(QuicTime::Zero().IsInitialized());
EXPECT_TRUE(QuicTime::FromMilliseconds(1).IsInitialized());
}
diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc
index 5c38cbd..1de1eb9 100644
--- a/net/quic/reliable_quic_stream.cc
+++ b/net/quic/reliable_quic_stream.cc
@@ -111,10 +111,11 @@ QuicConsumedData ReliableQuicStream::WriteOrBuffer(StringPiece data, bool fin) {
if (queued_data_.empty()) {
consumed_data = WriteDataInternal(string(data.data(), data.length()), fin);
+ DCHECK_LE(consumed_data.bytes_consumed, data.length());
}
- // if there's unconsumed data or an unconsumed fin, queue it.
- if (consumed_data.bytes_consumed != data.length() ||
+ // If there's unconsumed data or an unconsumed fin, queue it.
+ if (consumed_data.bytes_consumed < data.length() ||
(fin && !consumed_data.fin_consumed)) {
queued_data_.push_back(
string(data.data() + consumed_data.bytes_consumed,
diff --git a/net/quic/test_tools/mock_clock.cc b/net/quic/test_tools/mock_clock.cc
index 528865b..b85ae19 100644
--- a/net/quic/test_tools/mock_clock.cc
+++ b/net/quic/test_tools/mock_clock.cc
@@ -6,7 +6,7 @@
namespace net {
-MockClock::MockClock() {
+MockClock::MockClock() : now_(QuicTime::Zero()) {
}
MockClock::~MockClock() {
@@ -22,13 +22,13 @@ QuicTime MockClock::Now() const {
}
QuicTime::Delta MockClock::NowAsDeltaSinceUnixEpoch() const {
- return now_.Subtract(QuicTime());
+ return now_.Subtract(QuicTime::Zero());
}
base::TimeTicks MockClock::NowInTicks() const {
base::TimeTicks ticks;
return ticks + base::TimeDelta::FromMicroseconds(
- now_.Subtract(QuicTime()).ToMicroseconds());
+ now_.Subtract(QuicTime::Zero()).ToMicroseconds());
}
} // namespace net
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc
index 010380e..1411e5b 100644
--- a/net/quic/test_tools/quic_connection_peer.cc
+++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -4,6 +4,7 @@
#include "net/quic/test_tools/quic_connection_peer.h"
+#include "net/quic/congestion_control/quic_congestion_manager.h"
#include "net/quic/congestion_control/quic_receipt_metrics_collector.h"
#include "net/quic/congestion_control/quic_send_scheduler.h"
#include "net/quic/quic_connection.h"
@@ -19,13 +20,13 @@ void QuicConnectionPeer::SendAck(QuicConnection* connection) {
// static
void QuicConnectionPeer::SetCollector(QuicConnection* connection,
QuicReceiptMetricsCollector* collector) {
- connection->collector_.reset(collector);
+ connection->congestion_manager_.collector_.reset(collector);
}
// static
void QuicConnectionPeer::SetScheduler(QuicConnection* connection,
QuicSendScheduler* scheduler) {
- connection->scheduler_.reset(scheduler);
+ connection->congestion_manager_.scheduler_.reset(scheduler);
}
// static
@@ -39,6 +40,12 @@ QuicConnectionVisitorInterface* QuicConnectionPeer::GetVisitor(
return connection->visitor_;
}
+// static
+QuicPacketCreator* QuicConnectionPeer::GetPacketCreator(
+ QuicConnection* connection) {
+ return &connection->packet_creator_;
+}
+
bool QuicConnectionPeer::GetReceivedTruncatedAck(QuicConnection* connection) {
return connection->received_truncated_ack_;
}
diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h
index 532d1e4..46b20929 100644
--- a/net/quic/test_tools/quic_connection_peer.h
+++ b/net/quic/test_tools/quic_connection_peer.h
@@ -12,6 +12,7 @@ namespace net {
struct QuicAckFrame;
class QuicConnection;
class QuicConnectionVisitorInterface;
+class QuicPacketCreator;
class QuicReceiptMetricsCollector;
class QuicSendScheduler;
@@ -33,6 +34,8 @@ class QuicConnectionPeer {
static QuicConnectionVisitorInterface* GetVisitor(
QuicConnection* connection);
+ static QuicPacketCreator* GetPacketCreator(QuicConnection* connection);
+
static bool GetReceivedTruncatedAck(QuicConnection* connection);
private:
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index 052bd95..92793d1 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -103,9 +103,9 @@ PacketSavingConnection::~PacketSavingConnection() {
bool PacketSavingConnection::SendPacket(QuicPacketSequenceNumber number,
QuicPacket* packet,
- bool should_resend,
+ bool should_retransmit,
bool force,
- bool is_retransmit) {
+ bool is_retransmission) {
packets_.push_back(packet);
return true;
}
@@ -210,9 +210,10 @@ QuicPacket* ConstructHandshakePacket(QuicGuid guid, CryptoTag tag) {
QuicEncrypter::Create(kNULL));
QuicPacketHeader header;
- header.guid = guid;
+ header.public_header.guid = guid;
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
header.packet_sequence_number = 1;
- header.flags = PACKET_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.fec_group = 0;
QuicStreamFrame stream_frame(kCryptoStreamId, false, 0,
@@ -240,9 +241,10 @@ QuicPacket* ConstructClientHelloPacket(QuicGuid guid,
QuicEncrypter::Create(kNULL));
QuicPacketHeader header;
- header.guid = guid;
+ header.public_header.guid = guid;
+ header.public_header.flags = PACKET_PUBLIC_FLAGS_NONE;
header.packet_sequence_number = 1;
- header.flags = PACKET_FLAGS_NONE;
+ header.private_flags = PACKET_PRIVATE_FLAGS_NONE;
header.fec_group = 0;
QuicStreamFrame stream_frame(kCryptoStreamId, false, 0,
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index 0c2207f..c8e26c9 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -139,8 +139,7 @@ class MockHelper : public QuicConnectionHelperInterface {
QuicRandom* GetRandomGenerator();
MOCK_METHOD2(WritePacketToWire, int(const QuicEncryptedPacket& packet,
int* error));
- MOCK_METHOD2(SetResendAlarm, void(QuicPacketSequenceNumber sequence_number,
- QuicTime::Delta delay));
+ MOCK_METHOD1(SetRetransmissionAlarm, void(QuicTime::Delta delay));
MOCK_METHOD1(SetAckAlarm, void(QuicTime::Delta delay));
MOCK_METHOD1(SetSendAlarm, void(QuicTime::Delta delay));
MOCK_METHOD1(SetTimeoutAlarm, void(QuicTime::Delta delay));
@@ -183,9 +182,9 @@ class PacketSavingConnection : public MockConnection {
virtual bool SendPacket(QuicPacketSequenceNumber number,
QuicPacket* packet,
- bool should_resend,
+ bool should_retransmit,
bool force,
- bool is_retransmit) OVERRIDE;
+ bool is_retransmission) OVERRIDE;
std::vector<QuicPacket*> packets_;
@@ -209,7 +208,8 @@ class MockSession : public QuicSession {
MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*());
MOCK_METHOD4(WriteData, QuicConsumedData(QuicStreamId id,
base::StringPiece data,
- QuicStreamOffset offset, bool fin));
+ QuicStreamOffset offset,
+ bool fin));
MOCK_METHOD0(IsHandshakeComplete, bool());
private: