summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-03 10:20:28 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-03 10:20:28 +0000
commit9cda5fd9eb12ce1cec3d557c9733c9fb229844ee (patch)
tree65d69ac8bb2b9661b419247d74e0fadbd35b266a /net
parent008db1214e1a69af13f746085620b7ec49c95132 (diff)
downloadchromium_src-9cda5fd9eb12ce1cec3d557c9733c9fb229844ee.zip
chromium_src-9cda5fd9eb12ce1cec3d557c9733c9fb229844ee.tar.gz
chromium_src-9cda5fd9eb12ce1cec3d557c9733c9fb229844ee.tar.bz2
Land Recent QUIC Changes.
Ensuring that QUIC's pacing sender can have TimeUntilSend called multiple times and behave return the same time to send. Also add more tests to ensure the pacing sender properly makes up for lost time, but stops doing so after application limited sending. Merge internal change: 68257669 https://codereview.chromium.org/312573002/ Drop "Interface" from name of QUIC debug interfaces that should not be abstract. Drop Interface from some class names. Merge internal change: 68257565 https://codereview.chromium.org/310693002/ QUIC flow control now based on highest received byte offset rather than bytes buffered. No longer keep track of how many bytes we have buffered in the QUIC flow controller - this adds complexity when we can just track the highest received byte offset. This allows us to detect flow control violation earlier. QUIC flow control now based on highest received byte offset rather than bytes buffered. Protected behind (already ENABLEd) FLAGS_enable_quic_stream_flow_control_2 Merge internal change: 68200399 https://codereview.chromium.org/305033011/ Changes the pacing sender's alarm granularity from 1 microsecond to 5 milliseconds. Merge internal change: 68197640 https://codereview.chromium.org/302283004/ Remove unnecessary MaybeSendWindowUpdate from ReliableQuicStream: always try sending a WINDOW_UPDATE from inside AddBytesConsumed. Whenever bytes_consumed changes we may want to send a WINDOW_UPDATE, and this CL prevents future users calling AddBytesConsumed and forgetting MaybeSendWindowUpdate. QUIC: remove unnecessary MaybeSendWindowUpdate from ReliableQuicStream Merge internal change: 68188106 https://codereview.chromium.org/308363002/ Remove the TransmissionType argument from QuicConnection CanWrite and SentPacketManager TimeUntilSend by generalizing the QuicSentPackeManager's TLP alarm. Merge internal change: 68148420 https://codereview.chromium.org/306013009/ Cleanup in QuicConnection to always cancel the send alarm when CanWrite is consulted and use CanWrite when deciding to send in response to a packet receipt. Merge internal change: 68118973 https://codereview.chromium.org/304293009/ Allow QUIC's BBR congestion control to be negotiated in the crypto handshake. Adding an implementation of QuicFixedTagVector to QuicConfig to enable multiple congestion control options per connection. Merge internal change: 68114869 https://codereview.chromium.org/308273004/ Move test-only method from QuicFramer to quic_test_utils. Merge internal change: 68110215 https://codereview.chromium.org/305343002/ Replaced options from QuicPacketCreator with members and explicit getters/setters. A couple of small bugs fixed. Merge internal change: 68099048 https://codereview.chromium.org/301173007/ R=rch@chromium.org Review URL: https://codereview.chromium.org/312553003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274455 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/quic/congestion_control/pacing_sender.cc40
-rw-r--r--net/quic/congestion_control/pacing_sender.h4
-rw-r--r--net/quic/congestion_control/pacing_sender_test.cc99
-rw-r--r--net/quic/crypto/crypto_handshake_message.cc1
-rw-r--r--net/quic/crypto/crypto_protocol.h4
-rw-r--r--net/quic/quic_config.cc152
-rw-r--r--net/quic/quic_config.h52
-rw-r--r--net/quic/quic_config_test.cc20
-rw-r--r--net/quic/quic_connection.cc49
-rw-r--r--net/quic/quic_connection.h21
-rw-r--r--net/quic/quic_connection_logger.h2
-rw-r--r--net/quic/quic_connection_test.cc221
-rw-r--r--net/quic/quic_crypto_client_stream.cc2
-rw-r--r--net/quic/quic_crypto_client_stream_test.cc2
-rw-r--r--net/quic/quic_flow_controller.cc46
-rw-r--r--net/quic/quic_flow_controller.h22
-rw-r--r--net/quic/quic_flow_controller_test.cc9
-rw-r--r--net/quic/quic_framer.cc20
-rw-r--r--net/quic/quic_framer.h7
-rw-r--r--net/quic/quic_framer_test.cc87
-rw-r--r--net/quic/quic_packet_creator.cc73
-rw-r--r--net/quic/quic_packet_creator.h88
-rw-r--r--net/quic/quic_packet_creator_test.cc64
-rw-r--r--net/quic/quic_packet_generator.cc2
-rw-r--r--net/quic/quic_packet_generator.h10
-rw-r--r--net/quic/quic_packet_generator_test.cc9
-rw-r--r--net/quic/quic_protocol.cc5
-rw-r--r--net/quic/quic_protocol.h3
-rw-r--r--net/quic/quic_reliable_client_stream.cc3
-rw-r--r--net/quic/quic_sent_packet_manager.cc23
-rw-r--r--net/quic/quic_sent_packet_manager.h3
-rw-r--r--net/quic/quic_session.h2
-rw-r--r--net/quic/quic_stream_factory.cc2
-rw-r--r--net/quic/quic_stream_sequencer.cc4
-rw-r--r--net/quic/reliable_quic_stream.cc38
-rw-r--r--net/quic/reliable_quic_stream.h21
-rw-r--r--net/quic/reliable_quic_stream_test.cc26
-rw-r--r--net/quic/test_tools/mock_crypto_client_stream.cc2
-rw-r--r--net/quic/test_tools/quic_flow_controller_peer.cc2
-rw-r--r--net/quic/test_tools/quic_test_packet_maker.cc6
-rw-r--r--net/quic/test_tools/quic_test_utils.cc23
-rw-r--r--net/quic/test_tools/quic_test_utils.h7
-rw-r--r--net/tools/quic/quic_client.cc7
-rw-r--r--net/tools/quic/quic_client.h2
-rw-r--r--net/tools/quic/quic_time_wait_list_manager_test.cc5
-rw-r--r--net/tools/quic/test_tools/quic_test_client.cc4
-rw-r--r--net/tools/quic/test_tools/quic_test_client.h2
47 files changed, 705 insertions, 591 deletions
diff --git a/net/quic/congestion_control/pacing_sender.cc b/net/quic/congestion_control/pacing_sender.cc
index c487d2a..96f6c62 100644
--- a/net/quic/congestion_control/pacing_sender.cc
+++ b/net/quic/congestion_control/pacing_sender.cc
@@ -10,6 +10,7 @@ PacingSender::PacingSender(SendAlgorithmInterface* sender,
QuicTime::Delta alarm_granularity)
: sender_(sender),
alarm_granularity_(alarm_granularity),
+ last_delayed_packet_sent_time_(QuicTime::Zero()),
next_packet_send_time_(QuicTime::Zero()),
was_last_send_delayed_(false),
has_valid_rtt_(false) {
@@ -54,7 +55,29 @@ bool PacingSender::OnPacketSent(
const float kPacingAggression = 2;
QuicTime::Delta delay =
BandwidthEstimate().Scale(kPacingAggression).TransferTime(bytes);
- next_packet_send_time_ = next_packet_send_time_.Add(delay);
+ // If the last send was delayed, and the alarm took a long time to get
+ // invoked, allow the connection to make up for lost time.
+ if (was_last_send_delayed_) {
+ next_packet_send_time_ = next_packet_send_time_.Add(delay);
+ // As long as we're making up time and not application limited,
+ // continue to consider the packets delayed.
+ // The send was application limited if it takes longer than the
+ // pacing delay between sent packets.
+ const bool application_limited =
+ last_delayed_packet_sent_time_.IsInitialized() &&
+ sent_time > last_delayed_packet_sent_time_.Add(delay);
+ const bool making_up_for_lost_time = next_packet_send_time_ > sent_time;
+ if (making_up_for_lost_time || application_limited) {
+ was_last_send_delayed_ = false;
+ last_delayed_packet_sent_time_ = QuicTime::Zero();
+ } else {
+ last_delayed_packet_sent_time_ = sent_time;
+ }
+ } else {
+ next_packet_send_time_ =
+ QuicTime::Max(next_packet_send_time_.Add(delay),
+ sent_time.Add(delay).Subtract(alarm_granularity_));
+ }
}
return sender_->OnPacketSent(sent_time, bytes_in_flight, sequence_number,
bytes, has_retransmittable_data);
@@ -87,25 +110,14 @@ QuicTime::Delta PacingSender::TimeUntilSend(
return QuicTime::Delta::Zero();
}
- if (!was_last_send_delayed_ &&
- (!next_packet_send_time_.IsInitialized() ||
- now > next_packet_send_time_.Add(alarm_granularity_))) {
- // An alarm did not go off late, instead the application is "slow"
- // delivering data. In this case, we restrict the amount of lost time
- // that we can make up for.
- next_packet_send_time_ = now.Subtract(alarm_granularity_);
- }
-
- // If the end of the epoch is far enough in the future, delay the send.
+ // If the next send time is within the alarm granularity, send immediately.
if (next_packet_send_time_ > now.Add(alarm_granularity_)) {
- was_last_send_delayed_ = true;
DVLOG(1) << "Delaying packet: "
<< next_packet_send_time_.Subtract(now).ToMicroseconds();
+ was_last_send_delayed_ = true;
return next_packet_send_time_.Subtract(now);
}
- // Sent it immediately. The epoch end will be adjusted in OnPacketSent.
- was_last_send_delayed_ = false;
DVLOG(1) << "Sending packet now";
return QuicTime::Delta::Zero();
}
diff --git a/net/quic/congestion_control/pacing_sender.h b/net/quic/congestion_control/pacing_sender.h
index b1060ac..f7c2622 100644
--- a/net/quic/congestion_control/pacing_sender.h
+++ b/net/quic/congestion_control/pacing_sender.h
@@ -55,8 +55,10 @@ class NET_EXPORT_PRIVATE PacingSender : public SendAlgorithmInterface {
private:
scoped_ptr<SendAlgorithmInterface> sender_; // Underlying sender.
QuicTime::Delta alarm_granularity_;
+ // Send time of the last packet considered delayed.
+ QuicTime last_delayed_packet_sent_time_;
QuicTime next_packet_send_time_; // When can the next packet be sent.
- bool was_last_send_delayed_; // True when the last send was delayed.
+ mutable bool was_last_send_delayed_; // True when the last send was delayed.
bool has_valid_rtt_; // True if we have at least one RTT update.
DISALLOW_COPY_AND_ASSIGN(PacingSender);
diff --git a/net/quic/congestion_control/pacing_sender_test.cc b/net/quic/congestion_control/pacing_sender_test.cc
index 38e5d02..2dc6960 100644
--- a/net/quic/congestion_control/pacing_sender_test.cc
+++ b/net/quic/congestion_control/pacing_sender_test.cc
@@ -38,15 +38,17 @@ class PacingSenderTest : public ::testing::Test {
void CheckPacketIsSentImmediately() {
// In order for the packet to be sendable, the underlying sender must
// permit it to be sent immediately.
- EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
- kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA))
- .WillOnce(Return(zero_time_));
- // Verify that the packet can be sent immediately.
- EXPECT_EQ(zero_time_,
- pacing_sender_->TimeUntilSend(clock_.Now(),
- kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA));
+ for (int i = 0; i < 2; ++i) {
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+ kBytesInFlight,
+ HAS_RETRANSMITTABLE_DATA))
+ .WillOnce(Return(zero_time_));
+ // Verify that the packet can be sent immediately.
+ EXPECT_EQ(zero_time_,
+ pacing_sender_->TimeUntilSend(clock_.Now(),
+ kBytesInFlight,
+ HAS_RETRANSMITTABLE_DATA));
+ }
// Actually send the packet.
EXPECT_CALL(*mock_sender_,
@@ -82,15 +84,17 @@ class PacingSenderTest : public ::testing::Test {
void CheckPacketIsDelayed(QuicTime::Delta delay) {
// In order for the packet to be sendable, the underlying sender must
// permit it to be sent immediately.
- EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
- kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA))
- .WillOnce(Return(zero_time_));
- // Verify that the packet is delayed.
- EXPECT_EQ(delay.ToMicroseconds(),
- pacing_sender_->TimeUntilSend(
- clock_.Now(), kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA).ToMicroseconds());
+ for (int i = 0; i < 2; ++i) {
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+ kBytesInFlight,
+ HAS_RETRANSMITTABLE_DATA))
+ .WillOnce(Return(zero_time_));
+ // Verify that the packet is delayed.
+ EXPECT_EQ(delay.ToMicroseconds(),
+ pacing_sender_->TimeUntilSend(
+ clock_.Now(), kBytesInFlight,
+ HAS_RETRANSMITTABLE_DATA).ToMicroseconds());
+ }
}
const QuicTime::Delta zero_time_;
@@ -102,25 +106,29 @@ class PacingSenderTest : public ::testing::Test {
};
TEST_F(PacingSenderTest, NoSend) {
- EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
- kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA))
- .WillOnce(Return(infinite_time_));
- EXPECT_EQ(infinite_time_,
- pacing_sender_->TimeUntilSend(clock_.Now(),
- kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA));
+ for (int i = 0; i < 2; ++i) {
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+ kBytesInFlight,
+ HAS_RETRANSMITTABLE_DATA))
+ .WillOnce(Return(infinite_time_));
+ EXPECT_EQ(infinite_time_,
+ pacing_sender_->TimeUntilSend(clock_.Now(),
+ kBytesInFlight,
+ HAS_RETRANSMITTABLE_DATA));
+ }
}
TEST_F(PacingSenderTest, SendNow) {
- EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
- kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA))
- .WillOnce(Return(zero_time_));
- EXPECT_EQ(zero_time_,
- pacing_sender_->TimeUntilSend(clock_.Now(),
- kBytesInFlight,
- HAS_RETRANSMITTABLE_DATA));
+ for (int i = 0; i < 2; ++i) {
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+ kBytesInFlight,
+ HAS_RETRANSMITTABLE_DATA))
+ .WillOnce(Return(zero_time_));
+ EXPECT_EQ(zero_time_,
+ pacing_sender_->TimeUntilSend(clock_.Now(),
+ kBytesInFlight,
+ HAS_RETRANSMITTABLE_DATA));
+ }
}
TEST_F(PacingSenderTest, VariousSending) {
@@ -163,6 +171,29 @@ TEST_F(PacingSenderTest, VariousSending) {
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+ // Wake up really late.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+ // Wake up really late again, but application pause partway through.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
// Wake up too early.
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
diff --git a/net/quic/crypto/crypto_handshake_message.cc b/net/quic/crypto/crypto_handshake_message.cc
index f2cd696..4f593e8 100644
--- a/net/quic/crypto/crypto_handshake_message.cc
+++ b/net/quic/crypto/crypto_handshake_message.cc
@@ -256,6 +256,7 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
case kKEXS:
case kAEAD:
case kCGST:
+ case kCOPT:
case kLOSS:
case kPDMD:
case kVER:
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h
index c508147..49194e9 100644
--- a/net/quic/crypto/crypto_protocol.h
+++ b/net/quic/crypto/crypto_protocol.h
@@ -47,6 +47,9 @@ const QuicTag kQBIC = TAG('Q', 'B', 'I', 'C'); // TCP cubic
const QuicTag kPACE = TAG('P', 'A', 'C', 'E'); // Paced TCP cubic
const QuicTag kINAR = TAG('I', 'N', 'A', 'R'); // Inter arrival
+// Congestion control options
+const QuicTag kTBBR = TAG('T', 'B', 'B', 'R'); // Reduced Buffer Bloat TCP
+
// Loss detection algorithm types
const QuicTag kNACK = TAG('N', 'A', 'C', 'K'); // TCP style nack counting
const QuicTag kTIME = TAG('T', 'I', 'M', 'E'); // Time based
@@ -68,6 +71,7 @@ const QuicTag kAEAD = TAG('A', 'E', 'A', 'D'); // Authenticated
// encryption algorithms
const QuicTag kCGST = TAG('C', 'G', 'S', 'T'); // Congestion control
// feedback types
+const QuicTag kCOPT = TAG('C', 'O', 'P', 'T'); // Congestion control options
// kLOSS was 'L', 'O', 'S', 'S', but was changed from a tag vector to a tag.
const QuicTag kLOSS = TAG('L', 'O', 'S', 'A'); // Loss detection algorithms
const QuicTag kICSL = TAG('I', 'C', 'S', 'L'); // Idle connection state
diff --git a/net/quic/quic_config.cc b/net/quic/quic_config.cc
index 9c60671..b9703c4 100644
--- a/net/quic/quic_config.cc
+++ b/net/quic/quic_config.cc
@@ -129,8 +129,7 @@ QuicNegotiableTag::~QuicNegotiableTag() {}
void QuicNegotiableTag::set(const QuicTagVector& possible,
QuicTag default_value) {
- DCHECK(std::find(possible.begin(), possible.end(), default_value) !=
- possible.end());
+ DCHECK(ContainsQuicTag(possible, default_value));
possible_values_ = possible;
default_value_ = default_value;
}
@@ -194,8 +193,7 @@ QuicErrorCode QuicNegotiableTag::ProcessPeerHello(
if (hello_type == SERVER) {
if (received_tags_length != 1 ||
- std::find(possible_values_.begin(), possible_values_.end(),
- *received_tags) == possible_values_.end()) {
+ !ContainsQuicTag(possible_values_, *received_tags)) {
*error_details = "Invalid " + QuicUtils::TagToString(tag_);
return QUIC_INVALID_NEGOTIATED_VALUE;
}
@@ -268,11 +266,10 @@ QuicErrorCode QuicFixedUint32::ProcessPeerHello(
QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
switch (error) {
case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
- if (presence_ == PRESENCE_REQUIRED) {
- *error_details = "Missing " + QuicUtils::TagToString(tag_);
- break;
+ if (presence_ == PRESENCE_OPTIONAL) {
+ return QUIC_NO_ERROR;
}
- error = QUIC_NO_ERROR;
+ *error_details = "Missing " + QuicUtils::TagToString(tag_);
break;
case QUIC_NO_ERROR:
has_receive_value_ = true;
@@ -329,18 +326,17 @@ void QuicFixedTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
}
QuicErrorCode QuicFixedTag::ProcessPeerHello(
- const CryptoHandshakeMessage& client_hello,
+ const CryptoHandshakeMessage& peer_hello,
HelloType hello_type,
string* error_details) {
DCHECK(error_details != NULL);
- QuicErrorCode error = client_hello.GetUint32(tag_, &receive_value_);
+ QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
switch (error) {
case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
- if (presence_ == PRESENCE_REQUIRED) {
- *error_details = "Missing " + QuicUtils::TagToString(tag_);
- break;
+ if (presence_ == PRESENCE_OPTIONAL) {
+ return QUIC_NO_ERROR;
}
- error = QUIC_NO_ERROR;
+ *error_details = "Missing " + QuicUtils::TagToString(tag_);
break;
case QUIC_NO_ERROR:
has_receive_value_ = true;
@@ -352,8 +348,82 @@ QuicErrorCode QuicFixedTag::ProcessPeerHello(
return error;
}
+QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
+ QuicConfigPresence presence)
+ : QuicConfigValue(name, presence),
+ has_send_values_(false),
+ has_receive_values_(false) {
+}
+
+QuicFixedTagVector::~QuicFixedTagVector() {}
+
+bool QuicFixedTagVector::HasSendValues() const {
+ return has_send_values_;
+}
+
+QuicTagVector QuicFixedTagVector::GetSendValues() const {
+ LOG_IF(DFATAL, !has_send_values_) << "No send values to get for tag:" << tag_;
+ return send_values_;
+}
+
+void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
+ has_send_values_ = true;
+ send_values_ = values;
+}
+
+bool QuicFixedTagVector::HasReceivedValues() const {
+ return has_receive_values_;
+}
+
+QuicTagVector QuicFixedTagVector::GetReceivedValues() const {
+ LOG_IF(DFATAL, !has_receive_values_)
+ << "No receive value to get for tag:" << tag_;
+ return receive_values_;
+}
+
+void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
+ has_receive_values_ = true;
+ receive_values_ = values;
+}
+
+void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
+ if (has_send_values_) {
+ out->SetVector(tag_, send_values_);
+ }
+}
+
+QuicErrorCode QuicFixedTagVector::ProcessPeerHello(
+ const CryptoHandshakeMessage& peer_hello,
+ HelloType hello_type,
+ string* error_details) {
+ DCHECK(error_details != NULL);
+ const QuicTag* received_tags;
+ size_t received_tags_length;
+ QuicErrorCode error =
+ peer_hello.GetTaglist(tag_, &received_tags, &received_tags_length);
+ switch (error) {
+ case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
+ if (presence_ == PRESENCE_OPTIONAL) {
+ return QUIC_NO_ERROR;
+ }
+ *error_details = "Missing " + QuicUtils::TagToString(tag_);
+ break;
+ case QUIC_NO_ERROR:
+ has_receive_values_ = true;
+ for (size_t i = 0; i < received_tags_length; ++i) {
+ receive_values_.push_back(received_tags[i]);
+ }
+ break;
+ default:
+ *error_details = "Bad " + QuicUtils::TagToString(tag_);
+ break;
+ }
+ return error;
+}
+
QuicConfig::QuicConfig()
- : congestion_control_(kCGST, PRESENCE_REQUIRED),
+ : congestion_feedback_(kCGST, PRESENCE_REQUIRED),
+ congestion_options_(kCOPT, PRESENCE_OPTIONAL),
loss_detection_(kLOSS, PRESENCE_OPTIONAL),
idle_connection_state_lifetime_seconds_(kICSL, PRESENCE_REQUIRED),
keepalive_timeout_seconds_(kKATO, PRESENCE_OPTIONAL),
@@ -368,14 +438,27 @@ QuicConfig::QuicConfig()
QuicConfig::~QuicConfig() {}
-void QuicConfig::set_congestion_control(
- const QuicTagVector& congestion_control,
- QuicTag default_congestion_control) {
- congestion_control_.set(congestion_control, default_congestion_control);
+void QuicConfig::set_congestion_feedback(
+ const QuicTagVector& congestion_feedback,
+ QuicTag default_congestion_feedback) {
+ congestion_feedback_.set(congestion_feedback, default_congestion_feedback);
+}
+
+QuicTag QuicConfig::congestion_feedback() const {
+ return congestion_feedback_.GetTag();
}
-QuicTag QuicConfig::congestion_control() const {
- return congestion_control_.GetTag();
+void QuicConfig::SetCongestionOptionsToSend(
+ const QuicTagVector& congestion_options) {
+ congestion_options_.SetSendValues(congestion_options);
+}
+
+bool QuicConfig::HasReceivedCongestionOptions() const {
+ return congestion_options_.HasReceivedValues();
+}
+
+QuicTagVector QuicConfig::ReceivedCongestionOptions() const {
+ return congestion_options_.GetReceivedValues();
}
void QuicConfig::SetLossDetectionToSend(QuicTag loss_detection) {
@@ -466,19 +549,19 @@ bool QuicConfig::negotiated() {
// TODO(ianswett): Add the negotiated parameters once and iterate over all
// of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
// ProcessServerHello.
- return congestion_control_.negotiated() &&
+ return congestion_feedback_.negotiated() &&
idle_connection_state_lifetime_seconds_.negotiated() &&
keepalive_timeout_seconds_.negotiated() &&
max_streams_per_connection_.negotiated();
}
void QuicConfig::SetDefaults() {
- QuicTagVector congestion_control;
+ QuicTagVector congestion_feedback;
if (FLAGS_enable_quic_pacing) {
- congestion_control.push_back(kPACE);
+ congestion_feedback.push_back(kPACE);
}
- congestion_control.push_back(kQBIC);
- congestion_control_.set(congestion_control, kQBIC);
+ congestion_feedback.push_back(kQBIC);
+ congestion_feedback_.set(congestion_feedback, kQBIC);
idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs,
kDefaultInitialTimeoutSecs);
// kKATO is optional. Return 0 if not negotiated.
@@ -490,16 +573,16 @@ void QuicConfig::SetDefaults() {
}
void QuicConfig::EnablePacing(bool enable_pacing) {
- QuicTagVector congestion_control;
+ QuicTagVector congestion_feedback;
if (enable_pacing) {
- congestion_control.push_back(kPACE);
+ congestion_feedback.push_back(kPACE);
}
- congestion_control.push_back(kQBIC);
- congestion_control_.set(congestion_control, kQBIC);
+ congestion_feedback.push_back(kQBIC);
+ congestion_feedback_.set(congestion_feedback, kQBIC);
}
void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
- congestion_control_.ToHandshakeMessage(out);
+ congestion_feedback_.ToHandshakeMessage(out);
idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
keepalive_timeout_seconds_.ToHandshakeMessage(out);
max_streams_per_connection_.ToHandshakeMessage(out);
@@ -507,6 +590,7 @@ void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
initial_round_trip_time_us_.ToHandshakeMessage(out);
loss_detection_.ToHandshakeMessage(out);
initial_flow_control_window_bytes_.ToHandshakeMessage(out);
+ congestion_options_.ToHandshakeMessage(out);
}
QuicErrorCode QuicConfig::ProcessPeerHello(
@@ -517,7 +601,7 @@ QuicErrorCode QuicConfig::ProcessPeerHello(
QuicErrorCode error = QUIC_NO_ERROR;
if (error == QUIC_NO_ERROR) {
- error = congestion_control_.ProcessPeerHello(
+ error = congestion_feedback_.ProcessPeerHello(
peer_hello, hello_type, error_details);
}
if (error == QUIC_NO_ERROR) {
@@ -548,6 +632,10 @@ QuicErrorCode QuicConfig::ProcessPeerHello(
error = loss_detection_.ProcessPeerHello(
peer_hello, hello_type, error_details);
}
+ if (error == QUIC_NO_ERROR) {
+ error = congestion_options_.ProcessPeerHello(
+ peer_hello, hello_type, error_details);
+ }
return error;
}
diff --git a/net/quic/quic_config.h b/net/quic/quic_config.h
index 88ad8b6..4d65097 100644
--- a/net/quic/quic_config.h
+++ b/net/quic/quic_config.h
@@ -215,6 +215,42 @@ class NET_EXPORT_PRIVATE QuicFixedTag : public QuicConfigValue {
bool has_receive_value_;
};
+// Stores tag from CHLO or SHLO messages that are not negotiated.
+class NET_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue {
+ public:
+ QuicFixedTagVector(QuicTag name, QuicConfigPresence presence);
+ virtual ~QuicFixedTagVector();
+
+ bool HasSendValues() const;
+
+ QuicTagVector GetSendValues() const;
+
+ void SetSendValues(const QuicTagVector& values);
+
+ bool HasReceivedValues() const;
+
+ QuicTagVector GetReceivedValues() const;
+
+ void SetReceivedValues(const QuicTagVector& values);
+
+ // If has_send_value is true, serialises |tag_vector_| and |send_value_| to
+ // |out|.
+ virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const OVERRIDE;
+
+ // Sets |receive_values_| to the corresponding value from |client_hello_| if
+ // it exists.
+ virtual QuicErrorCode ProcessPeerHello(
+ const CryptoHandshakeMessage& peer_hello,
+ HelloType hello_type,
+ std::string* error_details) OVERRIDE;
+
+ private:
+ QuicTagVector send_values_;
+ bool has_send_values_;
+ QuicTagVector receive_values_;
+ bool has_receive_values_;
+};
+
// QuicConfig contains non-crypto configuration options that are negotiated in
// the crypto handshake.
class NET_EXPORT_PRIVATE QuicConfig {
@@ -222,10 +258,16 @@ class NET_EXPORT_PRIVATE QuicConfig {
QuicConfig();
~QuicConfig();
- void set_congestion_control(const QuicTagVector& congestion_control,
- QuicTag default_congestion_control);
+ void set_congestion_feedback(const QuicTagVector& congestion_feedback,
+ QuicTag default_congestion_feedback);
+
+ QuicTag congestion_feedback() const;
+
+ void SetCongestionOptionsToSend(const QuicTagVector& congestion_options);
+
+ bool HasReceivedCongestionOptions() const;
- QuicTag congestion_control() const;
+ QuicTagVector ReceivedCongestionOptions() const;
void SetLossDetectionToSend(QuicTag loss_detection);
@@ -294,7 +336,9 @@ class NET_EXPORT_PRIVATE QuicConfig {
friend class test::QuicConfigPeer;
// Congestion control feedback type.
- QuicNegotiableTag congestion_control_;
+ QuicNegotiableTag congestion_feedback_;
+ // Congestion control option.
+ QuicFixedTagVector congestion_options_;
// Loss detection feedback type.
QuicFixedTag loss_detection_;
// Idle connection state lifetime
diff --git a/net/quic/quic_config_test.cc b/net/quic/quic_config_test.cc
index 9ca449d..63299e5 100644
--- a/net/quic/quic_config_test.cc
+++ b/net/quic/quic_config_test.cc
@@ -69,12 +69,12 @@ TEST_F(QuicConfigTest, ToHandshakeMessageWithPacing) {
EXPECT_EQ(kQBIC, out[1]);
}
-TEST_F(QuicConfigTest, ProcessPeerHello) {
+TEST_F(QuicConfigTest, ProcessClientHello) {
QuicConfig client_config;
QuicTagVector cgst;
cgst.push_back(kINAR);
cgst.push_back(kQBIC);
- client_config.set_congestion_control(cgst, kQBIC);
+ client_config.set_congestion_feedback(cgst, kQBIC);
client_config.set_idle_connection_state_lifetime(
QuicTime::Delta::FromSeconds(2 * kDefaultTimeoutSecs),
QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs));
@@ -82,6 +82,9 @@ TEST_F(QuicConfigTest, ProcessPeerHello) {
2 * kDefaultMaxStreamsPerConnection, kDefaultMaxStreamsPerConnection);
client_config.SetInitialRoundTripTimeUsToSend(
10 * base::Time::kMicrosecondsPerMillisecond);
+ QuicTagVector copt;
+ copt.push_back(kTBBR);
+ client_config.SetCongestionOptionsToSend(copt);
CryptoHandshakeMessage msg;
client_config.ToHandshakeMessage(&msg);
string error_details;
@@ -89,7 +92,7 @@ TEST_F(QuicConfigTest, ProcessPeerHello) {
config_.ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
EXPECT_TRUE(config_.negotiated());
- EXPECT_EQ(kQBIC, config_.congestion_control());
+ EXPECT_EQ(kQBIC, config_.congestion_feedback());
EXPECT_EQ(QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs),
config_.idle_connection_state_lifetime());
EXPECT_EQ(kDefaultMaxStreamsPerConnection,
@@ -98,13 +101,16 @@ TEST_F(QuicConfigTest, ProcessPeerHello) {
EXPECT_EQ(10 * base::Time::kMicrosecondsPerMillisecond,
config_.ReceivedInitialRoundTripTimeUs());
EXPECT_FALSE(config_.HasReceivedLossDetection());
+ EXPECT_TRUE(config_.HasReceivedCongestionOptions());
+ EXPECT_EQ(1u, config_.ReceivedCongestionOptions().size());
+ EXPECT_EQ(config_.ReceivedCongestionOptions()[0], kTBBR);
}
TEST_F(QuicConfigTest, ProcessServerHello) {
QuicConfig server_config;
QuicTagVector cgst;
cgst.push_back(kQBIC);
- server_config.set_congestion_control(cgst, kQBIC);
+ server_config.set_congestion_feedback(cgst, kQBIC);
server_config.set_idle_connection_state_lifetime(
QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs / 2),
QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs / 2));
@@ -121,7 +127,7 @@ TEST_F(QuicConfigTest, ProcessServerHello) {
config_.ProcessPeerHello(msg, SERVER, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
EXPECT_TRUE(config_.negotiated());
- EXPECT_EQ(kQBIC, config_.congestion_control());
+ EXPECT_EQ(kQBIC, config_.congestion_feedback());
EXPECT_EQ(QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs / 2),
config_.idle_connection_state_lifetime());
EXPECT_EQ(kDefaultMaxStreamsPerConnection / 2,
@@ -211,7 +217,7 @@ TEST_F(QuicConfigTest, MultipleNegotiatedValuesInVectorTag) {
QuicTagVector cgst;
cgst.push_back(kQBIC);
cgst.push_back(kINAR);
- server_config.set_congestion_control(cgst, kQBIC);
+ server_config.set_congestion_feedback(cgst, kQBIC);
CryptoHandshakeMessage msg;
server_config.ToHandshakeMessage(&msg);
@@ -226,7 +232,7 @@ TEST_F(QuicConfigTest, NoOverLapInCGST) {
server_config.SetDefaults();
QuicTagVector cgst;
cgst.push_back(kINAR);
- server_config.set_congestion_control(cgst, kINAR);
+ server_config.set_congestion_feedback(cgst, kINAR);
CryptoHandshakeMessage msg;
string error_details;
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 8162c3c..04426d3 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -949,15 +949,8 @@ void QuicConnection::MaybeSendInResponseToPacket() {
// Now that we have received an ack, we might be able to send packets which
// are queued locally, or drain streams which are blocked.
- QuicTime::Delta delay = sent_packet_manager_.TimeUntilSend(
- time_of_last_received_packet_, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- if (delay.IsZero()) {
- send_alarm_->Cancel();
- WriteIfNotBlocked();
- } else if (!delay.IsInfinite()) {
- send_alarm_->Cancel();
- send_alarm_->Set(time_of_last_received_packet_.Add(delay));
+ if (CanWrite(HAS_RETRANSMITTABLE_DATA)) {
+ OnCanWrite();
}
}
@@ -1066,7 +1059,7 @@ const QuicConnectionStats& QuicConnection::GetStats() {
stats_.estimated_bandwidth =
sent_packet_manager_.BandwidthEstimate().ToBytesPerSecond();
stats_.congestion_window = sent_packet_manager_.GetCongestionWindow();
- stats_.max_packet_size = options()->max_packet_length;
+ stats_.max_packet_size = packet_creator_.max_packet_length();
return stats_;
}
@@ -1145,7 +1138,7 @@ void QuicConnection::OnCanWrite() {
// or the congestion manager to prohibit sending. If we've sent everything
// we had queued and we're still not blocked, let the visitor know it can
// write more.
- if (!CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA)) {
+ if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
return;
}
@@ -1159,7 +1152,7 @@ void QuicConnection::OnCanWrite() {
// blocked or the congestion manager to prohibit sending, so check again.
if (visitor_->WillingAndAbleToWrite() &&
!resume_writes_alarm_->IsSet() &&
- CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA)) {
+ CanWrite(HAS_RETRANSMITTABLE_DATA)) {
// 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 connections and events have had a chance to use the thread.
@@ -1196,8 +1189,8 @@ bool QuicConnection::ProcessValidatedPacket() {
<< time_of_last_received_packet_.ToDebuggingValue();
if (is_server_ && encryption_level_ == ENCRYPTION_NONE &&
- last_size_ > options()->max_packet_length) {
- options()->max_packet_length = last_size_;
+ last_size_ > packet_creator_.max_packet_length()) {
+ packet_creator_.set_max_packet_length(last_size_);
}
return true;
}
@@ -1230,7 +1223,7 @@ void QuicConnection::WritePendingRetransmissions() {
const QuicSentPacketManager::PendingRetransmission pending =
sent_packet_manager_.NextPendingRetransmission();
if (GetPacketType(&pending.retransmittable_frames) == NORMAL &&
- !CanWrite(pending.transmission_type, HAS_RETRANSMITTABLE_DATA)) {
+ !CanWrite(HAS_RETRANSMITTABLE_DATA)) {
break;
}
@@ -1288,35 +1281,25 @@ bool QuicConnection::ShouldGeneratePacket(
return true;
}
- return CanWrite(transmission_type, retransmittable);
+ return CanWrite(retransmittable);
}
-bool QuicConnection::CanWrite(TransmissionType transmission_type,
- HasRetransmittableData retransmittable) {
+bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) {
if (writer_->IsWriteBlocked()) {
visitor_->OnWriteBlocked();
return false;
}
- // TODO(rch): consider removing this check so that if an ACK comes in
- // before the alarm goes it, we might be able send out a packet.
- // This check assumes that if the send alarm is set, it applies equally to all
- // types of transmissions.
- if (send_alarm_->IsSet()) {
- DVLOG(1) << "Send alarm set. Not sending.";
- return false;
- }
-
+ send_alarm_->Cancel();
QuicTime now = clock_->Now();
QuicTime::Delta delay = sent_packet_manager_.TimeUntilSend(
- now, transmission_type, retransmittable);
+ now, retransmittable);
if (delay.IsInfinite()) {
return false;
}
// If the scheduler requires a delay, then we can not send this packet now.
if (!delay.IsZero()) {
- send_alarm_->Cancel();
send_alarm_->Set(now.Add(delay));
DVLOG(1) << "Delaying sending.";
return false;
@@ -1339,8 +1322,7 @@ bool QuicConnection::WritePacket(QueuedPacket packet) {
// This ensures packets are sent in sequence number order.
// TODO(ianswett): The congestion control should have been consulted before
// serializing the packet, so this could be turned into a LOG_IF(DFATAL).
- if (packet.type == NORMAL && !CanWrite(packet.transmission_type,
- packet.retransmittable)) {
+ if (packet.type == NORMAL && !CanWrite(packet.retransmittable)) {
return false;
}
@@ -1375,9 +1357,10 @@ bool QuicConnection::WritePacket(QueuedPacket packet) {
encrypted_deleter.reset(encrypted);
}
- LOG_IF(DFATAL, encrypted->length() > options()->max_packet_length)
+ LOG_IF(DFATAL, encrypted->length() >
+ packet_creator_.max_packet_length())
<< "Writing an encrypted packet larger than max_packet_length:"
- << options()->max_packet_length << " encrypted length: "
+ << packet_creator_.max_packet_length() << " encrypted length: "
<< encrypted->length();
DVLOG(1) << ENDPOINT << "Sending packet " << sequence_number
<< " : " << (packet.packet->is_fec_packet() ? "FEC " :
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 2f91bb4..c35e863 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -111,10 +111,10 @@ class NET_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// Interface which gets callbacks from the QuicConnection at interesting
// points. Implementations must not mutate the state of the connection
// as a result of these callbacks.
-class NET_EXPORT_PRIVATE QuicConnectionDebugVisitorInterface
- : public QuicPacketGenerator::DebugDelegateInterface {
+class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor
+ : public QuicPacketGenerator::DebugDelegate {
public:
- virtual ~QuicConnectionDebugVisitorInterface() {}
+ virtual ~QuicConnectionDebugVisitor() {}
// Called when a packet has been sent.
virtual void OnPacketSent(QuicPacketSequenceNumber sequence_number,
@@ -344,7 +344,7 @@ class NET_EXPORT_PRIVATE QuicConnection
void set_visitor(QuicConnectionVisitorInterface* visitor) {
visitor_ = visitor;
}
- void set_debug_visitor(QuicConnectionDebugVisitorInterface* debug_visitor) {
+ void set_debug_visitor(QuicConnectionDebugVisitor* debug_visitor) {
debug_visitor_ = debug_visitor;
packet_generator_.set_debug_delegate(debug_visitor);
}
@@ -353,8 +353,12 @@ class NET_EXPORT_PRIVATE QuicConnection
QuicConnectionId connection_id() const { return connection_id_; }
const QuicClock* clock() const { return clock_; }
QuicRandom* random_generator() const { return random_generator_; }
-
- QuicPacketCreator::Options* options() { return packet_creator_.options(); }
+ size_t max_packet_length() const {
+ return packet_creator_.max_packet_length();
+ }
+ void set_max_packet_length(size_t length) {
+ return packet_creator_.set_max_packet_length(length);
+ }
bool connected() const { return connected_; }
@@ -455,8 +459,7 @@ class NET_EXPORT_PRIVATE QuicConnection
return sent_packet_manager_;
}
- bool CanWrite(TransmissionType transmission_type,
- HasRetransmittableData retransmittable);
+ bool CanWrite(HasRetransmittableData retransmittable);
// Stores current batch state for connection, puts the connection
// into batch mode, and destruction restores the stored batch state.
@@ -695,7 +698,7 @@ class NET_EXPORT_PRIVATE QuicConnection
scoped_ptr<QuicAlarm> ping_alarm_;
QuicConnectionVisitorInterface* visitor_;
- QuicConnectionDebugVisitorInterface* debug_visitor_;
+ QuicConnectionDebugVisitor* debug_visitor_;
QuicPacketCreator packet_creator_;
QuicPacketGenerator packet_generator_;
diff --git a/net/quic/quic_connection_logger.h b/net/quic/quic_connection_logger.h
index 8baa1b8..c50cb9e 100644
--- a/net/quic/quic_connection_logger.h
+++ b/net/quic/quic_connection_logger.h
@@ -20,7 +20,7 @@ class CryptoHandshakeMessage;
// This class is a debug visitor of a QuicConnection which logs
// events to |net_log|.
class NET_EXPORT_PRIVATE QuicConnectionLogger
- : public QuicConnectionDebugVisitorInterface {
+ : public QuicConnectionDebugVisitor {
public:
explicit QuicConnectionLogger(const BoundNetLog& net_log);
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 603680f..6707c4a 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -556,7 +556,7 @@ class TestConnection : public QuicConnection {
// Used for testing packets revived from FEC packets.
class FecQuicConnectionDebugVisitor
- : public QuicConnectionDebugVisitorInterface {
+ : public QuicConnectionDebugVisitor {
public:
virtual void OnRevivedPacket(const QuicPacketHeader& header,
StringPiece data) OVERRIDE {
@@ -577,7 +577,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> {
QuicConnectionTest()
: connection_id_(42),
framer_(SupportedVersions(version()), QuicTime::Zero(), false),
- creator_(connection_id_, &framer_, &random_generator_, false),
+ peer_creator_(connection_id_, &framer_, &random_generator_, false),
send_algorithm_(new StrictMock<MockSendAlgorithm>),
loss_algorithm_(new MockLossAlgorithm()),
helper_(new TestConnectionHelper(&clock_, &random_generator_)),
@@ -652,9 +652,10 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> {
QuicPacketEntropyHash ProcessFramePacket(QuicFrame frame) {
QuicFrames frames;
frames.push_back(QuicFrame(frame));
- QuicPacketCreatorPeer::SetSendVersionInPacket(&creator_,
+ QuicPacketCreatorPeer::SetSendVersionInPacket(&peer_creator_,
connection_.is_server());
- SerializedPacket serialized_packet = creator_.SerializeAllFrames(frames);
+ SerializedPacket serialized_packet =
+ peer_creator_.SerializeAllFrames(frames);
scoped_ptr<QuicPacket> packet(serialized_packet.packet);
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.EncryptPacket(ENCRYPTION_NONE,
@@ -816,7 +817,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> {
QuicFrame frame(&frame1_);
frames.push_back(frame);
QuicPacket* packet =
- framer_.BuildUnsizedDataPacket(header_, frames).packet;
+ BuildUnsizedDataPacket(&framer_, header_, frames).packet;
EXPECT_TRUE(packet != NULL);
return packet;
}
@@ -839,7 +840,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> {
QuicFrame frame(&qccf);
frames.push_back(frame);
QuicPacket* packet =
- framer_.BuildUnsizedDataPacket(header_, frames).packet;
+ BuildUnsizedDataPacket(&framer_, header_, frames).packet;
EXPECT_TRUE(packet != NULL);
return packet;
}
@@ -913,9 +914,21 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> {
EXPECT_CALL(visitor_, OnWriteBlocked()).Times(AtLeast(1));
}
+ void CongestionBlockWrites() {
+ EXPECT_CALL(*send_algorithm_,
+ TimeUntilSend(_, _, _)).WillRepeatedly(
+ testing::Return(QuicTime::Delta::FromSeconds(1)));
+ }
+
+ void CongestionUnblockWrites() {
+ EXPECT_CALL(*send_algorithm_,
+ TimeUntilSend(_, _, _)).WillRepeatedly(
+ testing::Return(QuicTime::Delta::Zero()));
+ }
+
QuicConnectionId connection_id_;
QuicFramer framer_;
- QuicPacketCreator creator_;
+ QuicPacketCreator peer_creator_;
MockEntropyCalculator entropy_calculator_;
MockSendAlgorithm* send_algorithm_;
@@ -1016,7 +1029,7 @@ TEST_P(QuicConnectionTest, PacketsOutOfOrderWithAdditionsAndLeastAwaiting) {
// packet the peer will not retransmit. It indicates this by sending 'least
// awaiting' is 4. The connection should then realize 1 will not be
// retransmitted, and will remove it from the missing list.
- creator_.set_sequence_number(5);
+ peer_creator_.set_sequence_number(5);
QuicAckFrame frame = InitAckFrame(1, 4);
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _));
ProcessAckPacket(&frame);
@@ -1109,7 +1122,7 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSendBadEntropy) {
TimeUntilSend(_, _, _)).WillRepeatedly(
testing::Return(QuicTime::Delta::Zero()));
// Skip a packet and then record an ack.
- creator_.set_sequence_number(2);
+ peer_creator_.set_sequence_number(2);
QuicAckFrame frame = InitAckFrame(0, 3);
ProcessAckPacket(&frame);
}
@@ -1205,7 +1218,7 @@ TEST_P(QuicConnectionTest, LeastUnackedLower) {
SendStreamDataToPeer(1, "eep", 6, !kFin, NULL);
// Start out saying the least unacked is 2.
- creator_.set_sequence_number(5);
+ peer_creator_.set_sequence_number(5);
if (version() > QUIC_VERSION_15) {
QuicStopWaitingFrame frame = InitStopWaitingFrame(2);
ProcessStopWaitingPacket(&frame);
@@ -1216,7 +1229,7 @@ TEST_P(QuicConnectionTest, LeastUnackedLower) {
// Change it to 1, but lower the sequence number to fake out-of-order packets.
// This should be fine.
- creator_.set_sequence_number(1);
+ peer_creator_.set_sequence_number(1);
// The scheduler will not process out of order acks, but all packet processing
// causes the connection to try to write.
EXPECT_CALL(visitor_, OnCanWrite());
@@ -1231,7 +1244,7 @@ TEST_P(QuicConnectionTest, LeastUnackedLower) {
// Now claim it's one, but set the ordering so it was sent "after" the first
// one. This should cause a connection error.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
- creator_.set_sequence_number(7);
+ peer_creator_.set_sequence_number(7);
if (version() > QUIC_VERSION_15) {
EXPECT_CALL(visitor_,
OnConnectionClosed(QUIC_INVALID_STOP_WAITING_DATA, false));
@@ -1277,17 +1290,19 @@ TEST_P(QuicConnectionTest, AckAll) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(1);
- creator_.set_sequence_number(1);
+ peer_creator_.set_sequence_number(1);
QuicAckFrame frame1 = InitAckFrame(0, 1);
ProcessAckPacket(&frame1);
}
TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) {
QuicPacketSequenceNumber last_packet;
+ QuicPacketCreator* creator =
+ QuicConnectionPeer::GetPacketCreator(&connection_);
SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet);
EXPECT_EQ(1u, last_packet);
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
- connection_.options()->send_sequence_number_length);
+ creator->next_sequence_number_length());
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
writer_->header().public_header.sequence_number_length);
@@ -1297,7 +1312,7 @@ TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) {
SendStreamDataToPeer(1, "bar", 3, !kFin, &last_packet);
EXPECT_EQ(2u, last_packet);
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
- connection_.options()->send_sequence_number_length);
+ creator->next_sequence_number_length());
// The 1 packet lag is due to the sequence number length being recalculated in
// QuicConnection after a packet is sent.
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
@@ -1309,7 +1324,7 @@ TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) {
SendStreamDataToPeer(1, "foo", 6, !kFin, &last_packet);
EXPECT_EQ(3u, last_packet);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
- connection_.options()->send_sequence_number_length);
+ creator->next_sequence_number_length());
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
writer_->header().public_header.sequence_number_length);
@@ -1319,7 +1334,7 @@ TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) {
SendStreamDataToPeer(1, "bar", 9, !kFin, &last_packet);
EXPECT_EQ(4u, last_packet);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
- connection_.options()->send_sequence_number_length);
+ creator->next_sequence_number_length());
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
writer_->header().public_header.sequence_number_length);
@@ -1329,52 +1344,51 @@ TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) {
SendStreamDataToPeer(1, "foo", 12, !kFin, &last_packet);
EXPECT_EQ(5u, last_packet);
EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER,
- connection_.options()->send_sequence_number_length);
+ creator->next_sequence_number_length());
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
writer_->header().public_header.sequence_number_length);
}
TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsUnackedDelta) {
QuicPacketSequenceNumber last_packet;
+ QuicPacketCreator* creator =
+ QuicConnectionPeer::GetPacketCreator(&connection_);
SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet);
EXPECT_EQ(1u, last_packet);
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
- connection_.options()->send_sequence_number_length);
+ creator->next_sequence_number_length());
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
writer_->header().public_header.sequence_number_length);
- QuicConnectionPeer::GetPacketCreator(&connection_)->set_sequence_number(100);
+ creator->set_sequence_number(100);
SendStreamDataToPeer(1, "bar", 3, !kFin, &last_packet);
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
- connection_.options()->send_sequence_number_length);
+ creator->next_sequence_number_length());
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
writer_->header().public_header.sequence_number_length);
- QuicConnectionPeer::GetPacketCreator(&connection_)->set_sequence_number(
- 100 * 256);
+ creator->set_sequence_number(100 * 256);
SendStreamDataToPeer(1, "foo", 6, !kFin, &last_packet);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
- connection_.options()->send_sequence_number_length);
+ creator->next_sequence_number_length());
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
writer_->header().public_header.sequence_number_length);
- QuicConnectionPeer::GetPacketCreator(&connection_)->set_sequence_number(
- 100 * 256 * 256);
+ creator->set_sequence_number(100 * 256 * 256);
SendStreamDataToPeer(1, "bar", 9, !kFin, &last_packet);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
- connection_.options()->send_sequence_number_length);
+ creator->next_sequence_number_length());
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
writer_->header().public_header.sequence_number_length);
- QuicConnectionPeer::GetPacketCreator(&connection_)->set_sequence_number(
- 100 * 256 * 256 * 256);
+ creator->set_sequence_number(100 * 256 * 256 * 256);
SendStreamDataToPeer(1, "foo", 12, !kFin, &last_packet);
EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER,
- connection_.options()->send_sequence_number_length);
+ creator->next_sequence_number_length());
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
writer_->header().public_header.sequence_number_length);
}
@@ -1432,18 +1446,21 @@ TEST_P(QuicConnectionTest, BasicSending) {
TEST_P(QuicConnectionTest, FECSending) {
// All packets carry version info till version is negotiated.
+ QuicPacketCreator* creator =
+ QuicConnectionPeer::GetPacketCreator(&connection_);
size_t payload_length;
// GetPacketLengthForOneStream() assumes a stream offset of 0 in determining
// packet length. The size of the offset field in a stream frame is 0 for
- // offset 0, and 2 for non-zero offsets up through 16K. Increase
+ // offset 0, and 2 for non-zero offsets up through 64K. Increase
// max_packet_length by 2 so that subsequent packets containing subsequent
// stream frames with non-zero offets will fit within the packet length.
- connection_.options()->max_packet_length = 2 + GetPacketLengthForOneStream(
+ size_t length = 2 + GetPacketLengthForOneStream(
connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
IN_FEC_GROUP, &payload_length);
+ creator->set_max_packet_length(length);
+
// And send FEC every two packets.
- EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(
- QuicConnectionPeer::GetPacketCreator(&connection_), 2));
+ EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(creator, 2));
// Send 4 data packets and 2 FEC packets.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6);
@@ -1451,25 +1468,28 @@ TEST_P(QuicConnectionTest, FECSending) {
const string payload(payload_length * 4 + 2, 'a');
connection_.SendStreamDataWithString(1, payload, 0, !kFin, NULL);
// Expect the FEC group to be closed after SendStreamDataWithString.
- EXPECT_FALSE(creator_.ShouldSendFec(true));
+ EXPECT_FALSE(creator->ShouldSendFec(true));
+ EXPECT_TRUE(creator->IsFecProtected());
}
TEST_P(QuicConnectionTest, FECQueueing) {
// All packets carry version info till version is negotiated.
size_t payload_length;
- connection_.options()->max_packet_length =
- GetPacketLengthForOneStream(
- connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
- IN_FEC_GROUP, &payload_length);
+ QuicPacketCreator* creator =
+ QuicConnectionPeer::GetPacketCreator(&connection_);
+ size_t length = GetPacketLengthForOneStream(
+ connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
+ IN_FEC_GROUP, &payload_length);
+ creator->set_max_packet_length(length);
// And send FEC every two packets.
- EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(
- QuicConnectionPeer::GetPacketCreator(&connection_), 2));
+ EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(creator, 2));
EXPECT_EQ(0u, connection_.NumQueuedPackets());
BlockOnNextWrite();
const string payload(payload_length, 'a');
connection_.SendStreamDataWithString(1, payload, 0, !kFin, NULL);
- EXPECT_FALSE(creator_.ShouldSendFec(true));
+ EXPECT_FALSE(creator->ShouldSendFec(true));
+ EXPECT_TRUE(creator->IsFecProtected());
// Expect the first data packet and the fec packet to be queued.
EXPECT_EQ(2u, connection_.NumQueuedPackets());
}
@@ -1560,9 +1580,7 @@ TEST_P(QuicConnectionTest, AbandonAllFEC) {
}
TEST_P(QuicConnectionTest, FramePacking) {
- // Block the connection.
- connection_.GetSendAlarm()->Set(
- clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
+ CongestionBlockWrites();
// Send an ack and two stream frames in 1 packet by queueing them.
connection_.SendAck();
@@ -1573,7 +1591,7 @@ TEST_P(QuicConnectionTest, FramePacking) {
&TestConnection::SendStreamData5))));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- // Unblock the connection.
+ CongestionUnblockWrites();
connection_.GetSendAlarm()->Fire();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
@@ -1587,15 +1605,13 @@ TEST_P(QuicConnectionTest, FramePacking) {
EXPECT_EQ(3u, writer_->frame_count());
}
EXPECT_FALSE(writer_->ack_frames().empty());
- EXPECT_EQ(2u, writer_->stream_frames().size());
+ ASSERT_EQ(2u, writer_->stream_frames().size());
EXPECT_EQ(kClientDataStreamId1, writer_->stream_frames()[0].stream_id);
EXPECT_EQ(kClientDataStreamId2, writer_->stream_frames()[1].stream_id);
}
TEST_P(QuicConnectionTest, FramePackingNonCryptoThenCrypto) {
- // Block the connection.
- connection_.GetSendAlarm()->Set(
- clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
+ CongestionBlockWrites();
// Send an ack and two stream frames (one non-crypto, then one crypto) in 2
// packets by queueing them.
@@ -1607,21 +1623,19 @@ TEST_P(QuicConnectionTest, FramePackingNonCryptoThenCrypto) {
&TestConnection::SendCryptoStreamData))));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
- // Unblock the connection.
+ CongestionUnblockWrites();
connection_.GetSendAlarm()->Fire();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
// Parse the last packet and ensure it's the crypto stream frame.
EXPECT_EQ(1u, writer_->frame_count());
- EXPECT_EQ(1u, writer_->stream_frames().size());
+ ASSERT_EQ(1u, writer_->stream_frames().size());
EXPECT_EQ(kCryptoStreamId, writer_->stream_frames()[0].stream_id);
}
TEST_P(QuicConnectionTest, FramePackingCryptoThenNonCrypto) {
- // Block the connection.
- connection_.GetSendAlarm()->Set(
- clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
+ CongestionBlockWrites();
// Send an ack and two stream frames (one crypto, then one non-crypto) in 3
// packets by queueing them.
@@ -1633,28 +1647,23 @@ TEST_P(QuicConnectionTest, FramePackingCryptoThenNonCrypto) {
&TestConnection::SendStreamData3))));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3);
- // Unblock the connection.
+ CongestionUnblockWrites();
connection_.GetSendAlarm()->Fire();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
// Parse the last packet and ensure it's the stream frame from stream 3.
EXPECT_EQ(1u, writer_->frame_count());
- EXPECT_EQ(1u, writer_->stream_frames().size());
+ ASSERT_EQ(1u, writer_->stream_frames().size());
EXPECT_EQ(kClientDataStreamId1, writer_->stream_frames()[0].stream_id);
}
TEST_P(QuicConnectionTest, FramePackingFEC) {
- if (version() < QUIC_VERSION_15) {
- return;
- }
// Enable fec.
EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(
QuicConnectionPeer::GetPacketCreator(&connection_), 6));
- // Block the connection.
- connection_.GetSendAlarm()->Set(
- clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
+ CongestionBlockWrites();
// Send an ack and two stream frames in 1 packet by queueing them.
connection_.SendAck();
@@ -1665,7 +1674,7 @@ TEST_P(QuicConnectionTest, FramePackingFEC) {
&TestConnection::SendStreamData5))));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
- // Unblock the connection.
+ CongestionUnblockWrites();
connection_.GetSendAlarm()->Fire();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
@@ -1690,7 +1699,7 @@ TEST_P(QuicConnectionTest, FramePackingAckResponse) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
// Process an ack to cause the visitor's OnCanWrite to be invoked.
- creator_.set_sequence_number(2);
+ peer_creator_.set_sequence_number(2);
QuicAckFrame ack_one = InitAckFrame(0, 0);
ProcessAckPacket(&ack_one);
@@ -2099,9 +2108,6 @@ TEST_P(QuicConnectionTest, DontLatchUnackedPacket) {
}
TEST_P(QuicConnectionTest, ReviveMissingPacketAfterFecPacket) {
- if (version() < QUIC_VERSION_15) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Don't send missing packet 1.
@@ -2111,9 +2117,6 @@ TEST_P(QuicConnectionTest, ReviveMissingPacketAfterFecPacket) {
}
TEST_P(QuicConnectionTest, ReviveMissingPacketWithVaryingSeqNumLengths) {
- if (version() < QUIC_VERSION_15) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Set up a debug visitor to the connection.
@@ -2143,9 +2146,6 @@ TEST_P(QuicConnectionTest, ReviveMissingPacketWithVaryingSeqNumLengths) {
}
TEST_P(QuicConnectionTest, ReviveMissingPacketWithVaryingConnectionIdLengths) {
- if (version() < QUIC_VERSION_15) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Set up a debug visitor to the connection.
@@ -2175,9 +2175,6 @@ TEST_P(QuicConnectionTest, ReviveMissingPacketWithVaryingConnectionIdLengths) {
}
TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacketThenFecPacket) {
- if (version() < QUIC_VERSION_15) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessFecProtectedPacket(1, false, kEntropyFlag);
@@ -2188,9 +2185,6 @@ TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacketThenFecPacket) {
}
TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacketsThenFecPacket) {
- if (version() < QUIC_VERSION_15) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessFecProtectedPacket(1, false, !kEntropyFlag);
@@ -2203,9 +2197,6 @@ TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacketsThenFecPacket) {
}
TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacket) {
- if (version() < QUIC_VERSION_15) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Don't send missing packet 1.
@@ -2217,9 +2208,6 @@ TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacket) {
}
TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPackets) {
- if (version() < QUIC_VERSION_15) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessFecProtectedPacket(1, false, !kEntropyFlag);
@@ -2548,7 +2536,7 @@ TEST_P(QuicConnectionTest, CloseFecGroup) {
ASSERT_EQ(1u, connection_.NumFecGroups());
// Now send non-fec protected ack packet and close the group.
- creator_.set_sequence_number(4);
+ peer_creator_.set_sequence_number(4);
if (version() > QUIC_VERSION_15) {
QuicStopWaitingFrame frame = InitStopWaitingFrame(5);
ProcessStopWaitingPacket(&frame);
@@ -2585,9 +2573,6 @@ TEST_P(QuicConnectionTest, UpdateQuicCongestionFeedbackFrame) {
}
TEST_P(QuicConnectionTest, DontUpdateQuicCongestionFeedbackFrameForRevived) {
- if (version() < QUIC_VERSION_15) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
SendAckPacketToPeer();
// Process an FEC packet, and revive the missing data packet
@@ -2759,8 +2744,7 @@ TEST_P(QuicConnectionTest, SendSchedulerDelayThenSend) {
}
TEST_P(QuicConnectionTest, SendSchedulerDelayThenRetransmit) {
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
- .WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
+ CongestionUnblockWrites();
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _));
connection_.SendStreamDataWithString(3, "foo", 0, !kFin, NULL);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
@@ -2769,17 +2753,13 @@ TEST_P(QuicConnectionTest, SendSchedulerDelayThenRetransmit) {
// Test that if we send a retransmit with a delay, it ends up queued in the
// sent packet manager, but not yet serialized.
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
- EXPECT_CALL(*send_algorithm_,
- TimeUntilSend(_, _, _)).WillOnce(
- testing::Return(QuicTime::Delta::FromMicroseconds(1)));
+ CongestionBlockWrites();
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
// Advance the clock to fire the alarm, and configure the scheduler
// to permit the packet to be sent.
- EXPECT_CALL(*send_algorithm_,
- TimeUntilSend(_, _, _)).Times(3).
- WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
+ CongestionUnblockWrites();
// Ensure the scheduler is notified this is a retransmit.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
@@ -2854,9 +2834,7 @@ TEST_P(QuicConnectionTest, SendSchedulerDelayThenOnCanWrite) {
// TODO(ianswett): This test is unrealistic, because we would not serialize
// new data if the send algorithm said not to.
QuicPacket* packet = ConstructDataPacket(1, 0, !kEntropyFlag);
- EXPECT_CALL(*send_algorithm_,
- TimeUntilSend(_, _, _)).WillOnce(
- testing::Return(QuicTime::Delta::FromMicroseconds(10)));
+ CongestionBlockWrites();
connection_.SendPacket(
ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -2870,10 +2848,11 @@ TEST_P(QuicConnectionTest, SendSchedulerDelayThenOnCanWrite) {
TEST_P(QuicConnectionTest, TestQueueLimitsOnSendStreamData) {
// All packets carry version info till version is negotiated.
size_t payload_length;
- connection_.options()->max_packet_length =
- GetPacketLengthForOneStream(
- connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
- NOT_IN_FEC_GROUP, &payload_length);
+ size_t length = GetPacketLengthForOneStream(
+ connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
+ NOT_IN_FEC_GROUP, &payload_length);
+ QuicConnectionPeer::GetPacketCreator(&connection_)->set_max_packet_length(
+ length);
// Queue the first packet.
EXPECT_CALL(*send_algorithm_,
@@ -2894,9 +2873,11 @@ TEST_P(QuicConnectionTest, LoopThroughSendingPackets) {
// offset 0, and 2 for non-zero offsets up through 16K. Increase
// max_packet_length by 2 so that subsequent packets containing subsequent
// stream frames with non-zero offets will fit within the packet length.
- connection_.options()->max_packet_length = 2 + GetPacketLengthForOneStream(
+ size_t length = 2 + GetPacketLengthForOneStream(
connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
NOT_IN_FEC_GROUP, &payload_length);
+ QuicConnectionPeer::GetPacketCreator(&connection_)->set_max_packet_length(
+ length);
// Queue the first packet.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(7);
@@ -3160,7 +3141,7 @@ TEST_P(QuicConnectionTest, InvalidPacket) {
TEST_P(QuicConnectionTest, MissingPacketsBeforeLeastUnacked) {
// Set the sequence number of the ack packet to be least unacked (4).
- creator_.set_sequence_number(3);
+ peer_creator_.set_sequence_number(3);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
if (version() > QUIC_VERSION_15) {
QuicStopWaitingFrame frame = InitStopWaitingFrame(4);
@@ -3183,9 +3164,6 @@ TEST_P(QuicConnectionTest, ReceivedEntropyHashCalculation) {
}
TEST_P(QuicConnectionTest, ReceivedEntropyHashCalculationHalfFEC) {
- if (version() < QUIC_VERSION_15) {
- return;
- }
// FEC packets should not change the entropy hash calculation.
EXPECT_CALL(visitor_, OnStreamFrames(_)).Times(AtLeast(1));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -3204,7 +3182,7 @@ TEST_P(QuicConnectionTest, UpdateEntropyForReceivedPackets) {
ProcessDataPacket(4, 1, !kEntropyFlag);
EXPECT_EQ(34u, outgoing_ack()->received_info.entropy_hash);
// Make 4th packet my least unacked, and update entropy for 2, 3 packets.
- creator_.set_sequence_number(5);
+ peer_creator_.set_sequence_number(5);
QuicPacketEntropyHash six_packet_entropy_hash = 0;
QuicPacketEntropyHash kRandomEntropyHash = 129u;
if (version() > QUIC_VERSION_15) {
@@ -3232,7 +3210,7 @@ TEST_P(QuicConnectionTest, UpdateEntropyHashUptoCurrentPacket) {
ProcessDataPacket(5, 1, !kEntropyFlag);
ProcessDataPacket(22, 1, kEntropyFlag);
EXPECT_EQ(66u, outgoing_ack()->received_info.entropy_hash);
- creator_.set_sequence_number(22);
+ peer_creator_.set_sequence_number(22);
QuicPacketEntropyHash kRandomEntropyHash = 85u;
// Current packet is the least unacked packet.
QuicPacketEntropyHash ack_entropy_hash;
@@ -3278,7 +3256,7 @@ TEST_P(QuicConnectionTest, EntropyCalculationForTruncatedAck) {
}
TEST_P(QuicConnectionTest, CheckSentEntropyHash) {
- creator_.set_sequence_number(1);
+ peer_creator_.set_sequence_number(1);
SequenceNumberSet missing_packets;
QuicPacketEntropyHash entropy_hash = 0;
QuicPacketSequenceNumber max_sequence_number = 51;
@@ -3323,7 +3301,7 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacket) {
QuicFrame frame(&frame1_);
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header, frames).packet);
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
@@ -3361,7 +3339,7 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacketSocketBlocked) {
QuicFrame frame(&frame1_);
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header, frames).packet);
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
@@ -3406,7 +3384,7 @@ TEST_P(QuicConnectionTest,
QuicFrame frame(&frame1_);
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header, frames).packet);
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
@@ -3451,7 +3429,7 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
QuicFrame frame(&frame1_);
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header, frames).packet);
encrypted.reset(framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
EXPECT_CALL(visitor_, OnStreamFrames(_)).Times(1);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -3532,9 +3510,6 @@ TEST_P(QuicConnectionTest, CheckSendStats) {
}
TEST_P(QuicConnectionTest, CheckReceiveStats) {
- if (version() < QUIC_VERSION_15) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
size_t received_bytes = 0;
@@ -3596,7 +3571,7 @@ TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) {
frames.push_back(stream_frame);
frames.push_back(close_frame);
scoped_ptr<QuicPacket> packet(
- framer_.BuildUnsizedDataPacket(header_, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header_, frames).packet);
EXPECT_TRUE(NULL != packet.get());
scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(
ENCRYPTION_NONE, 1, *packet));
@@ -3886,7 +3861,7 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackAfterFECRecovery) {
ack_header.fec_group = 1;
QuicPacket* packet =
- framer_.BuildUnsizedDataPacket(ack_header, frames).packet;
+ BuildUnsizedDataPacket(&framer_, ack_header, frames).packet;
// Take the packet which contains the ACK frame, and construct and deliver an
// FEC packet which allows the ACK packet to be recovered.
@@ -3894,7 +3869,7 @@ TEST_P(QuicConnectionTest, AckNotifierCallbackAfterFECRecovery) {
}
class MockQuicConnectionDebugVisitor
- : public QuicConnectionDebugVisitorInterface {
+ : public QuicConnectionDebugVisitor {
public:
MOCK_METHOD1(OnFrameAddedToPacket,
void(const QuicFrame&));
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
index d684a49..9fa9367 100644
--- a/net/quic/quic_crypto_client_stream.cc
+++ b/net/quic/quic_crypto_client_stream.cc
@@ -132,7 +132,7 @@ void QuicCryptoClientStream::DoHandshakeLoop(
// Pad the inchoate client hello to fill up a packet.
const size_t kFramingOverhead = 50; // A rough estimate.
const size_t max_packet_size =
- session()->connection()->options()->max_packet_length;
+ session()->connection()->max_packet_length();
if (max_packet_size <= kFramingOverhead) {
DLOG(DFATAL) << "max_packet_length (" << max_packet_size
<< ") has no room for framing overhead.";
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
index 14ff3fd..3515d32 100644
--- a/net/quic/quic_crypto_client_stream_test.cc
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -93,7 +93,7 @@ TEST_F(QuicCryptoClientStreamTest, NegotiatedParameters) {
const QuicConfig* config = session_->config();
EXPECT_EQ(FLAGS_enable_quic_pacing ? kPACE : kQBIC,
- config->congestion_control());
+ config->congestion_feedback());
EXPECT_EQ(kDefaultTimeoutSecs,
config->idle_connection_state_lifetime().ToSeconds());
EXPECT_EQ(kDefaultMaxStreamsPerConnection,
diff --git a/net/quic/quic_flow_controller.cc b/net/quic/quic_flow_controller.cc
index 412f250..a469fd5 100644
--- a/net/quic/quic_flow_controller.cc
+++ b/net/quic/quic_flow_controller.cc
@@ -23,7 +23,7 @@ QuicFlowController::QuicFlowController(QuicVersion version,
is_enabled_(true),
is_server_(is_server),
bytes_consumed_(0),
- bytes_buffered_(0),
+ highest_received_byte_offset_(0),
bytes_sent_(0),
send_window_offset_(send_window_offset),
receive_window_offset_(receive_window_offset),
@@ -51,29 +51,21 @@ void QuicFlowController::AddBytesConsumed(uint64 bytes_consumed) {
DVLOG(1) << ENDPOINT << "Stream " << id_ << " consumed: " << bytes_consumed_;
}
-void QuicFlowController::AddBytesBuffered(uint64 bytes_buffered) {
+bool QuicFlowController::UpdateHighestReceivedOffset(uint64 new_offset) {
if (!IsEnabled()) {
- return;
- }
-
- bytes_buffered_ += bytes_buffered;
- DVLOG(1) << ENDPOINT << "Stream " << id_ << " buffered: " << bytes_buffered_;
-}
-
-void QuicFlowController::RemoveBytesBuffered(uint64 bytes_buffered) {
- if (!IsEnabled()) {
- return;
+ return false;
}
- if (bytes_buffered_ < bytes_buffered) {
- LOG(DFATAL) << "Trying to remove " << bytes_buffered << " bytes, when only "
- << bytes_buffered_ << " bytes are buffered";
- bytes_buffered_ = 0;
- return;
+ // Only update if offset has increased.
+ if (new_offset <= highest_received_byte_offset_) {
+ return false;
}
- bytes_buffered_ -= bytes_buffered;
- DVLOG(1) << ENDPOINT << "Stream " << id_ << " buffered: " << bytes_buffered_;
+ DVLOG(1) << ENDPOINT << "Stream " << id_
+ << " highest byte offset increased from: "
+ << highest_received_byte_offset_ << " to " << new_offset;
+ highest_received_byte_offset_ = new_offset;
+ return true;
}
void QuicFlowController::AddBytesSent(uint64 bytes_sent) {
@@ -98,12 +90,12 @@ bool QuicFlowController::FlowControlViolation() {
return false;
}
- if (receive_window_offset_ < TotalReceivedBytes()) {
- LOG(ERROR)
- << ENDPOINT << "Flow control violation on stream " << id_
- << ", receive window: " << receive_window_offset_
- << ", bytes received: " << TotalReceivedBytes();
-
+ if (highest_received_byte_offset_ > receive_window_offset_) {
+ LOG(ERROR) << ENDPOINT << "Flow control violation on stream "
+ << id_ << ", receive window offset: "
+ << receive_window_offset_
+ << ", highest received byte offset: "
+ << highest_received_byte_offset_;
return true;
}
return false;
@@ -201,8 +193,4 @@ uint64 QuicFlowController::SendWindowSize() const {
return send_window_offset_ - bytes_sent_;
}
-uint64 QuicFlowController::TotalReceivedBytes() const {
- return bytes_consumed_ + bytes_buffered_;
-}
-
} // namespace net
diff --git a/net/quic/quic_flow_controller.h b/net/quic/quic_flow_controller.h
index 3125b81..596ef1a 100644
--- a/net/quic/quic_flow_controller.h
+++ b/net/quic/quic_flow_controller.h
@@ -33,11 +33,11 @@ class NET_EXPORT_PRIVATE QuicFlowController {
uint64 max_receive_window);
~QuicFlowController() {}
- // Called when bytes are received from the peer, and buffered.
- void AddBytesBuffered(uint64 bytes_buffered);
-
- // Called when bytes currently buffered locally, are removed from the buffer.
- void RemoveBytesBuffered(uint64 bytes_buffered);
+ // Called when we see a new highest received byte offset from the peer, either
+ // via a data frame or a RST.
+ // Returns true if this call changes highest_received_byte_offset_, and false
+ // in the case where |new_offset| is <= highest_received_byte_offset_.
+ bool UpdateHighestReceivedOffset(uint64 new_offset);
// Called when bytes received from the peer are consumed locally.
void AddBytesConsumed(uint64 bytes_consumed);
@@ -71,12 +71,13 @@ class NET_EXPORT_PRIVATE QuicFlowController {
// Returns true if flow control receive limits have been violated by the peer.
bool FlowControlViolation();
+ uint64 highest_received_byte_offset() const {
+ return highest_received_byte_offset_;
+ }
+
private:
friend class test::QuicFlowControllerPeer;
- // Total received bytes is the sum of bytes buffered, and bytes consumed.
- uint64 TotalReceivedBytes() const;
-
// ID of stream this flow controller belongs to. This can be 0 if this is a
// connection level flow controller.
QuicStreamId id_;
@@ -91,8 +92,9 @@ class NET_EXPORT_PRIVATE QuicFlowController {
// locally.
uint64 bytes_consumed_;
- // Tracks number of bytes received from the peer, and buffered locally.
- uint64 bytes_buffered_;
+ // The highest byte offset we have seen from the peer. This could be the
+ // highest offset in a data frame, or a final value in a RST.
+ uint64 highest_received_byte_offset_;
// Tracks number of bytes sent to the peer.
uint64 bytes_sent_;
diff --git a/net/quic/quic_flow_controller_test.cc b/net/quic/quic_flow_controller_test.cc
index f0bf629..7ef9bb4 100644
--- a/net/quic/quic_flow_controller_test.cc
+++ b/net/quic/quic_flow_controller_test.cc
@@ -97,13 +97,13 @@ TEST_F(QuicFlowControllerTest, ReceivingBytes) {
EXPECT_FALSE(flow_controller_->FlowControlViolation());
// Buffer some bytes, not enough to fill window.
- flow_controller_->AddBytesBuffered(receive_window_ / 2);
+ EXPECT_TRUE(
+ flow_controller_->UpdateHighestReceivedOffset(1 + receive_window_ / 2));
EXPECT_FALSE(flow_controller_->FlowControlViolation());
- EXPECT_EQ(receive_window_ / 2,
+ EXPECT_EQ((receive_window_ / 2) - 1,
QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
// Consume enough bytes to send a WINDOW_UPDATE frame.
- flow_controller_->RemoveBytesBuffered(receive_window_ / 2);
flow_controller_->AddBytesConsumed(1 + receive_window_ / 2);
EXPECT_FALSE(flow_controller_->FlowControlViolation());
EXPECT_EQ((receive_window_ / 2) - 1,
@@ -132,8 +132,7 @@ TEST_F(QuicFlowControllerTest,
flow_controller_.get()));
flow_controller_->AddBytesSent(123);
flow_controller_->AddBytesConsumed(456);
- flow_controller_->AddBytesBuffered(789);
- flow_controller_->RemoveBytesBuffered(321);
+ flow_controller_->UpdateHighestReceivedOffset(789);
EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
EXPECT_EQ(send_window_,
QuicFlowControllerPeer::SendWindowOffset(flow_controller_.get()));
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index 8ff2ee7..e44bd2d 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -332,26 +332,6 @@ QuicPacketEntropyHash QuicFramer::GetPacketEntropyHash(
return header.entropy_flag << (header.packet_sequence_number % 8);
}
-// Test only.
-SerializedPacket QuicFramer::BuildUnsizedDataPacket(
- const QuicPacketHeader& header,
- const QuicFrames& frames) {
- const size_t max_plaintext_size = GetMaxPlaintextSize(kMaxPacketSize);
- size_t packet_size = GetPacketHeaderSize(header);
- for (size_t i = 0; i < frames.size(); ++i) {
- DCHECK_LE(packet_size, max_plaintext_size);
- bool first_frame = i == 0;
- bool last_frame = i == frames.size() - 1;
- const size_t frame_size = GetSerializedFrameLength(
- frames[i], max_plaintext_size - packet_size, first_frame, last_frame,
- header.is_in_fec_group,
- header.public_header.sequence_number_length);
- DCHECK(frame_size);
- packet_size += frame_size;
- }
- return BuildDataPacket(header, frames, packet_size);
-}
-
SerializedPacket QuicFramer::BuildDataPacket(
const QuicPacketHeader& header,
const QuicFrames& frames,
diff --git a/net/quic/quic_framer.h b/net/quic/quic_framer.h
index a7e8a08..e947eb4 100644
--- a/net/quic/quic_framer.h
+++ b/net/quic/quic_framer.h
@@ -306,13 +306,6 @@ class NET_EXPORT_PRIVATE QuicFramer {
QuicSequenceNumberLength sequence_number_length);
// Returns a SerializedPacket whose |packet| member is owned by the caller,
- // and is populated with the fields in |header| and |frames|, or is NULL if
- // the packet could not be created.
- // TODO(ianswett): Used for testing only.
- SerializedPacket BuildUnsizedDataPacket(const QuicPacketHeader& header,
- const QuicFrames& frames);
-
- // Returns a SerializedPacket whose |packet| member is owned by the caller,
// is created from the first |num_frames| frames, or is NULL if the packet
// could not be created. The packet must be of size |packet_size|.
SerializedPacket BuildDataPacket(const QuicPacketHeader& header,
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc
index 5dd3e35..fd206e1 100644
--- a/net/quic/quic_framer_test.cc
+++ b/net/quic/quic_framer_test.cc
@@ -494,6 +494,11 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
<< " wire_sequence_number: " << wire_sequence_number;
}
+ QuicPacket* BuildDataPacket(const QuicPacketHeader& header,
+ const QuicFrames& frames) {
+ return BuildUnsizedDataPacket(&framer_, header, frames).packet;
+ }
+
test::TestEncrypter* encrypter_;
test::TestDecrypter* decrypter_;
QuicVersion version_;
@@ -2148,8 +2153,7 @@ TEST_P(QuicFramerTest, AckFrameNoNacks) {
// Verify that the packet re-serializes identically.
QuicFrames frames;
frames.push_back(QuicFrame(frame));
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -2210,8 +2214,7 @@ TEST_P(QuicFramerTest, AckFrameNoNacks15) {
// Verify that the packet re-serializes identically.
QuicFrames frames;
frames.push_back(QuicFrame(frame));
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -2285,8 +2288,7 @@ TEST_P(QuicFramerTest, AckFrame500Nacks) {
// Verify that the packet re-serializes identically.
QuicFrames frames;
frames.push_back(QuicFrame(frame));
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -2367,8 +2369,7 @@ TEST_P(QuicFramerTest, AckFrame500Nacks15) {
// Verify that the packet re-serializes identically.
QuicFrames frames;
frames.push_back(QuicFrame(frame));
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3245,8 +3246,7 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3292,8 +3292,7 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
PACKET_4BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3339,8 +3338,7 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
PACKET_2BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3386,8 +3384,7 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3440,8 +3437,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
'r', 'l', 'd', '!',
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3496,8 +3492,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketInFecGroup) {
'r', 'l', 'd', '!',
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3552,8 +3547,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
};
QuicFramerPeer::SetIsServer(&framer_, false);
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3642,8 +3636,7 @@ TEST_P(QuicFramerTest, BuildAckFramePacket) {
0x00,
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3713,8 +3706,7 @@ TEST_P(QuicFramerTest, BuildAckFramePacket15) {
0x00,
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3946,8 +3938,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketTCP) {
0x03, 0x04,
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -4016,8 +4007,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInterArrival) {
0x02, 0x00, 0x00, 0x00,
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -4066,8 +4056,7 @@ TEST_P(QuicFramerTest, BuildStopWaitingPacket) {
0x00, 0x00,
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -4113,8 +4102,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketFixRate) {
0x01, 0x02, 0x03, 0x04,
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -4141,7 +4129,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInvalidFeedback) {
scoped_ptr<QuicPacket> data;
EXPECT_DFATAL(
- data.reset(framer_.BuildUnsizedDataPacket(header, frames).packet),
+ data.reset(BuildDataPacket(header, frames)),
"AppendCongestionFeedbackFrame failed");
ASSERT_TRUE(data == NULL);
}
@@ -4195,8 +4183,7 @@ TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
QuicFrames frames;
frames.push_back(QuicFrame(&rst_frame));
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -4246,8 +4233,7 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) {
'n',
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -4300,8 +4286,7 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) {
'n',
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
@@ -4347,8 +4332,7 @@ TEST_P(QuicFramerTest, BuildWindowUpdatePacket) {
0x44, 0x33, 0x22, 0x11,
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet", data->data(),
@@ -4390,8 +4374,7 @@ TEST_P(QuicFramerTest, BuildBlockedPacket) {
0x04, 0x03, 0x02, 0x01,
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet", data->data(),
@@ -4431,8 +4414,7 @@ TEST_P(QuicFramerTest, BuildPingPacket) {
};
if (version_ > QUIC_VERSION_17) {
- scoped_ptr<QuicPacket> data(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet", data->data(),
@@ -4441,7 +4423,7 @@ TEST_P(QuicFramerTest, BuildPingPacket) {
} else {
string expected_error =
"Attempt to add a PingFrame in " + QuicVersionToString(version_);
- EXPECT_DFATAL(framer_.BuildUnsizedDataPacket(header, frames),
+ EXPECT_DFATAL(BuildDataPacket(header, frames),
expected_error);
return;
}
@@ -4770,8 +4752,7 @@ TEST_P(QuicFramerTest, Truncation15) {
QuicFrames frames;
frames.push_back(frame);
- scoped_ptr<QuicPacket> raw_ack_packet(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames));
ASSERT_TRUE(raw_ack_packet != NULL);
scoped_ptr<QuicEncryptedPacket> ack_packet(
@@ -4819,8 +4800,7 @@ TEST_P(QuicFramerTest, CleanTruncation) {
QuicFrames frames;
frames.push_back(frame);
- scoped_ptr<QuicPacket> raw_ack_packet(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames));
ASSERT_TRUE(raw_ack_packet != NULL);
scoped_ptr<QuicEncryptedPacket> ack_packet(
@@ -4838,8 +4818,7 @@ TEST_P(QuicFramerTest, CleanTruncation) {
frames.push_back(frame);
size_t original_raw_length = raw_ack_packet->length();
- raw_ack_packet.reset(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ raw_ack_packet.reset(BuildDataPacket(header, frames));
ASSERT_TRUE(raw_ack_packet != NULL);
EXPECT_EQ(original_raw_length, raw_ack_packet->length());
ASSERT_TRUE(raw_ack_packet != NULL);
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc
index 4b64ae5..f7d2d14 100644
--- a/net/quic/quic_packet_creator.cc
+++ b/net/quic/quic_packet_creator.cc
@@ -68,7 +68,11 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id,
fec_group_number_(0),
is_server_(is_server),
send_version_in_packet_(!is_server),
- sequence_number_length_(options_.send_sequence_number_length),
+ max_packet_length_(kDefaultMaxPacketSize),
+ max_packets_per_fec_group_(0),
+ connection_id_length_(PACKET_8BYTE_CONNECTION_ID),
+ next_sequence_number_length_(PACKET_1BYTE_SEQUENCE_NUMBER),
+ sequence_number_length_(next_sequence_number_length_),
packet_size_(0) {
framer_->set_fec_builder(this);
}
@@ -87,7 +91,7 @@ void QuicPacketCreator::OnBuiltFecProtectedPayload(
bool QuicPacketCreator::ShouldSendFec(bool force_close) const {
return fec_group_.get() != NULL && fec_group_->NumReceivedPackets() > 0 &&
(force_close || fec_group_->NumReceivedPackets() >=
- options_.max_packets_per_fec_group);
+ max_packets_per_fec_group_);
}
void QuicPacketCreator::StartFecProtectingPackets() {
@@ -123,18 +127,7 @@ bool QuicPacketCreator::IsFecProtected() const {
}
bool QuicPacketCreator::IsFecEnabled() const {
- return options_.max_packets_per_fec_group > 0;
-}
-
-size_t QuicPacketCreator::max_packets_per_fec_group() const {
- return options_.max_packets_per_fec_group;
-}
-
-void QuicPacketCreator::set_max_packets_per_fec_group(
- size_t max_packets_per_fec_group) {
- // To turn off FEC protection, use StopFecProtectingPackets().
- DCHECK_NE(0u, max_packets_per_fec_group);
- options_.max_packets_per_fec_group = max_packets_per_fec_group;
+ return max_packets_per_fec_group_ > 0;
}
InFecGroup QuicPacketCreator::MaybeUpdateLengthsAndStartFec() {
@@ -147,8 +140,9 @@ InFecGroup QuicPacketCreator::MaybeUpdateLengthsAndStartFec() {
// Don't change creator state if there are frames queued.
return fec_group_.get() == NULL ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
}
- // TODO(jri): Add max_packet_length and send_connection_id_length here too.
- sequence_number_length_ = options_.send_sequence_number_length;
+
+ // Update sequence number length only on packet and FEC group boundaries.
+ sequence_number_length_ = next_sequence_number_length_;
if (!should_fec_protect_) {
return NOT_IN_FEC_GROUP;
@@ -179,12 +173,12 @@ void QuicPacketCreator::UpdateSequenceNumberLength(
// Since the packet creator will not change sequence number length mid FEC
// group, include the size of an FEC group to be safe.
const QuicPacketSequenceNumber current_delta =
- options_.max_packets_per_fec_group + sequence_number_ + 1
+ max_packets_per_fec_group_ + sequence_number_ + 1
- least_packet_awaited_by_peer;
const uint64 congestion_window_packets =
- congestion_window / options_.max_packet_length;
+ congestion_window / max_packet_length_;
const uint64 delta = max(current_delta, congestion_window_packets);
- options_.send_sequence_number_length =
+ next_sequence_number_length_ =
QuicFramer::GetMinSequenceNumberLength(delta * 4);
}
@@ -219,8 +213,7 @@ size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
QuicStreamOffset offset,
bool fin,
QuicFrame* frame) {
- DCHECK_GT(options_.max_packet_length,
- StreamFramePacketOverhead(
+ DCHECK_GT(max_packet_length_, StreamFramePacketOverhead(
framer_->version(), PACKET_8BYTE_CONNECTION_ID, kIncludeVersion,
PACKET_6BYTE_SEQUENCE_NUMBER, offset, IN_FEC_GROUP));
@@ -277,19 +270,19 @@ SerializedPacket QuicPacketCreator::ReserializeAllFrames(
QuicSequenceNumberLength original_length) {
DCHECK(fec_group_.get() == NULL);
const QuicSequenceNumberLength saved_length = sequence_number_length_;
- const QuicSequenceNumberLength saved_options_length =
- options_.send_sequence_number_length;
+ const QuicSequenceNumberLength saved_next_length =
+ next_sequence_number_length_;
const bool saved_should_fec_protect = should_fec_protect_;
// Temporarily set the sequence number length and stop FEC protection.
sequence_number_length_ = original_length;
- options_.send_sequence_number_length = original_length;
+ next_sequence_number_length_ = original_length;
should_fec_protect_ = false;
// Serialize the packet and restore the FEC and sequence number length state.
SerializedPacket serialized_packet = SerializeAllFrames(frames);
sequence_number_length_ = saved_length;
- options_.send_sequence_number_length = saved_options_length;
+ next_sequence_number_length_ = saved_next_length;
should_fec_protect_ = saved_should_fec_protect;
return serialized_packet;
@@ -330,26 +323,23 @@ size_t QuicPacketCreator::ExpansionOnNewFrame() const {
size_t QuicPacketCreator::BytesFree() const {
const size_t max_plaintext_size =
- framer_->GetMaxPlaintextSize(options_.max_packet_length);
+ framer_->GetMaxPlaintextSize(max_packet_length_);
DCHECK_GE(max_plaintext_size, PacketSize());
return max_plaintext_size - min(max_plaintext_size, PacketSize()
+ ExpansionOnNewFrame());
}
size_t QuicPacketCreator::PacketSize() const {
- if (queued_frames_.empty()) {
- // Only adjust the sequence number length when the FEC group is not open,
- // to ensure no packets in a group are too large.
- if (fec_group_.get() == NULL ||
- fec_group_->NumReceivedPackets() == 0) {
- sequence_number_length_ = options_.send_sequence_number_length;
- }
- packet_size_ = GetPacketHeaderSize(options_.send_connection_id_length,
- send_version_in_packet_,
- sequence_number_length_,
- should_fec_protect_ ? IN_FEC_GROUP :
- NOT_IN_FEC_GROUP);
+ if (!queued_frames_.empty()) {
+ return packet_size_;
}
+ if (fec_group_.get() == NULL) {
+ // Update sequence number length on packet and FEC boundary.
+ sequence_number_length_ = next_sequence_number_length_;
+ }
+ packet_size_ = GetPacketHeaderSize(
+ connection_id_length_, send_version_in_packet_, sequence_number_length_,
+ should_fec_protect_ ? IN_FEC_GROUP : NOT_IN_FEC_GROUP);
return packet_size_;
}
@@ -367,7 +357,7 @@ SerializedPacket QuicPacketCreator::SerializePacket() {
MaybeAddPadding();
size_t max_plaintext_size =
- framer_->GetMaxPlaintextSize(options_.max_packet_length);
+ framer_->GetMaxPlaintextSize(max_packet_length_);
DCHECK_GE(max_plaintext_size, packet_size_);
// ACK Frames will be truncated only if they're the only frame in the packet,
// and if packet_size_ was set to max_plaintext_size. If truncation occurred,
@@ -384,7 +374,6 @@ SerializedPacket QuicPacketCreator::SerializePacket() {
if (!possibly_truncated) {
DCHECK_EQ(packet_size_, serialized.packet->length());
}
-
packet_size_ = 0;
queued_frames_.clear();
serialized.retransmittable_frames = queued_retransmittable_frames_.release();
@@ -409,7 +398,7 @@ SerializedPacket QuicPacketCreator::SerializeFec() {
packet_size_ = 0;
LOG_IF(DFATAL, !serialized.packet)
<< "Failed to serialize fec packet for group:" << fec_data.fec_group;
- DCHECK_GE(options_.max_packet_length, serialized.packet->length());
+ DCHECK_GE(max_packet_length_, serialized.packet->length());
return serialized;
}
@@ -431,7 +420,7 @@ QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket(
QuicEncryptedPacket* encrypted =
framer_->BuildVersionNegotiationPacket(header, supported_versions);
DCHECK(encrypted);
- DCHECK_GE(options_.max_packet_length, encrypted->length());
+ DCHECK_GE(max_packet_length_, encrypted->length());
return encrypted;
}
diff --git a/net/quic/quic_packet_creator.h b/net/quic/quic_packet_creator.h
index 36ab5df..0e19887 100644
--- a/net/quic/quic_packet_creator.h
+++ b/net/quic/quic_packet_creator.h
@@ -29,22 +29,6 @@ class QuicRandomBoolSource;
class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
public:
- // Options for controlling how packets are created.
- struct Options {
- Options()
- : max_packet_length(kDefaultMaxPacketSize),
- max_packets_per_fec_group(0),
- send_connection_id_length(PACKET_8BYTE_CONNECTION_ID),
- send_sequence_number_length(PACKET_1BYTE_SEQUENCE_NUMBER) {}
-
- size_t max_packet_length;
- // 0 indicates fec is disabled.
- size_t max_packets_per_fec_group;
- // Length of connection_id to send over the wire.
- QuicConnectionIdLength send_connection_id_length;
- QuicSequenceNumberLength send_sequence_number_length;
- };
-
// QuicRandom* required for packet entropy.
QuicPacketCreator(QuicConnectionId connection_id,
QuicFramer* framer,
@@ -63,21 +47,15 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
void StartFecProtectingPackets();
// Turn off FEC protection for subsequently created packets. If the creator
- // has any open fec group, call will fail. It is the caller's responsibility
+ // has any open FEC group, call will fail. It is the caller's responsibility
// to flush out FEC packets in generation, and to verify with ShouldSendFec()
// that there is no open FEC group.
void StopFecProtectingPackets();
// Checks if it's time to send an FEC packet. |force_close| forces this to
- // return true if an fec group is open.
+ // return true if an FEC group is open.
bool ShouldSendFec(bool force_close) const;
- // Returns current max number of packets covered by an FEC group.
- size_t max_packets_per_fec_group() const;
-
- // Sets creator's max number of packets covered by an FEC group.
- void set_max_packets_per_fec_group(size_t max_packets_per_fec_group);
-
// Makes the framer not serialize the protocol version in sent packets.
void StopSendingVersion();
@@ -213,8 +191,39 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
sequence_number_ = s;
}
- Options* options() {
- return &options_;
+ QuicConnectionIdLength connection_id_length() const {
+ return connection_id_length_;
+ }
+
+ QuicSequenceNumberLength next_sequence_number_length() const {
+ return next_sequence_number_length_;
+ }
+
+ void set_next_sequence_number_length(QuicSequenceNumberLength length) {
+ next_sequence_number_length_ = length;
+ }
+
+ size_t max_packet_length() const {
+ return max_packet_length_;
+ }
+
+ void set_max_packet_length(size_t length) {
+ // |max_packet_length_| should not be changed mid-packet or mid-FEC group.
+ DCHECK(fec_group_.get() == NULL && queued_frames_.empty());
+ max_packet_length_ = length;
+ }
+
+ // Returns current max number of packets covered by an FEC group.
+ size_t max_packets_per_fec_group() const {
+ return max_packets_per_fec_group_;
+ }
+
+ // Sets creator's max number of packets covered by an FEC group.
+ void set_max_packets_per_fec_group(
+ size_t max_packets_per_fec_group) {
+ // To turn off FEC protection, use StopFecProtectingPackets().
+ DCHECK_NE(0u, max_packets_per_fec_group);
+ max_packets_per_fec_group_ = max_packets_per_fec_group;
}
private:
@@ -222,9 +231,12 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
static bool ShouldRetransmit(const QuicFrame& frame);
- // Updates sequence number length on a packet or FEC group boundary.
- // Also starts an FEC group if FEC protection is on and there is not already
- // an FEC group open.
+ // Updates sequence number and max packet lengths on a packet or FEC group
+ // boundary.
+ void MaybeUpdateLengths();
+
+ // Updates lengths and also starts an FEC group if FEC protection is on and
+ // there is not already an FEC group open.
InFecGroup MaybeUpdateLengthsAndStartFec();
void FillPacketHeader(QuicFecGroupNumber fec_group,
@@ -240,7 +252,6 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
// padding frame.
void MaybeAddPadding();
- Options options_;
QuicConnectionId connection_id_;
EncryptionLevel encryption_level_;
QuicFramer* framer_;
@@ -255,9 +266,20 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
// Controls whether protocol version should be included while serializing the
// packet.
bool send_version_in_packet_;
- // The sequence number length for the current packet and the current FEC group
- // if FEC is enabled.
- // Mutable so PacketSize() can adjust it when the packet is empty.
+ // Maximum length including headers and encryption (UDP payload length.)
+ size_t max_packet_length_;
+ // 0 indicates FEC is disabled.
+ size_t max_packets_per_fec_group_;
+ // Length of connection_id to send over the wire.
+ QuicConnectionIdLength connection_id_length_;
+ // Staging variable to hold next packet sequence number length. When sequence
+ // number length is to be changed, this variable holds the new length until
+ // a packet or FEC group boundary, when the creator's sequence_number_length_
+ // can be changed to this new value.
+ QuicSequenceNumberLength next_sequence_number_length_;
+ // Sequence number length for the current packet and for the current FEC group
+ // when FEC is enabled. Mutable so PacketSize() can adjust it when the packet
+ // is empty.
mutable QuicSequenceNumberLength sequence_number_length_;
// packet_size_ is mutable because it's just a cache of the current size.
// packet_size should never be read directly, use PacketSize() instead.
diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc
index 57bf2f4..d4b7f44 100644
--- a/net/quic/quic_packet_creator_test.cc
+++ b/net/quic/quic_packet_creator_test.cc
@@ -100,18 +100,17 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> {
// Returns the number of bytes consumed by the header of packet, including
// the version.
size_t GetPacketHeaderOverhead(InFecGroup is_in_fec_group) {
- return GetPacketHeaderSize(creator_.options()->send_connection_id_length,
+ return GetPacketHeaderSize(creator_.connection_id_length(),
kIncludeVersion,
- creator_.options()->send_sequence_number_length,
+ creator_.next_sequence_number_length(),
is_in_fec_group);
}
// Returns the number of bytes of overhead that will be added to a packet
// of maximum length.
size_t GetEncryptionOverhead() {
- return creator_.options()->max_packet_length -
- client_framer_.GetMaxPlaintextSize(
- creator_.options()->max_packet_length);
+ return creator_.max_packet_length() - client_framer_.GetMaxPlaintextSize(
+ creator_.max_packet_length());
}
// Returns the number of bytes consumed by the non-data fields of a stream
@@ -216,8 +215,7 @@ TEST_P(QuicPacketCreatorTest, SerializeWithFEC) {
TEST_P(QuicPacketCreatorTest, SerializeChangingSequenceNumberLength) {
frames_.push_back(QuicFrame(new QuicAckFrame(MakeAckFrame(0u, 0u))));
creator_.AddSavedFrame(frames_[0]);
- creator_.options()->send_sequence_number_length =
- PACKET_4BYTE_SEQUENCE_NUMBER;
+ creator_.set_next_sequence_number_length(PACKET_4BYTE_SEQUENCE_NUMBER);
SerializedPacket serialized = creator_.SerializePacket();
// The sequence number length will not change mid-packet.
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, serialized.sequence_number_length);
@@ -270,8 +268,7 @@ TEST_P(QuicPacketCreatorTest, ChangeSequenceNumberLengthMidPacket) {
creator_.AddSavedFrame(ack_frame);
// Now change sequence number length.
- creator_.options()->send_sequence_number_length =
- PACKET_4BYTE_SEQUENCE_NUMBER;
+ creator_.set_next_sequence_number_length(PACKET_4BYTE_SEQUENCE_NUMBER);
// Add a STOP_WAITING frame since it contains a packet sequence number,
// whose length should be 1.
@@ -351,8 +348,7 @@ TEST_P(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) {
// Generate Packet 1.
creator_.AddSavedFrame(frames_[0]);
// Change the sequence number length mid-FEC group and it should not change.
- creator_.options()->send_sequence_number_length =
- PACKET_4BYTE_SEQUENCE_NUMBER;
+ creator_.set_next_sequence_number_length(PACKET_4BYTE_SEQUENCE_NUMBER);
SerializedPacket serialized = creator_.SerializePacket();
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, serialized.sequence_number_length);
@@ -424,15 +420,14 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) {
// If the original packet sequence number length, the current sequence number
// length, and the configured send sequence number length are different, the
// retransmit must sent with the original length and the others do not change.
- creator_.options()->send_sequence_number_length =
- PACKET_4BYTE_SEQUENCE_NUMBER;
+ creator_.set_next_sequence_number_length(PACKET_4BYTE_SEQUENCE_NUMBER);
QuicPacketCreatorPeer::SetSequenceNumberLength(&creator_,
PACKET_2BYTE_SEQUENCE_NUMBER);
frames_.push_back(QuicFrame(new QuicStreamFrame(0u, false, 0u, IOVector())));
SerializedPacket serialized =
creator_.ReserializeAllFrames(frames_, PACKET_1BYTE_SEQUENCE_NUMBER);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
- creator_.options()->send_sequence_number_length);
+ creator_.next_sequence_number_length());
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
QuicPacketCreatorPeer::GetSequenceNumberLength(&creator_));
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, serialized.sequence_number_length);
@@ -582,7 +577,7 @@ TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) {
const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP)
+ GetEncryptionOverhead();
for (size_t i = overhead; i < overhead + 100; ++i) {
- creator_.options()->max_packet_length = i;
+ creator_.set_max_packet_length(i);
const bool should_have_room = i > overhead + GetStreamFrameOverhead(
NOT_IN_FEC_GROUP);
ASSERT_EQ(should_have_room, creator_.HasRoomForStreamFrame(
@@ -740,49 +735,49 @@ TEST_P(QuicPacketCreatorTest, SerializeVersionNegotiationPacket) {
TEST_P(QuicPacketCreatorTest, UpdatePacketSequenceNumberLengthLeastAwaiting) {
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
- creator_.options()->send_sequence_number_length);
+ creator_.next_sequence_number_length());
creator_.set_sequence_number(64);
creator_.UpdateSequenceNumberLength(2, 10000);
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
- creator_.options()->send_sequence_number_length);
+ creator_.next_sequence_number_length());
creator_.set_sequence_number(64 * 256);
creator_.UpdateSequenceNumberLength(2, 10000);
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
- creator_.options()->send_sequence_number_length);
+ creator_.next_sequence_number_length());
creator_.set_sequence_number(64 * 256 * 256);
creator_.UpdateSequenceNumberLength(2, 10000);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
- creator_.options()->send_sequence_number_length);
+ creator_.next_sequence_number_length());
creator_.set_sequence_number(GG_UINT64_C(64) * 256 * 256 * 256 * 256);
creator_.UpdateSequenceNumberLength(2, 10000);
EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER,
- creator_.options()->send_sequence_number_length);
+ creator_.next_sequence_number_length());
}
TEST_P(QuicPacketCreatorTest, UpdatePacketSequenceNumberLengthBandwidth) {
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
- creator_.options()->send_sequence_number_length);
+ creator_.next_sequence_number_length());
creator_.UpdateSequenceNumberLength(1, 10000);
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
- creator_.options()->send_sequence_number_length);
+ creator_.next_sequence_number_length());
creator_.UpdateSequenceNumberLength(1, 10000 * 256);
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
- creator_.options()->send_sequence_number_length);
+ creator_.next_sequence_number_length());
creator_.UpdateSequenceNumberLength(1, 10000 * 256 * 256);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
- creator_.options()->send_sequence_number_length);
+ creator_.next_sequence_number_length());
creator_.UpdateSequenceNumberLength(
1, GG_UINT64_C(1000) * 256 * 256 * 256 * 256);
EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER,
- creator_.options()->send_sequence_number_length);
+ creator_.next_sequence_number_length());
}
TEST_P(QuicPacketCreatorTest, CreateStreamFrameWithNotifier) {
@@ -833,10 +828,10 @@ TEST_P(QuicPacketCreatorTest, CreateStreamFrameTooLarge) {
}
// A string larger than fits into a frame.
size_t payload_length;
- creator_.options()->max_packet_length = GetPacketLengthForOneStream(
+ creator_.set_max_packet_length(GetPacketLengthForOneStream(
client_framer_.version(),
QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
- PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP, &payload_length);
+ PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP, &payload_length));
QuicFrame frame;
const string too_long_payload(payload_length * 2, 'a');
size_t consumed = creator_.CreateStreamFrame(
@@ -852,11 +847,11 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndSerialize) {
creator_.StopSendingVersion();
}
const size_t max_plaintext_size =
- client_framer_.GetMaxPlaintextSize(creator_.options()->max_packet_length);
+ client_framer_.GetMaxPlaintextSize(creator_.max_packet_length());
EXPECT_FALSE(creator_.HasPendingFrames());
EXPECT_EQ(max_plaintext_size -
GetPacketHeaderSize(
- creator_.options()->send_connection_id_length,
+ creator_.connection_id_length(),
QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP),
creator_.BytesFree());
@@ -900,7 +895,7 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndSerialize) {
EXPECT_FALSE(creator_.HasPendingFrames());
EXPECT_EQ(max_plaintext_size -
GetPacketHeaderSize(
- creator_.options()->send_connection_id_length,
+ creator_.connection_id_length(),
QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
PACKET_1BYTE_SEQUENCE_NUMBER,
NOT_IN_FEC_GROUP),
@@ -911,9 +906,9 @@ TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithLargePacketSize) {
if (!GetParam().version_serialization) {
creator_.StopSendingVersion();
}
- creator_.options()->max_packet_length = kMaxPacketSize;
+ creator_.set_max_packet_length(kMaxPacketSize);
const size_t max_plaintext_size =
- client_framer_.GetMaxPlaintextSize(creator_.options()->max_packet_length);
+ client_framer_.GetMaxPlaintextSize(creator_.max_packet_length());
// Serialized length of ack frame with 2000 nack ranges should be limited by
// the number of nack ranges that can be fit in an ack frame.
@@ -955,9 +950,10 @@ TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithSmallPacketSize) {
if (!GetParam().version_serialization) {
creator_.StopSendingVersion();
}
- creator_.options()->max_packet_length = 500u;
+ creator_.set_max_packet_length(500u);
+
const size_t max_plaintext_size =
- client_framer_.GetMaxPlaintextSize(creator_.options()->max_packet_length);
+ client_framer_.GetMaxPlaintextSize(creator_.max_packet_length());
EXPECT_EQ(max_plaintext_size - creator_.PacketSize(), creator_.BytesFree());
// Serialized length of ack frame with 2000 nack ranges should be limited by
diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc
index 785c940..b91ccc6 100644
--- a/net/quic/quic_packet_generator.cc
+++ b/net/quic/quic_packet_generator.cc
@@ -16,7 +16,7 @@ namespace net {
class QuicAckNotifier;
QuicPacketGenerator::QuicPacketGenerator(DelegateInterface* delegate,
- DebugDelegateInterface* debug_delegate,
+ DebugDelegate* debug_delegate,
QuicPacketCreator* creator)
: delegate_(delegate),
debug_delegate_(debug_delegate),
diff --git a/net/quic/quic_packet_generator.h b/net/quic/quic_packet_generator.h
index 12caf34..d9de488 100644
--- a/net/quic/quic_packet_generator.h
+++ b/net/quic/quic_packet_generator.h
@@ -78,16 +78,16 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
// Interface which gets callbacks from the QuicPacketGenerator at interesting
// points. Implementations must not mutate the state of the generator
// as a result of these callbacks.
- class NET_EXPORT_PRIVATE DebugDelegateInterface {
+ class NET_EXPORT_PRIVATE DebugDelegate {
public:
- virtual ~DebugDelegateInterface() {}
+ virtual ~DebugDelegate() {}
// Called when a frame has been added to the current packet.
virtual void OnFrameAddedToPacket(const QuicFrame& frame) {}
};
QuicPacketGenerator(DelegateInterface* delegate,
- DebugDelegateInterface* debug_delegate,
+ DebugDelegate* debug_delegate,
QuicPacketCreator* creator);
virtual ~QuicPacketGenerator();
@@ -131,7 +131,7 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
bool HasQueuedFrames() const;
- void set_debug_delegate(DebugDelegateInterface* debug_delegate) {
+ void set_debug_delegate(DebugDelegate* debug_delegate) {
debug_delegate_ = debug_delegate;
}
@@ -152,7 +152,7 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
void SerializeAndSendPacket();
DelegateInterface* delegate_;
- DebugDelegateInterface* debug_delegate_;
+ DebugDelegate* debug_delegate_;
QuicPacketCreator* packet_creator_;
QuicFrames queued_control_frames_;
diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc
index 16f9748..c06f6f6 100644
--- a/net/quic/quic_packet_generator_test.cc
+++ b/net/quic/quic_packet_generator_test.cc
@@ -231,7 +231,7 @@ class QuicPacketGeneratorTest : public ::testing::Test {
scoped_ptr<char[]> data_array_;
};
-class MockDebugDelegate : public QuicPacketGenerator::DebugDelegateInterface {
+class MockDebugDelegate : public QuicPacketGenerator::DebugDelegate {
public:
MOCK_METHOD1(OnFrameAddedToPacket,
void(const QuicFrame&));
@@ -503,11 +503,11 @@ TEST_F(QuicPacketGeneratorTest, ConsumeDataSendsFecAtEnd) {
TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
// Set the packet size be enough for two stream frames with 0 stream offset,
// but not enough for a stream frame of 0 offset and one with non-zero offset.
- creator_.options()->max_packet_length =
+ size_t length =
NullEncrypter().GetCiphertextSize(0) +
- GetPacketHeaderSize(creator_.options()->send_connection_id_length,
+ GetPacketHeaderSize(creator_.connection_id_length(),
true,
- creator_.options()->send_sequence_number_length,
+ creator_.next_sequence_number_length(),
NOT_IN_FEC_GROUP) +
// Add an extra 3 bytes for the payload and 1 byte so BytesFree is larger
// than the GetMinStreamFrameSize.
@@ -515,6 +515,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
NOT_IN_FEC_GROUP) + 3 +
QuicFramer::GetMinStreamFrameSize(framer_.version(), 1, 0, true,
NOT_IN_FEC_GROUP) + 1;
+ creator_.set_max_packet_length(length);
delegate_.SetCanWriteAnything();
{
InSequence dummy;
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index df3bfa5..7502cdb 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -144,6 +144,11 @@ uint32 MakeQuicTag(char a, char b, char c, char d) {
static_cast<uint32>(d) << 24;
}
+bool ContainsQuicTag(QuicTagVector tag_vector, QuicTag tag) {
+ return std::find(tag_vector.begin(), tag_vector.end(), tag)
+ != tag_vector.end();
+}
+
QuicVersionVector QuicSupportedVersions() {
QuicVersionVector supported_versions;
for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index 6fb423a..6dd8ef3 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -318,6 +318,9 @@ NET_EXPORT_PRIVATE std::string QuicVersionVectorToString(
// MakeQuicTag('C', 'H', 'L', 'O');
NET_EXPORT_PRIVATE QuicTag MakeQuicTag(char a, char b, char c, char d);
+// Returns true if the tag vector contains the specified tag.
+bool ContainsQuicTag(QuicTagVector tag_vector, QuicTag tag);
+
// Size in bytes of the data or fec packet header.
NET_EXPORT_PRIVATE size_t GetPacketHeaderSize(const QuicPacketHeader& header);
diff --git a/net/quic/quic_reliable_client_stream.cc b/net/quic/quic_reliable_client_stream.cc
index 6445ff2..4eb74d6 100644
--- a/net/quic/quic_reliable_client_stream.cc
+++ b/net/quic/quic_reliable_client_stream.cc
@@ -93,8 +93,7 @@ void QuicReliableClientStream::OnError(int error) {
}
bool QuicReliableClientStream::CanWrite(const CompletionCallback& callback) {
- bool can_write = session()->connection()->CanWrite(
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ bool can_write = session()->connection()->CanWrite(HAS_RETRANSMITTABLE_DATA);
if (!can_write) {
session()->MarkWriteBlocked(id(), EffectivePriority());
DCHECK(callback_.is_null());
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc
index eaf66bd..286ef56 100644
--- a/net/quic/quic_sent_packet_manager.cc
+++ b/net/quic/quic_sent_packet_manager.cc
@@ -69,6 +69,7 @@ QuicSentPacketManager::QuicSentPacketManager(bool is_server,
consecutive_rto_count_(0),
consecutive_tlp_count_(0),
consecutive_crypto_retransmission_count_(0),
+ pending_tlp_transmission_(false),
max_tail_loss_probes_(kDefaultMaxTailLossProbes),
using_pacing_(false) {
}
@@ -82,7 +83,13 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
rtt_stats_.set_initial_rtt_us(min(kMaxInitialRoundTripTimeUs,
config.ReceivedInitialRoundTripTimeUs()));
}
- if (config.congestion_control() == kPACE) {
+ // TODO(ianswett): BBR is currently a server only feature.
+ if (config.HasReceivedCongestionOptions() &&
+ ContainsQuicTag(config.ReceivedCongestionOptions(), kTBBR)) {
+ send_algorithm_.reset(
+ SendAlgorithmInterface::Create(clock_, &rtt_stats_, kTCPBBR, stats_));
+ }
+ if (config.congestion_feedback() == kPACE) {
MaybeEnablePacing();
}
if (config.HasReceivedLossDetection() &&
@@ -396,6 +403,7 @@ bool QuicSentPacketManager::OnPacketSent(
HasRetransmittableData has_retransmittable_data) {
DCHECK_LT(0u, sequence_number);
LOG_IF(DFATAL, bytes == 0) << "Cannot send empty packets.";
+ pending_tlp_transmission_ = false;
// In rare circumstances, the packet could be serialized, sent, and then acked
// before OnPacketSent is called.
if (!unacked_packets_.IsUnacked(sequence_number)) {
@@ -446,6 +454,7 @@ void QuicSentPacketManager::OnRetransmissionTimeout() {
// If no tail loss probe can be sent, because there are no retransmittable
// packets, execute a conventional RTO to abandon old packets.
++stats_->tlp_count;
+ pending_tlp_transmission_ = true;
RetransmitOldestPacket();
return;
case RTO_MODE:
@@ -497,12 +506,8 @@ void QuicSentPacketManager::RetransmitOldestPacket() {
}
void QuicSentPacketManager::RetransmitAllPackets() {
- // Abandon all retransmittable packets and packets older than the
- // retransmission delay.
-
- DVLOG(1) << "OnRetransmissionTimeout() fired with "
+ DVLOG(1) << "RetransmitAllPackets() called with "
<< unacked_packets_.GetNumUnackedPackets() << " unacked packets.";
-
// Request retransmission of all retransmittable packets when the RTO
// fires, and let the congestion manager decide how many to send
// immediately and the remaining packets will be queued.
@@ -605,11 +610,10 @@ bool QuicSentPacketManager::MaybeUpdateRTT(
QuicTime::Delta QuicSentPacketManager::TimeUntilSend(
QuicTime now,
- TransmissionType transmission_type,
HasRetransmittableData retransmittable) {
// The TLP logic is entirely contained within QuicSentPacketManager, so the
// send algorithm does not need to be consulted.
- if (transmission_type == TLP_RETRANSMISSION) {
+ if (pending_tlp_transmission_) {
return QuicTime::Delta::Zero();
}
return send_algorithm_->TimeUntilSend(
@@ -731,10 +735,11 @@ void QuicSentPacketManager::MaybeEnablePacing() {
return;
}
+ // Set up a pacing sender with a 5 millisecond alarm granularity.
using_pacing_ = true;
send_algorithm_.reset(
new PacingSender(send_algorithm_.release(),
- QuicTime::Delta::FromMicroseconds(1)));
+ QuicTime::Delta::FromMilliseconds(5)));
}
} // namespace net
diff --git a/net/quic/quic_sent_packet_manager.h b/net/quic/quic_sent_packet_manager.h
index d65e361..5823942 100644
--- a/net/quic/quic_sent_packet_manager.h
+++ b/net/quic/quic_sent_packet_manager.h
@@ -133,7 +133,6 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
// Note 2: Send algorithms may or may not use |retransmit| in their
// calculations.
virtual QuicTime::Delta TimeUntilSend(QuicTime now,
- TransmissionType transmission_type,
HasRetransmittableData retransmittable);
// Returns amount of time for delayed ack timer.
@@ -274,6 +273,8 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
size_t consecutive_tlp_count_;
// Number of times the crypto handshake has been retransmitted.
size_t consecutive_crypto_retransmission_count_;
+ // Whether a tlp packet can be sent even if the send algorithm says not to.
+ bool pending_tlp_transmission_;
// Maximum number of tail loss probes to send before firing an RTO.
size_t max_tail_loss_probes_;
bool using_pacing_;
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h
index d23b684..b9ce0de5 100644
--- a/net/quic/quic_session.h
+++ b/net/quic/quic_session.h
@@ -175,8 +175,6 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
return connection_->connection_id();
}
- QuicPacketCreator::Options* options() { return connection()->options(); }
-
// Returns the number of currently open streams, including those which have
// been implicitly created, but excluding the reserved headers and crypto
// streams.
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 5f2a5df..9ab7732 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -749,7 +749,7 @@ int QuicStreamFactory::CreateSession(
new QuicConnection(connection_id, addr, helper_.get(), writer.get(),
false, supported_versions_);
writer->SetConnection(connection);
- connection->options()->max_packet_length = max_packet_length_;
+ connection->set_max_packet_length(max_packet_length_);
InitializeCachedStateInCryptoConfig(server_id, server_info);
diff --git a/net/quic/quic_stream_sequencer.cc b/net/quic/quic_stream_sequencer.cc
index 61b4f7c..d0b6933 100644
--- a/net/quic/quic_stream_sequencer.cc
+++ b/net/quic/quic_stream_sequencer.cc
@@ -68,7 +68,6 @@ bool QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
}
num_bytes_consumed_ += bytes_consumed;
stream_->AddBytesConsumed(bytes_consumed);
- stream_->MaybeSendWindowUpdate();
if (MaybeCloseStream()) {
return true;
@@ -95,7 +94,6 @@ bool QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
byte_offset, string(static_cast<char*>(iov.iov_base), iov.iov_len)));
byte_offset += iov.iov_len;
num_bytes_buffered_ += iov.iov_len;
- stream_->AddBytesBuffered(iov.iov_len);
}
return true;
}
@@ -248,8 +246,6 @@ void QuicStreamSequencer::RecordBytesConsumed(size_t bytes_consumed) {
num_bytes_buffered_ -= bytes_consumed;
stream_->AddBytesConsumed(bytes_consumed);
- stream_->RemoveBytesBuffered(bytes_consumed);
- stream_->MaybeSendWindowUpdate();
}
} // namespace net
diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc
index aefdb41..64d8aae 100644
--- a/net/quic/reliable_quic_stream.cc
+++ b/net/quic/reliable_quic_stream.cc
@@ -151,7 +151,11 @@ bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
}
// This count include duplicate data received.
- stream_bytes_read_ += frame.data.TotalBufferSize();
+ size_t frame_payload_size = frame.data.TotalBufferSize();
+ stream_bytes_read_ += frame_payload_size;
+
+ // Flow control is interested in tracking highest received offset.
+ MaybeIncreaseHighestReceivedOffset(frame.offset + frame_payload_size);
bool accepted = sequencer_.OnStreamFrame(frame);
@@ -160,16 +164,10 @@ bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
session_->connection()->SendConnectionClose(QUIC_FLOW_CONTROL_ERROR);
return false;
}
- MaybeSendWindowUpdate();
return accepted;
}
-void ReliableQuicStream::MaybeSendWindowUpdate() {
- flow_controller_.MaybeSendWindowUpdate(session()->connection());
- connection_flow_controller_->MaybeSendWindowUpdate(session()->connection());
-}
-
int ReliableQuicStream::num_frames_received() const {
return sequencer_.num_frames_received();
}
@@ -179,6 +177,8 @@ int ReliableQuicStream::num_duplicate_frames_received() const {
}
void ReliableQuicStream::OnStreamReset(const QuicRstStreamFrame& frame) {
+ MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
+
stream_error_ = frame.error_code;
CloseWriteSide();
CloseReadSide();
@@ -436,17 +436,18 @@ void ReliableQuicStream::OnWindowUpdateFrame(
}
}
-void ReliableQuicStream::AddBytesBuffered(uint64 bytes) {
- if (flow_controller_.IsEnabled()) {
- flow_controller_.AddBytesBuffered(bytes);
- connection_flow_controller_->AddBytesBuffered(bytes);
- }
-}
-
-void ReliableQuicStream::RemoveBytesBuffered(uint64 bytes) {
+void ReliableQuicStream::MaybeIncreaseHighestReceivedOffset(uint64 new_offset) {
if (flow_controller_.IsEnabled()) {
- flow_controller_.RemoveBytesBuffered(bytes);
- connection_flow_controller_->RemoveBytesBuffered(bytes);
+ uint64 increment =
+ new_offset - flow_controller_.highest_received_byte_offset();
+ if (flow_controller_.UpdateHighestReceivedOffset(new_offset)) {
+ // If |new_offset| increased the stream flow controller's highest received
+ // offset, then we need to increase the connection flow controller's value
+ // by the incremental difference.
+ connection_flow_controller_->UpdateHighestReceivedOffset(
+ connection_flow_controller_->highest_received_byte_offset() +
+ increment);
+ }
}
}
@@ -460,7 +461,10 @@ void ReliableQuicStream::AddBytesSent(uint64 bytes) {
void ReliableQuicStream::AddBytesConsumed(uint64 bytes) {
if (flow_controller_.IsEnabled()) {
flow_controller_.AddBytesConsumed(bytes);
+ flow_controller_.MaybeSendWindowUpdate(session()->connection());
+
connection_flow_controller_->AddBytesConsumed(bytes);
+ connection_flow_controller_->MaybeSendWindowUpdate(session()->connection());
}
}
diff --git a/net/quic/reliable_quic_stream.h b/net/quic/reliable_quic_stream.h
index 90cdac44..68ff6dd 100644
--- a/net/quic/reliable_quic_stream.h
+++ b/net/quic/reliable_quic_stream.h
@@ -92,24 +92,19 @@ class NET_EXPORT_PRIVATE ReliableQuicStream {
// Adjust our flow control windows according to new offset in |frame|.
virtual void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame);
- // If our receive window has dropped below the threshold, then send a
- // WINDOW_UPDATE frame. This is called whenever bytes are consumed from the
- // sequencer's buffer.
- void MaybeSendWindowUpdate();
-
int num_frames_received() const;
int num_duplicate_frames_received() const;
QuicFlowController* flow_controller() { return &flow_controller_; }
- // Called by the stream sequeuncer as bytes are added to the buffer.
- void AddBytesBuffered(uint64 bytes);
- // Called by the stream sequeuncer as bytes are removed from the buffer.
- void RemoveBytesBuffered(uint64 bytes);
+ // Called when we see a frame which could increase the highest offset.
+ void MaybeIncreaseHighestReceivedOffset(uint64 new_offset);
// Called when bytese are sent to the peer.
void AddBytesSent(uint64 bytes);
- // Called by the stream sequeuncer as bytes are consumed from the buffer.
+ // Called by the stream sequencer as bytes are consumed from the buffer.
+ // If our receive window has dropped below the threshold, then send a
+ // WINDOW_UPDATE frame.
void AddBytesConsumed(uint64 bytes);
// Returns true if the stream is flow control blocked, by the stream flow
@@ -171,12 +166,6 @@ class NET_EXPORT_PRIVATE ReliableQuicStream {
scoped_refptr<ProxyAckNotifierDelegate> delegate;
};
- // Calculates and returns available flow control send window.
- uint64 SendWindowSize() const;
-
- // Calculates and returns total number of bytes this stream has received.
- uint64 TotalReceivedBytes() const;
-
// Calls MaybeSendBlocked on our flow controller, and connection level flow
// controller. If we are flow control blocked, marks this stream as write
// blocked.
diff --git a/net/quic/reliable_quic_stream_test.cc b/net/quic/reliable_quic_stream_test.cc
index 9e212ce..2fc4e9d 100644
--- a/net/quic/reliable_quic_stream_test.cc
+++ b/net/quic/reliable_quic_stream_test.cc
@@ -11,6 +11,7 @@
#include "net/quic/quic_write_blocked_list.h"
#include "net/quic/spdy_utils.h"
#include "net/quic/test_tools/quic_config_peer.h"
+#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_flow_controller_peer.h"
#include "net/quic/test_tools/quic_session_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
@@ -150,13 +151,14 @@ class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> {
TEST_F(ReliableQuicStreamTest, WriteAllData) {
Initialize(kShouldProcessData);
- connection_->options()->max_packet_length =
- 1 + QuicPacketCreator::StreamFramePacketOverhead(
- connection_->version(), PACKET_8BYTE_CONNECTION_ID,
- !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, 0u,
- NOT_IN_FEC_GROUP);
- EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _))
- .WillOnce(Return(QuicConsumedData(kDataLen, true)));
+ size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead(
+ connection_->version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ PACKET_6BYTE_SEQUENCE_NUMBER, 0u, NOT_IN_FEC_GROUP);
+ QuicConnectionPeer::GetPacketCreator(connection_)->set_max_packet_length(
+ length);
+
+ EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _)).WillOnce(
+ Return(QuicConsumedData(kDataLen, true)));
stream_->WriteOrBufferData(kData1, false, NULL);
EXPECT_FALSE(HasWriteBlockedStreams());
}
@@ -209,10 +211,12 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferData) {
Initialize(kShouldProcessData);
EXPECT_FALSE(HasWriteBlockedStreams());
- connection_->options()->max_packet_length =
- 1 + QuicPacketCreator::StreamFramePacketOverhead(
- connection_->version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- PACKET_6BYTE_SEQUENCE_NUMBER, 0u, NOT_IN_FEC_GROUP);
+ size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead(
+ connection_->version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ PACKET_6BYTE_SEQUENCE_NUMBER, 0u, NOT_IN_FEC_GROUP);
+ QuicConnectionPeer::GetPacketCreator(connection_)->set_max_packet_length(
+ length);
+
EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).WillOnce(
Return(QuicConsumedData(kDataLen - 1, false)));
stream_->WriteOrBufferData(kData1, false, NULL);
diff --git a/net/quic/test_tools/mock_crypto_client_stream.cc b/net/quic/test_tools/mock_crypto_client_stream.cc
index 6710dcd..a4b3ab0 100644
--- a/net/quic/test_tools/mock_crypto_client_stream.cc
+++ b/net/quic/test_tools/mock_crypto_client_stream.cc
@@ -83,7 +83,7 @@ void MockCryptoClientStream::SetConfigNegotiated() {
QuicTagVector cgst;
cgst.push_back(kINAR);
cgst.push_back(kQBIC);
- session()->config()->set_congestion_control(cgst, kQBIC);
+ session()->config()->set_congestion_feedback(cgst, kQBIC);
session()->config()->set_idle_connection_state_lifetime(
QuicTime::Delta::FromSeconds(2 * kDefaultTimeoutSecs),
QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs));
diff --git a/net/quic/test_tools/quic_flow_controller_peer.cc b/net/quic/test_tools/quic_flow_controller_peer.cc
index 80b5e2b..35882ed 100644
--- a/net/quic/test_tools/quic_flow_controller_peer.cc
+++ b/net/quic/test_tools/quic_flow_controller_peer.cc
@@ -54,7 +54,7 @@ uint64 QuicFlowControllerPeer::ReceiveWindowOffset(
uint64 QuicFlowControllerPeer::ReceiveWindowSize(
QuicFlowController* flow_controller) {
return flow_controller->receive_window_offset_ -
- flow_controller->TotalReceivedBytes();
+ flow_controller->highest_received_byte_offset_;
}
} // namespace test
diff --git a/net/quic/test_tools/quic_test_packet_maker.cc b/net/quic/test_tools/quic_test_packet_maker.cc
index 397f39f..7f0835f 100644
--- a/net/quic/test_tools/quic_test_packet_maker.cc
+++ b/net/quic/test_tools/quic_test_packet_maker.cc
@@ -84,7 +84,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckAndRstPacket(
QuicFramer framer(SupportedVersions(version_), QuicTime::Zero(), false);
scoped_ptr<QuicPacket> packet(
- framer.BuildUnsizedDataPacket(header, frames).packet);
+ BuildUnsizedDataPacket(&framer, header, frames).packet);
return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
ENCRYPTION_NONE, header.packet_sequence_number, *packet));
}
@@ -143,7 +143,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckPacket(
}
scoped_ptr<QuicPacket> packet(
- framer.BuildUnsizedDataPacket(header, frames).packet);
+ BuildUnsizedDataPacket(&framer, header, frames).packet);
return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
ENCRYPTION_NONE, header.packet_sequence_number, *packet));
}
@@ -227,7 +227,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakePacket(
QuicFrames frames;
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- framer.BuildUnsizedDataPacket(header, frames).packet);
+ BuildUnsizedDataPacket(&framer, header, frames).packet);
return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
ENCRYPTION_NONE, header.packet_sequence_number, *packet));
}
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index 1f7759d..30bf282 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -63,6 +63,25 @@ QuicAckFrame MakeAckFrameWithNackRanges(
return ack;
}
+SerializedPacket BuildUnsizedDataPacket(QuicFramer* framer,
+ const QuicPacketHeader& header,
+ const QuicFrames& frames) {
+ const size_t max_plaintext_size = framer->GetMaxPlaintextSize(kMaxPacketSize);
+ size_t packet_size = GetPacketHeaderSize(header);
+ for (size_t i = 0; i < frames.size(); ++i) {
+ DCHECK_LE(packet_size, max_plaintext_size);
+ bool first_frame = i == 0;
+ bool last_frame = i == frames.size() - 1;
+ const size_t frame_size = framer->GetSerializedFrameLength(
+ frames[i], max_plaintext_size - packet_size, first_frame, last_frame,
+ header.is_in_fec_group,
+ header.public_header.sequence_number_length);
+ DCHECK(frame_size);
+ packet_size += frame_size;
+ }
+ return framer->BuildDataPacket(header, frames, packet_size);
+}
+
MockFramerVisitor::MockFramerVisitor() {
// By default, we want to accept packets.
ON_CALL(*this, OnProtocolVersionMismatch(_))
@@ -423,7 +442,7 @@ QuicEncryptedPacket* ConstructEncryptedPacket(
frames.push_back(frame);
QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
scoped_ptr<QuicPacket> packet(
- framer.BuildUnsizedDataPacket(header, frames).packet);
+ BuildUnsizedDataPacket(&framer, header, frames).packet);
EXPECT_TRUE(packet != NULL);
QuicEncryptedPacket* encrypted = framer.EncryptPacket(ENCRYPTION_NONE,
sequence_number,
@@ -500,7 +519,7 @@ static QuicPacket* ConstructPacketFromHandshakeMessage(
QuicFrame frame(&stream_frame);
QuicFrames frames;
frames.push_back(frame);
- return quic_framer.BuildUnsizedDataPacket(header, frames).packet;
+ return BuildUnsizedDataPacket(&quic_framer, header, frames).packet;
}
QuicPacket* ConstructHandshakePacket(QuicConnectionId connection_id,
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index 8bf069b..5367c76 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -93,6 +93,13 @@ QuicAckFrame MakeAckFrame(QuicPacketSequenceNumber largest_observed,
QuicAckFrame MakeAckFrameWithNackRanges(size_t num_nack_ranges,
QuicPacketSequenceNumber least_unacked);
+// Returns a SerializedPacket whose |packet| member is owned by the caller,
+// and is populated with the fields in |header| and |frames|, or is NULL if
+// the packet could not be created.
+SerializedPacket BuildUnsizedDataPacket(QuicFramer* framer,
+ const QuicPacketHeader& header,
+ const QuicFrames& frames);
+
template<typename SaveType>
class ValueRestore {
public:
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc
index 8ecd997..f2802a2 100644
--- a/net/tools/quic/quic_client.cc
+++ b/net/tools/quic/quic_client.cc
@@ -296,13 +296,6 @@ void QuicClient::OnClose(QuicDataStream* stream) {
printf("%s\n", client_stream->data().c_str());
}
-QuicPacketCreator::Options* QuicClient::options() {
- if (session() == NULL) {
- return NULL;
- }
- return session_->options();
-}
-
bool QuicClient::connected() const {
return session_.get() && session_->connection() &&
session_->connection()->connected();
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h
index e1b1c2d..33dfeaa 100644
--- a/net/tools/quic/quic_client.h
+++ b/net/tools/quic/quic_client.h
@@ -116,8 +116,6 @@ class QuicClient : public EpollCallbackInterface,
// QuicDataStream::Visitor
virtual void OnClose(QuicDataStream* stream) OVERRIDE;
- QuicPacketCreator::Options* options();
-
QuicClientSession* session() { return session_.get(); }
bool connected() const;
diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc
index d58b4e1..4bc50c3 100644
--- a/net/tools/quic/quic_time_wait_list_manager_test.cc
+++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -21,10 +21,10 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using net::test::BuildUnsizedDataPacket;
using net::test::NoOpFramerVisitor;
using net::test::QuicVersionMax;
using net::test::QuicVersionMin;
-using testing::_;
using testing::Args;
using testing::Assign;
using testing::DoAll;
@@ -36,6 +36,7 @@ using testing::ReturnPointee;
using testing::SetArgPointee;
using testing::StrictMock;
using testing::Truly;
+using testing::_;
namespace net {
namespace tools {
@@ -150,7 +151,7 @@ class QuicTimeWaitListManagerTest : public ::testing::Test {
QuicFrames frames;
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header, frames).packet);
EXPECT_TRUE(packet != NULL);
QuicEncryptedPacket* encrypted = framer_.EncryptPacket(ENCRYPTION_NONE,
sequence_number,
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index c4f2706..625cf1a 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -272,10 +272,6 @@ ssize_t QuicTestClient::SendData(string data, bool last_data) {
return data.length();
}
-QuicPacketCreator::Options* QuicTestClient::options() {
- return client_->options();
-}
-
bool QuicTestClient::response_complete() const {
return response_complete_;
}
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h
index 837f154..975ce5a 100644
--- a/net/tools/quic/test_tools/quic_test_client.h
+++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -85,8 +85,6 @@ class QuicTestClient : public SimpleClient,
// Wraps data in a quic packet and sends it.
ssize_t SendData(string data, bool last_data);
- QuicPacketCreator::Options* options();
-
// From SimpleClient
// Clears any outstanding state and sends a simple GET of 'uri' to the
// server. Returns 0 if the request failed and no bytes were written.