summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrtenneti <rtenneti@chromium.org>2015-06-11 18:05:52 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-12 01:07:07 +0000
commitd39bd7637e411fef8a39e61a4cb3f3b006de49dd (patch)
tree272bce1402ab2adb6ac277cf56b3cf039b53f637
parent05c376f220bbffbc20ba6f5d8f1b42091467f12a (diff)
downloadchromium_src-d39bd7637e411fef8a39e61a4cb3f3b006de49dd.zip
chromium_src-d39bd7637e411fef8a39e61a4cb3f3b006de49dd.tar.gz
chromium_src-d39bd7637e411fef8a39e61a4cb3f3b006de49dd.tar.bz2
Landing Recent QUIC changes until 06/07/2015.
relnote: splitting quic client session into a virtual function (no-op) Move the creation of the quic client session into a function we can override to create custom sessions for quic-to-backend. Merge internal change: 95324185 https://codereview.chromium.org/1174173008/ relnote: Reorder some commonly used QUIC structs according ClassLayoutOptimizer's suggestions. Merge internal change: 95320291 https://codereview.chromium.org/1178273005/ Fix QuicSession::GetCryptoStream() in tests to return non-null during initialization. Previously in some tests GetCryptoStream() was returning nullptr when called during initialization and the stream was created later. That wouldn't work if the crypto stream needs to be used during initialization. Fixed tests that had this issue and added DCHECK in Initialize(). relnote: Minor cleanup in QUIC tests Merge internal change: 95316723 https://codereview.chromium.org/1180943004/ relnote: adding a default response to the quic cache (not used in production). Addding the option for a default value to be set for the quic in-memory cache. This is needed for quic-to-backend because the internal server tests assume a default response and one-offing per-url is silly. Plus I've run up against this lack of feature in annoying ways a few times now. Merge internal change: 95297412 https://codereview.chromium.org/1177043007/ relnote: Reverse the sense of flag quic_stop_early and rename it to FLAGS_quic_stop_early_2. This causes QUIC frames to not be processed after the connection is terminated. FIXED=21370767 Merge internal change: 95296106 https://codereview.chromium.org/1183543002/ Test handshake message handling on packet generator level. This tests the flush-on-handshake logic, and also verifies that the packet is correctly padded (which would be helpful for subsequent changes in which the packets will be tagged for padding by generator itself). relnote: n/a (test-only change) Merge internal change: 95202648 https://codereview.chromium.org/1178253002/ Remove implementation of pure virtual functions in QuicFramerVisitorInterface. relnote: n/a (removing dead code) Merge internal change: 95197850 https://codereview.chromium.org/1184503002/ Avoid overloading QuicSession::InitializeSession(). Previously QuicServerSession and QuicClientSession were overloading QuicSession::InitializeSession() with parameters. Moved the parameters to the constructors so these child classes now can override QuicSession::InitializeSession() instead of overloading it. Also made the method virtual. relnote: QuicSession cleanup, doesn't affect functionality Merge internal change: 95174532 https://codereview.chromium.org/1173343002/ Minor change to keep the code similar to internal source. Merge internal change: 95167379 https://codereview.chromium.org/1181533005/ relnote: Increase QUIC flow control window sizes dynamically if data flows quickly enough. Flag protected by FLAGS_quic_receive_window_auto_tune, and new AFCW connection tag. QUIC receivers send WINDOW_UPDATE when the flow passes the 1/2 point of the current window position. Analysis shows that WINDOW_UPDATES must be more than 1 * RTT apart to prevent the sender from being impeded due to insufficient window size, and a minimum receive window size of 2 * BDP. To avoid the sender becoming blocked, we monitor the timing of window updates relative to the flow rate, and if necessary increase the window size. To add some padding for transients, this algorithm uses trigger of 2 * RTT to increase receive window size, on the interval between successive WINDOW_UPDATES, which corresponds to targeting a receive window size of ~ 4 * BDP. Merge internal change: 95154188 https://codereview.chromium.org/1180693004/ Reversed if statements check for FEC_ANY_TRIGGER with FEC_ALARM_TRIGGER check. From jri: Since FEC_ANY_TRIGGER is the "catch-all" policy, it seems more readable to have the if clause reversed... i.e., check for FEC_ALARM_TRIGGER and the catch-all be in the else clause. relnote: n/a. Test only readability change. Merge internal change: 95122056 https://codereview.chromium.org/1175113004/ R=rch@chromium.org Review URL: https://codereview.chromium.org/1181643003 Cr-Commit-Position: refs/heads/master@{#334099}
-rw-r--r--net/quic/crypto/crypto_protocol.h2
-rw-r--r--net/quic/quic_client_session.cc27
-rw-r--r--net/quic/quic_client_session.h9
-rw-r--r--net/quic/quic_client_session_test.cc13
-rw-r--r--net/quic/quic_connection.cc16
-rw-r--r--net/quic/quic_crypto_client_stream_test.cc113
-rw-r--r--net/quic/quic_crypto_server_stream_test.cc150
-rw-r--r--net/quic/quic_flags.cc9
-rw-r--r--net/quic/quic_flags.h3
-rw-r--r--net/quic/quic_flow_controller.cc127
-rw-r--r--net/quic/quic_flow_controller.h65
-rw-r--r--net/quic/quic_flow_controller_test.cc233
-rw-r--r--net/quic/quic_framer.cc9
-rw-r--r--net/quic/quic_http_stream_test.cc11
-rw-r--r--net/quic/quic_packet_generator_test.cc131
-rw-r--r--net/quic/quic_protocol.cc12
-rw-r--r--net/quic/quic_protocol.h6
-rw-r--r--net/quic/quic_session.cc32
-rw-r--r--net/quic/quic_session.h6
-rw-r--r--net/quic/quic_session_test.cc2
-rw-r--r--net/quic/quic_stream_factory.cc8
-rw-r--r--net/quic/reliable_quic_stream.cc2
-rw-r--r--net/quic/test_tools/crypto_test_utils.cc53
-rw-r--r--net/quic/test_tools/quic_flow_controller_peer.cc8
-rw-r--r--net/quic/test_tools/quic_flow_controller_peer.h3
-rw-r--r--net/quic/test_tools/quic_test_utils.cc95
-rw-r--r--net/quic/test_tools/quic_test_utils.h80
-rw-r--r--net/tools/quic/end_to_end_test.cc3
-rw-r--r--net/tools/quic/quic_client.cc15
-rw-r--r--net/tools/quic/quic_client.h6
-rw-r--r--net/tools/quic/quic_client_session.cc17
-rw-r--r--net/tools/quic/quic_client_session.h8
-rw-r--r--net/tools/quic/quic_client_session_test.cc7
-rw-r--r--net/tools/quic/quic_dispatcher.cc5
-rw-r--r--net/tools/quic/quic_dispatcher_test.cc43
-rw-r--r--net/tools/quic/quic_in_memory_cache.cc7
-rw-r--r--net/tools/quic/quic_in_memory_cache.h11
-rw-r--r--net/tools/quic/quic_in_memory_cache_test.cc38
-rw-r--r--net/tools/quic/quic_server_session.cc16
-rw-r--r--net/tools/quic/quic_server_session.h8
-rw-r--r--net/tools/quic/quic_server_session_test.cc7
-rw-r--r--net/tools/quic/quic_simple_client.cc13
-rw-r--r--net/tools/quic/quic_simple_client.h6
-rw-r--r--net/tools/quic/quic_spdy_client_stream_test.cc11
-rw-r--r--net/tools/quic/test_tools/quic_test_utils.cc16
-rw-r--r--net/tools/quic/test_tools/quic_test_utils.h18
46 files changed, 949 insertions, 531 deletions
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h
index 1b4abe9..3e9468a 100644
--- a/net/quic/crypto/crypto_protocol.h
+++ b/net/quic/crypto/crypto_protocol.h
@@ -53,6 +53,8 @@ const QuicTag kSRBF = TAG('S', 'R', 'B', 'F'); // Socket receive buffer
const QuicTag kQBIC = TAG('Q', 'B', 'I', 'C'); // TCP cubic
// Connection options (COPT) values
+const QuicTag kAFCW = TAG('A', 'F', 'C', 'W'); // Auto-tune flow control
+ // receive windows.
const QuicTag kTBBR = TAG('T', 'B', 'B', 'R'); // Reduced Buffer Bloat TCP
const QuicTag kRENO = TAG('R', 'E', 'N', 'O'); // Reno Congestion Control
const QuicTag kBYTE = TAG('B', 'Y', 'T', 'E'); // TCP cubic or reno in bytes
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index f13028d..f62f61e 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -157,14 +157,18 @@ QuicClientSession::QuicClientSession(
QuicConnection* connection,
scoped_ptr<DatagramClientSocket> socket,
QuicStreamFactory* stream_factory,
+ QuicCryptoClientStreamFactory* crypto_client_stream_factory,
TransportSecurityState* transport_security_state,
scoped_ptr<QuicServerInfo> server_info,
+ const QuicServerId& server_id,
const QuicConfig& config,
+ QuicCryptoClientConfig* crypto_config,
const char* const connection_description,
base::TimeTicks dns_resolution_end_time,
base::TaskRunner* task_runner,
NetLog* net_log)
: QuicClientSessionBase(connection, config),
+ server_id_(server_id),
require_confirmation_(false),
stream_factory_(stream_factory),
socket_(socket.Pass()),
@@ -178,20 +182,6 @@ QuicClientSession::QuicClientSession(
logger_(new QuicConnectionLogger(this, connection_description, net_log_)),
going_away_(false),
weak_factory_(this) {
- connection->set_debug_visitor(logger_.get());
- IPEndPoint address;
- if (socket && socket->GetLocalAddress(&address) == OK &&
- address.GetFamily() == ADDRESS_FAMILY_IPV6) {
- connection->set_max_packet_length(
- connection->max_packet_length() - kAdditionalOverheadForIPv6);
- }
-}
-
-void QuicClientSession::InitializeSession(
- const QuicServerId& server_id,
- QuicCryptoClientConfig* crypto_config,
- QuicCryptoClientStreamFactory* crypto_client_stream_factory) {
- server_id_ = server_id;
crypto_stream_.reset(
crypto_client_stream_factory ?
crypto_client_stream_factory->CreateQuicCryptoClientStream(
@@ -199,12 +189,17 @@ void QuicClientSession::InitializeSession(
new QuicCryptoClientStream(server_id, this,
new ProofVerifyContextChromium(net_log_),
crypto_config));
- QuicClientSessionBase::InitializeSession();
- // TODO(rch): pass in full host port proxy pair
+ connection->set_debug_visitor(logger_.get());
net_log_.BeginEvent(NetLog::TYPE_QUIC_SESSION,
base::Bind(NetLogQuicClientSessionCallback,
&server_id,
require_confirmation_));
+ IPEndPoint address;
+ if (socket && socket->GetLocalAddress(&address) == OK &&
+ address.GetFamily() == ADDRESS_FAMILY_IPV6) {
+ connection->set_max_packet_length(connection->max_packet_length() -
+ kAdditionalOverheadForIPv6);
+ }
}
QuicClientSession::~QuicClientSession() {
diff --git a/net/quic/quic_client_session.h b/net/quic/quic_client_session.h
index 4300dcd..fe7033d 100644
--- a/net/quic/quic_client_session.h
+++ b/net/quic/quic_client_session.h
@@ -95,21 +95,18 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicClientSessionBase,
QuicClientSession(QuicConnection* connection,
scoped_ptr<DatagramClientSocket> socket,
QuicStreamFactory* stream_factory,
+ QuicCryptoClientStreamFactory* crypto_client_stream_factory,
TransportSecurityState* transport_security_state,
scoped_ptr<QuicServerInfo> server_info,
+ const QuicServerId& server_id,
const QuicConfig& config,
+ QuicCryptoClientConfig* crypto_config,
const char* const connection_description,
base::TimeTicks dns_resolution_end_time,
base::TaskRunner* task_runner,
NetLog* net_log);
~QuicClientSession() override;
- // Initialize session's connection to |server_id|.
- void InitializeSession(
- const QuicServerId& server_id,
- QuicCryptoClientConfig* config,
- QuicCryptoClientStreamFactory* crypto_client_stream_factory);
-
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
diff --git a/net/quic/quic_client_session_test.cc b/net/quic/quic_client_session_test.cc
index f487f8d..4c3179f 100644
--- a/net/quic/quic_client_session_test.cc
+++ b/net/quic/quic_client_session_test.cc
@@ -46,18 +46,21 @@ class QuicClientSessionTest : public ::testing::TestWithParam<QuicVersion> {
SupportedVersions(GetParam()))),
session_(connection_,
GetSocket().Pass(),
- nullptr,
+ /*stream_factory=*/nullptr,
+ /*crypto_client_stream_factory=*/nullptr,
&transport_security_state_,
make_scoped_ptr((QuicServerInfo*)nullptr),
+ QuicServerId(kServerHostname,
+ kServerPort,
+ /*is_secure=*/false,
+ PRIVACY_MODE_DISABLED),
DefaultQuicConfig(),
+ &crypto_config_,
"CONNECTION_UNKNOWN",
base::TimeTicks::Now(),
base::ThreadTaskRunnerHandle::Get().get(),
&net_log_) {
- session_.InitializeSession(QuicServerId(kServerHostname, kServerPort,
- /*is_secure=*/false,
- PRIVACY_MODE_DISABLED),
- &crypto_config_, nullptr);
+ session_.Initialize();
// Advance the time, because timers do not like uninitialized times.
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 5f17af5..48aa7c1 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -907,7 +907,7 @@ void QuicConnection::OnPacketComplete() {
if (!last_stream_frames_.empty()) {
visitor_->OnStreamFrames(last_stream_frames_);
- if (!connected_ && !FLAGS_quic_stop_early) {
+ if (!connected_ && FLAGS_quic_stop_early_2) {
return;
}
}
@@ -919,44 +919,44 @@ void QuicConnection::OnPacketComplete() {
// feedback.
if (!last_window_update_frames_.empty()) {
visitor_->OnWindowUpdateFrames(last_window_update_frames_);
- if (!connected_ && !FLAGS_quic_stop_early) {
+ if (!connected_ && FLAGS_quic_stop_early_2) {
return;
}
}
if (!last_blocked_frames_.empty()) {
visitor_->OnBlockedFrames(last_blocked_frames_);
- if (!connected_ && !FLAGS_quic_stop_early) {
+ if (!connected_ && FLAGS_quic_stop_early_2) {
return;
}
}
for (size_t i = 0; i < last_goaway_frames_.size(); ++i) {
visitor_->OnGoAway(last_goaway_frames_[i]);
- if (!connected_ && !FLAGS_quic_stop_early) {
+ if (!connected_ && FLAGS_quic_stop_early_2) {
return;
}
}
for (size_t i = 0; i < last_rst_frames_.size(); ++i) {
visitor_->OnRstStream(last_rst_frames_[i]);
- if (!connected_ && !FLAGS_quic_stop_early) {
+ if (!connected_ && FLAGS_quic_stop_early_2) {
return;
}
}
for (size_t i = 0; i < last_ack_frames_.size(); ++i) {
ProcessAckFrame(last_ack_frames_[i]);
- if (!connected_ && !FLAGS_quic_stop_early) {
+ if (!connected_ && FLAGS_quic_stop_early_2) {
return;
}
}
for (size_t i = 0; i < last_stop_waiting_frames_.size(); ++i) {
ProcessStopWaitingFrame(last_stop_waiting_frames_[i]);
- if (!connected_ && !FLAGS_quic_stop_early) {
+ if (!connected_ && FLAGS_quic_stop_early_2) {
return;
}
}
if (!last_close_frames_.empty()) {
CloseConnection(last_close_frames_[0].error_code, true);
DCHECK(!connected_);
- if (!FLAGS_quic_stop_early) {
+ if (FLAGS_quic_stop_early_2) {
return;
}
}
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
index 4fc872a..2dcf783 100644
--- a/net/quic/quic_crypto_client_stream_test.cc
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -30,21 +30,22 @@ const uint16 kServerPort = 80;
class QuicCryptoClientStreamTest : public ::testing::Test {
public:
QuicCryptoClientStreamTest()
- : connection_(new PacketSavingConnection(Perspective::IS_CLIENT)),
- session_(new TestClientSession(connection_, DefaultQuicConfig())),
- server_id_(kServerHostname, kServerPort, false, PRIVACY_MODE_DISABLED),
- stream_(new QuicCryptoClientStream(server_id_,
- session_.get(),
- nullptr,
- &crypto_config_)) {
- session_->SetCryptoStream(stream_.get());
+ : server_id_(kServerHostname, kServerPort, false, PRIVACY_MODE_DISABLED) {
+ CreateConnection();
+ }
+
+ void CreateConnection() {
+ connection_ = new PacketSavingConnection(Perspective::IS_CLIENT);
// Advance the time, because timers do not like uninitialized times.
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
+
+ session_.reset(new TestClientSession(connection_, DefaultQuicConfig(),
+ server_id_, &crypto_config_));
}
void CompleteCryptoHandshake() {
- stream_->CryptoConnect();
- CryptoTestUtils::HandshakeWithFakeServer(connection_, stream_.get());
+ stream()->CryptoConnect();
+ CryptoTestUtils::HandshakeWithFakeServer(connection_, stream());
}
void ConstructHandshakeMessage() {
@@ -52,24 +53,25 @@ class QuicCryptoClientStreamTest : public ::testing::Test {
message_data_.reset(framer.ConstructHandshakeMessage(message_));
}
+ QuicCryptoClientStream* stream() { return session_->GetCryptoStream(); }
+
PacketSavingConnection* connection_;
scoped_ptr<TestClientSession> session_;
QuicServerId server_id_;
- scoped_ptr<QuicCryptoClientStream> stream_;
CryptoHandshakeMessage message_;
scoped_ptr<QuicData> message_data_;
QuicCryptoClientConfig crypto_config_;
};
TEST_F(QuicCryptoClientStreamTest, NotInitiallyConected) {
- EXPECT_FALSE(stream_->encryption_established());
- EXPECT_FALSE(stream_->handshake_confirmed());
+ EXPECT_FALSE(stream()->encryption_established());
+ EXPECT_FALSE(stream()->handshake_confirmed());
}
TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) {
CompleteCryptoHandshake();
- EXPECT_TRUE(stream_->encryption_established());
- EXPECT_TRUE(stream_->handshake_confirmed());
+ EXPECT_TRUE(stream()->encryption_established());
+ EXPECT_TRUE(stream()->handshake_confirmed());
}
TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) {
@@ -79,18 +81,18 @@ TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) {
QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
message_.set_tag(kCHLO);
ConstructHandshakeMessage();
- stream_->ProcessRawData(message_data_->data(), message_data_->length());
+ stream()->ProcessRawData(message_data_->data(), message_data_->length());
}
TEST_F(QuicCryptoClientStreamTest, BadMessageType) {
- stream_->CryptoConnect();
+ stream()->CryptoConnect();
message_.set_tag(kCHLO);
ConstructHandshakeMessage();
EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
QUIC_INVALID_CRYPTO_MESSAGE_TYPE, "Expected REJ"));
- stream_->ProcessRawData(message_data_->data(), message_data_->length());
+ stream()->ProcessRawData(message_data_->data(), message_data_->length());
}
TEST_F(QuicCryptoClientStreamTest, NegotiatedParameters) {
@@ -103,39 +105,35 @@ TEST_F(QuicCryptoClientStreamTest, NegotiatedParameters) {
config->MaxStreamsPerConnection());
const QuicCryptoNegotiatedParameters& crypto_params(
- stream_->crypto_negotiated_params());
+ stream()->crypto_negotiated_params());
EXPECT_EQ(crypto_config_.aead[0], crypto_params.aead);
EXPECT_EQ(crypto_config_.kexs[0], crypto_params.key_exchange);
}
TEST_F(QuicCryptoClientStreamTest, InvalidHostname) {
- QuicServerId server_id("invalid", 80, false, PRIVACY_MODE_DISABLED);
- stream_.reset(new QuicCryptoClientStream(server_id, session_.get(), nullptr,
- &crypto_config_));
- session_->SetCryptoStream(stream_.get());
+ server_id_ =
+ QuicServerId("invalid", kServerPort, false, PRIVACY_MODE_DISABLED);
+
+ CreateConnection();
CompleteCryptoHandshake();
- EXPECT_TRUE(stream_->encryption_established());
- EXPECT_TRUE(stream_->handshake_confirmed());
+ EXPECT_TRUE(stream()->encryption_established());
+ EXPECT_TRUE(stream()->handshake_confirmed());
}
TEST_F(QuicCryptoClientStreamTest, ExpiredServerConfig) {
// Seed the config with a cached server config.
CompleteCryptoHandshake();
- connection_ = new PacketSavingConnection(Perspective::IS_CLIENT);
- session_.reset(new TestClientSession(connection_, DefaultQuicConfig()));
- stream_.reset(new QuicCryptoClientStream(server_id_, session_.get(), nullptr,
- &crypto_config_));
-
- session_->SetCryptoStream(stream_.get());
+ // Recreate connection with the new config.
+ CreateConnection();
// Advance time 5 years to ensure that we pass the expiry time of the cached
// server config.
connection_->AdvanceTime(
QuicTime::Delta::FromSeconds(60 * 60 * 24 * 365 * 5));
- stream_->CryptoConnect();
+ stream()->CryptoConnect();
// Check that a client hello was sent.
ASSERT_EQ(1u, connection_->encrypted_packets_.size());
}
@@ -179,7 +177,7 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdate) {
scoped_ptr<QuicData> data(
CryptoFramer::ConstructHandshakeMessage(server_config_update));
- stream_->ProcessRawData(data->data(), data->length());
+ stream()->ProcessRawData(data->data(), data->length());
// Make sure that the STK and SCFG are cached correctly.
EXPECT_EQ("xstk", state->source_address_token());
@@ -197,7 +195,7 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateBeforeHandshake) {
server_config_update.set_tag(kSCUP);
scoped_ptr<QuicData> data(
CryptoFramer::ConstructHandshakeMessage(server_config_update));
- stream_->ProcessRawData(data->data(), data->length());
+ stream()->ProcessRawData(data->data(), data->length());
}
class QuicCryptoClientStreamStatelessTest : public ::testing::Test {
@@ -207,54 +205,49 @@ class QuicCryptoClientStreamStatelessTest : public ::testing::Test {
QuicRandom::GetInstance()),
server_id_(kServerHostname, kServerPort, false, PRIVACY_MODE_DISABLED) {
TestClientSession* client_session = nullptr;
- QuicCryptoClientStream* client_stream = nullptr;
- SetupCryptoClientStreamForTest(server_id_,
- /* supports_stateless_rejects= */ true,
- QuicTime::Delta::FromSeconds(100000),
- &client_crypto_config_, &client_connection_,
- &client_session, &client_stream);
+ CreateClientSessionForTest(server_id_,
+ /* supports_stateless_rejects= */ true,
+ QuicTime::Delta::FromSeconds(100000),
+ &client_crypto_config_, &client_connection_,
+ &client_session);
CHECK(client_session);
- CHECK(client_stream);
client_session_.reset(client_session);
- client_stream_.reset(client_stream);
+ }
+
+ QuicCryptoServerStream* server_stream() {
+ return server_session_->GetCryptoStream();
}
void AdvanceHandshakeWithFakeServer() {
- client_stream_->CryptoConnect();
- CryptoTestUtils::AdvanceHandshake(client_connection_, client_stream_.get(),
- 0, server_connection_,
- server_stream_.get(), 0);
+ client_session_->GetCryptoStream()->CryptoConnect();
+ CryptoTestUtils::AdvanceHandshake(client_connection_,
+ client_session_->GetCryptoStream(), 0,
+ server_connection_, server_stream(), 0);
}
// Initializes the server_stream_ for stateless rejects.
void InitializeFakeStatelessRejectServer() {
TestServerSession* server_session = nullptr;
- QuicCryptoServerStream* server_stream = nullptr;
- SetupCryptoServerStreamForTest(server_id_,
- QuicTime::Delta::FromSeconds(100000),
- &server_crypto_config_, &server_connection_,
- &server_session, &server_stream);
+ CreateServerSessionForTest(server_id_, QuicTime::Delta::FromSeconds(100000),
+ &server_crypto_config_, &server_connection_,
+ &server_session);
CHECK(server_session);
- CHECK(server_stream);
server_session_.reset(server_session);
- server_stream_.reset(server_stream);
CryptoTestUtils::SetupCryptoServerConfigForTest(
server_connection_->clock(), server_connection_->random_generator(),
server_session_->config(), &server_crypto_config_);
- server_stream_->set_use_stateless_rejects_if_peer_supported(true);
+ server_stream()->set_use_stateless_rejects_if_peer_supported(true);
}
// Client crypto stream state
PacketSavingConnection* client_connection_;
scoped_ptr<TestClientSession> client_session_;
- scoped_ptr<QuicCryptoClientStream> client_stream_;
QuicCryptoClientConfig client_crypto_config_;
// Server crypto stream state
PacketSavingConnection* server_connection_;
scoped_ptr<TestServerSession> server_session_;
QuicCryptoServerConfig server_crypto_config_;
- scoped_ptr<QuicCryptoServerStream> server_stream_;
QuicServerId server_id_;
};
@@ -271,11 +264,11 @@ TEST_F(QuicCryptoClientStreamStatelessTest, StatelessReject) {
InitializeFakeStatelessRejectServer();
AdvanceHandshakeWithFakeServer();
- EXPECT_EQ(1, server_stream_->num_handshake_messages());
- EXPECT_EQ(0, server_stream_->num_handshake_messages_with_server_nonces());
+ EXPECT_EQ(1, server_stream()->num_handshake_messages());
+ EXPECT_EQ(0, server_stream()->num_handshake_messages_with_server_nonces());
- EXPECT_FALSE(client_stream_->encryption_established());
- EXPECT_FALSE(client_stream_->handshake_confirmed());
+ EXPECT_FALSE(client_session_->GetCryptoStream()->encryption_established());
+ EXPECT_FALSE(client_session_->GetCryptoStream()->handshake_confirmed());
// Even though the handshake was not complete, the cached client_state is
// complete, and can be used for a subsequent successful handshake.
EXPECT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc
index 2a51402..f47c03b 100644
--- a/net/quic/quic_crypto_server_stream_test.cc
+++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -96,33 +96,34 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
// called multiple times.
void InitializeServer() {
TestServerSession* server_session = nullptr;
- QuicCryptoServerStream* server_stream = nullptr;
- SetupCryptoServerStreamForTest(server_id_,
- QuicTime::Delta::FromSeconds(100000),
- &server_crypto_config_, &server_connection_,
- &server_session, &server_stream);
+ CreateServerSessionForTest(server_id_, QuicTime::Delta::FromSeconds(100000),
+ &server_crypto_config_, &server_connection_,
+ &server_session);
CHECK(server_session);
- CHECK(server_stream);
server_session_.reset(server_session);
- server_stream_.reset(server_stream);
CryptoTestUtils::SetupCryptoServerConfigForTest(
server_connection_->clock(), server_connection_->random_generator(),
server_session_->config(), &server_crypto_config_);
}
+ QuicCryptoServerStream* server_stream() {
+ return server_session_->GetCryptoStream();
+ }
+
+ QuicCryptoClientStream* client_stream() {
+ return client_session_->GetCryptoStream();
+ }
+
// Initializes a fake client, and all its associated state, for
// testing. May be called multiple times.
void InitializeFakeClient(bool supports_stateless_rejects) {
TestClientSession* client_session = nullptr;
- QuicCryptoClientStream* client_stream = nullptr;
- SetupCryptoClientStreamForTest(server_id_, supports_stateless_rejects,
- QuicTime::Delta::FromSeconds(100000),
- &client_crypto_config_, &client_connection_,
- &client_session, &client_stream);
+ CreateClientSessionForTest(server_id_, supports_stateless_rejects,
+ QuicTime::Delta::FromSeconds(100000),
+ &client_crypto_config_, &client_connection_,
+ &client_session);
CHECK(client_session);
- CHECK(client_stream);
client_session_.reset(client_session);
- client_stream_.reset(client_stream);
}
bool AsyncStrikeRegisterVerification() {
@@ -136,24 +137,21 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
int CompleteCryptoHandshake() {
CHECK(server_connection_);
- CHECK(server_stream_ != nullptr);
+ CHECK(server_session_ != nullptr);
return CryptoTestUtils::HandshakeWithFakeClient(
- server_connection_, server_stream_.get(), client_options_);
+ server_connection_, server_stream(), client_options_);
}
// Performs a single round of handshake message-exchange between the
// client and server.
void AdvanceHandshakeWithFakeClient() {
CHECK(server_connection_);
- CHECK(server_stream_ != nullptr);
CHECK(client_session_ != nullptr);
- CHECK(client_stream_ != nullptr);
EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
- client_stream_->CryptoConnect();
- CryptoTestUtils::AdvanceHandshake(client_connection_, client_stream_.get(),
- 0, server_connection_,
- server_stream_.get(), 0);
+ client_stream()->CryptoConnect();
+ CryptoTestUtils::AdvanceHandshake(client_connection_, client_stream(), 0,
+ server_connection_, server_stream(), 0);
}
protected:
@@ -161,14 +159,12 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
PacketSavingConnection* server_connection_;
scoped_ptr<TestServerSession> server_session_;
QuicCryptoServerConfig server_crypto_config_;
- scoped_ptr<QuicCryptoServerStream> server_stream_;
QuicServerId server_id_;
// Client state
PacketSavingConnection* client_connection_;
QuicCryptoClientConfig client_crypto_config_;
scoped_ptr<TestClientSession> client_session_;
- scoped_ptr<QuicCryptoClientStream> client_stream_;
CryptoHandshakeMessage message_;
scoped_ptr<QuicData> message_data_;
@@ -179,13 +175,13 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
INSTANTIATE_TEST_CASE_P(Tests, QuicCryptoServerStreamTest, testing::Bool());
TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) {
- EXPECT_FALSE(server_stream_->encryption_established());
- EXPECT_FALSE(server_stream_->handshake_confirmed());
+ EXPECT_FALSE(server_stream()->encryption_established());
+ EXPECT_FALSE(server_stream()->handshake_confirmed());
}
TEST_P(QuicCryptoServerStreamTest, NotInitiallySendingStatelessRejects) {
- EXPECT_FALSE(server_stream_->use_stateless_rejects_if_peer_supported());
- EXPECT_FALSE(server_stream_->peer_supports_stateless_rejects());
+ EXPECT_FALSE(server_stream()->use_stateless_rejects_if_peer_supported());
+ EXPECT_FALSE(server_stream()->peer_supports_stateless_rejects());
}
TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
@@ -194,21 +190,21 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
// * One to get a source-address token and certificates.
// * One to complete the handshake.
EXPECT_EQ(2, CompleteCryptoHandshake());
- EXPECT_TRUE(server_stream_->encryption_established());
- EXPECT_TRUE(server_stream_->handshake_confirmed());
+ EXPECT_TRUE(server_stream()->encryption_established());
+ EXPECT_TRUE(server_stream()->handshake_confirmed());
}
TEST_P(QuicCryptoServerStreamTest, StatelessRejectAfterCHLO) {
ValueRestore<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support,
true);
- server_stream_->set_use_stateless_rejects_if_peer_supported(true);
+ server_stream()->set_use_stateless_rejects_if_peer_supported(true);
InitializeFakeClient(/* supports_stateless_rejects= */ true);
AdvanceHandshakeWithFakeClient();
// Check the server to make the sure the handshake did not succeed.
- EXPECT_FALSE(server_stream_->encryption_established());
- EXPECT_FALSE(server_stream_->handshake_confirmed());
+ EXPECT_FALSE(server_stream()->encryption_established());
+ EXPECT_FALSE(server_stream()->handshake_confirmed());
// Check the client state to make sure that it received a server-designated
// connection id.
@@ -233,16 +229,16 @@ TEST_P(QuicCryptoServerStreamTest, StatelessRejectAfterCHLO) {
TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) {
ValueRestore<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support,
true);
- server_stream_->set_use_stateless_rejects_if_peer_supported(true);
+ server_stream()->set_use_stateless_rejects_if_peer_supported(true);
InitializeFakeClient(/* supports_stateless_rejects= */ true);
AdvanceHandshakeWithFakeClient();
// On the first round, encryption will not be established.
- EXPECT_FALSE(server_stream_->encryption_established());
- EXPECT_FALSE(server_stream_->handshake_confirmed());
- EXPECT_EQ(1, server_stream_->num_handshake_messages());
- EXPECT_EQ(0, server_stream_->num_handshake_messages_with_server_nonces());
+ EXPECT_FALSE(server_stream()->encryption_established());
+ EXPECT_FALSE(server_stream()->handshake_confirmed());
+ EXPECT_EQ(1, server_stream()->num_handshake_messages());
+ EXPECT_EQ(0, server_stream()->num_handshake_messages_with_server_nonces());
// Now check the client state.
QuicCryptoClientConfig::CachedState* client_state =
@@ -261,11 +257,11 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) {
// Now create new client and server streams with the existing config
// and try the handshake again (0-RTT handshake).
InitializeServer();
- server_stream_->set_use_stateless_rejects_if_peer_supported(true);
+ server_stream()->set_use_stateless_rejects_if_peer_supported(true);
InitializeFakeClient(/* supports_stateless_rejects= */ true);
- client_stream_->CryptoConnect();
+ client_stream()->CryptoConnect();
// In the stateless case, the second handshake contains a server-nonce, so the
// AsyncStrikeRegisterVerification() case will still succeed (unlike a 0-RTT
@@ -273,16 +269,16 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) {
AdvanceHandshakeWithFakeClient();
// On the second round, encryption will be established.
- EXPECT_TRUE(server_stream_->encryption_established());
- EXPECT_TRUE(server_stream_->handshake_confirmed());
- EXPECT_EQ(2, server_stream_->num_handshake_messages());
- EXPECT_EQ(1, server_stream_->num_handshake_messages_with_server_nonces());
+ EXPECT_TRUE(server_stream()->encryption_established());
+ EXPECT_TRUE(server_stream()->handshake_confirmed());
+ EXPECT_EQ(2, server_stream()->num_handshake_messages());
+ EXPECT_EQ(1, server_stream()->num_handshake_messages_with_server_nonces());
}
TEST_P(QuicCryptoServerStreamTest, NoStatelessRejectIfNoClientSupport) {
ValueRestore<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support,
true);
- server_stream_->set_use_stateless_rejects_if_peer_supported(true);
+ server_stream()->set_use_stateless_rejects_if_peer_supported(true);
// The server is configured to use stateless rejects, but the client does not
// support it.
@@ -290,8 +286,8 @@ TEST_P(QuicCryptoServerStreamTest, NoStatelessRejectIfNoClientSupport) {
AdvanceHandshakeWithFakeClient();
// Check the server to make the sure the handshake did not succeed.
- EXPECT_FALSE(server_stream_->encryption_established());
- EXPECT_FALSE(server_stream_->handshake_confirmed());
+ EXPECT_FALSE(server_stream()->encryption_established());
+ EXPECT_FALSE(server_stream()->handshake_confirmed());
// Check the client state to make sure that it did not receive a
// server-designated connection id.
@@ -314,42 +310,42 @@ TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
InitializeFakeClient(/* supports_stateless_rejects= */ false);
InitializeServer();
- client_stream_->CryptoConnect();
+ client_stream()->CryptoConnect();
if (AsyncStrikeRegisterVerification()) {
- EXPECT_FALSE(client_stream_->handshake_confirmed());
- EXPECT_FALSE(server_stream_->handshake_confirmed());
+ EXPECT_FALSE(client_stream()->handshake_confirmed());
+ EXPECT_FALSE(server_stream()->handshake_confirmed());
// Advance the handshake. Expect that the server will be stuck waiting for
// client nonce verification to complete.
pair<size_t, size_t> messages_moved = CryptoTestUtils::AdvanceHandshake(
- client_connection_, client_stream_.get(), 0, server_connection_,
- server_stream_.get(), 0);
+ client_connection_, client_stream(), 0, server_connection_,
+ server_stream(), 0);
EXPECT_EQ(1u, messages_moved.first);
EXPECT_EQ(0u, messages_moved.second);
EXPECT_EQ(1, strike_register_client_->PendingVerifications());
- EXPECT_FALSE(client_stream_->handshake_confirmed());
- EXPECT_FALSE(server_stream_->handshake_confirmed());
+ EXPECT_FALSE(client_stream()->handshake_confirmed());
+ EXPECT_FALSE(server_stream()->handshake_confirmed());
// The server handshake completes once the nonce verification completes.
strike_register_client_->RunPendingVerifications();
- EXPECT_FALSE(client_stream_->handshake_confirmed());
- EXPECT_TRUE(server_stream_->handshake_confirmed());
+ EXPECT_FALSE(client_stream()->handshake_confirmed());
+ EXPECT_TRUE(server_stream()->handshake_confirmed());
messages_moved = CryptoTestUtils::AdvanceHandshake(
- client_connection_, client_stream_.get(), messages_moved.first,
- server_connection_, server_stream_.get(), messages_moved.second);
+ client_connection_, client_stream(), messages_moved.first,
+ server_connection_, server_stream(), messages_moved.second);
EXPECT_EQ(1u, messages_moved.first);
EXPECT_EQ(1u, messages_moved.second);
- EXPECT_TRUE(client_stream_->handshake_confirmed());
- EXPECT_TRUE(server_stream_->handshake_confirmed());
+ EXPECT_TRUE(client_stream()->handshake_confirmed());
+ EXPECT_TRUE(server_stream()->handshake_confirmed());
} else {
CryptoTestUtils::CommunicateHandshakeMessages(
- client_connection_, client_stream_.get(), server_connection_,
- server_stream_.get());
+ client_connection_, client_stream(), server_connection_,
+ server_stream());
}
- EXPECT_EQ(1, client_stream_->num_sent_client_hellos());
+ EXPECT_EQ(1, client_stream()->num_sent_client_hellos());
}
TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) {
@@ -359,8 +355,8 @@ TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) {
SendConnectionClose(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
message_.set_tag(kCHLO);
ConstructHandshakeMessage();
- server_stream_->ProcessRawData(message_data_->data(),
- message_data_->length());
+ server_stream()->ProcessRawData(message_data_->data(),
+ message_data_->length());
}
TEST_P(QuicCryptoServerStreamTest, BadMessageType) {
@@ -368,8 +364,8 @@ TEST_P(QuicCryptoServerStreamTest, BadMessageType) {
ConstructHandshakeMessage();
EXPECT_CALL(*server_connection_,
SendConnectionClose(QUIC_INVALID_CRYPTO_MESSAGE_TYPE));
- server_stream_->ProcessRawData(message_data_->data(),
- message_data_->length());
+ server_stream()->ProcessRawData(message_data_->data(),
+ message_data_->length());
}
TEST_P(QuicCryptoServerStreamTest, WithoutCertificates) {
@@ -379,34 +375,34 @@ TEST_P(QuicCryptoServerStreamTest, WithoutCertificates) {
// Only 2 client hellos need to be sent in the no-certs case: one to get the
// source-address token and the second to finish.
EXPECT_EQ(2, CompleteCryptoHandshake());
- EXPECT_TRUE(server_stream_->encryption_established());
- EXPECT_TRUE(server_stream_->handshake_confirmed());
+ EXPECT_TRUE(server_stream()->encryption_established());
+ EXPECT_TRUE(server_stream()->handshake_confirmed());
}
TEST_P(QuicCryptoServerStreamTest, ChannelID) {
client_options_.channel_id_enabled = true;
client_options_.channel_id_source_async = false;
// CompleteCryptoHandshake verifies
- // server_stream_->crypto_negotiated_params().channel_id is correct.
+ // server_stream()->crypto_negotiated_params().channel_id is correct.
EXPECT_EQ(2, CompleteCryptoHandshake());
- EXPECT_TRUE(server_stream_->encryption_established());
- EXPECT_TRUE(server_stream_->handshake_confirmed());
+ EXPECT_TRUE(server_stream()->encryption_established());
+ EXPECT_TRUE(server_stream()->handshake_confirmed());
}
TEST_P(QuicCryptoServerStreamTest, ChannelIDAsync) {
client_options_.channel_id_enabled = true;
client_options_.channel_id_source_async = true;
// CompleteCryptoHandshake verifies
- // server_stream_->crypto_negotiated_params().channel_id is correct.
+ // server_stream()->crypto_negotiated_params().channel_id is correct.
EXPECT_EQ(2, CompleteCryptoHandshake());
- EXPECT_TRUE(server_stream_->encryption_established());
- EXPECT_TRUE(server_stream_->handshake_confirmed());
+ EXPECT_TRUE(server_stream()->encryption_established());
+ EXPECT_TRUE(server_stream()->handshake_confirmed());
}
TEST_P(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) {
// An attempt to send a SCUP before completing handshake should fail.
- server_stream_->SendServerConfigUpdate(nullptr);
- EXPECT_EQ(0, server_stream_->num_server_config_update_messages_sent());
+ server_stream()->SendServerConfigUpdate(nullptr);
+ EXPECT_EQ(0, server_stream()->num_server_config_update_messages_sent());
}
TEST_P(QuicCryptoServerStreamTest, DoesPeerSupportStatelessRejects) {
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc
index cf3b262..f36b667 100644
--- a/net/quic/quic_flags.cc
+++ b/net/quic/quic_flags.cc
@@ -42,6 +42,9 @@ int64 FLAGS_quic_time_wait_list_max_connections = 50000;
// Enables server-side support for QUIC stateless rejects.
bool FLAGS_enable_quic_stateless_reject_support = false;
-// If true, stop processing quic data as soon as the connection is closed rather
-// than processing a full packet.
-bool FLAGS_quic_stop_early = true;
+// If true, flow controller may grow the receive window size if necessary.
+bool FLAGS_quic_auto_tune_receive_window = true;
+
+// If true, stop processing quic data as soon as the connection is
+// closed rather than processing a full packet.
+bool FLAGS_quic_stop_early_2 = true;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h
index 30bf0ae..c72be26 100644
--- a/net/quic/quic_flags.h
+++ b/net/quic/quic_flags.h
@@ -18,6 +18,7 @@ NET_EXPORT_PRIVATE extern bool FLAGS_quic_too_many_outstanding_packets;
NET_EXPORT_PRIVATE extern int64 FLAGS_quic_time_wait_list_seconds;
NET_EXPORT_PRIVATE extern int64 FLAGS_quic_time_wait_list_max_connections;
NET_EXPORT_PRIVATE extern bool FLAGS_enable_quic_stateless_reject_support;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_stop_early;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_auto_tune_receive_window;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_stop_early_2;
#endif // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/quic/quic_flow_controller.cc b/net/quic/quic_flow_controller.cc
index af79b95..699f836 100644
--- a/net/quic/quic_flow_controller.cc
+++ b/net/quic/quic_flow_controller.cc
@@ -11,6 +11,11 @@
namespace net {
+namespace {
+const QuicByteCount kStreamReceiveWindowLimit = 16 * 1024 * 1024; // 16 MB
+const QuicByteCount kSessionReceiveWindowLimit = 24 * 1024 * 1024; // 24 MB
+}
+
#define ENDPOINT \
(perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ")
@@ -19,22 +24,28 @@ QuicFlowController::QuicFlowController(QuicConnection* connection,
Perspective perspective,
QuicStreamOffset send_window_offset,
QuicStreamOffset receive_window_offset,
- QuicByteCount max_receive_window)
+ bool should_auto_tune_receive_window)
: connection_(connection),
id_(id),
perspective_(perspective),
- bytes_consumed_(0),
- highest_received_byte_offset_(0),
bytes_sent_(0),
send_window_offset_(send_window_offset),
+ bytes_consumed_(0),
+ highest_received_byte_offset_(0),
receive_window_offset_(receive_window_offset),
- max_receive_window_(max_receive_window),
- last_blocked_send_window_offset_(0) {
+ receive_window_size_(receive_window_offset),
+ auto_tune_receive_window_(should_auto_tune_receive_window),
+ last_blocked_send_window_offset_(0),
+ prev_window_update_time_(QuicTime::Zero()) {
+ receive_window_size_limit_ = (id_ == kConnectionLevelId)
+ ? kSessionReceiveWindowLimit
+ : kStreamReceiveWindowLimit;
+
DVLOG(1) << ENDPOINT << "Created flow controller for stream " << id_
<< ", setting initial receive window offset to: "
<< receive_window_offset_
- << ", max receive window to: "
- << max_receive_window_
+ << ", max receive window to: " << receive_window_size_
+ << ", max receive window limit to: " << receive_window_size_limit_
<< ", setting send window offset to: " << send_window_offset_;
}
@@ -87,28 +98,102 @@ bool QuicFlowController::FlowControlViolation() {
return false;
}
+void QuicFlowController::MaybeIncreaseMaxWindowSize() {
+ // Core of receive window auto tuning. This method should be called before a
+ // WINDOW_UPDATE frame is sent. Ideally, window updates should occur close to
+ // once per RTT. If a window update happens much faster than RTT, it implies
+ // that the flow control window is imposing a bottleneck. To prevent this,
+ // this method will increase the receive window size (subject to a reasonable
+ // upper bound). For simplicity this algorithm is deliberately asymmetric, in
+ // that it may increase window size but never decreases.
+
+ if (!FLAGS_quic_auto_tune_receive_window) {
+ return;
+ }
+
+ // Keep track of timing between successive window updates.
+ QuicTime now = connection_->clock()->ApproximateNow();
+ QuicTime prev = prev_window_update_time_;
+ prev_window_update_time_ = now;
+ if (!prev.IsInitialized()) {
+ DVLOG(1) << ENDPOINT << "first window update for stream " << id_;
+ return;
+ }
+
+ if (!auto_tune_receive_window_) {
+ return;
+ }
+
+ // Get outbound RTT.
+ QuicTime::Delta rtt =
+ connection_->sent_packet_manager().GetRttStats()->smoothed_rtt();
+ if (rtt.IsZero()) {
+ DVLOG(1) << ENDPOINT << "rtt zero for stream " << id_;
+ return;
+ }
+
+ // Now we can compare timing of window updates with RTT.
+ QuicTime::Delta since_last = now.Subtract(prev);
+ QuicTime::Delta two_rtt = rtt.Multiply(2);
+
+ if (since_last >= two_rtt) {
+ // If interval between window updates is sufficiently large, there
+ // is no need to increase receive_window_size_.
+ return;
+ }
+
+ QuicByteCount old_window = receive_window_size_;
+ receive_window_size_ *= 2;
+ receive_window_size_ =
+ std::min(receive_window_size_, receive_window_size_limit_);
+
+ if (receive_window_size_ > old_window) {
+ DVLOG(1) << ENDPOINT << "New max window increase for stream " << id_
+ << " after " << since_last.ToMicroseconds() << " us, and RTT is "
+ << rtt.ToMicroseconds()
+ << "us. max wndw: " << receive_window_size_;
+ } else {
+ // TODO(ckrasic) - add a varz to track this (?).
+ DVLOG(1) << ENDPOINT << "Max window at limit for stream " << id_
+ << " after " << since_last.ToMicroseconds() << " us, and RTT is "
+ << rtt.ToMicroseconds()
+ << "us. Limit size: " << receive_window_size_;
+ }
+}
+
+QuicByteCount QuicFlowController::WindowUpdateThreshold() {
+ return receive_window_size_ / 2;
+}
+
void QuicFlowController::MaybeSendWindowUpdate() {
// Send WindowUpdate to increase receive window if
// (receive window offset - consumed bytes) < (max window / 2).
// This is behaviour copied from SPDY.
- DCHECK_LT(bytes_consumed_, receive_window_offset_);
+ DCHECK_LE(bytes_consumed_, receive_window_offset_);
QuicStreamOffset available_window = receive_window_offset_ - bytes_consumed_;
- QuicByteCount threshold = (max_receive_window_ / 2);
-
- if (available_window < threshold) {
- // Update our receive window.
- receive_window_offset_ += (max_receive_window_ - available_window);
+ QuicByteCount threshold = WindowUpdateThreshold();
- DVLOG(1) << ENDPOINT << "Sending WindowUpdate frame for stream " << id_
- << ", consumed bytes: " << bytes_consumed_
+ if (available_window >= threshold) {
+ DVLOG(1) << ENDPOINT << "Not sending WindowUpdate for stream " << id_
<< ", available window: " << available_window
- << ", and threshold: " << threshold
- << ", and max recvw: " << max_receive_window_
- << ". New receive window offset is: " << receive_window_offset_;
-
- // Inform the peer of our new receive window.
- connection_->SendWindowUpdate(id_, receive_window_offset_);
+ << ">= threshold: " << threshold;
+ return;
}
+
+ MaybeIncreaseMaxWindowSize();
+
+ // Update our receive window.
+ receive_window_offset_ += (receive_window_size_ - available_window);
+
+ DVLOG(1) << ENDPOINT << "Sending WindowUpdate frame for stream " << id_
+ << ", consumed bytes: " << bytes_consumed_
+ << ", available window: " << available_window
+ << ", and threshold: " << threshold
+ << ", and receive window size: " << receive_window_size_
+ << ". New receive window offset is: " << receive_window_offset_;
+
+ // Inform the peer of our new receive window.
+ connection_->SendWindowUpdate(id_, receive_window_offset_);
}
void QuicFlowController::MaybeSendBlocked() {
diff --git a/net/quic/quic_flow_controller.h b/net/quic/quic_flow_controller.h
index afa022b1..f1973f2 100644
--- a/net/quic/quic_flow_controller.h
+++ b/net/quic/quic_flow_controller.h
@@ -30,7 +30,8 @@ class NET_EXPORT_PRIVATE QuicFlowController {
Perspective perspective,
QuicStreamOffset send_window_offset,
QuicStreamOffset receive_window_offset,
- QuicByteCount max_receive_window);
+ bool should_auto_tune_receive_window);
+
~QuicFlowController() {}
// Called when we see a new highest received byte offset from the peer, either
@@ -68,12 +69,26 @@ class NET_EXPORT_PRIVATE QuicFlowController {
return highest_received_byte_offset_;
}
+ void set_receive_window_size_limit(QuicByteCount receive_window_size_limit) {
+ DCHECK_GE(receive_window_size_limit, receive_window_size_limit_);
+ receive_window_size_limit_ = receive_window_size_limit;
+ }
+
+ void set_auto_tune_receive_window(bool enable) {
+ auto_tune_receive_window_ = enable;
+ }
+
+ bool auto_tune_receive_window() { return auto_tune_receive_window_; }
+
private:
friend class test::QuicFlowControllerPeer;
// Send a WINDOW_UPDATE frame if appropriate.
void MaybeSendWindowUpdate();
+ // Auto-tune the max receive window size.
+ void MaybeIncreaseMaxWindowSize();
+
// The parent connection, used to send connection close on flow control
// violation, and WINDOW_UPDATE and BLOCKED frames when appropriate.
// Not owned.
@@ -86,6 +101,33 @@ class NET_EXPORT_PRIVATE QuicFlowController {
// Tracks if this is owned by a server or a client.
Perspective perspective_;
+ // Tracks number of bytes sent to the peer.
+ QuicByteCount bytes_sent_;
+
+ // The absolute offset in the outgoing byte stream. If this offset is reached
+ // then we become flow control blocked until we receive a WINDOW_UPDATE.
+ QuicStreamOffset send_window_offset_;
+
+ // Overview of receive flow controller.
+ //
+ // 0=...===1=======2-------3 ...... FIN
+ // |<--- <= 4 --->|
+ //
+
+ // 1) bytes_consumed_ - moves forward when data is read out of the
+ // stream.
+ //
+ // 2) highest_received_byte_offset_ - moves when data is received
+ // from the peer.
+ //
+ // 3) receive_window_offset_ - moves when WINDOW_UPDATE is sent.
+ //
+ // 4) receive_window_size_ - maximum allowed unread data (3 - 1).
+ // This value may be increased by auto-tuning.
+ //
+ // 5) receive_window_size_limit_ - limit on receive_window_size_;
+ // auto-tuning will not increase window size beyond this limit.
+
// Track number of bytes received from the peer, which have been consumed
// locally.
QuicByteCount bytes_consumed_;
@@ -94,24 +136,31 @@ class NET_EXPORT_PRIVATE QuicFlowController {
// highest offset in a data frame, or a final value in a RST.
QuicStreamOffset highest_received_byte_offset_;
- // Tracks number of bytes sent to the peer.
- QuicByteCount bytes_sent_;
-
- // The absolute offset in the outgoing byte stream. If this offset is reached
- // then we become flow control blocked until we receive a WINDOW_UPDATE.
- QuicStreamOffset send_window_offset_;
// The absolute offset in the incoming byte stream. The peer should never send
// us bytes which are beyond this offset.
QuicStreamOffset receive_window_offset_;
// Largest size the receive window can grow to.
- QuicByteCount max_receive_window_;
+ QuicByteCount receive_window_size_;
+
+ // Upper limit on receive_window_size_;
+ QuicByteCount receive_window_size_limit_;
+
+ // Used to dynamically enable receive window auto-tuning.
+ bool auto_tune_receive_window_;
+
+ // Send window update when receive window size drops below this.
+ QuicByteCount WindowUpdateThreshold();
// Keep track of the last time we sent a BLOCKED frame. We should only send
// another when the number of bytes we have sent has changed.
QuicStreamOffset last_blocked_send_window_offset_;
+ // Keep time of the last time a window update was sent. We use this
+ // as part of the receive window auto tuning.
+ QuicTime prev_window_update_time_;
+
DISALLOW_COPY_AND_ASSIGN(QuicFlowController);
};
diff --git a/net/quic/quic_flow_controller_test.cc b/net/quic/quic_flow_controller_test.cc
index 4562a14..dffbd56 100644
--- a/net/quic/quic_flow_controller_test.cc
+++ b/net/quic/quic_flow_controller_test.cc
@@ -6,9 +6,11 @@
#include "base/format_macros.h"
#include "base/strings/stringprintf.h"
+#include "net/quic/quic_flags.h"
#include "net/quic/quic_utils.h"
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_flow_controller_peer.h"
+#include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -16,26 +18,27 @@
namespace net {
namespace test {
+// Receive window auto-tuning uses RTT in its logic.
+const int64 kRtt = 100;
+
class QuicFlowControllerTest : public ::testing::Test {
public:
QuicFlowControllerTest()
: stream_id_(1234),
send_window_(kInitialSessionFlowControlWindowForTest),
receive_window_(kInitialSessionFlowControlWindowForTest),
- max_receive_window_(kInitialSessionFlowControlWindowForTest),
connection_(Perspective::IS_CLIENT) {}
void Initialize() {
- flow_controller_.reset(new QuicFlowController(
- &connection_, stream_id_, Perspective::IS_CLIENT, send_window_,
- receive_window_, max_receive_window_));
+ flow_controller_.reset(
+ new QuicFlowController(&connection_, stream_id_, Perspective::IS_CLIENT,
+ send_window_, receive_window_, false));
}
protected:
QuicStreamId stream_id_;
QuicByteCount send_window_;
QuicByteCount receive_window_;
- QuicByteCount max_receive_window_;
scoped_ptr<QuicFlowController> flow_controller_;
MockConnection connection_;
};
@@ -147,5 +150,225 @@ TEST_F(QuicFlowControllerTest, OnlySendBlockedFrameOncePerOffset) {
flow_controller_->MaybeSendBlocked();
}
+TEST_F(QuicFlowControllerTest, ReceivingBytesFastIncreasesFlowWindow) {
+ ValueRestore<bool> old_flag(&FLAGS_quic_auto_tune_receive_window, true);
+ // This test will generate two WINDOW_UPDATE frames.
+ EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, ::testing::_)).Times(2);
+
+ Initialize();
+ flow_controller_->set_auto_tune_receive_window(true);
+
+ // Make sure clock is inititialized.
+ connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+
+ QuicSentPacketManager* manager =
+ QuicConnectionPeer::GetSentPacketManager(&connection_);
+
+ RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager);
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kRtt),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+
+ EXPECT_FALSE(flow_controller_->IsBlocked());
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ QuicByteCount threshold =
+ QuicFlowControllerPeer::WindowUpdateThreshold(flow_controller_.get());
+
+ QuicStreamOffset receive_offset = threshold + 1;
+ // Receive some bytes, updating highest received offset, but not enough to
+ // fill flow control receive window.
+ EXPECT_TRUE(flow_controller_->UpdateHighestReceivedOffset(receive_offset));
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest - receive_offset,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ // Consume enough bytes to send a WINDOW_UPDATE frame.
+ flow_controller_->AddBytesConsumed(threshold + 1);
+ // Result is that once again we have a fully open receive window.
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ // Move time forward, but by less than two RTTs. Then receive and consume
+ // some more, forcing a second WINDOW_UPDATE with an increased max window
+ // size.
+ connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2 * kRtt - 1));
+ receive_offset += threshold + 1;
+ EXPECT_TRUE(flow_controller_->UpdateHighestReceivedOffset(receive_offset));
+ flow_controller_->AddBytesConsumed(threshold + 1);
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ QuicByteCount new_threshold =
+ QuicFlowControllerPeer::WindowUpdateThreshold(flow_controller_.get());
+ EXPECT_GT(new_threshold, threshold);
+}
+
+TEST_F(QuicFlowControllerTest, ReceivingBytesFastStatusQuo) {
+ ValueRestore<bool> old_flag(&FLAGS_quic_auto_tune_receive_window, false);
+ // This test will generate two WINDOW_UPDATE frames.
+ EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, ::testing::_)).Times(2);
+
+ Initialize();
+ flow_controller_->set_auto_tune_receive_window(true);
+
+ // Make sure clock is inititialized.
+ connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+
+ QuicSentPacketManager* manager =
+ QuicConnectionPeer::GetSentPacketManager(&connection_);
+
+ RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager);
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kRtt),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+
+ EXPECT_FALSE(flow_controller_->IsBlocked());
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ QuicByteCount threshold =
+ QuicFlowControllerPeer::WindowUpdateThreshold(flow_controller_.get());
+
+ QuicStreamOffset receive_offset = threshold + 1;
+ // Receive some bytes, updating highest received offset, but not enough to
+ // fill flow control receive window.
+ EXPECT_TRUE(flow_controller_->UpdateHighestReceivedOffset(receive_offset));
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest - receive_offset,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ // Consume enough bytes to send a WINDOW_UPDATE frame.
+ flow_controller_->AddBytesConsumed(threshold + 1);
+ // Result is that once again we have a fully open receive window.
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ // Move time forward, but by less than two RTTs. Then receive and consume
+ // some more, forcing a second WINDOW_UPDATE with an increased max window
+ // size.
+ connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2 * kRtt - 1));
+ receive_offset += threshold + 1;
+ EXPECT_TRUE(flow_controller_->UpdateHighestReceivedOffset(receive_offset));
+ flow_controller_->AddBytesConsumed(threshold + 1);
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ QuicByteCount new_threshold =
+ QuicFlowControllerPeer::WindowUpdateThreshold(flow_controller_.get());
+ EXPECT_EQ(new_threshold, threshold);
+}
+
+TEST_F(QuicFlowControllerTest, ReceivingBytesNormalStableFlowWindow) {
+ ValueRestore<bool> old_flag(&FLAGS_quic_auto_tune_receive_window, true);
+ // This test will generate two WINDOW_UPDATE frames.
+ EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, ::testing::_)).Times(2);
+
+ Initialize();
+ flow_controller_->set_auto_tune_receive_window(true);
+
+ // Make sure clock is inititialized.
+ connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+
+ QuicSentPacketManager* manager =
+ QuicConnectionPeer::GetSentPacketManager(&connection_);
+ RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager);
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kRtt),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+
+ EXPECT_FALSE(flow_controller_->IsBlocked());
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ QuicByteCount threshold =
+ QuicFlowControllerPeer::WindowUpdateThreshold(flow_controller_.get());
+
+ QuicStreamOffset receive_offset = threshold + 1;
+ // Receive some bytes, updating highest received offset, but not enough to
+ // fill flow control receive window.
+ EXPECT_TRUE(flow_controller_->UpdateHighestReceivedOffset(receive_offset));
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest - receive_offset,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ flow_controller_->AddBytesConsumed(threshold + 1);
+
+ // Result is that once again we have a fully open receive window.
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ // Move time forward, but by more than two RTTs. Then receive and consume
+ // some more, forcing a second WINDOW_UPDATE with unchanged max window size.
+ connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2 * kRtt + 1));
+
+ receive_offset += threshold + 1;
+ EXPECT_TRUE(flow_controller_->UpdateHighestReceivedOffset(receive_offset));
+
+ flow_controller_->AddBytesConsumed(threshold + 1);
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+
+ QuicByteCount new_threshold =
+ QuicFlowControllerPeer::WindowUpdateThreshold(flow_controller_.get());
+
+ EXPECT_EQ(new_threshold, threshold);
+}
+
+TEST_F(QuicFlowControllerTest, ReceivingBytesNormalStatusQuo) {
+ ValueRestore<bool> old_flag(&FLAGS_quic_auto_tune_receive_window, false);
+ // This test will generate two WINDOW_UPDATE frames.
+ EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, ::testing::_)).Times(2);
+
+ Initialize();
+ flow_controller_->set_auto_tune_receive_window(true);
+
+ // Make sure clock is inititialized.
+ connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+
+ QuicSentPacketManager* manager =
+ QuicConnectionPeer::GetSentPacketManager(&connection_);
+ RttStats* rtt_stats = QuicSentPacketManagerPeer::GetRttStats(manager);
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kRtt),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+
+ EXPECT_FALSE(flow_controller_->IsBlocked());
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ QuicByteCount threshold =
+ QuicFlowControllerPeer::WindowUpdateThreshold(flow_controller_.get());
+
+ QuicStreamOffset receive_offset = threshold + 1;
+ // Receive some bytes, updating highest received offset, but not enough to
+ // fill flow control receive window.
+ EXPECT_TRUE(flow_controller_->UpdateHighestReceivedOffset(receive_offset));
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest - receive_offset,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ flow_controller_->AddBytesConsumed(threshold + 1);
+
+ // Result is that once again we have a fully open receive window.
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest,
+ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
+
+ // Move time forward, but by more than two RTTs. Then receive and consume
+ // some more, forcing a second WINDOW_UPDATE with unchanged max window size.
+ connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2 * kRtt + 1));
+
+ receive_offset += threshold + 1;
+ EXPECT_TRUE(flow_controller_->UpdateHighestReceivedOffset(receive_offset));
+
+ flow_controller_->AddBytesConsumed(threshold + 1);
+ EXPECT_FALSE(flow_controller_->FlowControlViolation());
+
+ QuicByteCount new_threshold =
+ QuicFlowControllerPeer::WindowUpdateThreshold(flow_controller_.get());
+
+ EXPECT_EQ(new_threshold, threshold);
+}
+
} // namespace test
} // namespace net
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index 26eb314..babdea4 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -135,15 +135,6 @@ QuicSequenceNumberLength ReadSequenceNumberLength(uint8 flags) {
} // namespace
-bool QuicFramerVisitorInterface::OnWindowUpdateFrame(
- const QuicWindowUpdateFrame& frame) {
- return true;
-}
-
-bool QuicFramerVisitorInterface::OnBlockedFrame(const QuicBlockedFrame& frame) {
- return true;
-}
-
QuicFramer::QuicFramer(const QuicVersionVector& supported_versions,
QuicTime creation_time,
Perspective perspective)
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index e39aefb..639135c 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -208,14 +208,15 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
connection_->set_visitor(&visitor_);
connection_->SetSendAlgorithm(send_algorithm_);
session_.reset(new QuicClientSession(
- connection_, scoped_ptr<DatagramClientSocket>(socket), nullptr,
+ connection_, scoped_ptr<DatagramClientSocket>(socket),
+ /*stream_factory=*/nullptr, &crypto_client_stream_factory_,
&transport_security_state_, make_scoped_ptr((QuicServerInfo*)nullptr),
- DefaultQuicConfig(), "CONNECTION_UNKNOWN", base::TimeTicks::Now(),
- base::ThreadTaskRunnerHandle::Get().get(), nullptr));
- session_->InitializeSession(
QuicServerId(kDefaultServerHostName, kDefaultServerPort,
/*is_secure=*/false, PRIVACY_MODE_DISABLED),
- &crypto_config_, &crypto_client_stream_factory_);
+ DefaultQuicConfig(), &crypto_config_, "CONNECTION_UNKNOWN",
+ base::TimeTicks::Now(), base::ThreadTaskRunnerHandle::Get().get(),
+ nullptr));
+ session_->Initialize();
session_->GetCryptoStream()->CryptoConnect();
EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
stream_.reset(use_closing_stream_ ?
diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc
index 6e82b9b..0238a4c 100644
--- a/net/quic/quic_packet_generator_test.cc
+++ b/net/quic/quic_packet_generator_test.cc
@@ -375,6 +375,29 @@ TEST_P(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) {
CheckPacketContains(contents, 0);
}
+// Test the behavior of ConsumeData when the data consumed is for the crypto
+// handshake stream. Ensure that the packet is always sent and padded even if
+// the generator operates in batch mode.
+TEST_P(QuicPacketGeneratorTest, ConsumeData_Handshake) {
+ delegate_.SetCanWriteAnything();
+ generator_.StartBatchOperations();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
+ QuicConsumedData consumed = generator_.ConsumeData(
+ kCryptoStreamId, MakeIOVector("foo"), 0, false, MAY_FEC_PROTECT, nullptr);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_FALSE(generator_.HasQueuedFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+
+ ASSERT_EQ(1u, packets_.size());
+ ASSERT_EQ(kDefaultMaxPacketSize, generator_.max_packet_length());
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].packet->length());
+}
+
TEST_P(QuicPacketGeneratorTest, ConsumeData_EmptyData) {
EXPECT_DFATAL(generator_.ConsumeData(kHeadersStreamId, MakeIOVector(""), 0,
false, MAY_FEC_PROTECT, nullptr),
@@ -431,13 +454,13 @@ TEST_P(QuicPacketGeneratorTest, ConsumeDataFecOnMaxGroupSize) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- } else {
+ FEC_ALARM_TRIGGER) {
// FEC packet is not sent when send policy is FEC_ALARM_TRIGGER, but FEC
// group is closed.
EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
+ } else {
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
}
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
@@ -455,12 +478,12 @@ TEST_P(QuicPacketGeneratorTest, ConsumeDataFecOnMaxGroupSize) {
CheckPacketHasSingleStreamFrame(0);
CheckPacketHasSingleStreamFrame(1);
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
- // FEC packet is sent when send policy is FEC_ANY_TRIGGER.
+ FEC_ALARM_TRIGGER) {
+ // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER.
+ CheckPacketHasSingleStreamFrame(2);
+ } else {
CheckPacketIsFec(2, 1);
CheckPacketHasSingleStreamFrame(3);
- } else {
- CheckPacketHasSingleStreamFrame(2);
}
EXPECT_TRUE(creator_->IsFecProtected());
@@ -477,22 +500,22 @@ TEST_P(QuicPacketGeneratorTest, ConsumeDataFecOnMaxGroupSize) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
+ FEC_ALARM_TRIGGER) {
+ EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
+ } else {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- } else {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
}
}
consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT,
nullptr);
EXPECT_EQ(1u, consumed.bytes_consumed);
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
+ FEC_ALARM_TRIGGER) {
+ CheckPacketHasSingleStreamFrame(3);
+ } else {
CheckPacketHasSingleStreamFrame(4);
CheckPacketIsFec(5, 4);
- } else {
- CheckPacketHasSingleStreamFrame(3);
}
EXPECT_FALSE(creator_->IsFecProtected());
}
@@ -792,11 +815,11 @@ TEST_P(QuicPacketGeneratorTest, FecGroupSizeChangeWithOpenGroup) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
+ FEC_ALARM_TRIGGER) {
+ EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
+ } else {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- } else {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
}
}
consumed = generator_.ConsumeData(7, CreateData(kDefaultMaxPacketSize), 0,
@@ -836,11 +859,12 @@ TEST_P(QuicPacketGeneratorTest, SwitchFecOnOff) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
+ FEC_ALARM_TRIGGER) {
+ // If FEC send policy is FEC_ALARM_TRIGGER, FEC group is closed.
+ EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
+ } else {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- } else {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
}
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
@@ -860,11 +884,11 @@ TEST_P(QuicPacketGeneratorTest, SwitchFecOnOff) {
CheckPacketHasSingleStreamFrame(1);
CheckPacketHasSingleStreamFrame(2);
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
+ FEC_ALARM_TRIGGER) {
+ CheckPacketHasSingleStreamFrame(3);
+ } else {
CheckPacketIsFec(3, /*fec_group=*/2u);
CheckPacketHasSingleStreamFrame(4);
- } else {
- CheckPacketHasSingleStreamFrame(3);
}
// Calling OnFecTimeout should emit the pending FEC packet.
@@ -872,10 +896,10 @@ TEST_P(QuicPacketGeneratorTest, SwitchFecOnOff) {
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
generator_.OnFecTimeout();
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
- CheckPacketIsFec(5, /*fec_group=*/5u);
- } else {
+ FEC_ALARM_TRIGGER) {
CheckPacketIsFec(4, /*fec_group=*/4u);
+ } else {
+ CheckPacketIsFec(5, /*fec_group=*/5u);
}
// Send one unprotected data packet.
@@ -888,10 +912,10 @@ TEST_P(QuicPacketGeneratorTest, SwitchFecOnOff) {
EXPECT_FALSE(creator_->IsFecProtected());
// Verify that one unprotected data packet was sent.
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
- CheckPacketContains(contents, 6);
- } else {
+ FEC_ALARM_TRIGGER) {
CheckPacketContains(contents, 5);
+ } else {
+ CheckPacketContains(contents, 6);
}
}
@@ -1018,11 +1042,11 @@ TEST_P(QuicPacketGeneratorTest, SwitchFecOnOffWithSubsequentPacketsProtected) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
+ FEC_ALARM_TRIGGER) {
+ EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
+ } else {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- } else {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
}
}
consumed = generator_.ConsumeData(5, CreateData(1u), 0, true, MAY_FEC_PROTECT,
@@ -1075,11 +1099,11 @@ TEST_P(QuicPacketGeneratorTest, SwitchFecOnOffThenOnWithCreatorProtectionOn) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
+ FEC_ALARM_TRIGGER) {
+ EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
+ } else {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- } else {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
}
}
consumed = generator_.ConsumeData(5, CreateData(data_len), 0, true,
@@ -1113,13 +1137,13 @@ TEST_P(QuicPacketGeneratorTest, ResetFecGroupNoTimeout) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- } else {
+ FEC_ALARM_TRIGGER) {
// FEC packet is not sent when send policy is FEC_ALARM_TRIGGER, but FEC
// group is closed.
EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
+ } else {
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
}
// Fin Packet.
EXPECT_CALL(delegate_, OnSerializedPacket(_))
@@ -1134,13 +1158,14 @@ TEST_P(QuicPacketGeneratorTest, ResetFecGroupNoTimeout) {
CheckPacketHasSingleStreamFrame(0);
CheckPacketHasSingleStreamFrame(1);
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
+ FEC_ALARM_TRIGGER) {
+ // FEC packet is not sent when send policy is FEC_ALARM_TRIGGER.
+ CheckPacketHasSingleStreamFrame(2);
+ } else {
// FEC packet is sent after 2 packets and when send policy is
// FEC_ANY_TRIGGER.
CheckPacketIsFec(2, 1);
CheckPacketHasSingleStreamFrame(3);
- } else {
- CheckPacketHasSingleStreamFrame(2);
}
EXPECT_TRUE(creator_->IsFecProtected());
@@ -1153,11 +1178,11 @@ TEST_P(QuicPacketGeneratorTest, ResetFecGroupNoTimeout) {
// FEC_ANY_TRIGGER. When policy is FEC_ALARM_TRIGGER, FEC group is closed
// and FEC packet is not sent.
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
+ FEC_ALARM_TRIGGER) {
+ EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
+ } else {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- } else {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
}
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
@@ -1167,11 +1192,11 @@ TEST_P(QuicPacketGeneratorTest, ResetFecGroupNoTimeout) {
// FEC_ANY_TRIGGER. When policy is FEC_ALARM_TRIGGER, FEC group is closed
// and FEC packet is not sent.
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
+ FEC_ALARM_TRIGGER) {
+ EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
+ } else {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- } else {
- EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1);
}
}
consumed = generator_.ConsumeData(7, CreateData(data_len), 0, true,
@@ -1180,7 +1205,11 @@ TEST_P(QuicPacketGeneratorTest, ResetFecGroupNoTimeout) {
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
if (QuicPacketGeneratorPeer::GetFecSendPolicy(&generator_) ==
- FEC_ANY_TRIGGER) {
+ FEC_ALARM_TRIGGER) {
+ CheckPacketHasSingleStreamFrame(3);
+ CheckPacketHasSingleStreamFrame(4);
+ CheckPacketHasSingleStreamFrame(5);
+ } else {
CheckPacketHasSingleStreamFrame(4);
// FEC packet is sent after 2 packets and when send policy is
// FEC_ANY_TRIGGER.
@@ -1190,10 +1219,6 @@ TEST_P(QuicPacketGeneratorTest, ResetFecGroupNoTimeout) {
// FEC packet is sent after 2 packets and when send policy is
// FEC_ANY_TRIGGER.
CheckPacketIsFec(8, 7);
- } else {
- CheckPacketHasSingleStreamFrame(3);
- CheckPacketHasSingleStreamFrame(4);
- CheckPacketHasSingleStreamFrame(5);
}
EXPECT_TRUE(creator_->IsFecProtected());
}
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index 0c325e0..df482a8 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -73,20 +73,20 @@ QuicPacketPublicHeader::QuicPacketPublicHeader(
QuicPacketPublicHeader::~QuicPacketPublicHeader() {}
QuicPacketHeader::QuicPacketHeader()
- : fec_flag(false),
+ : packet_sequence_number(0),
+ fec_flag(false),
entropy_flag(false),
entropy_hash(0),
- packet_sequence_number(0),
is_in_fec_group(NOT_IN_FEC_GROUP),
fec_group(0) {
}
QuicPacketHeader::QuicPacketHeader(const QuicPacketPublicHeader& header)
: public_header(header),
+ packet_sequence_number(0),
fec_flag(false),
entropy_flag(false),
entropy_hash(0),
- packet_sequence_number(0),
is_in_fec_group(NOT_IN_FEC_GROUP),
fec_group(0) {
}
@@ -627,11 +627,11 @@ SerializedPacket::SerializedPacket(
QuicEncryptedPacket* packet,
QuicPacketEntropyHash entropy_hash,
RetransmittableFrames* retransmittable_frames)
- : sequence_number(sequence_number),
+ : packet(packet),
+ retransmittable_frames(retransmittable_frames),
+ sequence_number(sequence_number),
sequence_number_length(sequence_number_length),
- packet(packet),
entropy_hash(entropy_hash),
- retransmittable_frames(retransmittable_frames),
is_fec_packet(false) {
}
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index 3f69ce3..3be0b14 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -625,10 +625,10 @@ struct NET_EXPORT_PRIVATE QuicPacketHeader {
std::ostream& os, const QuicPacketHeader& s);
QuicPacketPublicHeader public_header;
+ QuicPacketSequenceNumber packet_sequence_number;
bool fec_flag;
bool entropy_flag;
QuicPacketEntropyHash entropy_hash;
- QuicPacketSequenceNumber packet_sequence_number;
InFecGroup is_in_fec_group;
QuicFecGroupNumber fec_group;
};
@@ -1023,11 +1023,11 @@ struct NET_EXPORT_PRIVATE SerializedPacket {
RetransmittableFrames* retransmittable_frames);
~SerializedPacket();
+ QuicEncryptedPacket* packet;
+ RetransmittableFrames* retransmittable_frames;
QuicPacketSequenceNumber sequence_number;
QuicSequenceNumberLength sequence_number_length;
- QuicEncryptedPacket* packet;
QuicPacketEntropyHash entropy_hash;
- RetransmittableFrames* retransmittable_frames;
bool is_fec_packet;
// Optional notifiers which will be informed when this packet has been ACKed.
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index 1f78b32..fc0365b 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -110,13 +110,16 @@ QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config)
perspective(),
kMinimumFlowControlSendWindow,
config_.GetInitialSessionFlowControlWindowToSend(),
- config_.GetInitialSessionFlowControlWindowToSend()),
+ false),
goaway_received_(false),
goaway_sent_(false),
has_pending_handshake_(false) {
}
-void QuicSession::InitializeSession() {
+void QuicSession::Initialize() {
+ // Crypto stream must exist when Initialize is called.
+ DCHECK(GetCryptoStream());
+
connection_->set_visitor(visitor_shim_.get());
connection_->SetFromConfig(config_);
headers_stream_.reset(new QuicHeadersStream(this));
@@ -467,6 +470,11 @@ void QuicSession::OnConfigNegotiated() {
max_streams =
max(max_streams + kMaxStreamsMinimumIncrement,
static_cast<uint32>(max_streams * kMaxStreamsMultiplier));
+
+ if (config_.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config_.ReceivedConnectionOptions(), kAFCW)) {
+ EnableAutoTuneReceiveWindow();
+ }
}
set_max_open_streams(max_streams);
@@ -482,6 +490,16 @@ void QuicSession::OnConfigNegotiated() {
}
}
+void QuicSession::EnableAutoTuneReceiveWindow() {
+ flow_controller_.set_auto_tune_receive_window(true);
+ // Inform all existing streams about the new window.
+ GetCryptoStream()->flow_controller()->set_auto_tune_receive_window(true);
+ headers_stream_->flow_controller()->set_auto_tune_receive_window(true);
+ for (auto const& kv : stream_map_) {
+ kv.second->flow_controller()->set_auto_tune_receive_window(true);
+ }
+}
+
void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) {
if (new_window < kMinimumFlowControlSendWindow) {
LOG(ERROR) << "Peer sent us an invalid stream flow control send window: "
@@ -496,9 +514,8 @@ void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) {
// Inform all existing streams about the new window.
GetCryptoStream()->UpdateSendWindowOffset(new_window);
headers_stream_->UpdateSendWindowOffset(new_window);
- for (DataStreamMap::iterator it = stream_map_.begin();
- it != stream_map_.end(); ++it) {
- it->second->UpdateSendWindowOffset(new_window);
+ for (auto const& kv : stream_map_) {
+ kv.second->UpdateSendWindowOffset(new_window);
}
}
@@ -729,9 +746,8 @@ bool QuicSession::IsStreamFlowControlBlocked() {
GetCryptoStream()->flow_controller()->IsBlocked()) {
return true;
}
- for (DataStreamMap::iterator it = stream_map_.begin();
- it != stream_map_.end(); ++it) {
- if (it->second->flow_controller()->IsBlocked()) {
+ for (auto const& kv : stream_map_) {
+ if (kv.second->flow_controller()->IsBlocked()) {
return true;
}
}
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h
index 4a401bf..9a8bee3 100644
--- a/net/quic/quic_session.h
+++ b/net/quic/quic_session.h
@@ -56,7 +56,7 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
};
QuicSession(QuicConnection* connection, const QuicConfig& config);
- void InitializeSession();
+ virtual void Initialize();
~QuicSession() override;
@@ -284,6 +284,10 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// control window in a negotiated config. Closes the connection if invalid.
void OnNewSessionFlowControlWindow(QuicStreamOffset new_window);
+ // Called in OnConfigNegotiated when auto-tuning is enabled for flow
+ // control receive windows.
+ void EnableAutoTuneReceiveWindow();
+
// Keep track of highest received byte offset of locally closed streams, while
// waiting for a definitive final highest offset from the peer.
std::map<QuicStreamId, QuicStreamOffset>
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc
index b4df636..a9a1c91 100644
--- a/net/quic/quic_session_test.cc
+++ b/net/quic/quic_session_test.cc
@@ -125,7 +125,7 @@ class TestSession : public QuicSession {
: QuicSession(connection, DefaultQuicConfig()),
crypto_stream_(this),
writev_consumes_all_data_(false) {
- InitializeSession();
+ Initialize();
}
TestCryptoStream* GetCryptoStream() override { return &crypto_stream_; }
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index b3b0a67..dde1639 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -1109,15 +1109,15 @@ int QuicStreamFactory::CreateSession(const QuicServerId& server_id,
}
*session = new QuicClientSession(
- connection, socket.Pass(), this, transport_security_state_,
- server_info.Pass(), config, network_connection_.GetDescription(),
+ connection, socket.Pass(), this, quic_crypto_client_stream_factory_,
+ transport_security_state_, server_info.Pass(), server_id, config,
+ &crypto_config_, network_connection_.GetDescription(),
dns_resolution_end_time, base::ThreadTaskRunnerHandle::Get().get(),
net_log.net_log());
all_sessions_[*session] = server_id; // owning pointer
- (*session)->InitializeSession(server_id, &crypto_config_,
- quic_crypto_client_stream_factory_);
+ (*session)->Initialize();
bool closed_during_initialize =
!ContainsKey(all_sessions_, *session) ||
!(*session)->connection()->connected();
diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc
index d64f010..0d19090 100644
--- a/net/quic/reliable_quic_stream.cc
+++ b/net/quic/reliable_quic_stream.cc
@@ -133,7 +133,7 @@ ReliableQuicStream::ReliableQuicStream(QuicStreamId id, QuicSession* session)
perspective_,
GetReceivedFlowControlWindow(session),
GetInitialStreamFlowControlWindowToSend(session),
- GetInitialStreamFlowControlWindowToSend(session)),
+ session_->flow_controller()->auto_tune_receive_window()),
connection_flow_controller_(session_->flow_controller()),
stream_contributes_to_connection_flow_control_(true) {
}
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index 45d94d5..ba3bce7 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -181,25 +181,23 @@ int CryptoTestUtils::HandshakeWithFakeServer(
QuicCryptoClientStream* client) {
PacketSavingConnection* server_conn = new PacketSavingConnection(
Perspective::IS_SERVER, client_conn->supported_versions());
- TestSession server_session(server_conn, DefaultQuicConfig());
- server_session.InitializeSession();
+
+ QuicConfig config = DefaultQuicConfig();
QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance());
+ SetupCryptoServerConfigForTest(server_conn->clock(),
+ server_conn->random_generator(), &config,
+ &crypto_config);
- SetupCryptoServerConfigForTest(
- server_session.connection()->clock(),
- server_session.connection()->random_generator(),
- server_session.config(), &crypto_config);
-
- QuicCryptoServerStream server(&crypto_config, &server_session);
- server_session.SetCryptoStream(&server);
+ TestServerSession server_session(server_conn, config, &crypto_config);
// The client's handshake must have been started already.
CHECK_NE(0u, client_conn->encrypted_packets_.size());
- CommunicateHandshakeMessages(client_conn, client, server_conn, &server);
+ CommunicateHandshakeMessages(client_conn, client, server_conn,
+ server_session.GetCryptoStream());
- CompareClientAndServerKeys(client, &server);
+ CompareClientAndServerKeys(client, server_session.GetCryptoStream());
return client->num_sent_client_hellos();
}
@@ -213,14 +211,8 @@ int CryptoTestUtils::HandshakeWithFakeClient(
new PacketSavingConnection(Perspective::IS_CLIENT);
// Advance the time, because timers do not like uninitialized times.
client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1));
- TestClientSession client_session(client_conn, DefaultQuicConfig());
- QuicCryptoClientConfig crypto_config;
- if (!options.dont_verify_certs) {
- // TODO(wtc): replace this with ProofVerifierForTesting() when we have
- // a working ProofSourceForTesting().
- crypto_config.SetProofVerifier(FakeProofVerifierForTesting());
- }
+ QuicCryptoClientConfig crypto_config;
bool is_https = false;
AsyncTestChannelIDSource* async_channel_id_source = nullptr;
if (options.channel_id_enabled) {
@@ -235,18 +227,22 @@ int CryptoTestUtils::HandshakeWithFakeClient(
}
QuicServerId server_id(kServerHostname, kServerPort, is_https,
PRIVACY_MODE_DISABLED);
- QuicCryptoClientStream client(server_id, &client_session,
- ProofVerifyContextForTesting(),
- &crypto_config);
- client_session.SetCryptoStream(&client);
+ if (!options.dont_verify_certs) {
+ // TODO(wtc): replace this with ProofVerifierForTesting() when we have
+ // a working ProofSourceForTesting().
+ crypto_config.SetProofVerifier(FakeProofVerifierForTesting());
+ }
+ TestClientSession client_session(client_conn, DefaultQuicConfig(), server_id,
+ &crypto_config);
- client.CryptoConnect();
+ client_session.GetCryptoStream()->CryptoConnect();
CHECK_EQ(1u, client_conn->encrypted_packets_.size());
CommunicateHandshakeMessagesAndRunCallbacks(
- client_conn, &client, server_conn, server, async_channel_id_source);
+ client_conn, client_session.GetCryptoStream(), server_conn, server,
+ async_channel_id_source);
- CompareClientAndServerKeys(&client, server);
+ CompareClientAndServerKeys(client_session.GetCryptoStream(), server);
if (options.channel_id_enabled) {
scoped_ptr<ChannelIDKey> channel_id_key;
@@ -255,11 +251,12 @@ int CryptoTestUtils::HandshakeWithFakeClient(
EXPECT_EQ(QUIC_SUCCESS, status);
EXPECT_EQ(channel_id_key->SerializeKey(),
server->crypto_negotiated_params().channel_id);
- EXPECT_EQ(options.channel_id_source_async,
- client.WasChannelIDSourceCallbackRun());
+ EXPECT_EQ(
+ options.channel_id_source_async,
+ client_session.GetCryptoStream()->WasChannelIDSourceCallbackRun());
}
- return client.num_sent_client_hellos();
+ return client_session.GetCryptoStream()->num_sent_client_hellos();
}
// static
diff --git a/net/quic/test_tools/quic_flow_controller_peer.cc b/net/quic/test_tools/quic_flow_controller_peer.cc
index d6a1098..602aaf8 100644
--- a/net/quic/test_tools/quic_flow_controller_peer.cc
+++ b/net/quic/test_tools/quic_flow_controller_peer.cc
@@ -30,7 +30,7 @@ void QuicFlowControllerPeer::SetReceiveWindowOffset(
void QuicFlowControllerPeer::SetMaxReceiveWindow(
QuicFlowController* flow_controller,
QuicByteCount window_size) {
- flow_controller->max_receive_window_ = window_size;
+ flow_controller->receive_window_size_ = window_size;
}
// static
@@ -58,5 +58,11 @@ QuicByteCount QuicFlowControllerPeer::ReceiveWindowSize(
flow_controller->highest_received_byte_offset_;
}
+// static
+QuicByteCount QuicFlowControllerPeer::WindowUpdateThreshold(
+ QuicFlowController* flow_controller) {
+ return flow_controller->WindowUpdateThreshold();
+}
+
} // namespace test
} // namespace net
diff --git a/net/quic/test_tools/quic_flow_controller_peer.h b/net/quic/test_tools/quic_flow_controller_peer.h
index 4270d96..3d7c9d0 100644
--- a/net/quic/test_tools/quic_flow_controller_peer.h
+++ b/net/quic/test_tools/quic_flow_controller_peer.h
@@ -33,6 +33,9 @@ class QuicFlowControllerPeer {
static QuicByteCount ReceiveWindowSize(QuicFlowController* flow_controller);
+ static QuicByteCount WindowUpdateThreshold(
+ QuicFlowController* flow_controller);
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicFlowControllerPeer);
};
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index 549dae5..7036d57 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -17,6 +17,7 @@
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
#include "net/quic/quic_utils.h"
+#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/spdy/spdy_frame_builder.h"
#include "net/tools/quic/quic_per_connection_packet_writer.h"
@@ -339,7 +340,8 @@ void PacketSavingConnection::SendOrQueuePacket(QueuedPacket packet) {
MockSession::MockSession(QuicConnection* connection)
: QuicSession(connection, DefaultQuicConfig()) {
- InitializeSession();
+ crypto_stream_.reset(new QuicCryptoStream(this));
+ Initialize();
ON_CALL(*this, WritevData(_, _, _, _, _, _))
.WillByDefault(testing::Return(QuicConsumedData(0, false)));
}
@@ -347,46 +349,37 @@ MockSession::MockSession(QuicConnection* connection)
MockSession::~MockSession() {
}
-TestSession::TestSession(QuicConnection* connection, const QuicConfig& config)
- : QuicSession(connection, config),
- crypto_stream_(nullptr) {
- InitializeSession();
+TestServerSession::TestServerSession(
+ QuicConnection* connection,
+ const QuicConfig& config,
+ const QuicCryptoServerConfig* crypto_config)
+ : QuicSession(connection, config) {
+ crypto_stream_.reset(new QuicCryptoServerStream(crypto_config, this));
+ Initialize();
}
-TestSession::~TestSession() {}
-
-void TestSession::SetCryptoStream(QuicCryptoStream* stream) {
- crypto_stream_ = stream;
+TestServerSession::~TestServerSession() {
}
-QuicCryptoStream* TestSession::GetCryptoStream() {
- return crypto_stream_;
+QuicCryptoServerStream* TestServerSession::GetCryptoStream() {
+ return crypto_stream_.get();
}
TestClientSession::TestClientSession(QuicConnection* connection,
- const QuicConfig& config)
- : QuicClientSessionBase(connection, config),
- crypto_stream_(nullptr) {
- EXPECT_CALL(*this, OnProofValid(_)).Times(AnyNumber());
- InitializeSession();
+ const QuicConfig& config,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config)
+ : QuicClientSessionBase(connection, config) {
+ crypto_stream_.reset(new QuicCryptoClientStream(
+ server_id, this, CryptoTestUtils::ProofVerifyContextForTesting(),
+ crypto_config));
+ Initialize();
}
TestClientSession::~TestClientSession() {}
-void TestClientSession::SetCryptoStream(QuicCryptoStream* stream) {
- crypto_stream_ = stream;
-}
-
-QuicCryptoStream* TestClientSession::GetCryptoStream() {
- return crypto_stream_;
-}
-
-TestServerSession::TestServerSession(const QuicConfig& config,
- QuicConnection* connection)
- : QuicServerSession(config, connection, nullptr) {
-}
-
-TestServerSession::~TestServerSession() {
+QuicCryptoClientStream* TestClientSession::GetCryptoStream() {
+ return crypto_stream_.get();
}
MockPacketWriter::MockPacketWriter() {
@@ -795,18 +788,15 @@ MockQuicConnectionDebugVisitor::MockQuicConnectionDebugVisitor() {
MockQuicConnectionDebugVisitor::~MockQuicConnectionDebugVisitor() {
}
-void SetupCryptoClientStreamForTest(
- QuicServerId server_id,
- bool supports_stateless_rejects,
- QuicTime::Delta connection_start_time,
- QuicCryptoClientConfig* crypto_client_config,
- PacketSavingConnection** client_connection,
- TestClientSession** client_session,
- QuicCryptoClientStream** client_stream) {
+void CreateClientSessionForTest(QuicServerId server_id,
+ bool supports_stateless_rejects,
+ QuicTime::Delta connection_start_time,
+ QuicCryptoClientConfig* crypto_client_config,
+ PacketSavingConnection** client_connection,
+ TestClientSession** client_session) {
CHECK(crypto_client_config);
CHECK(client_connection);
CHECK(client_session);
- CHECK(client_stream);
CHECK(!connection_start_time.IsZero())
<< "Connections must start at non-zero times, otherwise the "
<< "strike-register will be unhappy.";
@@ -815,35 +805,26 @@ void SetupCryptoClientStreamForTest(
? DefaultQuicConfigStatelessRejects()
: DefaultQuicConfig();
*client_connection = new PacketSavingConnection(Perspective::IS_CLIENT);
- *client_session = new TestClientSession(*client_connection, config);
- *client_stream = new QuicCryptoClientStream(server_id, *client_session,
- nullptr, crypto_client_config);
- (*client_session)->SetCryptoStream(*client_stream);
+ *client_session = new TestClientSession(*client_connection, config, server_id,
+ crypto_client_config);
(*client_connection)->AdvanceTime(connection_start_time);
}
-// Setup or create?
-void SetupCryptoServerStreamForTest(
- QuicServerId server_id,
- QuicTime::Delta connection_start_time,
- QuicCryptoServerConfig* server_crypto_config,
- PacketSavingConnection** server_connection,
- TestServerSession** server_session,
- QuicCryptoServerStream** server_stream) {
+void CreateServerSessionForTest(QuicServerId server_id,
+ QuicTime::Delta connection_start_time,
+ QuicCryptoServerConfig* server_crypto_config,
+ PacketSavingConnection** server_connection,
+ TestServerSession** server_session) {
CHECK(server_crypto_config);
CHECK(server_connection);
CHECK(server_session);
- CHECK(server_stream);
CHECK(!connection_start_time.IsZero())
<< "Connections must start at non-zero times, otherwise the "
<< "strike-register will be unhappy.";
*server_connection = new PacketSavingConnection(Perspective::IS_SERVER);
- *server_session =
- new TestServerSession(DefaultQuicConfig(), *server_connection);
- *server_stream =
- new QuicCryptoServerStream(server_crypto_config, *server_session);
- (*server_session)->InitializeSession(server_crypto_config);
+ *server_session = new TestServerSession(
+ *server_connection, DefaultQuicConfig(), server_crypto_config);
// We advance the clock initially because the default time is zero and the
// strike register worries that we've just overflowed a uint32 time.
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index 5557074..fa97422 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -426,9 +426,11 @@ class MockSession : public QuicSession {
public:
explicit MockSession(QuicConnection* connection);
~MockSession() override;
+
+ QuicCryptoStream* GetCryptoStream() { return crypto_stream_.get(); }
+
MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
- MOCK_METHOD0(GetCryptoStream, QuicCryptoStream*());
MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*());
MOCK_METHOD6(WritevData,
QuicConsumedData(QuicStreamId id,
@@ -452,30 +454,35 @@ class MockSession : public QuicSession {
using QuicSession::ActivateStream;
private:
+ scoped_ptr<QuicCryptoStream> crypto_stream_;
+
DISALLOW_COPY_AND_ASSIGN(MockSession);
};
-class TestSession : public QuicSession {
+class TestServerSession : public QuicSession {
public:
- TestSession(QuicConnection* connection, const QuicConfig& config);
- ~TestSession() override;
+ TestServerSession(QuicConnection* connection,
+ const QuicConfig& config,
+ const QuicCryptoServerConfig* crypto_config);
+ ~TestServerSession() override;
MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*());
- void SetCryptoStream(QuicCryptoStream* stream);
-
- QuicCryptoStream* GetCryptoStream() override;
+ QuicCryptoServerStream* GetCryptoStream() override;
private:
- QuicCryptoStream* crypto_stream_;
+ scoped_ptr<QuicCryptoServerStream> crypto_stream_;
- DISALLOW_COPY_AND_ASSIGN(TestSession);
+ DISALLOW_COPY_AND_ASSIGN(TestServerSession);
};
class TestClientSession : public QuicClientSessionBase {
public:
- TestClientSession(QuicConnection* connection, const QuicConfig& config);
+ TestClientSession(QuicConnection* connection,
+ const QuicConfig& config,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config);
~TestClientSession() override;
// QuicClientSessionBase
@@ -488,12 +495,10 @@ class TestClientSession : public QuicClientSessionBase {
MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*());
- void SetCryptoStream(QuicCryptoStream* stream);
-
- QuicCryptoStream* GetCryptoStream() override;
+ QuicCryptoClientStream* GetCryptoStream() override;
private:
- QuicCryptoStream* crypto_stream_;
+ scoped_ptr<QuicCryptoClientStream> crypto_stream_;
DISALLOW_COPY_AND_ASSIGN(TestClientSession);
};
@@ -715,17 +720,7 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
void(const QuicPacketHeader&, StringPiece payload));
};
-class TestServerSession : public tools::QuicServerSession {
- public:
- TestServerSession(const QuicConfig& config, QuicConnection* connection);
- ~TestServerSession() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestServerSession);
-};
-
-// Creates and sets up a QuicCryptoClientStream for testing, and all
-// its associated state.
+// Creates a client session for testing.
//
// server_id: The server id associated with this stream.
// supports_stateless_rejects: Does this client support stateless rejects.
@@ -739,19 +734,14 @@ class TestServerSession : public tools::QuicServerSession {
// client_session.
// client_session: Pointer reference for the newly created client
// session. The new object will be owned by the caller.
-// client_stream: Pointer reference for the newly created crypto
-// client stream. The new object will be owned by the caller.
-void SetupCryptoClientStreamForTest(
- QuicServerId server_id,
- bool supports_stateless_rejects,
- QuicTime::Delta connection_start_time,
- QuicCryptoClientConfig* crypto_client_config,
- PacketSavingConnection** client_connection,
- TestClientSession** client_session,
- QuicCryptoClientStream** client_stream);
-
-// Creates and sets up a QuicCryptoServerStream for testing, and all
-// its associated state.
+void CreateClientSessionForTest(QuicServerId server_id,
+ bool supports_stateless_rejects,
+ QuicTime::Delta connection_start_time,
+ QuicCryptoClientConfig* crypto_client_config,
+ PacketSavingConnection** client_connection,
+ TestClientSession** client_session);
+
+// Creates a server session for testing.
//
// server_id: The server id associated with this stream.
// connection_start_time: The time to set for the connection clock.
@@ -764,15 +754,11 @@ void SetupCryptoClientStreamForTest(
// server_session.
// server_session: Pointer reference for the newly created server
// session. The new object will be owned by the caller.
-// server_stream: Pointer reference for the newly created crypto
-// server stream. The new object will be owned by the caller.
-void SetupCryptoServerStreamForTest(
- QuicServerId server_id,
- QuicTime::Delta connection_start_time,
- QuicCryptoServerConfig* crypto_server_config,
- PacketSavingConnection** server_connection,
- TestServerSession** server_session,
- QuicCryptoServerStream** server_stream);
+void CreateServerSessionForTest(QuicServerId server_id,
+ QuicTime::Delta connection_start_time,
+ QuicCryptoServerConfig* crypto_server_config,
+ PacketSavingConnection** server_connection,
+ TestServerSession** server_session);
} // namespace test
} // namespace net
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index a2c9522..430dbe0 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -657,8 +657,7 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
string body;
GenerateBody(&body, 20480);
- HTTPMessage request(HttpConstants::HTTP_1_1,
- HttpConstants::POST, "/foo");
+ HTTPMessage request(HttpConstants::HTTP_1_1, HttpConstants::POST, "/foo");
request.AddBody(body, true);
EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc
index 30236df..24ce0007 100644
--- a/net/tools/quic/quic_client.cc
+++ b/net/tools/quic/quic_client.cc
@@ -195,6 +195,14 @@ bool QuicClient::Connect() {
return session_->connection()->connected();
}
+QuicClientSession* QuicClient::CreateQuicClientSession(
+ const QuicConfig& config,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config) {
+ return new QuicClientSession(config, connection, server_id_, &crypto_config_);
+}
+
void QuicClient::StartConnect() {
DCHECK(initialized_);
DCHECK(!connected());
@@ -203,19 +211,20 @@ void QuicClient::StartConnect() {
DummyPacketWriterFactory factory(writer);
- session_.reset(new QuicClientSession(
+ session_.reset(CreateQuicClientSession(
config_,
new QuicConnection(GenerateConnectionId(), server_address_, helper_.get(),
factory,
/* owns_writer= */ false, Perspective::IS_CLIENT,
- server_id_.is_https(), supported_versions_)));
+ server_id_.is_https(), supported_versions_),
+ server_id_, &crypto_config_));
// Reset |writer_| after |session_| so that the old writer outlives the old
// session.
if (writer_.get() != writer) {
writer_.reset(writer);
}
- session_->InitializeSession(server_id_, &crypto_config_);
+ session_->Initialize();
session_->CryptoConnect();
}
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h
index dc9abe7..fd511cc 100644
--- a/net/tools/quic/quic_client.h
+++ b/net/tools/quic/quic_client.h
@@ -199,6 +199,12 @@ class QuicClient : public EpollCallbackInterface,
IPEndPoint* server_address,
IPAddressNumber* client_ip);
+ virtual QuicClientSession* CreateQuicClientSession(
+ const QuicConfig& config,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config);
+
EpollServer* epoll_server() { return epoll_server_; }
// If the socket has been created, then unregister and close() the FD.
diff --git a/net/tools/quic/quic_client_session.cc b/net/tools/quic/quic_client_session.cc
index 92eec04..0b99420 100644
--- a/net/tools/quic/quic_client_session.cc
+++ b/net/tools/quic/quic_client_session.cc
@@ -15,21 +15,18 @@ namespace net {
namespace tools {
QuicClientSession::QuicClientSession(const QuicConfig& config,
- QuicConnection* connection)
- : QuicClientSessionBase(connection, config), respect_goaway_(true) {
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config)
+ : QuicClientSessionBase(connection, config),
+ crypto_stream_(
+ new QuicCryptoClientStream(server_id, this, nullptr, crypto_config)),
+ respect_goaway_(true) {
}
QuicClientSession::~QuicClientSession() {
}
-void QuicClientSession::InitializeSession(
- const QuicServerId& server_id,
- QuicCryptoClientConfig* crypto_config) {
- crypto_stream_.reset(
- new QuicCryptoClientStream(server_id, this, nullptr, crypto_config));
- QuicClientSessionBase::InitializeSession();
-}
-
void QuicClientSession::OnProofValid(
const QuicCryptoClientConfig::CachedState& /*cached*/) {}
diff --git a/net/tools/quic/quic_client_session.h b/net/tools/quic/quic_client_session.h
index 3438a23..3722868 100644
--- a/net/tools/quic/quic_client_session.h
+++ b/net/tools/quic/quic_client_session.h
@@ -25,12 +25,12 @@ namespace tools {
class QuicClientSession : public QuicClientSessionBase {
public:
- QuicClientSession(const QuicConfig& config, QuicConnection* connection);
+ QuicClientSession(const QuicConfig& config,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config);
~QuicClientSession() override;
- void InitializeSession(const QuicServerId& server_id,
- QuicCryptoClientConfig* config);
-
// QuicSession methods:
QuicSpdyClientStream* CreateOutgoingDataStream() override;
QuicCryptoClientStream* GetCryptoStream() override;
diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc
index 6dc80a0..d7f4101 100644
--- a/net/tools/quic/quic_client_session_test.cc
+++ b/net/tools/quic/quic_client_session_test.cc
@@ -45,10 +45,11 @@ class ToolsQuicClientSessionTest
ToolsQuicClientSessionTest()
: connection_(new PacketSavingConnection(Perspective::IS_CLIENT,
SupportedVersions(GetParam()))) {
- session_.reset(new QuicClientSession(DefaultQuicConfig(), connection_));
- session_->InitializeSession(
+ session_.reset(new QuicClientSession(
+ DefaultQuicConfig(), connection_,
QuicServerId(kServerHostname, kPort, false, PRIVACY_MODE_DISABLED),
- &crypto_config_);
+ &crypto_config_));
+ session_->Initialize();
// Advance the time, because timers do not like uninitialized times.
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc
index 9447c22..71031f7 100644
--- a/net/tools/quic/quic_dispatcher.cc
+++ b/net/tools/quic/quic_dispatcher.cc
@@ -470,8 +470,9 @@ QuicServerSession* QuicDispatcher::CreateQuicSession(
/* owns_writer= */ true, Perspective::IS_SERVER,
crypto_config_->HasProofSource(), supported_versions_);
- QuicServerSession* session = new QuicServerSession(config_, connection, this);
- session->InitializeSession(crypto_config_);
+ QuicServerSession* session =
+ new QuicServerSession(config_, connection, this, crypto_config_);
+ session->Initialize();
if (FLAGS_quic_session_map_threshold_for_stateless_rejects != -1 &&
session_map_.size() >=
static_cast<size_t>(
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc
index 95b0030..bf94210 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -46,8 +46,11 @@ namespace {
class TestServerSession : public QuicServerSession {
public:
- TestServerSession(const QuicConfig& config, QuicConnection* connection)
- : QuicServerSession(config, connection, nullptr) {}
+ TestServerSession(const QuicConfig& config,
+ QuicConnection* connection,
+ const QuicCryptoServerConfig* crypto_config)
+ : QuicServerSession(config, connection, nullptr, crypto_config),
+ crypto_stream_(QuicServerSession::GetCryptoStream()) {}
~TestServerSession() override{};
MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
@@ -110,10 +113,11 @@ QuicServerSession* CreateSession(QuicDispatcher* dispatcher,
const QuicConfig& config,
QuicConnectionId connection_id,
const IPEndPoint& client_address,
+ const QuicCryptoServerConfig* crypto_config,
TestServerSession** session) {
MockServerConnection* connection =
new MockServerConnection(connection_id, dispatcher);
- *session = new TestServerSession(config, connection);
+ *session = new TestServerSession(config, connection, crypto_config);
connection->set_visitor(*session);
ON_CALL(*connection, SendConnectionClose(_)).WillByDefault(
WithoutArgs(Invoke(
@@ -209,15 +213,17 @@ TEST_F(QuicDispatcherTest, ProcessPackets) {
server_address_ = IPEndPoint(net::test::Any4(), 5);
EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, client_address))
- .WillOnce(testing::Return(
- CreateSession(&dispatcher_, config_, 1, client_address, &session1_)));
+ .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1,
+ client_address, &crypto_config_,
+ &session1_)));
ProcessPacket(client_address, 1, true, "foo");
EXPECT_EQ(client_address, dispatcher_.current_client_address());
EXPECT_EQ(server_address_, dispatcher_.current_server_address());
EXPECT_CALL(dispatcher_, CreateQuicSession(2, _, client_address))
- .WillOnce(testing::Return(
- CreateSession(&dispatcher_, config_, 2, client_address, &session2_)));
+ .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 2,
+ client_address, &crypto_config_,
+ &session2_)));
ProcessPacket(client_address, 2, true, "bar");
EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
@@ -231,8 +237,9 @@ TEST_F(QuicDispatcherTest, Shutdown) {
IPEndPoint client_address(net::test::Loopback4(), 1);
EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
- .WillOnce(testing::Return(
- CreateSession(&dispatcher_, config_, 1, client_address, &session1_)));
+ .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1,
+ client_address, &crypto_config_,
+ &session1_)));
ProcessPacket(client_address, 1, true, "foo");
@@ -249,8 +256,9 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
IPEndPoint client_address(net::test::Loopback4(), 1);
QuicConnectionId connection_id = 1;
EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, _, client_address))
- .WillOnce(testing::Return(CreateSession(
- &dispatcher_, config_, connection_id, client_address, &session1_)));
+ .WillOnce(testing::Return(CreateSession(&dispatcher_, config_,
+ connection_id, client_address,
+ &crypto_config_, &session1_)));
ProcessPacket(client_address, connection_id, true, "foo");
// Close the connection by sending public reset packet.
@@ -401,7 +409,7 @@ class QuicDispatcherStatelessRejectTest
QuicConnectionId connection_id,
const IPEndPoint& client_address) {
CreateSession(&dispatcher_, config_, connection_id, client_address,
- &session1_);
+ &crypto_config_, &session1_);
crypto_stream1_ = new MockQuicCryptoServerStream(crypto_config_, session1_);
session1_->SetCryptoStream(crypto_stream1_);
@@ -437,8 +445,9 @@ TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
server_address_ = IPEndPoint(net::test::Any4(), 5);
EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, client_address))
- .WillOnce(testing::Return(
- CreateSession(&dispatcher_, config_, 1, client_address, &session1_)));
+ .WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1,
+ client_address, &crypto_config_,
+ &session1_)));
// A packet whose sequence number is the largest that is allowed to start a
// connection.
ProcessPacket(client_address, connection_id, true, "data",
@@ -577,12 +586,14 @@ class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
.WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 1,
- client_address, &session1_)));
+ client_address, &crypto_config_,
+ &session1_)));
ProcessPacket(client_address, 1, true, "foo");
EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
.WillOnce(testing::Return(CreateSession(&dispatcher_, config_, 2,
- client_address, &session2_)));
+ client_address, &crypto_config_,
+ &session2_)));
ProcessPacket(client_address, 2, true, "bar");
blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(&dispatcher_);
diff --git a/net/tools/quic/quic_in_memory_cache.cc b/net/tools/quic/quic_in_memory_cache.cc
index cb90bb5..302e198 100644
--- a/net/tools/quic/quic_in_memory_cache.cc
+++ b/net/tools/quic/quic_in_memory_cache.cc
@@ -35,6 +35,9 @@ const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse(
StringPiece path) const {
ResponseMap::const_iterator it = responses_.find(GetKey(host, path));
if (it == responses_.end()) {
+ if (default_response_.get()) {
+ return default_response_.get();
+ }
return nullptr;
}
return it->second;
@@ -55,6 +58,10 @@ void QuicInMemoryCache::AddSimpleResponse(StringPiece host,
AddResponse(host, path, response_headers, body);
}
+void QuicInMemoryCache::AddDefaultResponse(Response* response) {
+ default_response_.reset(response);
+}
+
void QuicInMemoryCache::AddResponse(StringPiece host,
StringPiece path,
const SpdyHeaderBlock& response_headers,
diff --git a/net/tools/quic/quic_in_memory_cache.h b/net/tools/quic/quic_in_memory_cache.h
index a14e540..e10e02d 100644
--- a/net/tools/quic/quic_in_memory_cache.h
+++ b/net/tools/quic/quic_in_memory_cache.h
@@ -44,9 +44,6 @@ class QuicInMemoryCache {
const SpdyHeaderBlock& headers() const { return headers_; }
const StringPiece body() const { return StringPiece(body_); }
- private:
- friend class QuicInMemoryCache;
-
void set_response_type(SpecialResponseType response_type) {
response_type_ = response_type;
}
@@ -57,6 +54,7 @@ class QuicInMemoryCache {
body.CopyToString(&body_);
}
+ private:
SpecialResponseType response_type_;
SpdyHeaderBlock headers_;
std::string body_;
@@ -91,6 +89,10 @@ class QuicInMemoryCache {
base::StringPiece path,
SpecialResponseType response_type);
+ // Sets a default response in case of cache misses. Takes ownership of
+ // 'response'.
+ void AddDefaultResponse(Response* response);
+
// |cache_cirectory| can be generated using `wget -p --save-headers <url>`.
void InitializeFromDirectory(const std::string& cache_directory);
@@ -116,6 +118,9 @@ class QuicInMemoryCache {
// Cached responses.
ResponseMap responses_;
+ // The default response for cache misses, if set.
+ scoped_ptr<Response> default_response_;
+
DISALLOW_COPY_AND_ASSIGN(QuicInMemoryCache);
};
diff --git a/net/tools/quic/quic_in_memory_cache_test.cc b/net/tools/quic/quic_in_memory_cache_test.cc
index d93a344..534edff 100644
--- a/net/tools/quic/quic_in_memory_cache_test.cc
+++ b/net/tools/quic/quic_in_memory_cache_test.cc
@@ -10,6 +10,7 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
+#include "net/spdy/spdy_framer.h"
#include "net/tools/balsa/balsa_headers.h"
#include "net/tools/quic/quic_in_memory_cache.h"
#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
@@ -94,6 +95,43 @@ TEST_F(QuicInMemoryCacheTest, UsesOriginalUrl) {
EXPECT_LT(0U, response->body().length());
}
+TEST_F(QuicInMemoryCacheTest, DefaultResponse) {
+ // Verify GetResponse returns nullptr when no default is set.
+ QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
+ const QuicInMemoryCache::Response* response =
+ cache->GetResponse("www.google.com", "/");
+ ASSERT_FALSE(response);
+
+ // Add a default response.
+ SpdyHeaderBlock response_headers;
+ response_headers[":version"] = "HTTP/1.1";
+ response_headers[":status"] = "200 OK";
+ response_headers["content-length"] = "0";
+ QuicInMemoryCache::Response* default_response =
+ new QuicInMemoryCache::Response;
+ default_response->set_headers(response_headers);
+ cache->AddDefaultResponse(default_response);
+
+ // Now we should get the default response for the original request.
+ response = cache->GetResponse("www.google.com", "/");
+ ASSERT_TRUE(response);
+ ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
+ EXPECT_EQ("200 OK", response->headers().find(":status")->second);
+
+ // Now add a set response for / and make sure it is returned
+ cache->AddSimpleResponse("www.google.com", "/", 302, "foo", "");
+ response = cache->GetResponse("www.google.com", "/");
+ ASSERT_TRUE(response);
+ ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
+ EXPECT_EQ("302 foo", response->headers().find(":status")->second);
+
+ // We should get the default response for other requests.
+ response = cache->GetResponse("www.google.com", "/asd");
+ ASSERT_TRUE(response);
+ ASSERT_TRUE(ContainsKey(response->headers(), ":status"));
+ EXPECT_EQ("200 OK", response->headers().find(":status")->second);
+}
+
} // namespace test
} // namespace tools
} // namespace net
diff --git a/net/tools/quic/quic_server_session.cc b/net/tools/quic/quic_server_session.cc
index 8999397..10d95e8 100644
--- a/net/tools/quic/quic_server_session.cc
+++ b/net/tools/quic/quic_server_session.cc
@@ -14,10 +14,13 @@
namespace net {
namespace tools {
-QuicServerSession::QuicServerSession(const QuicConfig& config,
- QuicConnection* connection,
- QuicServerSessionVisitor* visitor)
+QuicServerSession::QuicServerSession(
+ const QuicConfig& config,
+ QuicConnection* connection,
+ QuicServerSessionVisitor* visitor,
+ const QuicCryptoServerConfig* crypto_config)
: QuicSession(connection, config),
+ crypto_config_(crypto_config),
visitor_(visitor),
bandwidth_resumption_enabled_(false),
bandwidth_estimate_sent_to_client_(QuicBandwidth::Zero()),
@@ -27,10 +30,9 @@ QuicServerSession::QuicServerSession(const QuicConfig& config,
QuicServerSession::~QuicServerSession() {}
-void QuicServerSession::InitializeSession(
- const QuicCryptoServerConfig* crypto_config) {
- QuicSession::InitializeSession();
- crypto_stream_.reset(CreateQuicCryptoServerStream(crypto_config));
+void QuicServerSession::Initialize() {
+ crypto_stream_.reset(CreateQuicCryptoServerStream(crypto_config_));
+ QuicSession::Initialize();
}
QuicCryptoServerStream* QuicServerSession::CreateQuicCryptoServerStream(
diff --git a/net/tools/quic/quic_server_session.h b/net/tools/quic/quic_server_session.h
index dc63341..757cab6 100644
--- a/net/tools/quic/quic_server_session.h
+++ b/net/tools/quic/quic_server_session.h
@@ -52,9 +52,11 @@ class QuicServerSessionVisitor {
class QuicServerSession : public QuicSession {
public:
+ // |crypto_config| must outlive the session.
QuicServerSession(const QuicConfig& config,
QuicConnection* connection,
- QuicServerSessionVisitor* visitor);
+ QuicServerSessionVisitor* visitor,
+ const QuicCryptoServerConfig* crypto_config);
// Override the base class to notify the owner of the connection close.
void OnConnectionClosed(QuicErrorCode error, bool from_peer) override;
@@ -66,8 +68,7 @@ class QuicServerSession : public QuicSession {
~QuicServerSession() override;
- // |crypto_config| must outlive the session.
- virtual void InitializeSession(const QuicCryptoServerConfig* crypto_config);
+ void Initialize() override;
const QuicCryptoServerStream* crypto_stream() const {
return crypto_stream_.get();
@@ -118,6 +119,7 @@ class QuicServerSession : public QuicSession {
private:
friend class test::QuicServerSessionPeer;
+ const QuicCryptoServerConfig* crypto_config_;
scoped_ptr<QuicCryptoServerStream> crypto_stream_;
QuicServerSessionVisitor* visitor_;
diff --git a/net/tools/quic/quic_server_session_test.cc b/net/tools/quic/quic_server_session_test.cc
index 4716e81..1df0dc6 100644
--- a/net/tools/quic/quic_server_session_test.cc
+++ b/net/tools/quic/quic_server_session_test.cc
@@ -78,12 +78,13 @@ class QuicServerSessionTest : public ::testing::TestWithParam<QuicVersion> {
connection_ = new StrictMock<MockConnection>(Perspective::IS_SERVER,
SupportedVersions(GetParam()));
- session_.reset(new QuicServerSession(config_, connection_, &owner_));
+ session_.reset(
+ new QuicServerSession(config_, connection_, &owner_, &crypto_config_));
MockClock clock;
handshake_message_.reset(crypto_config_.AddDefaultConfig(
QuicRandom::GetInstance(), &clock,
QuicCryptoServerConfig::ConfigOptions()));
- session_->InitializeSession(&crypto_config_);
+ session_->Initialize();
visitor_ = QuicConnectionPeer::GetVisitor(connection_);
}
@@ -266,7 +267,7 @@ TEST_P(QuicServerSessionTest, GetEvenIncomingError) {
TEST_P(QuicServerSessionTest, GetStreamDisconnected) {
// Don't create new streams if the connection is disconnected.
QuicConnectionPeer::CloseConnection(connection_);
- EXPECT_DFATAL(QuicServerSessionPeer::GetIncomingDataStream(session_.get(), 4),
+ EXPECT_DFATAL(QuicServerSessionPeer::GetIncomingDataStream(session_.get(), 5),
"ShouldCreateIncomingDataStream called when disconnected");
}
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc
index 03aae4f..9ba6e69 100644
--- a/net/tools/quic/quic_simple_client.cc
+++ b/net/tools/quic/quic_simple_client.cc
@@ -145,6 +145,14 @@ bool QuicSimpleClient::Connect() {
return session_->connection()->connected();
}
+QuicClientSession* QuicSimpleClient::CreateQuicClientSession(
+ const QuicConfig& config,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config) {
+ return new QuicClientSession(config, connection, server_id_, &crypto_config_);
+}
+
void QuicSimpleClient::StartConnect() {
DCHECK(initialized_);
DCHECK(!connected());
@@ -158,8 +166,9 @@ void QuicSimpleClient::StartConnect() {
Perspective::IS_CLIENT,
server_id_.is_https(),
supported_versions_);
- session_.reset(new QuicClientSession(config_, connection_));
- session_->InitializeSession(server_id_, &crypto_config_);
+ session_.reset(CreateQuicClientSession(config_, connection_, server_id_,
+ &crypto_config_));
+ session_->Initialize();
session_->CryptoConnect();
}
diff --git a/net/tools/quic/quic_simple_client.h b/net/tools/quic/quic_simple_client.h
index 1e63a87..cb70970 100644
--- a/net/tools/quic/quic_simple_client.h
+++ b/net/tools/quic/quic_simple_client.h
@@ -189,6 +189,12 @@ class QuicSimpleClient : public QuicDataStream::Visitor,
virtual QuicConnectionHelper* CreateQuicConnectionHelper();
virtual QuicPacketWriter* CreateQuicPacketWriter();
+ virtual QuicClientSession* CreateQuicClientSession(
+ const QuicConfig& config,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config);
+
private:
friend class net::tools::test::QuicClientPeer;
diff --git a/net/tools/quic/quic_spdy_client_stream_test.cc b/net/tools/quic/quic_spdy_client_stream_test.cc
index 7e30c92..9503a45 100644
--- a/net/tools/quic/quic_spdy_client_stream_test.cc
+++ b/net/tools/quic/quic_spdy_client_stream_test.cc
@@ -33,11 +33,12 @@ class QuicSpdyClientStreamTest : public TestWithParam<QuicVersion> {
: connection_(
new StrictMock<MockConnection>(Perspective::IS_CLIENT,
SupportedVersions(GetParam()))),
- session_(DefaultQuicConfig(), connection_),
+ session_(DefaultQuicConfig(),
+ connection_,
+ QuicServerId("example.com", 80, false, PRIVACY_MODE_DISABLED),
+ &crypto_config_),
body_("hello world") {
- session_.InitializeSession(
- QuicServerId("example.com", 80, false, PRIVACY_MODE_DISABLED),
- &crypto_config_);
+ session_.Initialize();
headers_.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "Ok");
headers_.ReplaceOrAppendHeader("content-length", "11");
@@ -55,12 +56,12 @@ class QuicSpdyClientStreamTest : public TestWithParam<QuicVersion> {
}
StrictMock<MockConnection>* connection_;
+ QuicCryptoClientConfig crypto_config_;
QuicClientSession session_;
scoped_ptr<QuicSpdyClientStream> stream_;
BalsaHeaders headers_;
string headers_string_;
string body_;
- QuicCryptoClientConfig crypto_config_;
};
INSTANTIATE_TEST_CASE_P(Tests, QuicSpdyClientStreamTest,
diff --git a/net/tools/quic/test_tools/quic_test_utils.cc b/net/tools/quic/test_tools/quic_test_utils.cc
index 4c5a8d2..69b571d 100644
--- a/net/tools/quic/test_tools/quic_test_utils.cc
+++ b/net/tools/quic/test_tools/quic_test_utils.cc
@@ -32,22 +32,6 @@ QuicAckFrame MakeAckFrameWithNackRanges(
return ack;
}
-TestSession::TestSession(QuicConnection* connection, const QuicConfig& config)
- : QuicSession(connection, config),
- crypto_stream_(nullptr) {
- InitializeSession();
-}
-
-TestSession::~TestSession() {}
-
-void TestSession::SetCryptoStream(QuicCryptoStream* stream) {
- crypto_stream_ = stream;
-}
-
-QuicCryptoStream* TestSession::GetCryptoStream() {
- return crypto_stream_;
-}
-
MockPacketWriter::MockPacketWriter() {
}
diff --git a/net/tools/quic/test_tools/quic_test_utils.h b/net/tools/quic/test_tools/quic_test_utils.h
index dac5f5c..3fe48f5 100644
--- a/net/tools/quic/test_tools/quic_test_utils.h
+++ b/net/tools/quic/test_tools/quic_test_utils.h
@@ -40,24 +40,6 @@ static const uint32 kInitialSessionFlowControlWindowForTest =
QuicAckFrame MakeAckFrameWithNackRanges(size_t num_nack_ranges,
QuicPacketSequenceNumber least_unacked);
-class TestSession : public QuicSession {
- public:
- TestSession(QuicConnection* connection, const QuicConfig& config);
- ~TestSession() override;
-
- MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
- MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*());
-
- void SetCryptoStream(QuicCryptoStream* stream);
-
- QuicCryptoStream* GetCryptoStream() override;
-
- private:
- QuicCryptoStream* crypto_stream_;
-
- DISALLOW_COPY_AND_ASSIGN(TestSession);
-};
-
class MockPacketWriter : public QuicPacketWriter {
public:
MockPacketWriter();