OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/quic/quic_server_session_base.h" | |
6 | |
7 #include <cstdint> | |
8 #include <memory> | |
9 | |
10 #include "base/macros.h" | |
11 #include "net/quic/crypto/quic_crypto_server_config.h" | |
12 #include "net/quic/crypto/quic_random.h" | |
13 #include "net/quic/proto/cached_network_parameters.pb.h" | |
14 #include "net/quic/quic_connection.h" | |
15 #include "net/quic/quic_crypto_server_stream.h" | |
16 #include "net/quic/quic_utils.h" | |
17 #include "net/quic/test_tools/crypto_test_utils.h" | |
18 #include "net/quic/test_tools/quic_config_peer.h" | |
19 #include "net/quic/test_tools/quic_connection_peer.h" | |
20 #include "net/quic/test_tools/quic_sent_packet_manager_peer.h" | |
21 #include "net/quic/test_tools/quic_session_peer.h" | |
22 #include "net/quic/test_tools/quic_spdy_session_peer.h" | |
23 #include "net/quic/test_tools/quic_spdy_stream_peer.h" | |
24 #include "net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h" | |
25 #include "net/quic/test_tools/quic_test_utils.h" | |
26 #include "net/test/gtest_util.h" | |
27 #include "net/tools/quic/quic_simple_server_stream.h" | |
28 #include "net/tools/quic/test_tools/mock_quic_server_session_visitor.h" | |
29 #include "testing/gmock/include/gmock/gmock.h" | |
30 #include "testing/gtest/include/gtest/gtest.h" | |
31 | |
32 using net::test::CryptoTestUtils; | |
33 using net::test::MockQuicConnection; | |
34 using net::test::MockQuicConnectionHelper; | |
35 using net::test::QuicConfigPeer; | |
36 using net::test::QuicConnectionPeer; | |
37 using net::test::QuicSpdyStreamPeer; | |
38 using net::test::QuicSentPacketManagerPeer; | |
39 using net::test::QuicSessionPeer; | |
40 using net::test::QuicSpdySessionPeer; | |
41 using net::test::QuicSustainedBandwidthRecorderPeer; | |
42 using net::test::SupportedVersions; | |
43 using net::test::ValueRestore; | |
44 using net::test::kClientDataStreamId1; | |
45 using net::test::kClientDataStreamId2; | |
46 using net::test::kClientDataStreamId3; | |
47 using net::test::kInitialSessionFlowControlWindowForTest; | |
48 using net::test::kInitialStreamFlowControlWindowForTest; | |
49 using std::string; | |
50 using testing::StrictMock; | |
51 using testing::_; | |
52 | |
53 namespace net { | |
54 namespace test { | |
55 | |
56 class QuicServerSessionBasePeer { | |
57 public: | |
58 static ReliableQuicStream* GetOrCreateDynamicStream(QuicServerSessionBase* s, | |
59 QuicStreamId id) { | |
60 return s->GetOrCreateDynamicStream(id); | |
61 } | |
62 static void SetCryptoStream(QuicServerSessionBase* s, | |
63 QuicCryptoServerStream* crypto_stream) { | |
64 s->crypto_stream_.reset(crypto_stream); | |
65 s->static_streams()[kCryptoStreamId] = crypto_stream; | |
66 } | |
67 static bool IsBandwidthResumptionEnabled(QuicServerSessionBase* s) { | |
68 return s->bandwidth_resumption_enabled_; | |
69 } | |
70 }; | |
71 | |
72 namespace { | |
73 | |
74 class TestServerSession : public QuicServerSessionBase { | |
75 public: | |
76 TestServerSession(const QuicConfig& config, | |
77 QuicConnection* connection, | |
78 QuicServerSessionBase::Visitor* visitor, | |
79 QuicServerSessionBase::Helper* helper, | |
80 const QuicCryptoServerConfig* crypto_config, | |
81 QuicCompressedCertsCache* compressed_certs_cache) | |
82 : QuicServerSessionBase(config, | |
83 connection, | |
84 visitor, | |
85 helper, | |
86 crypto_config, | |
87 compressed_certs_cache) {} | |
88 | |
89 ~TestServerSession() override{}; | |
90 | |
91 protected: | |
92 QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override { | |
93 if (!ShouldCreateIncomingDynamicStream(id)) { | |
94 return nullptr; | |
95 } | |
96 QuicSpdyStream* stream = new QuicSimpleServerStream(id, this); | |
97 ActivateStream(stream); | |
98 return stream; | |
99 } | |
100 | |
101 QuicSpdyStream* CreateOutgoingDynamicStream(SpdyPriority priority) override { | |
102 if (!ShouldCreateOutgoingDynamicStream()) { | |
103 return nullptr; | |
104 } | |
105 | |
106 QuicSpdyStream* stream = | |
107 new QuicSimpleServerStream(GetNextOutgoingStreamId(), this); | |
108 stream->SetPriority(priority); | |
109 ActivateStream(stream); | |
110 return stream; | |
111 } | |
112 | |
113 QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( | |
114 const QuicCryptoServerConfig* crypto_config, | |
115 QuicCompressedCertsCache* compressed_certs_cache) override { | |
116 return new QuicCryptoServerStream( | |
117 crypto_config, compressed_certs_cache, | |
118 FLAGS_enable_quic_stateless_reject_support, this); | |
119 } | |
120 }; | |
121 | |
122 const size_t kMaxStreamsForTest = 10; | |
123 | |
124 class QuicServerSessionBaseTest : public ::testing::TestWithParam<QuicVersion> { | |
125 protected: | |
126 QuicServerSessionBaseTest() | |
127 : crypto_config_(QuicCryptoServerConfig::TESTING, | |
128 QuicRandom::GetInstance(), | |
129 CryptoTestUtils::ProofSourceForTesting()), | |
130 compressed_certs_cache_( | |
131 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) { | |
132 FLAGS_quic_always_log_bugs_for_tests = true; | |
133 config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest); | |
134 config_.SetMaxIncomingDynamicStreamsToSend(kMaxStreamsForTest); | |
135 QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(&config_, | |
136 kMaxStreamsForTest); | |
137 config_.SetInitialStreamFlowControlWindowToSend( | |
138 kInitialStreamFlowControlWindowForTest); | |
139 config_.SetInitialSessionFlowControlWindowToSend( | |
140 kInitialSessionFlowControlWindowForTest); | |
141 | |
142 connection_ = new StrictMock<MockQuicConnection>( | |
143 &helper_, &alarm_factory_, Perspective::IS_SERVER, | |
144 SupportedVersions(GetParam())); | |
145 session_.reset(new TestServerSession(config_, connection_, &owner_, | |
146 &session_helper_, &crypto_config_, | |
147 &compressed_certs_cache_)); | |
148 MockClock clock; | |
149 handshake_message_.reset(crypto_config_.AddDefaultConfig( | |
150 QuicRandom::GetInstance(), &clock, | |
151 QuicCryptoServerConfig::ConfigOptions())); | |
152 session_->Initialize(); | |
153 visitor_ = QuicConnectionPeer::GetVisitor(connection_); | |
154 } | |
155 | |
156 StrictMock<MockQuicServerSessionVisitor> owner_; | |
157 StrictMock<MockQuicServerSessionHelper> session_helper_; | |
158 MockQuicConnectionHelper helper_; | |
159 MockAlarmFactory alarm_factory_; | |
160 StrictMock<MockQuicConnection>* connection_; | |
161 QuicConfig config_; | |
162 QuicCryptoServerConfig crypto_config_; | |
163 QuicCompressedCertsCache compressed_certs_cache_; | |
164 std::unique_ptr<TestServerSession> session_; | |
165 std::unique_ptr<CryptoHandshakeMessage> handshake_message_; | |
166 QuicConnectionVisitorInterface* visitor_; | |
167 }; | |
168 | |
169 // Compares CachedNetworkParameters. | |
170 MATCHER_P(EqualsProto, network_params, "") { | |
171 CachedNetworkParameters reference(network_params); | |
172 return (arg->bandwidth_estimate_bytes_per_second() == | |
173 reference.bandwidth_estimate_bytes_per_second() && | |
174 arg->bandwidth_estimate_bytes_per_second() == | |
175 reference.bandwidth_estimate_bytes_per_second() && | |
176 arg->max_bandwidth_estimate_bytes_per_second() == | |
177 reference.max_bandwidth_estimate_bytes_per_second() && | |
178 arg->max_bandwidth_timestamp_seconds() == | |
179 reference.max_bandwidth_timestamp_seconds() && | |
180 arg->min_rtt_ms() == reference.min_rtt_ms() && | |
181 arg->previous_connection_state() == | |
182 reference.previous_connection_state()); | |
183 } | |
184 | |
185 INSTANTIATE_TEST_CASE_P(Tests, | |
186 QuicServerSessionBaseTest, | |
187 ::testing::ValuesIn(QuicSupportedVersions())); | |
188 | |
189 TEST_P(QuicServerSessionBaseTest, ServerPushDisabledByDefault) { | |
190 // Without the client explicitly sending kSPSH, server push will be disabled | |
191 // at the server. | |
192 EXPECT_FALSE( | |
193 session_->config()->HasReceivedConnectionOptions() && | |
194 ContainsQuicTag(session_->config()->ReceivedConnectionOptions(), kSPSH)); | |
195 session_->OnConfigNegotiated(); | |
196 EXPECT_FALSE(session_->server_push_enabled()); | |
197 } | |
198 | |
199 TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) { | |
200 // Open a stream, then reset it. | |
201 // Send two bytes of payload to open it. | |
202 QuicStreamFrame data1(kClientDataStreamId1, false, 0, StringPiece("HT")); | |
203 session_->OnStreamFrame(data1); | |
204 EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); | |
205 | |
206 // Send a reset (and expect the peer to send a RST in response). | |
207 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, | |
208 0); | |
209 EXPECT_CALL(*connection_, | |
210 SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); | |
211 visitor_->OnRstStream(rst1); | |
212 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); | |
213 | |
214 // Send the same two bytes of payload in a new packet. | |
215 visitor_->OnStreamFrame(data1); | |
216 | |
217 // The stream should not be re-opened. | |
218 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); | |
219 EXPECT_TRUE(connection_->connected()); | |
220 } | |
221 | |
222 TEST_P(QuicServerSessionBaseTest, NeverOpenStreamDueToReset) { | |
223 // Send a reset (and expect the peer to send a RST in response). | |
224 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, | |
225 0); | |
226 EXPECT_CALL(*connection_, | |
227 SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); | |
228 visitor_->OnRstStream(rst1); | |
229 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); | |
230 | |
231 // Send two bytes of payload. | |
232 QuicStreamFrame data1(kClientDataStreamId1, false, 0, StringPiece("HT")); | |
233 visitor_->OnStreamFrame(data1); | |
234 | |
235 // The stream should never be opened, now that the reset is received. | |
236 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); | |
237 EXPECT_TRUE(connection_->connected()); | |
238 } | |
239 | |
240 TEST_P(QuicServerSessionBaseTest, AcceptClosedStream) { | |
241 // Send (empty) compressed headers followed by two bytes of data. | |
242 QuicStreamFrame frame1(kClientDataStreamId1, false, 0, | |
243 StringPiece("\1\0\0\0\0\0\0\0HT")); | |
244 QuicStreamFrame frame2(kClientDataStreamId2, false, 0, | |
245 StringPiece("\2\0\0\0\0\0\0\0HT")); | |
246 visitor_->OnStreamFrame(frame1); | |
247 visitor_->OnStreamFrame(frame2); | |
248 EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams()); | |
249 | |
250 // Send a reset (and expect the peer to send a RST in response). | |
251 QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, 0); | |
252 EXPECT_CALL(*connection_, | |
253 SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); | |
254 visitor_->OnRstStream(rst); | |
255 | |
256 // If we were tracking, we'd probably want to reject this because it's data | |
257 // past the reset point of stream 3. As it's a closed stream we just drop the | |
258 // data on the floor, but accept the packet because it has data for stream 5. | |
259 QuicStreamFrame frame3(kClientDataStreamId1, false, 2, StringPiece("TP")); | |
260 QuicStreamFrame frame4(kClientDataStreamId2, false, 2, StringPiece("TP")); | |
261 visitor_->OnStreamFrame(frame3); | |
262 visitor_->OnStreamFrame(frame4); | |
263 // The stream should never be opened, now that the reset is received. | |
264 EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); | |
265 EXPECT_TRUE(connection_->connected()); | |
266 } | |
267 | |
268 TEST_P(QuicServerSessionBaseTest, MaxOpenStreams) { | |
269 // Test that the server refuses if a client attempts to open too many data | |
270 // streams. The server accepts slightly more than the negotiated stream limit | |
271 // to deal with rare cases where a client FIN/RST is lost. | |
272 | |
273 if (GetParam() <= QUIC_VERSION_34) { | |
274 EXPECT_EQ(kMaxStreamsForTest, session_->max_open_incoming_streams()); | |
275 } | |
276 | |
277 // The slightly increased stream limit is set during config negotiation. It | |
278 // is either an increase of 10 over negotiated limit, or a fixed percentage | |
279 // scaling, whichever is larger. Test both before continuing. | |
280 session_->OnConfigNegotiated(); | |
281 EXPECT_LT(kMaxStreamsMultiplier * kMaxStreamsForTest, | |
282 kMaxStreamsForTest + kMaxStreamsMinimumIncrement); | |
283 EXPECT_EQ(kMaxStreamsForTest + kMaxStreamsMinimumIncrement, | |
284 session_->max_open_incoming_streams()); | |
285 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); | |
286 QuicStreamId stream_id = kClientDataStreamId1; | |
287 // Open the max configured number of streams, should be no problem. | |
288 for (size_t i = 0; i < kMaxStreamsForTest; ++i) { | |
289 EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateDynamicStream( | |
290 session_.get(), stream_id)); | |
291 stream_id += 2; | |
292 } | |
293 | |
294 // Open more streams: server should accept slightly more than the limit. | |
295 for (size_t i = 0; i < kMaxStreamsMinimumIncrement; ++i) { | |
296 EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateDynamicStream( | |
297 session_.get(), stream_id)); | |
298 stream_id += 2; | |
299 } | |
300 | |
301 // Now violate the server's internal stream limit. | |
302 stream_id += 2; | |
303 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); | |
304 EXPECT_CALL(*connection_, SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0)); | |
305 // Even if the connection remains open, the stream creation should fail. | |
306 EXPECT_FALSE(QuicServerSessionBasePeer::GetOrCreateDynamicStream( | |
307 session_.get(), stream_id)); | |
308 } | |
309 | |
310 TEST_P(QuicServerSessionBaseTest, MaxAvailableStreams) { | |
311 // Test that the server closes the connection if a client makes too many data | |
312 // streams available. The server accepts slightly more than the negotiated | |
313 // stream limit to deal with rare cases where a client FIN/RST is lost. | |
314 | |
315 if (GetParam() <= QUIC_VERSION_34) { | |
316 // The slightly increased stream limit is set during config negotiation. | |
317 EXPECT_EQ(kMaxStreamsForTest, session_->max_open_incoming_streams()); | |
318 } | |
319 session_->OnConfigNegotiated(); | |
320 const size_t kAvailableStreamLimit = session_->MaxAvailableStreams(); | |
321 EXPECT_EQ( | |
322 session_->max_open_incoming_streams() * kMaxAvailableStreamsMultiplier, | |
323 session_->MaxAvailableStreams()); | |
324 // The protocol specification requires that there can be at least 10 times | |
325 // as many available streams as the connection's maximum open streams. | |
326 EXPECT_LE(10 * kMaxStreamsForTest, kAvailableStreamLimit); | |
327 | |
328 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); | |
329 EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateDynamicStream( | |
330 session_.get(), kClientDataStreamId1)); | |
331 | |
332 // Establish available streams up to the server's limit. | |
333 const int kLimitingStreamId = | |
334 kClientDataStreamId1 + (kAvailableStreamLimit)*2 + 2; | |
335 EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateDynamicStream( | |
336 session_.get(), kLimitingStreamId)); | |
337 | |
338 // A further available stream will result in connection close. | |
339 EXPECT_CALL(*connection_, | |
340 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _)); | |
341 // This forces stream kLimitingStreamId + 2 to become available, which | |
342 // violates the quota. | |
343 EXPECT_FALSE(QuicServerSessionBasePeer::GetOrCreateDynamicStream( | |
344 session_.get(), kLimitingStreamId + 4)); | |
345 } | |
346 | |
347 TEST_P(QuicServerSessionBaseTest, EnableServerPushThroughConnectionOption) { | |
348 // Assume server received server push connection option. | |
349 QuicTagVector copt; | |
350 copt.push_back(kSPSH); | |
351 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt); | |
352 session_->OnConfigNegotiated(); | |
353 EXPECT_TRUE(session_->server_push_enabled()); | |
354 } | |
355 | |
356 TEST_P(QuicServerSessionBaseTest, GetEvenIncomingError) { | |
357 // Incoming streams on the server session must be odd. | |
358 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _)); | |
359 EXPECT_EQ(nullptr, QuicServerSessionBasePeer::GetOrCreateDynamicStream( | |
360 session_.get(), 4)); | |
361 } | |
362 | |
363 TEST_P(QuicServerSessionBaseTest, GetStreamDisconnected) { | |
364 // Don't create new streams if the connection is disconnected. | |
365 QuicConnectionPeer::TearDownLocalConnectionState(connection_); | |
366 EXPECT_DFATAL( | |
367 QuicServerSessionBasePeer::GetOrCreateDynamicStream(session_.get(), 5), | |
368 "ShouldCreateIncomingDynamicStream called when disconnected"); | |
369 } | |
370 | |
371 class MockQuicCryptoServerStream : public QuicCryptoServerStream { | |
372 public: | |
373 explicit MockQuicCryptoServerStream( | |
374 const QuicCryptoServerConfig* crypto_config, | |
375 QuicCompressedCertsCache* compressed_certs_cache, | |
376 QuicServerSessionBase* session) | |
377 : QuicCryptoServerStream(crypto_config, | |
378 compressed_certs_cache, | |
379 FLAGS_enable_quic_stateless_reject_support, | |
380 session) {} | |
381 ~MockQuicCryptoServerStream() override {} | |
382 | |
383 MOCK_METHOD1(SendServerConfigUpdate, | |
384 void(const CachedNetworkParameters* cached_network_parameters)); | |
385 | |
386 void set_encryption_established(bool has_established) { | |
387 encryption_established_ = has_established; | |
388 } | |
389 | |
390 private: | |
391 DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream); | |
392 }; | |
393 | |
394 TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) { | |
395 // Test that bandwidth estimate updates are sent to the client, only when | |
396 // bandwidth resumption is enabled, the bandwidth estimate has changed | |
397 // sufficiently, enough time has passed, | |
398 // and we don't have any other data to write. | |
399 | |
400 // Client has sent kBWRE connection option to trigger bandwidth resumption. | |
401 // Disable this flag because if connection uses multipath sent packet manager, | |
402 // static_cast here does not work. | |
403 QuicTagVector copt; | |
404 copt.push_back(kBWRE); | |
405 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt); | |
406 session_->OnConfigNegotiated(); | |
407 EXPECT_TRUE( | |
408 QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get())); | |
409 | |
410 int32_t bandwidth_estimate_kbytes_per_second = 123; | |
411 int32_t max_bandwidth_estimate_kbytes_per_second = 134; | |
412 int32_t max_bandwidth_estimate_timestamp = 1122334455; | |
413 const string serving_region = "not a real region"; | |
414 session_->set_serving_region(serving_region); | |
415 | |
416 MockQuicCryptoServerStream* crypto_stream = new MockQuicCryptoServerStream( | |
417 &crypto_config_, &compressed_certs_cache_, session_.get()); | |
418 QuicServerSessionBasePeer::SetCryptoStream(session_.get(), crypto_stream); | |
419 | |
420 // Set some initial bandwidth values. | |
421 QuicSentPacketManager* sent_packet_manager = | |
422 QuicConnectionPeer::GetSentPacketManager(session_->connection(), | |
423 kDefaultPathId); | |
424 QuicSustainedBandwidthRecorder& bandwidth_recorder = | |
425 QuicSentPacketManagerPeer::GetBandwidthRecorder(sent_packet_manager); | |
426 // Seed an rtt measurement equal to the initial default rtt. | |
427 RttStats* rtt_stats = | |
428 const_cast<RttStats*>(sent_packet_manager->GetRttStats()); | |
429 rtt_stats->UpdateRtt( | |
430 QuicTime::Delta::FromMicroseconds(rtt_stats->initial_rtt_us()), | |
431 QuicTime::Delta::Zero(), QuicTime::Zero()); | |
432 QuicSustainedBandwidthRecorderPeer::SetBandwidthEstimate( | |
433 &bandwidth_recorder, bandwidth_estimate_kbytes_per_second); | |
434 QuicSustainedBandwidthRecorderPeer::SetMaxBandwidthEstimate( | |
435 &bandwidth_recorder, max_bandwidth_estimate_kbytes_per_second, | |
436 max_bandwidth_estimate_timestamp); | |
437 // Queue up some pending data. | |
438 session_->MarkConnectionLevelWriteBlocked(kCryptoStreamId); | |
439 EXPECT_TRUE(session_->HasDataToWrite()); | |
440 | |
441 // There will be no update sent yet - not enough time has passed. | |
442 QuicTime now = QuicTime::Zero(); | |
443 session_->OnCongestionWindowChange(now); | |
444 | |
445 // Bandwidth estimate has now changed sufficiently but not enough time has | |
446 // passed to send a Server Config Update. | |
447 bandwidth_estimate_kbytes_per_second = | |
448 bandwidth_estimate_kbytes_per_second * 1.6; | |
449 session_->OnCongestionWindowChange(now); | |
450 | |
451 // Bandwidth estimate has now changed sufficiently and enough time has passed, | |
452 // but not enough packets have been sent. | |
453 int64_t srtt_ms = | |
454 sent_packet_manager->GetRttStats()->smoothed_rtt().ToMilliseconds(); | |
455 now = now + QuicTime::Delta::FromMilliseconds( | |
456 kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms); | |
457 session_->OnCongestionWindowChange(now); | |
458 | |
459 // The connection no longer has pending data to be written. | |
460 session_->OnCanWrite(); | |
461 EXPECT_FALSE(session_->HasDataToWrite()); | |
462 session_->OnCongestionWindowChange(now); | |
463 | |
464 // Bandwidth estimate has now changed sufficiently, enough time has passed, | |
465 // and enough packets have been sent. | |
466 QuicConnectionPeer::SetPacketNumberOfLastSentPacket( | |
467 session_->connection(), kMinPacketsBetweenServerConfigUpdates); | |
468 | |
469 // Verify that the proto has exactly the values we expect. | |
470 CachedNetworkParameters expected_network_params; | |
471 expected_network_params.set_bandwidth_estimate_bytes_per_second( | |
472 bandwidth_recorder.BandwidthEstimate().ToBytesPerSecond()); | |
473 expected_network_params.set_max_bandwidth_estimate_bytes_per_second( | |
474 bandwidth_recorder.MaxBandwidthEstimate().ToBytesPerSecond()); | |
475 expected_network_params.set_max_bandwidth_timestamp_seconds( | |
476 bandwidth_recorder.MaxBandwidthTimestamp()); | |
477 expected_network_params.set_min_rtt_ms(session_->connection() | |
478 ->sent_packet_manager() | |
479 .GetRttStats() | |
480 ->min_rtt() | |
481 .ToMilliseconds()); | |
482 expected_network_params.set_previous_connection_state( | |
483 CachedNetworkParameters::CONGESTION_AVOIDANCE); | |
484 expected_network_params.set_timestamp( | |
485 session_->connection()->clock()->WallNow().ToUNIXSeconds()); | |
486 expected_network_params.set_serving_region(serving_region); | |
487 | |
488 EXPECT_CALL(*crypto_stream, | |
489 SendServerConfigUpdate(EqualsProto(expected_network_params))) | |
490 .Times(1); | |
491 EXPECT_CALL(*connection_, OnSendConnectionState(_)).Times(1); | |
492 session_->OnCongestionWindowChange(now); | |
493 } | |
494 | |
495 TEST_P(QuicServerSessionBaseTest, BandwidthResumptionExperiment) { | |
496 // Test that if a client provides a CachedNetworkParameters with the same | |
497 // serving region as the current server, and which was made within an hour of | |
498 // now, that this data is passed down to the send algorithm. | |
499 | |
500 // Client has sent kBWRE connection option to trigger bandwidth resumption. | |
501 QuicTagVector copt; | |
502 copt.push_back(kBWRE); | |
503 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt); | |
504 | |
505 const string kTestServingRegion = "a serving region"; | |
506 session_->set_serving_region(kTestServingRegion); | |
507 | |
508 // Set the time to be one hour + one second from the 0 baseline. | |
509 connection_->AdvanceTime( | |
510 QuicTime::Delta::FromSeconds(kNumSecondsPerHour + 1)); | |
511 | |
512 QuicCryptoServerStream* crypto_stream = static_cast<QuicCryptoServerStream*>( | |
513 QuicSessionPeer::GetCryptoStream(session_.get())); | |
514 | |
515 // No effect if no CachedNetworkParameters provided. | |
516 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0); | |
517 session_->OnConfigNegotiated(); | |
518 | |
519 // No effect if CachedNetworkParameters provided, but different serving | |
520 // regions. | |
521 CachedNetworkParameters cached_network_params; | |
522 cached_network_params.set_bandwidth_estimate_bytes_per_second(1); | |
523 cached_network_params.set_serving_region("different serving region"); | |
524 crypto_stream->SetPreviousCachedNetworkParams(cached_network_params); | |
525 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0); | |
526 session_->OnConfigNegotiated(); | |
527 | |
528 // Same serving region, but timestamp is too old, should have no effect. | |
529 cached_network_params.set_serving_region(kTestServingRegion); | |
530 cached_network_params.set_timestamp(0); | |
531 crypto_stream->SetPreviousCachedNetworkParams(cached_network_params); | |
532 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0); | |
533 session_->OnConfigNegotiated(); | |
534 | |
535 // Same serving region, and timestamp is recent: estimate is stored. | |
536 cached_network_params.set_timestamp( | |
537 connection_->clock()->WallNow().ToUNIXSeconds()); | |
538 crypto_stream->SetPreviousCachedNetworkParams(cached_network_params); | |
539 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(1); | |
540 session_->OnConfigNegotiated(); | |
541 } | |
542 | |
543 TEST_P(QuicServerSessionBaseTest, BandwidthMaxEnablesResumption) { | |
544 EXPECT_FALSE( | |
545 QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get())); | |
546 | |
547 // Client has sent kBWMX connection option to trigger bandwidth resumption. | |
548 QuicTagVector copt; | |
549 copt.push_back(kBWMX); | |
550 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt); | |
551 session_->OnConfigNegotiated(); | |
552 EXPECT_TRUE( | |
553 QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get())); | |
554 } | |
555 | |
556 TEST_P(QuicServerSessionBaseTest, NoBandwidthResumptionByDefault) { | |
557 EXPECT_FALSE( | |
558 QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get())); | |
559 session_->OnConfigNegotiated(); | |
560 EXPECT_FALSE( | |
561 QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get())); | |
562 } | |
563 | |
564 } // namespace | |
565 } // namespace test | |
566 } // namespace net | |
OLD | NEW |