diff options
| author | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-17 15:51:33 +0000 |
|---|---|---|
| committer | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-17 15:51:33 +0000 |
| commit | ce7bb141d5359dfe1224a85bafa802a09f1e683d (patch) | |
| tree | d2f27658cb8e127a89d7b4198fe04949283e30e7 | |
| parent | f5d0fa6e33af3ac62a6d98e4cac1b1420533f6d7 (diff) | |
| download | chromium_src-ce7bb141d5359dfe1224a85bafa802a09f1e683d.zip chromium_src-ce7bb141d5359dfe1224a85bafa802a09f1e683d.tar.gz chromium_src-ce7bb141d5359dfe1224a85bafa802a09f1e683d.tar.bz2 | |
Land Recent QUIC Changes.
Stub for BBRv2, based on TCP congestion feedback frames.
Merge internal change: 67154078
https://codereview.chromium.org/283333008/
Update QuicSentPacketManager to sample a new recent min rtt within the
first 2 rtt samples after quiescence.
Merge internal change: 67149500
https://codereview.chromium.org/286143007/
Change the test QUIC stream id to be the first non reserved stream ID
(and also to use the right typedef).
Merge internal change: 67146383
https://codereview.chromium.org/292453003/
Adds dynamic FEC on/off switch in packet creator. Tightens use of
max_packets_per_fec_group through use of a setter method across the QUIC
code. FEC operations are now decided based on should_fec_protect_, which
is expected to be a dynamic on/off control in the packet creator,
instead of max_packets_per_fec_group.
Adds dynamic FEC on/off switch in packet_creator.
Merge internal change: 67144415
https://codereview.chromium.org/286153003/
Minor cleanup to simplify QuicSentPacketManager's OnPacketSent and
always reset the retransmission alarm anytime a new pending packet is
sent.
Always setting the retransmission alarm is only a simplification of the
approach, and not intended to fix any issues.
Merge internal change: 67143274
https://codereview.chromium.org/288333002/
Don't set QUIC's write alarm if we are connection flow control blocked.
Added QUIC_VERSION_19 to kSupportedQuicVersions.
Merge internal change: 67141668
https://codereview.chromium.org/285193006/
Minor cleanup of QuicUnackedPacketMap to simplify the implementation of
HasPendingPackets and move a test only method,
GetNumRetransmittablePackets, into QuicSentPacketManagerPeer.
Merge internal change: 67123054
https://codereview.chromium.org/282323003/
Fix a QUIC bug where a crypto packet was never removed from the
UnackedPacketMap if it was not acked and spuriously retransmitted at
least twice.
Merge internal change: 67050631
https://codereview.chromium.org/284273002/
Refactor: move flow controller from QuicConnection to QuicSession.
No behavior change intended.
Merge internal change: 67036889
https://codereview.chromium.org/286213002/
Fix a QUIC bug where a packet could remain in the UnackedPacketMap
indefinitely. This can cause a memory leak when tracking entropy.
Merge internal change: 67028206
https://codereview.chromium.org/285233006/
Delete dead code used only in tests.
Merge internal change: 66938996
https://codereview.chromium.org/288303002/
Add handling + parsing for ALTSVC frame. Also change frame type number
and add an extra version check for BLOCKED frame. SPDY4/HTTP2 only.
Merge internal change: 66925490
https://codereview.chromium.org/286173002/
QUIC loadtest fixes:
- Wait for the QUIC handshake to complete before saying that the
QuicTestClient is connected.
- Force connect at client creation time when talking HTTP/HTTPS/SPDY
for consistency.
Merge internal change: 66855236
https://codereview.chromium.org/282153004/
QUIC now respects configured SPDY stream limits.
Merge internal change: 66831620
https://codereview.chromium.org/286113004/
R=rch@chromium.org
Review URL: https://codereview.chromium.org/288313003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271211 0039d316-1c4b-4281-b951-d872f2087c98
62 files changed, 674 insertions, 463 deletions
diff --git a/net/net.gypi b/net/net.gypi index 7db357e..2b407ef 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -751,7 +751,6 @@ 'quic/congestion_control/paced_sender.h', 'quic/congestion_control/pacing_sender.cc', 'quic/congestion_control/pacing_sender.h', - 'quic/congestion_control/quic_max_sized_map.h', 'quic/congestion_control/receive_algorithm_interface.cc', 'quic/congestion_control/receive_algorithm_interface.h', 'quic/congestion_control/rtt_stats.cc', @@ -1425,7 +1424,6 @@ 'quic/congestion_control/leaky_bucket_test.cc', 'quic/congestion_control/paced_sender_test.cc', 'quic/congestion_control/pacing_sender_test.cc', - 'quic/congestion_control/quic_max_sized_map_test.cc', 'quic/congestion_control/rtt_stats_test.cc', 'quic/congestion_control/tcp_cubic_sender_test.cc', 'quic/congestion_control/tcp_loss_algorithm_test.cc', diff --git a/net/quic/congestion_control/quic_max_sized_map.h b/net/quic/congestion_control/quic_max_sized_map.h deleted file mode 100644 index a4ed776..0000000 --- a/net/quic/congestion_control/quic_max_sized_map.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Simple max sized map. Automatically deletes the oldest element when the -// max limit is reached. -// Note: the ConstIterator will NOT be valid after an Insert or RemoveAll. -#ifndef NET_QUIC_CONGESTION_CONTROL_QUIC_MAX_SIZED_MAP_H_ -#define NET_QUIC_CONGESTION_CONTROL_QUIC_MAX_SIZED_MAP_H_ - -#include <stdlib.h> - -#include <list> -#include <map> - -#include "base/basictypes.h" - -namespace net { - -template <class Key, class Value> -class QuicMaxSizedMap { - public: - typedef typename std::multimap<Key, Value>::const_iterator ConstIterator; - - explicit QuicMaxSizedMap(size_t max_numer_of_items) - : max_numer_of_items_(max_numer_of_items) { - } - - size_t MaxSize() const { - return max_numer_of_items_; - } - - size_t Size() const { - return table_.size(); - } - - void Insert(const Key& k, const Value& value) { - if (Size() == MaxSize()) { - ListIterator list_it = insert_order_.begin(); - table_.erase(*list_it); - insert_order_.pop_front(); - } - TableIterator it = table_.insert(std::pair<Key, Value>(k, value)); - insert_order_.push_back(it); - } - - void RemoveAll() { - table_.clear(); - insert_order_.clear(); - } - - // STL style const_iterator support. - ConstIterator Find(const Key& k) const { - return table_.find(k); - } - - ConstIterator Begin() const { - return ConstIterator(table_.begin()); - } - - ConstIterator End() const { - return ConstIterator(table_.end()); - } - - private: - typedef typename std::multimap<Key, Value>::iterator TableIterator; - typedef typename std::list<TableIterator>::iterator ListIterator; - - const size_t max_numer_of_items_; - std::multimap<Key, Value> table_; - std::list<TableIterator> insert_order_; - - DISALLOW_COPY_AND_ASSIGN(QuicMaxSizedMap); -}; - -} // namespace net -#endif // NET_QUIC_CONGESTION_CONTROL_QUIC_MAX_SIZED_MAP_H_ diff --git a/net/quic/congestion_control/quic_max_sized_map_test.cc b/net/quic/congestion_control/quic_max_sized_map_test.cc deleted file mode 100644 index 89c05cc..0000000 --- a/net/quic/congestion_control/quic_max_sized_map_test.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/logging.h" -#include "net/quic/congestion_control/quic_max_sized_map.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { -namespace test { - -class QuicMaxSizedMapTest : public ::testing::Test { -}; - -TEST_F(QuicMaxSizedMapTest, Basic) { - QuicMaxSizedMap<int, int> test_map(100); - EXPECT_EQ(100u, test_map.MaxSize()); - EXPECT_EQ(0u, test_map.Size()); - test_map.Insert(1, 2); - test_map.Insert(1, 3); - EXPECT_EQ(100u, test_map.MaxSize()); - EXPECT_EQ(2u, test_map.Size()); - test_map.RemoveAll(); - EXPECT_EQ(100u, test_map.MaxSize()); - EXPECT_EQ(0u, test_map.Size()); -} - -TEST_F(QuicMaxSizedMapTest, Find) { - QuicMaxSizedMap<int, int> test_map(100); - test_map.Insert(1, 2); - test_map.Insert(1, 3); - test_map.Insert(2, 4); - test_map.Insert(3, 5); - QuicMaxSizedMap<int, int>::ConstIterator it = test_map.Find(2); - EXPECT_TRUE(it != test_map.End()); - EXPECT_EQ(4, it->second); - it = test_map.Find(1); - EXPECT_TRUE(it != test_map.End()); - EXPECT_EQ(2, it->second); - ++it; - EXPECT_TRUE(it != test_map.End()); - EXPECT_EQ(3, it->second); -} - -TEST_F(QuicMaxSizedMapTest, Sort) { - QuicMaxSizedMap<int, int> test_map(100); - test_map.Insert(9, 9); - test_map.Insert(8, 8); - test_map.Insert(7, 7); - test_map.Insert(6, 6); - test_map.Insert(2, 2); - test_map.Insert(4, 4); - test_map.Insert(5, 5); - test_map.Insert(3, 3); - test_map.Insert(0, 0); - test_map.Insert(1, 1); - QuicMaxSizedMap<int, int>::ConstIterator it = test_map.Begin(); - for (int i = 0; i < 10; ++i, ++it) { - EXPECT_TRUE(it != test_map.End()); - EXPECT_EQ(i, it->first); - EXPECT_EQ(i, it->second); - } -} - -} // namespace test -} // namespace net diff --git a/net/quic/congestion_control/receive_algorithm_interface.cc b/net/quic/congestion_control/receive_algorithm_interface.cc index f5672f8..5384bdc 100644 --- a/net/quic/congestion_control/receive_algorithm_interface.cc +++ b/net/quic/congestion_control/receive_algorithm_interface.cc @@ -15,6 +15,9 @@ ReceiveAlgorithmInterface* ReceiveAlgorithmInterface::Create( switch (type) { case kTCP: return new TcpReceiver(); + case kTCPBBR: + LOG(DFATAL) << "TCPBBR is not yet supported."; + return NULL; case kInterArrival: LOG(DFATAL) << "InterArrivalSendAlgorithm no longer supported."; return NULL; diff --git a/net/quic/congestion_control/send_algorithm_interface.cc b/net/quic/congestion_control/send_algorithm_interface.cc index e5c3329..58b92bc 100644 --- a/net/quic/congestion_control/send_algorithm_interface.cc +++ b/net/quic/congestion_control/send_algorithm_interface.cc @@ -29,6 +29,9 @@ SendAlgorithmInterface* SendAlgorithmInterface::Create( return NULL; case kFixRate: return new FixRateSender(rtt_stats); + case kTCPBBR: + LOG(DFATAL) << "BbrTcpSender is not supported."; + return NULL; } return NULL; } diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h index 8412a043..12cf8f6 100644 --- a/net/quic/congestion_control/send_algorithm_interface.h +++ b/net/quic/congestion_control/send_algorithm_interface.h @@ -51,10 +51,11 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface { const CongestionMap& acked_packets, const CongestionMap& lost_packets) = 0; - // Inform that we sent x bytes to the wire, and if that was a retransmission. - // Returns true if the packet should be tracked by the congestion manager, - // false otherwise. This is used by implementations such as tcp_cubic_sender - // that do not count outgoing ACK packets against the congestion window. + // Inform that we sent |bytes| to the wire, and if the packet is + // retransmittable. Returns true if the packet should be tracked by the + // congestion manager and included in bytes_in_flight, false otherwise. + // |bytes_in_flight| is the number of bytes in flight before the packet was + // sent. // Note: this function must be called for every packet sent to the wire. virtual bool OnPacketSent(QuicTime sent_time, QuicByteCount bytes_in_flight, diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h index 3327bda..12fd997 100644 --- a/net/quic/congestion_control/tcp_cubic_sender.h +++ b/net/quic/congestion_control/tcp_cubic_sender.h @@ -21,9 +21,6 @@ namespace net { -// Default maximum packet size used in Linux TCP implementations. -const QuicByteCount kDefaultTCPMSS = 1460; - class RttStats; namespace test { diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc index b154970..0dd5606 100644 --- a/net/quic/quic_client_session.cc +++ b/net/quic/quic_client_session.cc @@ -136,9 +136,12 @@ QuicClientSession::QuicClientSession( scoped_ptr<QuicServerInfo> server_info, const QuicServerId& server_id, const QuicConfig& config, + uint32 max_flow_control_receive_window_bytes, QuicCryptoClientConfig* crypto_config, NetLog* net_log) - : QuicClientSessionBase(connection, config), + : QuicClientSessionBase(connection, + max_flow_control_receive_window_bytes, + config), require_confirmation_(false), stream_factory_(stream_factory), socket_(socket.Pass()), diff --git a/net/quic/quic_client_session.h b/net/quic/quic_client_session.h index 94c5c59..35eca5f 100644 --- a/net/quic/quic_client_session.h +++ b/net/quic/quic_client_session.h @@ -97,6 +97,7 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicClientSessionBase { scoped_ptr<QuicServerInfo> server_info, const QuicServerId& server_id, const QuicConfig& config, + uint32 max_flow_control_receive_window_bytes, QuicCryptoClientConfig* crypto_config, NetLog* net_log); diff --git a/net/quic/quic_client_session_base.cc b/net/quic/quic_client_session_base.cc index b9cbaff..f735fac 100644 --- a/net/quic/quic_client_session_base.cc +++ b/net/quic/quic_client_session_base.cc @@ -6,9 +6,13 @@ namespace net { -QuicClientSessionBase::QuicClientSessionBase(QuicConnection* connection, - const QuicConfig& config) - : QuicSession(connection, config) {} +QuicClientSessionBase::QuicClientSessionBase( + QuicConnection* connection, + uint32 max_flow_control_receive_window_bytes, + const QuicConfig& config) + : QuicSession(connection, + max_flow_control_receive_window_bytes, + config) {} QuicClientSessionBase::~QuicClientSessionBase() {} diff --git a/net/quic/quic_client_session_base.h b/net/quic/quic_client_session_base.h index eab5d08..007d3ba 100644 --- a/net/quic/quic_client_session_base.h +++ b/net/quic/quic_client_session_base.h @@ -14,6 +14,7 @@ namespace net { class NET_EXPORT_PRIVATE QuicClientSessionBase : public QuicSession { public: QuicClientSessionBase(QuicConnection* connection, + uint32 max_flow_control_receive_window_bytes, const QuicConfig& config); virtual ~QuicClientSessionBase(); diff --git a/net/quic/quic_client_session_test.cc b/net/quic/quic_client_session_test.cc index 9e55602..22f8024 100644 --- a/net/quic/quic_client_session_test.cc +++ b/net/quic/quic_client_session_test.cc @@ -22,6 +22,7 @@ #include "net/socket/socket_test_util.h" #include "net/udp/datagram_client_socket.h" +using net::test::kInitialFlowControlWindowForTest; using testing::_; namespace net { @@ -72,7 +73,8 @@ class QuicClientSessionTest : public ::testing::TestWithParam<QuicVersion> { make_scoped_ptr((QuicServerInfo*)NULL), QuicServerId(kServerHostname, kServerPort, false, PRIVACY_MODE_DISABLED), - DefaultQuicConfig(), &crypto_config_, &net_log_) { + DefaultQuicConfig(), kInitialFlowControlWindowForTest, + &crypto_config_, &net_log_) { session_.config()->SetDefaults(); crypto_config_.SetDefaults(); } diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc index be606c2..523ce6e 100644 --- a/net/quic/quic_connection.cc +++ b/net/quic/quic_connection.cc @@ -23,7 +23,6 @@ #include "net/quic/quic_bandwidth.h" #include "net/quic/quic_config.h" #include "net/quic/quic_flags.h" -#include "net/quic/quic_flow_controller.h" #include "net/quic/quic_utils.h" using base::hash_map; @@ -193,8 +192,7 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id, QuicConnectionHelperInterface* helper, QuicPacketWriter* writer, bool is_server, - const QuicVersionVector& supported_versions, - uint32 max_flow_control_receive_window_bytes) + const QuicVersionVector& supported_versions) : framer_(supported_versions, helper->GetClock()->ApproximateNow(), is_server), helper_(helper), @@ -238,22 +236,7 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id, peer_ip_changed_(false), peer_port_changed_(false), self_ip_changed_(false), - self_port_changed_(false), - max_flow_control_receive_window_bytes_( - max_flow_control_receive_window_bytes) { - if (max_flow_control_receive_window_bytes_ < kDefaultFlowControlSendWindow) { - DLOG(ERROR) << "Initial receive window (" - << max_flow_control_receive_window_bytes_ - << ") cannot be set lower than default (" - << kDefaultFlowControlSendWindow << ")."; - max_flow_control_receive_window_bytes_ = kDefaultFlowControlSendWindow; - } - - flow_controller_.reset(new QuicFlowController( - supported_versions.front(), 0, is_server_, - kDefaultFlowControlSendWindow, max_flow_control_receive_window_bytes_, - max_flow_control_receive_window_bytes_)); - + self_port_changed_(false) { if (!is_server_) { // Pacing will be enabled if the client negotiates it. sent_packet_manager_.MaybeEnablePacing(); @@ -375,10 +358,6 @@ bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) { // Store the new version. framer_.set_version(received_version); - if (received_version < QUIC_VERSION_19) { - flow_controller_->Disable(); - } - // TODO(satyamshekhar): Store the sequence number of this packet and close the // connection if we ever received a packet with incorrect version and whose // sequence number is greater. @@ -494,9 +473,6 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) { DCHECK_EQ(header.public_header.versions[0], version()); version_negotiation_state_ = NEGOTIATED_VERSION; visitor_->OnSuccessfulVersionNegotiation(version()); - if (version() < QUIC_VERSION_19) { - flow_controller_->Disable(); - } } } else { DCHECK(!header.public_header.version_flag); @@ -505,9 +481,6 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) { packet_creator_.StopSendingVersion(); version_negotiation_state_ = NEGOTIATED_VERSION; visitor_->OnSuccessfulVersionNegotiation(version()); - if (version() < QUIC_VERSION_19) { - flow_controller_->Disable(); - } } } @@ -1184,7 +1157,8 @@ void QuicConnection::OnCanWrite() { // After the visitor writes, it may have caused the socket to become write // blocked or the congestion manager to prohibit sending, so check again. - if (visitor_->HasPendingWrites() && !resume_writes_alarm_->IsSet() && + if (visitor_->WillingAndAbleToWrite() && + !resume_writes_alarm_->IsSet() && CanWrite(NOT_RETRANSMISSION, 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 diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h index 3e43e9d..8b6e034 100644 --- a/net/quic/quic_connection.h +++ b/net/quic/quic_connection.h @@ -49,7 +49,6 @@ class QuicConnection; class QuicDecrypter; class QuicEncrypter; class QuicFecGroup; -class QuicFlowController; class QuicRandom; namespace test { @@ -94,10 +93,12 @@ class NET_EXPORT_PRIVATE QuicConnectionVisitorInterface { // Called when a blocked socket becomes writable. virtual void OnCanWrite() = 0; - // Called to ask if any writes are pending in this visitor. Writes may be - // pending because they were write-blocked, congestion-throttled or - // yielded to other connections. - virtual bool HasPendingWrites() const = 0; + // Called to ask if the visitor wants to schedule write resumption as it has + // both has pending data to write, and is able to write (e.g. based on flow + // control limits). + // Writes may be pending because they were write-blocked, congestion-throttled + // or yielded to other connections. + virtual bool WillingAndAbleToWrite() const = 0; // Called to ask if any handshake messages are pending in this visitor. virtual bool HasPendingHandshake() const = 0; @@ -217,8 +218,7 @@ class NET_EXPORT_PRIVATE QuicConnection QuicConnectionHelperInterface* helper, QuicPacketWriter* writer, bool is_server, - const QuicVersionVector& supported_versions, - uint32 max_flow_control_receive_window_bytes); + const QuicVersionVector& supported_versions); virtual ~QuicConnection(); // Sets connection parameters from the supplied |config|. @@ -267,8 +267,6 @@ class NET_EXPORT_PRIVATE QuicConnection QuicStreamId last_good_stream_id, const std::string& reason); - QuicFlowController* flow_controller() { return flow_controller_.get(); } - // Returns statistics tracked for this connection. const QuicConnectionStats& GetStats(); @@ -460,10 +458,6 @@ class NET_EXPORT_PRIVATE QuicConnection bool CanWrite(TransmissionType transmission_type, HasRetransmittableData retransmittable); - uint32 max_flow_control_receive_window_bytes() const { - return max_flow_control_receive_window_bytes_; - } - // Stores current batch state for connection, puts the connection // into batch mode, and destruction restores the stored batch state. // While the bundler is in scope, any generated frames are bundled @@ -760,12 +754,6 @@ class NET_EXPORT_PRIVATE QuicConnection // version negotiation packet. QuicVersionVector server_supported_versions_; - // Initial flow control receive window size for new streams. - uint32 max_flow_control_receive_window_bytes_; - - // Used for connection level flow control. - scoped_ptr<QuicFlowController> flow_controller_; - DISALLOW_COPY_AND_ASSIGN(QuicConnection); }; diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc index 477cc7e..3dd13e8 100644 --- a/net/quic/quic_connection_logger.cc +++ b/net/quic/quic_connection_logger.cc @@ -150,6 +150,10 @@ base::Value* NetLogQuicCongestionFeedbackFrameCallback( dict->SetString("type", "TCP"); dict->SetInteger("receive_window", frame->tcp.receive_window); break; + case kTCPBBR: + dict->SetString("type", "TCPBBR"); + // TODO(rtenneti): Add support for BBR. + break; } return dict; diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc index 6ca7c30..48cb2db 100644 --- a/net/quic/quic_connection_test.cc +++ b/net/quic/quic_connection_test.cc @@ -419,11 +419,9 @@ class TestConnection : public QuicConnection { TestConnectionHelper* helper, TestPacketWriter* writer, bool is_server, - QuicVersion version, - uint32 flow_control_send_window) + QuicVersion version) : QuicConnection(connection_id, address, helper, writer, is_server, - SupportedVersions(version), - flow_control_send_window), + SupportedVersions(version)), writer_(writer) { // Disable tail loss probes for most tests. QuicSentPacketManagerPeer::SetMaxTailLossProbes( @@ -588,8 +586,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> { helper_(new TestConnectionHelper(&clock_, &random_generator_)), writer_(new TestPacketWriter(version())), connection_(connection_id_, IPEndPoint(), helper_.get(), - writer_.get(), false, version(), - kDefaultFlowControlSendWindow), + writer_.get(), false, version()), frame1_(1, false, 0, MakeIOVector(data1)), frame2_(1, false, 3, MakeIOVector(data2)), sequence_number_length_(PACKET_6BYTE_SEQUENCE_NUMBER), @@ -613,7 +610,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<QuicVersion> { Return(kMaxPacketSize)); ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillByDefault(Return(true)); - EXPECT_CALL(visitor_, HasPendingWrites()).Times(AnyNumber()); + EXPECT_CALL(visitor_, WillingAndAbleToWrite()).Times(AnyNumber()); EXPECT_CALL(visitor_, HasPendingHandshake()).Times(AnyNumber()); EXPECT_CALL(visitor_, OnCanWrite()).Times(AnyNumber()); EXPECT_CALL(visitor_, HasOpenDataStreams()).WillRepeatedly(Return(false)); @@ -1444,7 +1441,8 @@ TEST_P(QuicConnectionTest, FECSending) { connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER, IN_FEC_GROUP, &payload_length); // And send FEC every two packets. - connection_.options()->max_packets_per_fec_group = 2; + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn( + QuicConnectionPeer::GetPacketCreator(&connection_), 2)); // Send 4 data packets and 2 FEC packets. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6); @@ -1463,7 +1461,8 @@ TEST_P(QuicConnectionTest, FECQueueing) { connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER, IN_FEC_GROUP, &payload_length); // And send FEC every two packets. - connection_.options()->max_packets_per_fec_group = 2; + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn( + QuicConnectionPeer::GetPacketCreator(&connection_), 2)); EXPECT_EQ(0u, connection_.NumQueuedPackets()); BlockOnNextWrite(); @@ -1475,7 +1474,9 @@ TEST_P(QuicConnectionTest, FECQueueing) { } TEST_P(QuicConnectionTest, AbandonFECFromCongestionWindow) { - connection_.options()->max_packets_per_fec_group = 1; + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn( + QuicConnectionPeer::GetPacketCreator(&connection_), 1)); + // 1 Data and 1 FEC packet. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); connection_.SendStreamDataWithString(3, "foo", 0, !kFin, NULL); @@ -1493,7 +1494,8 @@ TEST_P(QuicConnectionTest, AbandonFECFromCongestionWindow) { TEST_P(QuicConnectionTest, DontAbandonAckedFEC) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.options()->max_packets_per_fec_group = 1; + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn( + QuicConnectionPeer::GetPacketCreator(&connection_), 1)); // 1 Data and 1 FEC packet. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6); @@ -1520,7 +1522,8 @@ TEST_P(QuicConnectionTest, DontAbandonAckedFEC) { TEST_P(QuicConnectionTest, AbandonAllFEC) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.options()->max_packets_per_fec_group = 1; + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn( + QuicConnectionPeer::GetPacketCreator(&connection_), 1)); // 1 Data and 1 FEC packet. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6); @@ -1645,7 +1648,9 @@ TEST_P(QuicConnectionTest, FramePackingFEC) { return; } // Enable fec. - connection_.options()->max_packets_per_fec_group = 6; + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn( + QuicConnectionPeer::GetPacketCreator(&connection_), 6)); + // Block the connection. connection_.GetSendAlarm()->Set( clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1))); @@ -1778,7 +1783,7 @@ TEST_P(QuicConnectionTest, OnCanWrite) { &TestConnection::SendStreamData3)), IgnoreResult(InvokeWithoutArgs(&connection_, &TestConnection::SendStreamData5)))); - EXPECT_CALL(visitor_, HasPendingWrites()).WillOnce(Return(true)); + EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillOnce(Return(true)); EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)).WillRepeatedly( testing::Return(QuicTime::Delta::Zero())); @@ -3948,11 +3953,9 @@ TEST_P(QuicConnectionTest, Pacing) { ValueRestore<bool> old_flag(&FLAGS_enable_quic_pacing, true); TestConnection server(connection_id_, IPEndPoint(), helper_.get(), - writer_.get(), true, version(), - kDefaultFlowControlSendWindow); + writer_.get(), true, version()); TestConnection client(connection_id_, IPEndPoint(), helper_.get(), - writer_.get(), false, version(), - kDefaultFlowControlSendWindow); + writer_.get(), false, version()); EXPECT_TRUE(client.sent_packet_manager().using_pacing()); EXPECT_FALSE(server.sent_packet_manager().using_pacing()); } @@ -3980,17 +3983,6 @@ TEST_P(QuicConnectionTest, ControlFramesInstigateAcks) { EXPECT_TRUE(ack_alarm->IsSet()); } -TEST_P(QuicConnectionTest, InvalidFlowControlWindow) { - ValueRestore<bool> old_flag(&FLAGS_enable_quic_pacing, true); - - const uint32 kSmallerFlowControlWindow = kDefaultFlowControlSendWindow - 1; - TestConnection connection(connection_id_, IPEndPoint(), helper_.get(), - writer_.get(), true, version(), - kSmallerFlowControlWindow); - EXPECT_EQ(kDefaultFlowControlSendWindow, - connection.max_flow_control_receive_window_bytes()); -} - } // namespace } // namespace test } // namespace net diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc index 97452f5..d684a49 100644 --- a/net/quic/quic_crypto_client_stream.cc +++ b/net/quic/quic_crypto_client_stream.cc @@ -155,7 +155,7 @@ void QuicCryptoClientStream::DoHandshakeLoop( server_id_, session()->connection()->connection_id(), session()->connection()->supported_versions().front(), - session()->connection()->max_flow_control_receive_window_bytes(), + session()->max_flow_control_receive_window_bytes(), cached, session()->connection()->clock()->WallNow(), session()->connection()->random_generator(), diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc index c9ed0ece..62b7795 100644 --- a/net/quic/quic_crypto_server_stream.cc +++ b/net/quic/quic_crypto_server_stream.cc @@ -91,6 +91,7 @@ void QuicCryptoServerStream::FinishProcessingHandshakeMessage( // If we are returning a SHLO then we accepted the handshake. QuicConfig* config = session()->config(); + OverrideQuicConfigDefaults(config); error = config->ProcessPeerHello(message, CLIENT, &error_details); if (error != QUIC_NO_ERROR) { CloseConnectionWithDetails(error, error_details); @@ -172,12 +173,15 @@ QuicErrorCode QuicCryptoServerStream::ProcessClientHello( session()->connection()->peer_address(), session()->connection()->version(), session()->connection()->supported_versions(), - session()->connection()->max_flow_control_receive_window_bytes(), + session()->max_flow_control_receive_window_bytes(), session()->connection()->clock(), session()->connection()->random_generator(), &crypto_negotiated_params_, reply, error_details); } +void QuicCryptoServerStream::OverrideQuicConfigDefaults(QuicConfig* config) { +} + QuicCryptoServerStream::ValidateCallback::ValidateCallback( QuicCryptoServerStream* parent) : parent_(parent) { } diff --git a/net/quic/quic_crypto_server_stream.h b/net/quic/quic_crypto_server_stream.h index 316ae85..ee40131 100644 --- a/net/quic/quic_crypto_server_stream.h +++ b/net/quic/quic_crypto_server_stream.h @@ -51,6 +51,10 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream : public QuicCryptoStream { CryptoHandshakeMessage* reply, std::string* error_details); + // Hook that allows the server to set QuicConfig defaults just + // before going through the parameter negotiation step. + virtual void OverrideQuicConfigDefaults(QuicConfig* config); + private: friend class test::CryptoTestUtils; diff --git a/net/quic/quic_data_stream_test.cc b/net/quic/quic_data_stream_test.cc index b3c0f4c..164e7e4 100644 --- a/net/quic/quic_data_stream_test.cc +++ b/net/quic/quic_data_stream_test.cc @@ -30,7 +30,9 @@ namespace net { namespace test { namespace { -const QuicConnectionId kStreamId = 3; +// First non-reserved client stream ID. +const QuicStreamId kStreamId = 5; + const bool kIsServer = true; const bool kShouldProcessData = true; @@ -435,9 +437,9 @@ TEST_P(QuicDataStreamTest, ConnectionFlowControlWindowUpdate) { kWindow); QuicFlowControllerPeer::SetMaxReceiveWindow(stream2_->flow_controller(), kWindow); - QuicFlowControllerPeer::SetReceiveWindowOffset(connection_->flow_controller(), + QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(), kWindow); - QuicFlowControllerPeer::SetMaxReceiveWindow(connection_->flow_controller(), + QuicFlowControllerPeer::SetMaxReceiveWindow(session_->flow_controller(), kWindow); // Supply headers to both streams so that they are happy to receive data. @@ -463,7 +465,7 @@ TEST_P(QuicDataStreamTest, ConnectionFlowControlWindowUpdate) { EXPECT_CALL(*connection_, SendWindowUpdate(kStreamId + 2, _)).Times(0); EXPECT_CALL(*connection_, SendWindowUpdate(0, QuicFlowControllerPeer::ReceiveWindowOffset( - connection_->flow_controller()) + + session_->flow_controller()) + 1 + kWindow / 2)); QuicStreamFrame frame3(kStreamId, false, (kWindow / 4), MakeIOVector("a")); stream_->OnStreamFrame(frame3); @@ -518,7 +520,7 @@ TEST_P(QuicDataStreamTest, ConnectionFlowControlViolation) { const uint64 kConnectionWindow = 10; QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), kStreamWindow); - QuicFlowControllerPeer::SetReceiveWindowOffset(connection_->flow_controller(), + QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(), kConnectionWindow); string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); diff --git a/net/quic/quic_headers_stream_test.cc b/net/quic/quic_headers_stream_test.cc index 1c83b77..4022073 100644 --- a/net/quic/quic_headers_stream_test.cc +++ b/net/quic/quic_headers_stream_test.cc @@ -62,6 +62,12 @@ class MockVisitor : public SpdyFramerVisitorInterface { SpdyStreamId promised_stream_id, bool end)); MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end)); + MOCK_METHOD6(OnAltSvc, void(SpdyStreamId stream_id, + uint32 max_age, + uint16 port, + StringPiece protocol_id, + StringPiece host, + StringPiece origin)); }; class QuicHeadersStreamTest : public ::testing::TestWithParam<bool> { diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc index 557e976..206c00d 100644 --- a/net/quic/quic_http_stream_test.cc +++ b/net/quic/quic_http_stream_test.cc @@ -60,7 +60,7 @@ class TestQuicConnection : public QuicConnection { QuicConnectionHelper* helper, QuicPacketWriter* writer) : QuicConnection(connection_id, address, helper, writer, false, - versions, kInitialFlowControlWindowForTest) { + versions) { } void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) { @@ -212,7 +212,9 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> { make_scoped_ptr((QuicServerInfo*)NULL), QuicServerId(kServerHostname, kServerPort, false, PRIVACY_MODE_DISABLED), - DefaultQuicConfig(), &crypto_config_, NULL)); + DefaultQuicConfig(), + kInitialFlowControlWindowForTest, &crypto_config_, + NULL)); session_->GetCryptoStream()->CryptoConnect(); EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed()); stream_.reset(use_closing_stream_ ? diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc index 4c57b4b..e567a05 100644 --- a/net/quic/quic_packet_creator.cc +++ b/net/quic/quic_packet_creator.cc @@ -64,6 +64,7 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id, framer_(framer), random_bool_source_(new QuicRandomBoolSource(random_generator)), sequence_number_(0), + should_fec_protect_(false), fec_group_number_(0), is_server_(is_server), send_version_in_packet_(!is_server), @@ -85,12 +86,59 @@ 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); + (force_close || fec_group_->NumReceivedPackets() >= + options_.max_packets_per_fec_group); } -InFecGroup QuicPacketCreator::MaybeStartFEC() { - if (IsFecEnabled() && fec_group_.get() == NULL) { +void QuicPacketCreator::StartFecProtectingPackets() { + if (!IsFecEnabled()) { + LOG(DFATAL) << "Cannot start FEC protection when FEC is not enabled."; + return; + } + // TODO(jri): This currently requires that the generator flush out any + // pending frames when FEC protection is turned on. If current packet can be + // converted to an FEC protected packet, do it. This will require the + // generator to check if the resulting expansion still allows the incoming + // frame to be added to the packet. + if (HasPendingFrames()) { + LOG(DFATAL) << "Cannot start FEC protection with pending frames."; + return; + } + DCHECK(!should_fec_protect_); + should_fec_protect_ = true; +} + +void QuicPacketCreator::StopFecProtectingPackets() { + if (fec_group_.get() != NULL) { + LOG(DFATAL) << "Cannot stop FEC protection with open FEC group."; + return; + } + DCHECK(should_fec_protect_); + should_fec_protect_ = false; + fec_group_number_ = 0; +} + +bool QuicPacketCreator::IsFecProtected() const { + return should_fec_protect_; +} + +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; +} + +InFecGroup QuicPacketCreator::MaybeStartFec() { + if (should_fec_protect_ && fec_group_.get() == NULL) { DCHECK(queued_frames_.empty()); // Set the fec group number to the sequence number of the next packet. fec_group_number_ = sequence_number() + 1; @@ -134,7 +182,8 @@ bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id, // QuicPacketCreator. return BytesFree() > QuicFramer::GetMinStreamFrameSize(framer_->version(), id, offset, true, - IsFecEnabled()); + should_fec_protect_ ? IN_FEC_GROUP : + NOT_IN_FEC_GROUP); } // static @@ -159,7 +208,8 @@ size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id, StreamFramePacketOverhead( framer_->version(), PACKET_8BYTE_CONNECTION_ID, kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, IN_FEC_GROUP)); - InFecGroup is_in_fec_group = MaybeStartFEC(); + + InFecGroup is_in_fec_group = MaybeStartFec(); LOG_IF(DFATAL, !HasRoomForStreamFrame(id, offset)) << "No room for Stream frame, BytesFree: " << BytesFree() @@ -210,25 +260,22 @@ size_t QuicPacketCreator::CreateStreamFrameWithNotifier( SerializedPacket QuicPacketCreator::ReserializeAllFrames( const QuicFrames& frames, QuicSequenceNumberLength original_length) { - const QuicSequenceNumberLength start_length = sequence_number_length_; - const QuicSequenceNumberLength start_options_length = + DCHECK(fec_group_.get() == NULL); + const QuicSequenceNumberLength saved_length = sequence_number_length_; + const QuicSequenceNumberLength saved_options_length = options_.send_sequence_number_length; - const QuicFecGroupNumber start_fec_group = fec_group_number_; - const size_t start_max_packets_per_fec_group = - options_.max_packets_per_fec_group; + const bool saved_should_fec_protect = should_fec_protect_; - // Temporarily set the sequence number length and disable FEC. + // Temporarily set the sequence number length and stop FEC protection. sequence_number_length_ = original_length; options_.send_sequence_number_length = original_length; - fec_group_number_ = 0; - options_.max_packets_per_fec_group = 0; + should_fec_protect_ = false; - // Serialize the packet and restore the fec and sequence number length state. + // Serialize the packet and restore the FEC and sequence number length state. SerializedPacket serialized_packet = SerializeAllFrames(frames); - sequence_number_length_ = start_length; - options_.send_sequence_number_length = start_options_length; - fec_group_number_ = start_fec_group; - options_.max_packets_per_fec_group = start_max_packets_per_fec_group; + sequence_number_length_ = saved_length; + options_.send_sequence_number_length = saved_options_length; + should_fec_protect_ = saved_should_fec_protect; return serialized_packet; } @@ -256,7 +303,7 @@ bool QuicPacketCreator::HasPendingFrames() { size_t QuicPacketCreator::ExpansionOnNewFrame() const { // If packet is FEC protected, there's no expansion. - if (fec_group_.get() != NULL) { + if (should_fec_protect_) { return 0; } // If the last frame in the packet is a stream frame, then it will expand to @@ -274,11 +321,6 @@ size_t QuicPacketCreator::BytesFree() const { + ExpansionOnNewFrame()); } -InFecGroup QuicPacketCreator::IsFecEnabled() const { - return (options_.max_packets_per_fec_group == 0) ? - NOT_IN_FEC_GROUP : IN_FEC_GROUP; -} - size_t QuicPacketCreator::PacketSize() const { if (queued_frames_.empty()) { // Only adjust the sequence number length when the FEC group is not open, @@ -290,7 +332,8 @@ size_t QuicPacketCreator::PacketSize() const { packet_size_ = GetPacketHeaderSize(options_.send_connection_id_length, send_version_in_packet_, sequence_number_length_, - IsFecEnabled()); + should_fec_protect_ ? IN_FEC_GROUP : + NOT_IN_FEC_GROUP); } return packet_size_; } @@ -302,8 +345,9 @@ bool QuicPacketCreator::AddSavedFrame(const QuicFrame& frame) { SerializedPacket QuicPacketCreator::SerializePacket() { LOG_IF(DFATAL, queued_frames_.empty()) << "Attempt to serialize empty packet"; + DCHECK_GE(sequence_number_ + 1, fec_group_number_); QuicPacketHeader header; - FillPacketHeader(fec_group_number_, false, &header); + FillPacketHeader(should_fec_protect_ ? fec_group_number_ : 0, false, &header); MaybeAddPadding(); @@ -348,7 +392,6 @@ SerializedPacket QuicPacketCreator::SerializeFec() { fec_data.redundancy = fec_group_->payload_parity(); SerializedPacket serialized = framer_->BuildFecPacket(header, fec_data); fec_group_.reset(NULL); - fec_group_number_ = 0; packet_size_ = 0; LOG_IF(DFATAL, !serialized.packet) << "Failed to serialize fec packet for group:" << fec_data.fec_group; @@ -407,7 +450,7 @@ bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) { bool QuicPacketCreator::AddFrame(const QuicFrame& frame, bool save_retransmittable_frames) { DVLOG(1) << "Adding frame: " << frame; - InFecGroup is_in_fec_group = MaybeStartFEC(); + InFecGroup is_in_fec_group = MaybeStartFec(); size_t frame_len = framer_->GetSerializedFrameLength( frame, BytesFree(), queued_frames_.empty(), true, is_in_fec_group, options()->send_sequence_number_length); diff --git a/net/quic/quic_packet_creator.h b/net/quic/quic_packet_creator.h index 95c0847..f8b60ee 100644 --- a/net/quic/quic_packet_creator.h +++ b/net/quic/quic_packet_creator.h @@ -57,10 +57,27 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface { virtual void OnBuiltFecProtectedPayload(const QuicPacketHeader& header, base::StringPiece payload) OVERRIDE; + // Turn on FEC protection for subsequently created packets. FEC should + // be enabled first (set_max_packets_per_fec_group should be non-zero) for + // FEC protection to start. + 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 + // 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. 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(); @@ -109,19 +126,23 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface { // Re-serializes frames with the original packet's sequence number length. // Used for retransmitting packets to ensure they aren't too long. + // Caller must ensure that any open FEC group are closed before calling this + // method. SerializedPacket ReserializeAllFrames( const QuicFrames& frames, QuicSequenceNumberLength original_length); // Returns true if there are frames pending to be serialized. bool HasPendingFrames(); - // Returns IN_FEC_GROUP or NOT_IN_FEC_GROUP, depending on whether FEC is - // enabled or not. Note: This does not mean that an FEC group is currently - // active; i.e., fec_group_.get() may still be NULL. - // TODO(jri): Straighten out naming: Enabling FEC for the connection - // should use FEC_ENABLED/DISABLED, and IN_FEC_GROUP/NOT_IN_FEC_GROUP should - // be used if a given packet is in an fec group. - InFecGroup IsFecEnabled() const; + // Returns whether FEC protection is currently enabled. Note: Enabled does not + // mean that an FEC group is currently active; i.e., IsFecProtected() may + // still return NOT_IN_FEC_GROUP, and fec_group_.get() may still be NULL. + bool IsFecEnabled() const; + + // Returns true if subsequent packets will be FEC protected. Note: True does + // not mean that an FEC packet is currently under construction; i.e., + // fec_group_.get() may still be NULL, until MaybeStartFec() is called. + bool IsFecProtected() const; // Returns the number of bytes which are available to be used by additional // frames in the packet. Since stream frames are slightly smaller when they @@ -202,7 +223,7 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface { // Starts a new FEC group with the next serialized packet, if FEC is enabled // and there is not already an FEC group open. - InFecGroup MaybeStartFEC(); + InFecGroup MaybeStartFec(); void FillPacketHeader(QuicFecGroupNumber fec_group, bool fec_flag, @@ -223,6 +244,8 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface { QuicFramer* framer_; scoped_ptr<QuicRandomBoolSource> random_bool_source_; QuicPacketSequenceNumber sequence_number_; + // If true, any created packets will be FEC protected. + bool should_fec_protect_; QuicFecGroupNumber fec_group_number_; scoped_ptr<QuicFecGroup> fec_group_; // bool to keep track if this packet creator is being used the server. diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc index 6d0ea5c..72faf7e 100644 --- a/net/quic/quic_packet_creator_test.cc +++ b/net/quic/quic_packet_creator_test.cc @@ -119,7 +119,6 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> { return QuicFramer::GetMinStreamFrameSize( client_framer_.version(), kStreamId, kOffset, true, is_in_fec_group); } - static const QuicStreamId kStreamId = 1u; static const QuicStreamOffset kOffset = 1u; @@ -140,7 +139,6 @@ INSTANTIATE_TEST_CASE_P(QuicPacketCreatorTests, QuicPacketCreatorTest, ::testing::ValuesIn(GetTestParams())); - TEST_P(QuicPacketCreatorTest, SerializeFrames) { frames_.push_back(QuicFrame(new QuicAckFrame(MakeAckFrame(0u, 0u)))); frames_.push_back(QuicFrame(new QuicStreamFrame(0u, false, 0u, IOVector()))); @@ -167,7 +165,8 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) { } TEST_P(QuicPacketCreatorTest, SerializeWithFEC) { - creator_.options()->max_packets_per_fec_group = 6; + // Enable FEC protection, and send FEC packet every 6 packets. + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(&creator_, 6)); // Should return false since we do not have enough packets in the FEC group to // trigger an FEC packet. ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); @@ -259,7 +258,9 @@ TEST_P(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) { // P1 <change seq num length> P2 FEC, // and we expect that sequence number length should not change until the end // of the open FEC group. - creator_.options()->max_packets_per_fec_group = 6; + + // Enable FEC protection, and send FEC packet every 6 packets. + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(&creator_, 6)); // Should return false since we do not have enough packets in the FEC group to // trigger an FEC packet. ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); @@ -391,6 +392,83 @@ TEST_P(QuicPacketCreatorTest, SerializeConnectionClose) { delete serialized.packet; } +TEST_P(QuicPacketCreatorTest, SwitchFecOnOffWithNoGroup) { + // Enable FEC protection. + creator_.set_max_packets_per_fec_group(6); + EXPECT_TRUE(creator_.IsFecEnabled()); + EXPECT_FALSE(creator_.IsFecProtected()); + + // Turn on FEC protection. + creator_.StartFecProtectingPackets(); + EXPECT_TRUE(creator_.IsFecProtected()); + // We have no packets in the FEC group, so no FEC packet can be created. + EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/true)); + // Since no packets are in FEC group yet, we should be able to turn FEC + // off with no trouble. + creator_.StopFecProtectingPackets(); + EXPECT_FALSE(creator_.IsFecProtected()); +} + +TEST_P(QuicPacketCreatorTest, SwitchFecOnOffWithGroupInProgress) { + // Enable FEC protection, and send FEC packet every 6 packets. + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(&creator_, 6)); + frames_.push_back(QuicFrame(new QuicStreamFrame(0u, false, 0u, IOVector()))); + SerializedPacket serialized = creator_.SerializeAllFrames(frames_); + delete frames_[0].stream_frame; + delete serialized.packet; + + EXPECT_TRUE(creator_.IsFecProtected()); + // We do not have enough packets in the FEC group to trigger an FEC packet. + EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); + // Should return true since there are packets in the FEC group. + EXPECT_TRUE(creator_.ShouldSendFec(/*force_close=*/true)); + + // Switching FEC off should not change creator state, since there is an + // FEC packet under construction. + EXPECT_DFATAL(creator_.StopFecProtectingPackets(), + "Cannot stop FEC protection with open FEC group."); + EXPECT_TRUE(creator_.IsFecProtected()); + // Confirm that FEC packet is still under construction. + EXPECT_TRUE(creator_.ShouldSendFec(/*force_close=*/true)); + + serialized = creator_.SerializeFec(); + delete serialized.packet; + + // Switching FEC on/off should work now. + creator_.StopFecProtectingPackets(); + EXPECT_FALSE(creator_.IsFecProtected()); + creator_.StartFecProtectingPackets(); + EXPECT_TRUE(creator_.IsFecProtected()); +} + +TEST_P(QuicPacketCreatorTest, SwitchFecOnWithStreamFrameQueued) { + // Add a stream frame to the creator. + QuicFrame frame; + size_t consumed = creator_.CreateStreamFrame( + 1u, MakeIOVector("test"), 0u, false, &frame); + EXPECT_EQ(4u, consumed); + ASSERT_TRUE(frame.stream_frame); + EXPECT_TRUE(creator_.AddSavedFrame(frame)); + EXPECT_TRUE(creator_.HasPendingFrames()); + + // Enable FEC protection, and send FEC packet every 6 packets. + creator_.set_max_packets_per_fec_group(6); + EXPECT_TRUE(creator_.IsFecEnabled()); + EXPECT_DFATAL(creator_.StartFecProtectingPackets(), + "Cannot start FEC protection with pending frames."); + EXPECT_FALSE(creator_.IsFecProtected()); + + // Serialize packet for transmission. + SerializedPacket serialized = creator_.SerializePacket(); + delete serialized.packet; + delete serialized.retransmittable_frames; + EXPECT_FALSE(creator_.HasPendingFrames()); + + // Since all pending frames have been serialized, turning FEC on should work. + creator_.StartFecProtectingPackets(); + EXPECT_TRUE(creator_.IsFecProtected()); +} + TEST_P(QuicPacketCreatorTest, CreateStreamFrame) { QuicFrame frame; size_t consumed = creator_.CreateStreamFrame(1u, MakeIOVector("test"), 0u, @@ -469,8 +547,8 @@ TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) { } TEST_P(QuicPacketCreatorTest, StreamFrameConsumptionWithFec) { - // Turn on FEC protection. - creator_.options()->max_packets_per_fec_group = 6; + // Enable FEC protection, and send FEC packet every 6 packets. + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(&creator_, 6)); // Compute the total overhead for a single frame in packet. const size_t overhead = GetPacketHeaderOverhead(IN_FEC_GROUP) + GetEncryptionOverhead() + GetStreamFrameOverhead(IN_FEC_GROUP); diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc index 8bb1dfd..16f9748 100644 --- a/net/quic/quic_packet_generator_test.cc +++ b/net/quic/quic_packet_generator_test.cc @@ -11,6 +11,7 @@ #include "net/quic/crypto/quic_decrypter.h" #include "net/quic/crypto/quic_encrypter.h" #include "net/quic/quic_utils.h" +#include "net/quic/test_tools/quic_packet_creator_peer.h" #include "net/quic/test_tools/quic_test_utils.h" #include "net/quic/test_tools/simple_quic_framer.h" #include "testing/gmock/include/gmock/gmock.h" @@ -439,7 +440,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeDataFEC) { delegate_.SetCanWriteAnything(); // Send FEC every two packets. - creator_.options()->max_packets_per_fec_group = 2; + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(&creator_, 2)); { InSequence dummy; @@ -475,8 +476,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeDataSendsFecAtEnd) { delegate_.SetCanWriteAnything(); // Send FEC every six packets. - creator_.options()->max_packets_per_fec_group = 6; - + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(&creator_, 6)); { InSequence dummy; EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce( diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc index 32c5c31..0f92e45 100644 --- a/net/quic/quic_protocol.cc +++ b/net/quic/quic_protocol.cc @@ -525,6 +525,10 @@ ostream& operator<<(ostream& os, os << " receive_window: " << tcp.receive_window; break; } + case kTCPBBR: { + LOG(DFATAL) << "TCPBBR is not yet supported."; + break; + } } return os; } diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h index 1a14201..93236bb 100644 --- a/net/quic/quic_protocol.h +++ b/net/quic/quic_protocol.h @@ -57,6 +57,8 @@ const QuicByteCount kDefaultMaxPacketSize = 1200; // additional 8 bytes. This is a total overhead of 48 bytes. Ethernet's // max packet size is 1500 bytes, 1500 - 48 = 1452. const QuicByteCount kMaxPacketSize = 1452; +// Default maximum packet size used in Linux TCP implementations. +const QuicByteCount kDefaultTCPMSS = 1460; // Maximum size of the initial congestion window in packets. const size_t kDefaultInitialWindow = 10; @@ -275,7 +277,8 @@ enum QuicVersion { // // IMPORTANT: if you are addding to this list, follow the instructions at // http://sites/quic/adding-and-removing-versions -static const QuicVersion kSupportedQuicVersions[] = {QUIC_VERSION_18, +static const QuicVersion kSupportedQuicVersions[] = {QUIC_VERSION_19, + QUIC_VERSION_18, QUIC_VERSION_17, QUIC_VERSION_16, QUIC_VERSION_15}; @@ -688,6 +691,7 @@ enum CongestionFeedbackType { kTCP, // Used to mimic TCP. kInterArrival, // Use additional inter arrival information. kFixRate, // Provided for testing. + kTCPBBR, // BBR implementation based on TCP congestion feedback. }; enum LossDetectionType { diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc index cffdd4d..d92140a 100644 --- a/net/quic/quic_sent_packet_manager.cc +++ b/net/quic/quic_sent_packet_manager.cc @@ -38,6 +38,9 @@ static const size_t kMinHandshakeTimeoutMs = 10; static const size_t kDefaultMaxTailLossProbes = 2; static const int64 kMinTailLossProbeTimeoutMs = 10; +// Number of samples before we force a new recent min rtt to be captured. +static const size_t kNumMinRttSamplesAfterQuiescence = 2; + bool HasCryptoHandshake(const TransmissionInfo& transmission_info) { if (transmission_info.retransmittable_frames == NULL) { return false; @@ -172,7 +175,7 @@ void QuicSentPacketManager::HandleAckForSentPackets( if (IsAwaitingPacket(received_info, sequence_number)) { // Remove any packets not being tracked by the send algorithm, allowing // the high water mark to be raised if necessary. - if (QuicUnackedPacketMap::IsSentAndNotPending(it->second)) { + if (QuicUnackedPacketMap::IsForRttOnly(it->second)) { it = MarkPacketHandled(sequence_number, delta_largest_observed); } else { // Consider it multiple nacks when there is a gap between the missing @@ -261,10 +264,14 @@ void QuicSentPacketManager::NeuterUnencryptedPackets() { // they are not retransmitted or considered lost from a congestion control // perspective. pending_retransmissions_.erase(it->first); - // TODO(ianswett): This may cause packets to linger forever in the - // UnackedPacketMap. - unacked_packets_.NeuterPacket(it->first); unacked_packets_.SetNotPending(it->first); + // TODO(ianswett): Clean this up so UnackedPacketMap maintains the correct + // invariants between the various transmissions for NeuterPacket. + SequenceNumberSet all_transmissions = *it->second.all_transmissions; + for (SequenceNumberSet::const_iterator all_it = all_transmissions.begin(); + all_it != all_transmissions.end(); ++all_it) { + unacked_packets_.NeuterPacket(*all_it); + } } } } @@ -440,24 +447,25 @@ bool QuicSentPacketManager::OnPacketSent( return false; } - // Only track packets as pending that the send algorithm wants us to track. - if (!send_algorithm_->OnPacketSent(sent_time, - unacked_packets_.bytes_in_flight(), - sequence_number, - bytes, - has_retransmittable_data)) { - unacked_packets_.SetSent(sequence_number, sent_time, bytes, false); - // Do not reset the retransmission timer, since the packet isn't tracked. - return false; + if (unacked_packets_.bytes_in_flight() == 0) { + // TODO(ianswett): Consider being less aggressive to force a new + // recent_min_rtt, likely by not discarding a relatively new sample. + DVLOG(1) << "Sampling a new recent min rtt within 2 samples. currently:" + << rtt_stats_.recent_min_rtt().ToMilliseconds() << "ms"; + rtt_stats_.SampleNewRecentMinRtt(kNumMinRttSamplesAfterQuiescence); } - const bool set_retransmission_timer = !unacked_packets_.HasPendingPackets(); - - unacked_packets_.SetSent(sequence_number, sent_time, bytes, true); - - // Reset the retransmission timer anytime a packet is sent in tail loss probe - // mode or before the crypto handshake has completed. - return set_retransmission_timer || GetRetransmissionMode() != RTO_MODE; + // Only track packets as pending that the send algorithm wants us to track. + const bool pending = + send_algorithm_->OnPacketSent(sent_time, + unacked_packets_.bytes_in_flight(), + sequence_number, + bytes, + has_retransmittable_data); + unacked_packets_.SetSent(sequence_number, sent_time, bytes, pending); + + // Reset the retransmission timer anytime a pending packet is sent. + return pending; } void QuicSentPacketManager::OnRetransmissionTimeout() { diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc index 7d0bfed..aef7c10 100644 --- a/net/quic/quic_sent_packet_manager_test.cc +++ b/net/quic/quic_sent_packet_manager_test.cc @@ -191,6 +191,7 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> { SerializedPacket packet(CreateDataPacket(sequence_number)); packet.retransmittable_frames->AddStreamFrame( new QuicStreamFrame(1, false, 0, IOVector())); + packet.retransmittable_frames->set_encryption_level(ENCRYPTION_NONE); manager_.OnSerializedPacket(packet); manager_.OnPacketSent(sequence_number, clock_.ApproximateNow(), packet.packet->length(), NOT_RETRANSMISSION, @@ -981,6 +982,41 @@ TEST_F(QuicSentPacketManagerTest, EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_)); } +TEST_F(QuicSentPacketManagerTest, + CryptoHandshakeRetransmissionThenNeuterAndAck) { + // Send 1 crypto packet. + SendCryptoPacket(1); + EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_)); + + // Retransmit the crypto packet as 2. + manager_.OnRetransmissionTimeout(); + RetransmitNextPacket(2); + + // Retransmit the crypto packet as 3. + manager_.OnRetransmissionTimeout(); + RetransmitNextPacket(3); + + // Now neuter all unacked unencrypted packets, which occurs when the + // connection goes forward secure. + manager_.NeuterUnencryptedPackets(); + QuicPacketSequenceNumber unacked[] = { 1, 2, 3}; + VerifyUnackedPackets(unacked, arraysize(unacked)); + VerifyRetransmittablePackets(NULL, 0); + EXPECT_FALSE(manager_.HasPendingRetransmissions()); + EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_)); + EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_)); + + // Ensure both packets get discarded when packet 2 is acked. + ReceivedPacketInfo received_info; + received_info.largest_observed = 3; + received_info.missing_packets.insert(1); + received_info.missing_packets.insert(2); + ExpectUpdatedRtt(3); + manager_.OnIncomingAck(received_info, clock_.ApproximateNow()); + VerifyUnackedPackets(NULL, 0); + VerifyRetransmittablePackets(NULL, 0); +} + TEST_F(QuicSentPacketManagerTest, TailLossProbeTimeoutUnsentDataPacket) { QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2); // Serialize two data packets and send the latter. @@ -998,6 +1034,44 @@ TEST_F(QuicSentPacketManagerTest, TailLossProbeTimeoutUnsentDataPacket) { EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_)); } +TEST_F(QuicSentPacketManagerTest, ResetRecentMinRTTWithEmptyWindow) { + QuicTime::Delta min_rtt = QuicTime::Delta::FromMilliseconds(50); + QuicSentPacketManagerPeer::GetRttStats(&manager_)->UpdateRtt( + min_rtt, QuicTime::Delta::Zero(), QuicTime::Zero()); + EXPECT_EQ(min_rtt, + QuicSentPacketManagerPeer::GetRttStats(&manager_)->min_rtt()); + EXPECT_EQ(min_rtt, + QuicSentPacketManagerPeer::GetRttStats( + &manager_)->recent_min_rtt()); + + // Send two packets with no prior bytes in flight. + SendDataPacket(1); + SendDataPacket(2); + + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100)); + // Ack two packets with 100ms RTT observations. + ReceivedPacketInfo received_info; + received_info.delta_time_largest_observed = QuicTime::Delta::Zero(); + received_info.largest_observed = 1; + ExpectAck(1); + manager_.OnIncomingAck(received_info, clock_.Now()); + + // First ack does not change recent min rtt. + EXPECT_EQ(min_rtt, + QuicSentPacketManagerPeer::GetRttStats( + &manager_)->recent_min_rtt()); + + received_info.largest_observed = 2; + ExpectAck(2); + manager_.OnIncomingAck(received_info, clock_.Now()); + + EXPECT_EQ(min_rtt, + QuicSentPacketManagerPeer::GetRttStats(&manager_)->min_rtt()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), + QuicSentPacketManagerPeer::GetRttStats( + &manager_)->recent_min_rtt()); +} + TEST_F(QuicSentPacketManagerTest, RetransmissionTimeout) { // Send 100 packets and then ensure all are abandoned when the RTO fires. const size_t kNumSentPackets = 100; diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc index 6d749ec..9b28103 100644 --- a/net/quic/quic_session.cc +++ b/net/quic/quic_session.cc @@ -8,6 +8,7 @@ #include "net/quic/crypto/proof_verifier.h" #include "net/quic/quic_connection.h" #include "net/quic/quic_flags.h" +#include "net/quic/quic_flow_controller.h" #include "net/quic/quic_headers_stream.h" #include "net/ssl/ssl_info.h" @@ -78,8 +79,8 @@ class VisitorShim : public QuicConnectionVisitorInterface { session_->OnWriteBlocked(); } - virtual bool HasPendingWrites() const OVERRIDE { - return session_->HasPendingWrites(); + virtual bool WillingAndAbleToWrite() const OVERRIDE { + return session_->WillingAndAbleToWrite(); } virtual bool HasPendingHandshake() const OVERRIDE { @@ -95,6 +96,7 @@ class VisitorShim : public QuicConnectionVisitorInterface { }; QuicSession::QuicSession(QuicConnection* connection, + uint32 max_flow_control_receive_window_bytes, const QuicConfig& config) : connection_(connection), visitor_shim_(new VisitorShim(this)), @@ -105,7 +107,20 @@ QuicSession::QuicSession(QuicConnection* connection, error_(QUIC_NO_ERROR), goaway_received_(false), goaway_sent_(false), - has_pending_handshake_(false) { + has_pending_handshake_(false), + max_flow_control_receive_window_bytes_( + max_flow_control_receive_window_bytes) { + if (max_flow_control_receive_window_bytes_ < kDefaultFlowControlSendWindow) { + LOG(ERROR) << "Initial receive window (" + << max_flow_control_receive_window_bytes_ + << ") cannot be set lower than default (" + << kDefaultFlowControlSendWindow << ")."; + max_flow_control_receive_window_bytes_ = kDefaultFlowControlSendWindow; + } + flow_controller_.reset(new QuicFlowController( + connection_->supported_versions().front(), 0, is_server(), + kDefaultFlowControlSendWindow, max_flow_control_receive_window_bytes_, + max_flow_control_receive_window_bytes_)); connection_->set_visitor(visitor_shim_.get()); connection_->SetFromConfig(config_); @@ -229,8 +244,7 @@ void QuicSession::OnWindowUpdateFrames( << "Received connection level flow control window update with " "byte offset: " << frames[i].byte_offset; if (FLAGS_enable_quic_connection_flow_control && - connection()->flow_controller()->UpdateSendWindowOffset( - frames[i].byte_offset)) { + flow_controller_->UpdateSendWindowOffset(frames[i].byte_offset)) { connection_window_updated = true; } continue; @@ -261,9 +275,22 @@ void QuicSession::OnBlockedFrames(const vector<QuicBlockedFrame>& frames) { void QuicSession::OnCanWrite() { // We limit the number of writes to the number of pending streams. If more - // streams become pending, HasPendingWrites will be true, which will cause - // the connection to request resumption before yielding to other connections. + // streams become pending, WillingAndAbleToWrite will be true, which will + // cause the connection to request resumption before yielding to other + // connections. size_t num_writes = write_blocked_streams_.NumBlockedStreams(); + if (flow_controller_->IsBlocked()) { + // If we are connection level flow control blocked, then only allow the + // crypto and headers streams to try writing as all other streams will be + // blocked. + num_writes = 0; + if (write_blocked_streams_.crypto_stream_blocked()) { + num_writes += 1; + } + if (write_blocked_streams_.headers_stream_blocked()) { + num_writes += 1; + } + } if (num_writes == 0) { return; } @@ -271,7 +298,8 @@ void QuicSession::OnCanWrite() { QuicConnection::ScopedPacketBundler ack_bundler( connection_.get(), QuicConnection::NO_ACK); for (size_t i = 0; i < num_writes; ++i) { - if (!write_blocked_streams_.HasWriteBlockedStreams()) { + if (!(write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || + write_blocked_streams_.HasWriteBlockedDataStreams())) { // Writing one stream removed another!? Something's broken. LOG(DFATAL) << "WriteBlockedStream is missing"; connection_->CloseConnection(QUIC_INTERNAL_ERROR, false); @@ -293,8 +321,14 @@ void QuicSession::OnCanWrite() { } } -bool QuicSession::HasPendingWrites() const { - return write_blocked_streams_.HasWriteBlockedStreams(); +bool QuicSession::WillingAndAbleToWrite() const { + // If the crypto or headers streams are blocked, we want to schedule a write - + // they don't get blocked by connection level flow control. Otherwise only + // schedule a write if we are not flow control blocked at the connection + // level. + return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || + (!flow_controller_->IsBlocked() && + write_blocked_streams_.HasWriteBlockedDataStreams()); } bool QuicSession::HasPendingHandshake() const { @@ -399,8 +433,7 @@ void QuicSession::OnConfigNegotiated() { } // Update connection level window. - connection()->flow_controller()->UpdateSendWindowOffset( - new_flow_control_send_window); + flow_controller_->UpdateSendWindowOffset(new_flow_control_send_window); } } @@ -591,8 +624,9 @@ void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) { } bool QuicSession::HasDataToWrite() const { - return write_blocked_streams_.HasWriteBlockedStreams() || - connection_->HasQueuedData(); + return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || + write_blocked_streams_.HasWriteBlockedDataStreams() || + connection_->HasQueuedData(); } bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const { @@ -605,4 +639,10 @@ void QuicSession::PostProcessAfterData() { closed_streams_.clear(); } +void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) { + if (version < QUIC_VERSION_19) { + flow_controller_->Disable(); + } +} + } // namespace net diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h index 2bbd8ba..d23b684 100644 --- a/net/quic/quic_session.h +++ b/net/quic/quic_session.h @@ -25,6 +25,7 @@ namespace net { class QuicCryptoStream; +class QuicFlowController; class ReliableQuicStream; class SSLInfo; class VisitorShim; @@ -53,6 +54,7 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { }; QuicSession(QuicConnection* connection, + uint32 max_flow_control_receive_window_bytes, const QuicConfig& config); virtual ~QuicSession(); @@ -69,9 +71,9 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer) OVERRIDE; virtual void OnWriteBlocked() OVERRIDE {} virtual void OnSuccessfulVersionNegotiation( - const QuicVersion& version) OVERRIDE {} + const QuicVersion& version) OVERRIDE; virtual void OnCanWrite() OVERRIDE; - virtual bool HasPendingWrites() const OVERRIDE; + virtual bool WillingAndAbleToWrite() const OVERRIDE; virtual bool HasPendingHandshake() const OVERRIDE; virtual bool HasOpenDataStreams() const OVERRIDE; @@ -201,6 +203,12 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { bool is_server() const { return connection_->is_server(); } + uint32 max_flow_control_receive_window_bytes() { + return max_flow_control_receive_window_bytes_; + } + + QuicFlowController* flow_controller() { return flow_controller_.get(); } + protected: typedef base::hash_map<QuicStreamId, QuicDataStream*> DataStreamMap; @@ -295,6 +303,12 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { // Indicate if there is pending data for the crypto stream. bool has_pending_handshake_; + // Used for session level flow control. + scoped_ptr<QuicFlowController> flow_controller_; + + // Initial flow control receive window size for new streams. + uint32 max_flow_control_receive_window_bytes_; + DISALLOW_COPY_AND_ASSIGN(QuicSession); }; diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc index b2dfa0e..17f53f5 100644 --- a/net/quic/quic_session_test.cc +++ b/net/quic/quic_session_test.cc @@ -17,6 +17,7 @@ #include "net/quic/reliable_quic_stream.h" #include "net/quic/test_tools/quic_connection_peer.h" #include "net/quic/test_tools/quic_data_stream_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" #include "net/quic/test_tools/reliable_quic_stream_peer.h" @@ -66,6 +67,15 @@ class TestCryptoStream : public QuicCryptoStream { MOCK_METHOD0(OnCanWrite, void()); }; +class TestHeadersStream : public QuicHeadersStream { + public: + explicit TestHeadersStream(QuicSession* session) + : QuicHeadersStream(session) { + } + + MOCK_METHOD0(OnCanWrite, void()); +}; + class TestStream : public QuicDataStream { public: TestStream(QuicStreamId id, QuicSession* session) @@ -104,11 +114,12 @@ class StreamBlocker { class TestSession : public QuicSession { public: - explicit TestSession(QuicConnection* connection) - : QuicSession(connection, DefaultQuicConfig()), + explicit TestSession(QuicConnection* connection, + uint32 max_initial_flow_control_window) + : QuicSession(connection, max_initial_flow_control_window, + DefaultQuicConfig()), crypto_stream_(this), - writev_consumes_all_data_(false) { - } + writev_consumes_all_data_(false) {} virtual TestCryptoStream* GetCryptoStream() OVERRIDE { return &crypto_stream_; @@ -156,7 +167,7 @@ class TestSession : public QuicSession { } private: - TestCryptoStream crypto_stream_; + StrictMock<TestCryptoStream> crypto_stream_; bool writev_consumes_all_data_; }; @@ -165,7 +176,7 @@ class QuicSessionTest : public ::testing::TestWithParam<QuicVersion> { protected: QuicSessionTest() : connection_(new MockConnection(true, SupportedVersions(GetParam()))), - session_(connection_) { + session_(connection_, kInitialFlowControlWindowForTest) { headers_[":host"] = "www.google.com"; headers_[":path"] = "/index.hml"; headers_[":scheme"] = "http"; @@ -349,7 +360,7 @@ TEST_P(QuicSessionTest, OnCanWrite) { EXPECT_CALL(*stream6, OnCanWrite()); EXPECT_CALL(*stream4, OnCanWrite()); session_.OnCanWrite(); - EXPECT_TRUE(session_.HasPendingWrites()); + EXPECT_TRUE(session_.WillingAndAbleToWrite()); } TEST_P(QuicSessionTest, OnCanWriteBundlesStreams) { @@ -383,7 +394,7 @@ TEST_P(QuicSessionTest, OnCanWriteBundlesStreams) { Return(WriteResult(WRITE_STATUS_OK, 0))); EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _)); session_.OnCanWrite(); - EXPECT_FALSE(session_.HasPendingWrites()); + EXPECT_FALSE(session_.WillingAndAbleToWrite()); } TEST_P(QuicSessionTest, OnCanWriteCongestionControlBlocks) { @@ -413,13 +424,13 @@ TEST_P(QuicSessionTest, OnCanWriteCongestionControlBlocks) { // stream4->OnCanWrite is not called. session_.OnCanWrite(); - EXPECT_TRUE(session_.HasPendingWrites()); + EXPECT_TRUE(session_.WillingAndAbleToWrite()); // Still congestion-control blocked. EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _, _)).WillOnce(Return( QuicTime::Delta::Infinite())); session_.OnCanWrite(); - EXPECT_TRUE(session_.HasPendingWrites()); + EXPECT_TRUE(session_.WillingAndAbleToWrite()); // stream4->OnCanWrite is called once the connection stops being // congestion-control blocked. @@ -427,7 +438,7 @@ TEST_P(QuicSessionTest, OnCanWriteCongestionControlBlocks) { QuicTime::Delta::Zero())); EXPECT_CALL(*stream4, OnCanWrite()); session_.OnCanWrite(); - EXPECT_FALSE(session_.HasPendingWrites()); + EXPECT_FALSE(session_.WillingAndAbleToWrite()); } TEST_P(QuicSessionTest, BufferedHandshake) { @@ -474,7 +485,7 @@ TEST_P(QuicSessionTest, BufferedHandshake) { InvokeWithoutArgs(&stream4_blocker, &StreamBlocker::MarkWriteBlocked)); session_.OnCanWrite(); - EXPECT_TRUE(session_.HasPendingWrites()); + EXPECT_TRUE(session_.WillingAndAbleToWrite()); EXPECT_FALSE(session_.HasPendingHandshake()); // Crypto stream wrote. } @@ -492,7 +503,40 @@ TEST_P(QuicSessionTest, OnCanWriteWithClosedStream) { EXPECT_CALL(*stream2, OnCanWrite()); EXPECT_CALL(*stream4, OnCanWrite()); session_.OnCanWrite(); - EXPECT_FALSE(session_.HasPendingWrites()); + EXPECT_FALSE(session_.WillingAndAbleToWrite()); +} + +TEST_P(QuicSessionTest, OnCanWriteLimitsNumWritesIfFlowControlBlocked) { + ValueRestore<bool> old_flag(&FLAGS_enable_quic_connection_flow_control, true); + if (version() < QUIC_VERSION_19) { + return; + } + + // Ensure connection level flow control blockage. + QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0); + EXPECT_TRUE(session_.flow_controller()->IsBlocked()); + + // Mark the crypto and headers streams as write blocked, we expect them to be + // allowed to write later. + session_.MarkWriteBlocked(kCryptoStreamId, kHighestPriority); + session_.MarkWriteBlocked(kHeadersStreamId, kHighestPriority); + + // Create a data stream, and although it is write blocked we never expect it + // to be allowed to write as we are connection level flow control blocked. + TestStream* stream = session_.CreateOutgoingDataStream(); + session_.MarkWriteBlocked(stream->id(), kSomeMiddlePriority); + EXPECT_CALL(*stream, OnCanWrite()).Times(0); + + // The crypto and headers streams should be called even though we are + // connection flow control blocked. + TestCryptoStream* crypto_stream = session_.GetCryptoStream(); + EXPECT_CALL(*crypto_stream, OnCanWrite()).Times(1); + TestHeadersStream* headers_stream = new TestHeadersStream(&session_); + QuicSessionPeer::SetHeadersStream(&session_, headers_stream); + EXPECT_CALL(*headers_stream, OnCanWrite()).Times(1); + + session_.OnCanWrite(); + EXPECT_FALSE(session_.WillingAndAbleToWrite()); } TEST_P(QuicSessionTest, SendGoAway) { @@ -617,6 +661,17 @@ TEST_P(QuicSessionTest, InvalidFlowControlWindowInHandshake) { session_.OnConfigNegotiated(); } +TEST_P(QuicSessionTest, InvalidFlowControlWindow) { + QuicConnection* connection = + new MockConnection(true, SupportedVersions(GetParam())); + + const uint32 kSmallerFlowControlWindow = kDefaultFlowControlSendWindow - 1; + TestSession session(connection, kSmallerFlowControlWindow); + + EXPECT_EQ(kDefaultFlowControlSendWindow, + session.max_flow_control_receive_window_bytes()); +} + } // namespace } // namespace test } // namespace net diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 310f93e..b94b19b 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc @@ -736,7 +736,7 @@ int QuicStreamFactory::CreateSession( QuicConnection* connection = new QuicConnection(connection_id, addr, helper_.get(), writer.get(), - false, supported_versions_, kInitialReceiveWindowSize); + false, supported_versions_); writer->SetConnection(connection); connection->options()->max_packet_length = max_packet_length_; @@ -755,7 +755,7 @@ int QuicStreamFactory::CreateSession( *session = new QuicClientSession( connection, socket.Pass(), writer.Pass(), this, quic_crypto_client_stream_factory_, server_info.Pass(), server_id, - config, &crypto_config_, net_log.net_log()); + config, kInitialReceiveWindowSize, &crypto_config_, net_log.net_log()); all_sessions_[*session] = server_id; // owning pointer return OK; } diff --git a/net/quic/quic_unacked_packet_map.cc b/net/quic/quic_unacked_packet_map.cc index a21d4a5..a8fe3b5 100644 --- a/net/quic/quic_unacked_packet_map.cc +++ b/net/quic/quic_unacked_packet_map.cc @@ -166,11 +166,11 @@ void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames( } // static -bool QuicUnackedPacketMap::IsSentAndNotPending( +bool QuicUnackedPacketMap::IsForRttOnly( const TransmissionInfo& transmission_info) { return !transmission_info.pending && - transmission_info.sent_time != QuicTime::Zero() && - transmission_info.bytes_sent == 0; + transmission_info.retransmittable_frames == NULL && + transmission_info.all_transmissions->size() == 1; } bool QuicUnackedPacketMap::IsUnacked( @@ -198,13 +198,7 @@ bool QuicUnackedPacketMap::HasUnackedPackets() const { } bool QuicUnackedPacketMap::HasPendingPackets() const { - for (UnackedPacketMap::const_reverse_iterator it = - unacked_packets_.rbegin(); it != unacked_packets_.rend(); ++it) { - if (it->second.pending) { - return true; - } - } - return false; + return bytes_in_flight_ > 0; } const TransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo( @@ -271,17 +265,6 @@ bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const { return false; } -size_t QuicUnackedPacketMap::GetNumRetransmittablePackets() const { - size_t num_unacked_packets = 0; - for (UnackedPacketMap::const_iterator it = unacked_packets_.begin(); - it != unacked_packets_.end(); ++it) { - if (it->second.retransmittable_frames != NULL) { - ++num_unacked_packets; - } - } - return num_unacked_packets; -} - QuicPacketSequenceNumber QuicUnackedPacketMap::GetLeastUnackedSentPacket() const { if (unacked_packets_.empty()) { diff --git a/net/quic/quic_unacked_packet_map.h b/net/quic/quic_unacked_packet_map.h index 759bd7b..12a96a2 100644 --- a/net/quic/quic_unacked_packet_map.h +++ b/net/quic/quic_unacked_packet_map.h @@ -52,9 +52,6 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap { // frames. bool HasUnackedRetransmittableFrames() const; - // Returns the number of unacked packets which have retransmittable frames. - size_t GetNumRetransmittablePackets() const; - // Returns the largest sequence number that has been sent. QuicPacketSequenceNumber largest_sent_packet() const { return largest_sent_packet_; @@ -122,8 +119,10 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap { // frames, and sets all_transmissions to only include itself. void NeuterPacket(QuicPacketSequenceNumber sequence_number); - // Returns true if the packet has been marked as sent by SetSent. - static bool IsSentAndNotPending(const TransmissionInfo& transmission_info); + // Returns true if the packet's only purpose is to measure RTT. It must not + // be pending, have retransmittable frames, or be linked to transmissions + // with retransmittable frames. + static bool IsForRttOnly(const TransmissionInfo& transmission_info); private: void MaybeRemoveRetransmittableFrames(TransmissionInfo* transmission_info); diff --git a/net/quic/quic_write_blocked_list.h b/net/quic/quic_write_blocked_list.h index cddd58f..6727fb4 100644 --- a/net/quic/quic_write_blocked_list.h +++ b/net/quic/quic_write_blocked_list.h @@ -27,10 +27,12 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList { QuicWriteBlockedList(); ~QuicWriteBlockedList(); - bool HasWriteBlockedStreams() const { - return crypto_stream_blocked_ || - headers_stream_blocked_ || - base_write_blocked_list_.HasWriteBlockedStreams(); + bool HasWriteBlockedDataStreams() const { + return base_write_blocked_list_.HasWriteBlockedStreams(); + } + + bool HasWriteBlockedCryptoOrHeadersStream() const { + return crypto_stream_blocked_ || headers_stream_blocked_; } size_t NumBlockedStreams() const { @@ -89,6 +91,9 @@ class NET_EXPORT_PRIVATE QuicWriteBlockedList { return; } + bool crypto_stream_blocked() const { return crypto_stream_blocked_; } + bool headers_stream_blocked() const { return headers_stream_blocked_; } + private: QuicWriteBlockedListBase base_write_blocked_list_; bool crypto_stream_blocked_; diff --git a/net/quic/quic_write_blocked_list_test.cc b/net/quic/quic_write_blocked_list_test.cc index 6f6bba6..1643bc3 100644 --- a/net/quic/quic_write_blocked_list_test.cc +++ b/net/quic/quic_write_blocked_list_test.cc @@ -27,7 +27,8 @@ TEST(QuicWriteBlockedListTest, PriorityOrder) { QuicWriteBlockedList::kHighestPriority); EXPECT_EQ(5u, write_blocked_list.NumBlockedStreams()); - EXPECT_TRUE(write_blocked_list.HasWriteBlockedStreams()); + EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); + EXPECT_TRUE(write_blocked_list.HasWriteBlockedDataStreams()); // The Crypto stream is highest priority. EXPECT_EQ(kCryptoStreamId, write_blocked_list.PopFront()); // Followed by the Headers stream. @@ -39,7 +40,8 @@ TEST(QuicWriteBlockedListTest, PriorityOrder) { EXPECT_EQ(40u, write_blocked_list.PopFront()); EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams()); - EXPECT_FALSE(write_blocked_list.HasWriteBlockedStreams()); + EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); + EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams()); } TEST(QuicWriteBlockedListTest, CryptoStream) { @@ -48,10 +50,10 @@ TEST(QuicWriteBlockedListTest, CryptoStream) { QuicWriteBlockedList::kHighestPriority); EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams()); - EXPECT_TRUE(write_blocked_list.HasWriteBlockedStreams()); + EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); EXPECT_EQ(kCryptoStreamId, write_blocked_list.PopFront()); EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams()); - EXPECT_FALSE(write_blocked_list.HasWriteBlockedStreams()); + EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); } TEST(QuicWriteBlockedListTest, HeadersStream) { @@ -60,10 +62,10 @@ TEST(QuicWriteBlockedListTest, HeadersStream) { QuicWriteBlockedList::kHighestPriority); EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams()); - EXPECT_TRUE(write_blocked_list.HasWriteBlockedStreams()); + EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); EXPECT_EQ(kHeadersStreamId, write_blocked_list.PopFront()); EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams()); - EXPECT_FALSE(write_blocked_list.HasWriteBlockedStreams()); + EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); } TEST(QuicWriteBlockedListTest, VerifyHeadersStream) { @@ -74,13 +76,15 @@ TEST(QuicWriteBlockedListTest, VerifyHeadersStream) { QuicWriteBlockedList::kHighestPriority); EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); - EXPECT_TRUE(write_blocked_list.HasWriteBlockedStreams()); + EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); + EXPECT_TRUE(write_blocked_list.HasWriteBlockedDataStreams()); // In newer QUIC versions, there is a headers stream which is // higher priority than data streams. EXPECT_EQ(kHeadersStreamId, write_blocked_list.PopFront()); EXPECT_EQ(5u, write_blocked_list.PopFront()); EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams()); - EXPECT_FALSE(write_blocked_list.HasWriteBlockedStreams()); + EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); + EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams()); } TEST(QuicWriteBlockedListTest, NoDuplicateEntries) { @@ -99,12 +103,12 @@ TEST(QuicWriteBlockedListTest, NoDuplicateEntries) { // This should only result in one blocked stream being added. EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams()); - EXPECT_TRUE(write_blocked_list.HasWriteBlockedStreams()); + EXPECT_TRUE(write_blocked_list.HasWriteBlockedDataStreams()); // There should only be one stream to pop off the front. EXPECT_EQ(kBlockedId, write_blocked_list.PopFront()); EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams()); - EXPECT_FALSE(write_blocked_list.HasWriteBlockedStreams()); + EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams()); } } // namespace diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc index 218bb09..aefdb41 100644 --- a/net/quic/reliable_quic_stream.cc +++ b/net/quic/reliable_quic_stream.cc @@ -130,9 +130,9 @@ ReliableQuicStream::ReliableQuicStream(QuicStreamId id, QuicSession* session) session_->config()->HasReceivedInitialFlowControlWindowBytes() ? session_->config()->ReceivedInitialFlowControlWindowBytes() : kDefaultFlowControlSendWindow, - session_->connection()->max_flow_control_receive_window_bytes(), - session_->connection()->max_flow_control_receive_window_bytes()), - connection_flow_controller_(session_->connection()->flow_controller()) { + session_->max_flow_control_receive_window_bytes(), + session_->max_flow_control_receive_window_bytes()), + connection_flow_controller_(session_->flow_controller()) { } ReliableQuicStream::~ReliableQuicStream() { diff --git a/net/quic/reliable_quic_stream_test.cc b/net/quic/reliable_quic_stream_test.cc index d1ad909..48e8616 100644 --- a/net/quic/reliable_quic_stream_test.cc +++ b/net/quic/reliable_quic_stream_test.cc @@ -37,7 +37,7 @@ namespace { const char kData1[] = "FooAndBar"; const char kData2[] = "EepAndBaz"; const size_t kDataLen = 9; -const QuicConnectionId kStreamId = 3; +const QuicStreamId kStreamId = 3; const bool kIsServer = true; const bool kShouldProcessData = true; @@ -134,6 +134,11 @@ class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> { initial_flow_control_window_bytes_ = val; } + bool HasWriteBlockedStreams() { + return write_blocked_list_->HasWriteBlockedCryptoOrHeadersStream() || + write_blocked_list_->HasWriteBlockedDataStreams(); + } + protected: MockConnection* connection_; scoped_ptr<MockSession> session_; @@ -156,7 +161,7 @@ TEST_F(ReliableQuicStreamTest, WriteAllData) { EXPECT_CALL(*session_, WritevData(kStreamId, _, _, _, _)).WillOnce( Return(QuicConsumedData(kDataLen, true))); stream_->WriteOrBufferData(kData1, false, NULL); - EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams()); + EXPECT_FALSE(HasWriteBlockedStreams()); } TEST_F(ReliableQuicStreamTest, NoBlockingIfNoDataOrFin) { @@ -165,7 +170,7 @@ TEST_F(ReliableQuicStreamTest, NoBlockingIfNoDataOrFin) { // Write no data and no fin. If we consume nothing we should not be write // blocked. EXPECT_DFATAL(stream_->WriteOrBufferData(StringPiece(), false, NULL), ""); - EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams()); + EXPECT_FALSE(HasWriteBlockedStreams()); } TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) { @@ -179,7 +184,6 @@ TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) { ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams()); } - TEST_F(ReliableQuicStreamTest, BlockIfFinNotConsumedWithData) { Initialize(kShouldProcessData); @@ -207,7 +211,7 @@ TEST_F(ReliableQuicStreamTest, BlockIfSoloFinNotConsumed) { TEST_F(ReliableQuicStreamTest, WriteOrBufferData) { Initialize(kShouldProcessData); - EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams()); + EXPECT_FALSE(HasWriteBlockedStreams()); connection_->options()->max_packet_length = 1 + QuicPacketCreator::StreamFramePacketOverhead( connection_->version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, @@ -215,7 +219,7 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferData) { EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).WillOnce( Return(QuicConsumedData(kDataLen - 1, false))); stream_->WriteOrBufferData(kData1, false, NULL); - EXPECT_TRUE(write_blocked_list_->HasWriteBlockedStreams()); + EXPECT_TRUE(HasWriteBlockedStreams()); // Queue a bytes_consumed write. stream_->WriteOrBufferData(kData2, false, NULL); @@ -395,7 +399,7 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferDataWithQuicAckNotifier) { // Set a large flow control send window so this doesn't interfere with test. stream_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1); if (FLAGS_enable_quic_connection_flow_control) { - connection_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1); + session_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1); } scoped_refptr<QuicAckNotifier::DelegateInterface> proxy_delegate; @@ -405,7 +409,7 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferDataWithQuicAckNotifier) { &SaveProxyAckNotifierDelegate, &proxy_delegate))), Return(QuicConsumedData(kFirstWriteSize, false)))); stream_->WriteOrBufferData(kData, false, delegate.get()); - EXPECT_TRUE(write_blocked_list_->HasWriteBlockedStreams()); + EXPECT_TRUE(HasWriteBlockedStreams()); EXPECT_CALL(*session_, WritevData(kStreamId, _, _, _, proxy_delegate.get())). WillOnce( @@ -450,7 +454,7 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferDataAckNotificationBeforeFlush) { // Set a large flow control send window so this doesn't interfere with test. stream_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1); if (FLAGS_enable_quic_connection_flow_control) { - connection_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1); + session_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1); } scoped_refptr<QuicAckNotifier::DelegateInterface> proxy_delegate; @@ -460,7 +464,7 @@ TEST_F(ReliableQuicStreamTest, WriteOrBufferDataAckNotificationBeforeFlush) { &SaveProxyAckNotifierDelegate, &proxy_delegate))), Return(QuicConsumedData(kInitialWriteSize, false)))); stream_->WriteOrBufferData(kData, false, delegate.get()); - EXPECT_TRUE(write_blocked_list_->HasWriteBlockedStreams()); + EXPECT_TRUE(HasWriteBlockedStreams()); // Handle the ack of the first write. proxy_delegate->OnAckNotification(1, 2, 3, 4, zero_); @@ -491,7 +495,7 @@ TEST_F(ReliableQuicStreamTest, WriteAndBufferDataWithAckNotiferNoBuffer) { &SaveProxyAckNotifierDelegate, &proxy_delegate))), Return(QuicConsumedData(kDataLen, true)))); stream_->WriteOrBufferData(kData1, true, delegate.get()); - EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams()); + EXPECT_FALSE(HasWriteBlockedStreams()); // Handle the ack. EXPECT_CALL(*delegate, OnAckNotification(1, 2, 3, 4, zero_)); @@ -510,7 +514,7 @@ TEST_F(ReliableQuicStreamTest, BufferOnWriteAndBufferDataWithAckNotifer) { EXPECT_CALL(*session_, WritevData(kStreamId, _, _, _, _)).WillOnce( Return(QuicConsumedData(0, false))); stream_->WriteOrBufferData(kData1, true, delegate.get()); - EXPECT_TRUE(write_blocked_list_->HasWriteBlockedStreams()); + EXPECT_TRUE(HasWriteBlockedStreams()); EXPECT_CALL(*session_, WritevData(kStreamId, _, _, _, _)).WillOnce(DoAll( WithArgs<4>(Invoke(CreateFunctor( @@ -538,7 +542,7 @@ TEST_F(ReliableQuicStreamTest, WriteAndBufferDataWithAckNotiferOnlyFinRemains) { &SaveProxyAckNotifierDelegate, &proxy_delegate))), Return(QuicConsumedData(kDataLen, false)))); stream_->WriteOrBufferData(kData1, true, delegate.get()); - EXPECT_TRUE(write_blocked_list_->HasWriteBlockedStreams()); + EXPECT_TRUE(HasWriteBlockedStreams()); EXPECT_CALL(*session_, WritevData(kStreamId, _, _, _, _)).WillOnce(DoAll( WithArgs<4>(Invoke(CreateFunctor( diff --git a/net/quic/test_tools/quic_packet_creator_peer.cc b/net/quic/test_tools/quic_packet_creator_peer.cc index 1acdf24..07658e5 100644 --- a/net/quic/test_tools/quic_packet_creator_peer.cc +++ b/net/quic/test_tools/quic_packet_creator_peer.cc @@ -39,5 +39,13 @@ void QuicPacketCreatorPeer::SetIsServer(QuicPacketCreator* creator, creator->is_server_ = is_server; } +// static +bool QuicPacketCreatorPeer::SwitchFecProtectionOn( + QuicPacketCreator* creator, size_t max_packets_per_fec_group) { + creator->set_max_packets_per_fec_group(max_packets_per_fec_group); + creator->StartFecProtectingPackets(); + return creator->IsFecProtected(); +} + } // namespace test } // namespace net diff --git a/net/quic/test_tools/quic_packet_creator_peer.h b/net/quic/test_tools/quic_packet_creator_peer.h index 12ae676..95002a8 100644 --- a/net/quic/test_tools/quic_packet_creator_peer.h +++ b/net/quic/test_tools/quic_packet_creator_peer.h @@ -26,6 +26,9 @@ class QuicPacketCreatorPeer { static void SetIsServer(QuicPacketCreator* creator, bool is_server); + static bool SwitchFecProtectionOn(QuicPacketCreator* creator, + size_t max_packets_per_fec_group); + private: DISALLOW_COPY_AND_ASSIGN(QuicPacketCreatorPeer); }; diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.cc b/net/quic/test_tools/quic_sent_packet_manager_peer.cc index 7f72615..db1a26d 100644 --- a/net/quic/test_tools/quic_sent_packet_manager_peer.cc +++ b/net/quic/test_tools/quic_sent_packet_manager_peer.cc @@ -109,7 +109,15 @@ bool QuicSentPacketManagerPeer::HasUnackedCryptoPackets( // static size_t QuicSentPacketManagerPeer::GetNumRetransmittablePackets( const QuicSentPacketManager* sent_packet_manager) { - return sent_packet_manager->unacked_packets_.GetNumRetransmittablePackets(); + size_t num_unacked_packets = 0; + for (QuicUnackedPacketMap::const_iterator it = + sent_packet_manager->unacked_packets_.begin(); + it != sent_packet_manager->unacked_packets_.end(); ++it) { + if (it->second.retransmittable_frames != NULL) { + ++num_unacked_packets; + } + } + return num_unacked_packets; } // static diff --git a/net/quic/test_tools/quic_session_peer.cc b/net/quic/test_tools/quic_session_peer.cc index 080643b..a46b6fe 100644 --- a/net/quic/test_tools/quic_session_peer.cc +++ b/net/quic/test_tools/quic_session_peer.cc @@ -27,6 +27,12 @@ QuicHeadersStream* QuicSessionPeer::GetHeadersStream(QuicSession* session) { } // static +void QuicSessionPeer::SetHeadersStream(QuicSession* session, + QuicHeadersStream* headers_stream) { + session->headers_stream_.reset(headers_stream); +} + +// static QuicWriteBlockedList* QuicSessionPeer::GetWriteblockedStreams( QuicSession* session) { return &session->write_blocked_streams_; diff --git a/net/quic/test_tools/quic_session_peer.h b/net/quic/test_tools/quic_session_peer.h index d8f1c75..ef9fef7 100644 --- a/net/quic/test_tools/quic_session_peer.h +++ b/net/quic/test_tools/quic_session_peer.h @@ -21,6 +21,8 @@ class QuicSessionPeer { static void SetNextStreamId(QuicSession* session, QuicStreamId id); static void SetMaxOpenStreams(QuicSession* session, uint32 max_streams); static QuicHeadersStream* GetHeadersStream(QuicSession* session); + static void SetHeadersStream(QuicSession* session, + QuicHeadersStream* headers_stream); static QuicWriteBlockedList* GetWriteblockedStreams(QuicSession* session); static QuicDataStream* GetIncomingDataStream(QuicSession* session, QuicStreamId stream_id); diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc index 5e4d7f5..f14dd73 100644 --- a/net/quic/test_tools/quic_test_utils.cc +++ b/net/quic/test_tools/quic_test_utils.cc @@ -191,8 +191,7 @@ MockConnection::MockConnection(bool is_server) IPEndPoint(TestPeerIPAddress(), kTestPort), new testing::NiceMock<MockHelper>(), new testing::NiceMock<MockPacketWriter>(), - is_server, QuicSupportedVersions(), - kInitialFlowControlWindowForTest), + is_server, QuicSupportedVersions()), writer_(QuicConnectionPeer::GetWriter(this)), helper_(helper()) { } @@ -202,8 +201,7 @@ MockConnection::MockConnection(IPEndPoint address, : QuicConnection(kTestConnectionId, address, new testing::NiceMock<MockHelper>(), new testing::NiceMock<MockPacketWriter>(), - is_server, QuicSupportedVersions(), - kInitialFlowControlWindowForTest), + is_server, QuicSupportedVersions()), writer_(QuicConnectionPeer::GetWriter(this)), helper_(helper()) { } @@ -214,8 +212,7 @@ MockConnection::MockConnection(QuicConnectionId connection_id, IPEndPoint(TestPeerIPAddress(), kTestPort), new testing::NiceMock<MockHelper>(), new testing::NiceMock<MockPacketWriter>(), - is_server, QuicSupportedVersions(), - kInitialFlowControlWindowForTest), + is_server, QuicSupportedVersions()), writer_(QuicConnectionPeer::GetWriter(this)), helper_(helper()) { } @@ -226,8 +223,7 @@ MockConnection::MockConnection(bool is_server, IPEndPoint(TestPeerIPAddress(), kTestPort), new testing::NiceMock<MockHelper>(), new testing::NiceMock<MockPacketWriter>(), - is_server, supported_versions, - kInitialFlowControlWindowForTest), + is_server, supported_versions), writer_(QuicConnectionPeer::GetWriter(this)), helper_(helper()) { } @@ -266,7 +262,8 @@ bool PacketSavingConnection::SendOrQueuePacket( } MockSession::MockSession(QuicConnection* connection) - : QuicSession(connection, DefaultQuicConfig()) { + : QuicSession(connection, kInitialFlowControlWindowForTest, + DefaultQuicConfig()) { ON_CALL(*this, WritevData(_, _, _, _, _)) .WillByDefault(testing::Return(QuicConsumedData(0, false))); } @@ -274,11 +271,9 @@ MockSession::MockSession(QuicConnection* connection) MockSession::~MockSession() { } -TestSession::TestSession(QuicConnection* connection, - const QuicConfig& config) - : QuicSession(connection, config), - crypto_stream_(NULL) { -} +TestSession::TestSession(QuicConnection* connection, const QuicConfig& config) + : QuicSession(connection, kInitialFlowControlWindowForTest, config), + crypto_stream_(NULL) {} TestSession::~TestSession() {} @@ -292,7 +287,8 @@ QuicCryptoStream* TestSession::GetCryptoStream() { TestClientSession::TestClientSession(QuicConnection* connection, const QuicConfig& config) - : QuicClientSessionBase(connection, config), + : QuicClientSessionBase(connection, kInitialFlowControlWindowForTest, + config), crypto_stream_(NULL) { EXPECT_CALL(*this, OnProofValid(_)).Times(AnyNumber()); } diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h index 4582a0e..6901824 100644 --- a/net/quic/test_tools/quic_test_utils.h +++ b/net/quic/test_tools/quic_test_utils.h @@ -194,7 +194,7 @@ class MockConnectionVisitor : public QuicConnectionVisitorInterface { MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer)); MOCK_METHOD0(OnWriteBlocked, void()); MOCK_METHOD0(OnCanWrite, void()); - MOCK_CONST_METHOD0(HasPendingWrites, bool()); + MOCK_CONST_METHOD0(WillingAndAbleToWrite, bool()); MOCK_CONST_METHOD0(HasPendingHandshake, bool()); MOCK_CONST_METHOD0(HasOpenDataStreams, bool()); MOCK_METHOD1(OnSuccessfulVersionNegotiation, diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index cf56826..8d04535 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc @@ -24,6 +24,7 @@ #include "net/quic/quic_sent_packet_manager.h" #include "net/quic/quic_server_id.h" #include "net/quic/test_tools/quic_connection_peer.h" +#include "net/quic/test_tools/quic_packet_creator_peer.h" #include "net/quic/test_tools/quic_session_peer.h" #include "net/quic/test_tools/quic_test_utils.h" #include "net/quic/test_tools/reliable_quic_stream_peer.h" @@ -50,6 +51,7 @@ using base::WaitableEvent; using net::EpollServer; using net::test::GenerateBody; using net::test::QuicConnectionPeer; +using net::test::QuicPacketCreatorPeer; using net::test::QuicSessionPeer; using net::test::ReliableQuicStreamPeer; using net::tools::test::PacketDroppingTestWriter; @@ -644,7 +646,10 @@ TEST_P(EndToEndTest, LargePostFEC) { client_->client()->WaitForCryptoHandshakeConfirmed(); SetPacketLossPercentage(30); - client_->options()->max_packets_per_fec_group = 6; + // Turn on FEC protection. + QuicPacketCreator* creator = QuicConnectionPeer::GetPacketCreator( + client_->client()->session()->connection()); + EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(creator, 6)); string body; GenerateBody(&body, 10240); diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc index cb2b408..6935238 100644 --- a/net/tools/quic/quic_client.cc +++ b/net/tools/quic/quic_client.cc @@ -189,8 +189,8 @@ bool QuicClient::StartConnect() { server_id_, config_, new QuicConnection(GenerateConnectionId(), server_address_, helper_.get(), - writer_.get(), false, supported_versions_, - initial_flow_control_window_), + writer_.get(), false, supported_versions_), + initial_flow_control_window_, &crypto_config_)); return session_->CryptoConnect(); } @@ -218,6 +218,7 @@ void QuicClient::SendRequestsAndWaitForResponse( BalsaHeaders headers; headers.SetRequestFirstlineFromStringPieces("GET", args[i], "HTTP/1.1"); QuicSpdyClientStream* stream = CreateReliableClientStream(); + DCHECK(stream != NULL); stream->SendRequest(headers, "", true); stream->set_visitor(this); } @@ -236,7 +237,7 @@ QuicSpdyClientStream* QuicClient::CreateReliableClientStream() { void QuicClient::WaitForStreamToClose(QuicStreamId id) { DCHECK(connected()); - while (!session_->IsClosedStream(id)) { + while (connected() && !session_->IsClosedStream(id)) { epoll_server_.WaitForEventsAndExecuteCallbacks(); } } @@ -244,7 +245,7 @@ void QuicClient::WaitForStreamToClose(QuicStreamId id) { void QuicClient::WaitForCryptoHandshakeConfirmed() { DCHECK(connected()); - while (!session_->IsCryptoHandshakeConfirmed()) { + while (connected() && !session_->IsCryptoHandshakeConfirmed()) { epoll_server_.WaitForEventsAndExecuteCallbacks(); } } diff --git a/net/tools/quic/quic_client_session.cc b/net/tools/quic/quic_client_session.cc index aca5418..c8e28db 100644 --- a/net/tools/quic/quic_client_session.cc +++ b/net/tools/quic/quic_client_session.cc @@ -18,8 +18,11 @@ QuicClientSession::QuicClientSession( const QuicServerId& server_id, const QuicConfig& config, QuicConnection* connection, + uint32 max_flow_control_receive_window_bytes, QuicCryptoClientConfig* crypto_config) - : QuicClientSessionBase(connection, config), + : QuicClientSessionBase(connection, + max_flow_control_receive_window_bytes, + config), crypto_stream_(server_id, this, NULL, crypto_config) { } diff --git a/net/tools/quic/quic_client_session.h b/net/tools/quic/quic_client_session.h index 3aad445..d04b420 100644 --- a/net/tools/quic/quic_client_session.h +++ b/net/tools/quic/quic_client_session.h @@ -28,6 +28,7 @@ class QuicClientSession : public QuicClientSessionBase { QuicClientSession(const QuicServerId& server_id, const QuicConfig& config, QuicConnection* connection, + uint32 max_flow_control_receive_window_bytes, QuicCryptoClientConfig* crypto_config); virtual ~QuicClientSession(); diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc index 7b50f42..983106d 100644 --- a/net/tools/quic/quic_client_session_test.cc +++ b/net/tools/quic/quic_client_session_test.cc @@ -15,6 +15,7 @@ using net::test::CryptoTestUtils; using net::test::DefaultQuicConfig; +using net::test::kInitialFlowControlWindowForTest; using net::test::PacketSavingConnection; using net::test::SupportedVersions; using testing::_; @@ -38,6 +39,7 @@ class ToolsQuicClientSessionTest QuicServerId(kServerHostname, kPort, false, PRIVACY_MODE_DISABLED), DefaultQuicConfig(), connection_, + kInitialFlowControlWindowForTest, &crypto_config_)); session_->config()->SetDefaults(); } diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc index b074a5d..df9b9c6 100644 --- a/net/tools/quic/quic_dispatcher.cc +++ b/net/tools/quic/quic_dispatcher.cc @@ -382,8 +382,8 @@ QuicSession* QuicDispatcher::CreateQuicSession( config_, CreateQuicConnection(connection_id, server_address, - client_address, - initial_flow_control_window_bytes_), + client_address), + initial_flow_control_window_bytes_, this); session->InitializeSession(crypto_config_); return session; @@ -392,14 +392,12 @@ QuicSession* QuicDispatcher::CreateQuicSession( QuicConnection* QuicDispatcher::CreateQuicConnection( QuicConnectionId connection_id, const IPEndPoint& server_address, - const IPEndPoint& client_address, - uint32 initial_flow_control_window) { + const IPEndPoint& client_address) { if (FLAGS_enable_quic_stream_flow_control_2 && FLAGS_enable_quic_connection_flow_control) { DLOG(INFO) << "Creating QuicDispatcher with all versions."; return new QuicConnection(connection_id, client_address, helper_.get(), - writer_.get(), true, supported_versions_, - initial_flow_control_window_bytes_); + writer_.get(), true, supported_versions_); } if (FLAGS_enable_quic_stream_flow_control_2 && @@ -408,15 +406,14 @@ QuicConnection* QuicDispatcher::CreateQuicConnection( << "WITHOUT version 19 or higher."; return new QuicConnection(connection_id, client_address, helper_.get(), writer_.get(), true, - supported_versions_no_connection_flow_control_, - initial_flow_control_window_bytes_); + supported_versions_no_connection_flow_control_); } DLOG(INFO) << "Flow control disabled, creating QuicDispatcher WITHOUT " << "version 17 or higher."; - return new QuicConnection( - connection_id, client_address, helper_.get(), writer_.get(), true, - supported_versions_no_flow_control_, initial_flow_control_window_bytes_); + return new QuicConnection(connection_id, client_address, helper_.get(), + writer_.get(), true, + supported_versions_no_flow_control_); } QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() { diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h index fbb2f40..b19d5c5 100644 --- a/net/tools/quic/quic_dispatcher.h +++ b/net/tools/quic/quic_dispatcher.h @@ -113,8 +113,7 @@ class QuicDispatcher : public QuicServerSessionVisitor { virtual QuicConnection* CreateQuicConnection( QuicConnectionId connection_id, const IPEndPoint& server_address, - const IPEndPoint& client_address, - uint32 initial_flow_control_window); + const IPEndPoint& client_address); // Called by |framer_visitor_| when the public header has been parsed. virtual bool OnUnauthenticatedPublicHeader( diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc index db8b76a..bd0d204 100644 --- a/net/tools/quic/quic_dispatcher_test.cc +++ b/net/tools/quic/quic_dispatcher_test.cc @@ -290,16 +290,16 @@ TEST(QuicDispatcherFlowControlTest, NoNewVersion17ConnectionsIfFlagDisabled) { // When flag is enabled, new connections should support QUIC_VERSION_17. FLAGS_enable_quic_stream_flow_control_2 = true; scoped_ptr<QuicConnection> connection_1( - QuicDispatcherPeer::CreateQuicConnection( - &dispatcher, kCID, client, server, kInitialFlowControlWindowForTest)); + QuicDispatcherPeer::CreateQuicConnection(&dispatcher, kCID, client, + server)); EXPECT_EQ(QUIC_VERSION_17, connection_1->version()); // When flag is disabled, new connections should not support QUIC_VERSION_17. FLAGS_enable_quic_stream_flow_control_2 = false; scoped_ptr<QuicConnection> connection_2( - QuicDispatcherPeer::CreateQuicConnection( - &dispatcher, kCID, client, server, kInitialFlowControlWindowForTest)); + QuicDispatcherPeer::CreateQuicConnection(&dispatcher, kCID, client, + server)); EXPECT_EQ(QUIC_VERSION_16, connection_2->version()); } diff --git a/net/tools/quic/quic_server_session.cc b/net/tools/quic/quic_server_session.cc index 2fc824d..7c31ef0 100644 --- a/net/tools/quic/quic_server_session.cc +++ b/net/tools/quic/quic_server_session.cc @@ -12,11 +12,11 @@ namespace net { namespace tools { -QuicServerSession::QuicServerSession( - const QuicConfig& config, - QuicConnection* connection, - QuicServerSessionVisitor* visitor) - : QuicSession(connection, config), +QuicServerSession::QuicServerSession(const QuicConfig& config, + QuicConnection* connection, + uint32 max_flow_control_window_bytes, + QuicServerSessionVisitor* visitor) + : QuicSession(connection, max_flow_control_window_bytes, config), visitor_(visitor) {} QuicServerSession::~QuicServerSession() {} diff --git a/net/tools/quic/quic_server_session.h b/net/tools/quic/quic_server_session.h index ffd8b0a..41d7305 100644 --- a/net/tools/quic/quic_server_session.h +++ b/net/tools/quic/quic_server_session.h @@ -47,6 +47,7 @@ class QuicServerSession : public QuicSession { public: QuicServerSession(const QuicConfig& config, QuicConnection *connection, + uint32 max_flow_control_window_bytes, QuicServerSessionVisitor* visitor); // Override the base class to notify the owner of the connection close. diff --git a/net/tools/quic/quic_server_session_test.cc b/net/tools/quic/quic_server_session_test.cc index 22308fb..0d9c816 100644 --- a/net/tools/quic/quic_server_session_test.cc +++ b/net/tools/quic/quic_server_session_test.cc @@ -53,7 +53,7 @@ class QuicServerSessionTest : public ::testing::TestWithParam<QuicVersion> { connection_ = new StrictMock<MockConnection>(true, SupportedVersions(GetParam())); session_.reset(new QuicServerSession( - config_, connection_, &owner_)); + config_, connection_, kInitialFlowControlWindowForTest, &owner_)); session_->InitializeSession(crypto_config_); visitor_ = QuicConnectionPeer::GetVisitor(connection_); } diff --git a/net/tools/quic/quic_spdy_client_stream_test.cc b/net/tools/quic/quic_spdy_client_stream_test.cc index 67f9d89..98ca650 100644 --- a/net/tools/quic/quic_spdy_client_stream_test.cc +++ b/net/tools/quic/quic_spdy_client_stream_test.cc @@ -33,6 +33,7 @@ class QuicSpdyClientStreamTest : public TestWithParam<QuicVersion> { session_(QuicServerId("example.com", 80, false, PRIVACY_MODE_DISABLED), DefaultQuicConfig(), connection_, + kInitialFlowControlWindowForTest, &crypto_config_), body_("hello world") { crypto_config_.SetDefaults(); diff --git a/net/tools/quic/test_tools/quic_dispatcher_peer.cc b/net/tools/quic/test_tools/quic_dispatcher_peer.cc index 0622881..cd27802 100644 --- a/net/tools/quic/test_tools/quic_dispatcher_peer.cc +++ b/net/tools/quic/test_tools/quic_dispatcher_peer.cc @@ -41,12 +41,10 @@ QuicConnection* QuicDispatcherPeer::CreateQuicConnection( QuicDispatcher* dispatcher, QuicConnectionId connection_id, const IPEndPoint& server, - const IPEndPoint& client, - uint32 initial_flow_control_window_bytes) { + const IPEndPoint& client) { return dispatcher->CreateQuicConnection(connection_id, server, - client, - initial_flow_control_window_bytes); + client); } } // namespace test diff --git a/net/tools/quic/test_tools/quic_dispatcher_peer.h b/net/tools/quic/test_tools/quic_dispatcher_peer.h index e647820..45125c2 100644 --- a/net/tools/quic/test_tools/quic_dispatcher_peer.h +++ b/net/tools/quic/test_tools/quic_dispatcher_peer.h @@ -34,8 +34,7 @@ class QuicDispatcherPeer { QuicDispatcher* dispatcher, QuicConnectionId connection_id, const IPEndPoint& server, - const IPEndPoint& client, - uint32 initial_flow_control_window_bytes); + const IPEndPoint& client); private: DISALLOW_COPY_AND_ASSIGN(QuicDispatcherPeer); diff --git a/net/tools/quic/test_tools/quic_test_utils.cc b/net/tools/quic/test_tools/quic_test_utils.cc index 78e67ca..bbb03d3 100644 --- a/net/tools/quic/test_tools/quic_test_utils.cc +++ b/net/tools/quic/test_tools/quic_test_utils.cc @@ -13,6 +13,7 @@ using base::StringPiece; using net::test::kInitialFlowControlWindowForTest; using net::test::MockHelper; +using net::test::QuicConnectionPeer; namespace net { namespace tools { @@ -23,9 +24,8 @@ MockConnection::MockConnection(bool is_server) IPEndPoint(net::test::Loopback4(), kTestPort), new testing::NiceMock<MockHelper>(), new testing::NiceMock<MockPacketWriter>(), - is_server, QuicSupportedVersions(), - kInitialFlowControlWindowForTest), - writer_(net::test::QuicConnectionPeer::GetWriter(this)), + is_server, QuicSupportedVersions()), + writer_(QuicConnectionPeer::GetWriter(this)), helper_(helper()) { } @@ -34,9 +34,8 @@ MockConnection::MockConnection(IPEndPoint address, : QuicConnection(kTestConnectionId, address, new testing::NiceMock<MockHelper>(), new testing::NiceMock<MockPacketWriter>(), - is_server, QuicSupportedVersions(), - kInitialFlowControlWindowForTest), - writer_(net::test::QuicConnectionPeer::GetWriter(this)), + is_server, QuicSupportedVersions()), + writer_(QuicConnectionPeer::GetWriter(this)), helper_(helper()) { } @@ -46,9 +45,8 @@ MockConnection::MockConnection(QuicConnectionId connection_id, IPEndPoint(net::test::Loopback4(), kTestPort), new testing::NiceMock<MockHelper>(), new testing::NiceMock<MockPacketWriter>(), - is_server, QuicSupportedVersions(), - kInitialFlowControlWindowForTest), - writer_(net::test::QuicConnectionPeer::GetWriter(this)), + is_server, QuicSupportedVersions()), + writer_(QuicConnectionPeer::GetWriter(this)), helper_(helper()) { } @@ -58,9 +56,8 @@ MockConnection::MockConnection(bool is_server, IPEndPoint(net::test::Loopback4(), kTestPort), new testing::NiceMock<MockHelper>(), new testing::NiceMock<MockPacketWriter>(), - is_server, QuicSupportedVersions(), - kInitialFlowControlWindowForTest), - writer_(net::test::QuicConnectionPeer::GetWriter(this)), + is_server, QuicSupportedVersions()), + writer_(QuicConnectionPeer::GetWriter(this)), helper_(helper()) { } @@ -81,7 +78,7 @@ uint64 SimpleRandom::RandUint64() { TestSession::TestSession(QuicConnection* connection, const QuicConfig& config) - : QuicSession(connection, config), + : QuicSession(connection, kInitialFlowControlWindowForTest, config), crypto_stream_(NULL) { } |
