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.
5 #include "net/tools/quic/quic_server_session.h"
7 #include "net/quic/crypto/quic_crypto_server_config.h"
8 #include "net/quic/crypto/quic_random.h"
9 #include "net/quic/proto/cached_network_parameters.pb.h"
10 #include "net/quic/quic_connection.h"
11 #include "net/quic/quic_crypto_server_stream.h"
12 #include "net/quic/quic_flags.h"
13 #include "net/quic/quic_utils.h"
14 #include "net/quic/test_tools/quic_config_peer.h"
15 #include "net/quic/test_tools/quic_connection_peer.h"
16 #include "net/quic/test_tools/quic_data_stream_peer.h"
17 #include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
18 #include "net/quic/test_tools/quic_session_peer.h"
19 #include "net/quic/test_tools/quic_spdy_session_peer.h"
20 #include "net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h"
21 #include "net/quic/test_tools/quic_test_utils.h"
22 #include "net/test/gtest_util.h"
23 #include "net/tools/quic/quic_spdy_server_stream.h"
24 #include "net/tools/quic/test_tools/mock_quic_server_session_visitor.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 using __gnu_cxx::vector
;
29 using net::test::MockConnection
;
30 using net::test::QuicConfigPeer
;
31 using net::test::QuicConnectionPeer
;
32 using net::test::QuicDataStreamPeer
;
33 using net::test::QuicSentPacketManagerPeer
;
34 using net::test::QuicSessionPeer
;
35 using net::test::QuicSpdySessionPeer
;
36 using net::test::QuicSustainedBandwidthRecorderPeer
;
37 using net::test::SupportedVersions
;
38 using net::test::ValueRestore
;
39 using net::test::kClientDataStreamId1
;
40 using net::test::kClientDataStreamId2
;
41 using net::test::kClientDataStreamId3
;
42 using net::test::kInitialSessionFlowControlWindowForTest
;
43 using net::test::kInitialStreamFlowControlWindowForTest
;
45 using testing::StrictMock
;
52 class QuicServerSessionPeer
{
54 static ReliableQuicStream
* GetIncomingDynamicStream(QuicServerSession
* s
,
56 return s
->GetIncomingDynamicStream(id
);
58 static void SetCryptoStream(QuicServerSession
* s
,
59 QuicCryptoServerStream
* crypto_stream
) {
60 s
->crypto_stream_
.reset(crypto_stream
);
61 s
->static_streams()[kCryptoStreamId
] = crypto_stream
;
63 static bool IsBandwidthResumptionEnabled(QuicServerSession
* s
) {
64 return s
->bandwidth_resumption_enabled_
;
70 const size_t kMaxStreamsForTest
= 10;
72 class QuicServerSessionTest
: public ::testing::TestWithParam
<QuicVersion
> {
74 QuicServerSessionTest()
75 : crypto_config_(QuicCryptoServerConfig::TESTING
,
76 QuicRandom::GetInstance()) {
77 config_
.SetMaxStreamsPerConnection(kMaxStreamsForTest
,
79 config_
.SetInitialStreamFlowControlWindowToSend(
80 kInitialStreamFlowControlWindowForTest
);
81 config_
.SetInitialSessionFlowControlWindowToSend(
82 kInitialSessionFlowControlWindowForTest
);
84 connection_
= new StrictMock
<MockConnection
>(Perspective::IS_SERVER
,
85 SupportedVersions(GetParam()));
87 new QuicServerSession(config_
, connection_
, &owner_
, &crypto_config_
));
89 handshake_message_
.reset(crypto_config_
.AddDefaultConfig(
90 QuicRandom::GetInstance(), &clock
,
91 QuicCryptoServerConfig::ConfigOptions()));
92 session_
->Initialize();
93 visitor_
= QuicConnectionPeer::GetVisitor(connection_
);
96 StrictMock
<MockQuicServerSessionVisitor
> owner_
;
97 StrictMock
<MockConnection
>* connection_
;
99 QuicCryptoServerConfig crypto_config_
;
100 scoped_ptr
<QuicServerSession
> session_
;
101 scoped_ptr
<CryptoHandshakeMessage
> handshake_message_
;
102 QuicConnectionVisitorInterface
* visitor_
;
105 // Compares CachedNetworkParameters.
106 MATCHER_P(EqualsProto
, network_params
, "") {
107 CachedNetworkParameters
reference(network_params
);
108 return (arg
->bandwidth_estimate_bytes_per_second() ==
109 reference
.bandwidth_estimate_bytes_per_second() &&
110 arg
->bandwidth_estimate_bytes_per_second() ==
111 reference
.bandwidth_estimate_bytes_per_second() &&
112 arg
->max_bandwidth_estimate_bytes_per_second() ==
113 reference
.max_bandwidth_estimate_bytes_per_second() &&
114 arg
->max_bandwidth_timestamp_seconds() ==
115 reference
.max_bandwidth_timestamp_seconds() &&
116 arg
->min_rtt_ms() == reference
.min_rtt_ms() &&
117 arg
->previous_connection_state() ==
118 reference
.previous_connection_state());
121 INSTANTIATE_TEST_CASE_P(Tests
, QuicServerSessionTest
,
122 ::testing::ValuesIn(QuicSupportedVersions()));
124 TEST_P(QuicServerSessionTest
, CloseStreamDueToReset
) {
125 // Open a stream, then reset it.
126 // Send two bytes of payload to open it.
127 QuicStreamFrame
data1(kClientDataStreamId1
, false, 0, StringPiece("HT"));
128 session_
->OnStreamFrame(data1
);
129 EXPECT_EQ(1u, session_
->GetNumOpenStreams());
131 // Send a reset (and expect the peer to send a RST in response).
132 QuicRstStreamFrame
rst1(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
133 EXPECT_CALL(*connection_
,
134 SendRstStream(kClientDataStreamId1
, QUIC_RST_ACKNOWLEDGEMENT
, 0));
135 visitor_
->OnRstStream(rst1
);
136 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
138 // Send the same two bytes of payload in a new packet.
139 visitor_
->OnStreamFrame(data1
);
141 // The stream should not be re-opened.
142 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
143 EXPECT_TRUE(connection_
->connected());
146 TEST_P(QuicServerSessionTest
, NeverOpenStreamDueToReset
) {
147 // Send a reset (and expect the peer to send a RST in response).
148 QuicRstStreamFrame
rst1(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
149 EXPECT_CALL(*connection_
,
150 SendRstStream(kClientDataStreamId1
, QUIC_RST_ACKNOWLEDGEMENT
, 0));
151 visitor_
->OnRstStream(rst1
);
152 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
154 // Send two bytes of payload.
155 QuicStreamFrame
data1(kClientDataStreamId1
, false, 0, StringPiece("HT"));
156 visitor_
->OnStreamFrame(data1
);
158 // The stream should never be opened, now that the reset is received.
159 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
160 EXPECT_TRUE(connection_
->connected());
163 TEST_P(QuicServerSessionTest
, AcceptClosedStream
) {
164 // Send (empty) compressed headers followed by two bytes of data.
165 QuicStreamFrame
frame1(kClientDataStreamId1
, false, 0,
166 StringPiece("\1\0\0\0\0\0\0\0HT"));
167 QuicStreamFrame
frame2(kClientDataStreamId2
, false, 0,
168 StringPiece("\2\0\0\0\0\0\0\0HT"));
169 visitor_
->OnStreamFrame(frame1
);
170 visitor_
->OnStreamFrame(frame2
);
171 EXPECT_EQ(2u, session_
->GetNumOpenStreams());
173 // Send a reset (and expect the peer to send a RST in response).
174 QuicRstStreamFrame
rst(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
175 EXPECT_CALL(*connection_
,
176 SendRstStream(kClientDataStreamId1
, QUIC_RST_ACKNOWLEDGEMENT
, 0));
177 visitor_
->OnRstStream(rst
);
179 // If we were tracking, we'd probably want to reject this because it's data
180 // past the reset point of stream 3. As it's a closed stream we just drop the
181 // data on the floor, but accept the packet because it has data for stream 5.
182 QuicStreamFrame
frame3(kClientDataStreamId1
, false, 2, StringPiece("TP"));
183 QuicStreamFrame
frame4(kClientDataStreamId2
, false, 2, StringPiece("TP"));
184 visitor_
->OnStreamFrame(frame3
);
185 visitor_
->OnStreamFrame(frame4
);
186 // The stream should never be opened, now that the reset is received.
187 EXPECT_EQ(1u, session_
->GetNumOpenStreams());
188 EXPECT_TRUE(connection_
->connected());
191 TEST_P(QuicServerSessionTest
, MaxOpenStreams
) {
192 // Test that the server closes the connection if a client attempts to open too
193 // many data streams. The server accepts slightly more than the negotiated
194 // stream limit to deal with rare cases where a client FIN/RST is lost.
196 // The slightly increased stream limit is set during config negotiation. It
197 // should be either an increase of 10 over negotiated limit, or a fixed
198 // percentage scaling, whichever is larger. Test both before continuing.
199 EXPECT_EQ(kMaxStreamsForTest
, session_
->get_max_open_streams());
200 session_
->OnConfigNegotiated();
201 EXPECT_LT(kMaxStreamsMultiplier
* kMaxStreamsForTest
,
202 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
);
203 EXPECT_EQ(kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
,
204 session_
->get_max_open_streams());
205 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
206 QuicStreamId stream_id
= kClientDataStreamId1
;
207 // Open the max configured number of streams, should be no problem.
208 for (size_t i
= 0; i
< kMaxStreamsForTest
; ++i
) {
209 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream(session_
.get(),
214 // Open more streams: server should accept slightly more than the limit.
215 for (size_t i
= 0; i
< kMaxStreamsMinimumIncrement
; ++i
) {
216 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream(session_
.get(),
221 // Now violate the server's internal stream limit.
222 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS
));
224 EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDynamicStream(session_
.get(),
228 TEST_P(QuicServerSessionTest
, MaxOpenStreamsImplicit
) {
229 // Test that the server closes the connection if a client attempts to open too
230 // many data streams implicitly. The server accepts slightly more than the
231 // negotiated stream limit to deal with rare cases where a client FIN/RST is
234 // The slightly increased stream limit is set during config negotiation.
235 EXPECT_EQ(kMaxStreamsForTest
, session_
->get_max_open_streams());
236 session_
->OnConfigNegotiated();
237 EXPECT_LT(kMaxStreamsMultiplier
* kMaxStreamsForTest
,
238 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
);
239 EXPECT_EQ(kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
,
240 session_
->get_max_open_streams());
242 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
243 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream(
244 session_
.get(), kClientDataStreamId1
));
245 // Implicitly open streams up to the server's limit.
246 const int kActualMaxStreams
=
247 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
;
248 const int kMaxValidStreamId
=
249 kClientDataStreamId1
+ (kActualMaxStreams
- 1) * 2;
250 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDynamicStream(
251 session_
.get(), kMaxValidStreamId
));
253 // Opening a further stream will result in connection close.
254 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS
));
255 EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDynamicStream(
256 session_
.get(), kMaxValidStreamId
+ 2));
259 TEST_P(QuicServerSessionTest
, GetEvenIncomingError
) {
260 // Incoming streams on the server session must be odd.
261 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_INVALID_STREAM_ID
));
263 QuicServerSessionPeer::GetIncomingDynamicStream(session_
.get(), 4));
266 TEST_P(QuicServerSessionTest
, GetStreamDisconnected
) {
267 // Don't create new streams if the connection is disconnected.
268 QuicConnectionPeer::CloseConnection(connection_
);
270 QuicServerSessionPeer::GetIncomingDynamicStream(session_
.get(), 5),
271 "ShouldCreateIncomingDynamicStream called when disconnected");
274 TEST_P(QuicServerSessionTest
, SetFecProtectionFromConfig
) {
275 ValueRestore
<bool> old_flag(&FLAGS_enable_quic_fec
, true);
277 // Set received config to have FEC connection option.
279 copt
.push_back(kFHDR
);
280 QuicConfigPeer::SetReceivedConnectionOptions(session_
->config(), copt
);
281 session_
->OnConfigNegotiated();
283 // Verify that headers stream is always protected and data streams are
284 // optionally protected.
285 EXPECT_EQ(FEC_PROTECT_ALWAYS
, QuicSpdySessionPeer::GetHeadersStream(
286 session_
.get())->fec_policy());
287 ReliableQuicStream
* stream
= QuicServerSessionPeer::GetIncomingDynamicStream(
288 session_
.get(), kClientDataStreamId1
);
290 EXPECT_EQ(FEC_PROTECT_OPTIONAL
, stream
->fec_policy());
293 class MockQuicCryptoServerStream
: public QuicCryptoServerStream
{
295 explicit MockQuicCryptoServerStream(
296 const QuicCryptoServerConfig
* crypto_config
, QuicSession
* session
)
297 : QuicCryptoServerStream(crypto_config
, session
) {}
298 ~MockQuicCryptoServerStream() override
{}
300 MOCK_METHOD1(SendServerConfigUpdate
,
301 void(const CachedNetworkParameters
* cached_network_parameters
));
304 DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream
);
307 TEST_P(QuicServerSessionTest
, BandwidthEstimates
) {
308 // Test that bandwidth estimate updates are sent to the client, only when
309 // bandwidth resumption is enabled, the bandwidth estimate has changed
310 // sufficiently, enough time has passed,
311 // and we don't have any other data to write.
313 // Client has sent kBWRE connection option to trigger bandwidth resumption.
315 copt
.push_back(kBWRE
);
316 QuicConfigPeer::SetReceivedConnectionOptions(session_
->config(), copt
);
317 session_
->OnConfigNegotiated();
319 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_
.get()));
321 int32 bandwidth_estimate_kbytes_per_second
= 123;
322 int32 max_bandwidth_estimate_kbytes_per_second
= 134;
323 int32 max_bandwidth_estimate_timestamp
= 1122334455;
324 const string serving_region
= "not a real region";
325 session_
->set_serving_region(serving_region
);
327 MockQuicCryptoServerStream
* crypto_stream
=
328 new MockQuicCryptoServerStream(&crypto_config_
, session_
.get());
329 QuicServerSessionPeer::SetCryptoStream(session_
.get(), crypto_stream
);
331 // Set some initial bandwidth values.
332 QuicSentPacketManager
* sent_packet_manager
=
333 QuicConnectionPeer::GetSentPacketManager(session_
->connection());
334 QuicSustainedBandwidthRecorder
& bandwidth_recorder
=
335 QuicSentPacketManagerPeer::GetBandwidthRecorder(sent_packet_manager
);
336 // Seed an rtt measurement equal to the initial default rtt.
337 RttStats
* rtt_stats
=
338 QuicSentPacketManagerPeer::GetRttStats(sent_packet_manager
);
339 rtt_stats
->UpdateRtt(QuicTime::Delta::FromMicroseconds(
340 rtt_stats
->initial_rtt_us()), QuicTime::Delta::Zero(), QuicTime::Zero());
341 QuicSustainedBandwidthRecorderPeer::SetBandwidthEstimate(
342 &bandwidth_recorder
, bandwidth_estimate_kbytes_per_second
);
343 QuicSustainedBandwidthRecorderPeer::SetMaxBandwidthEstimate(
344 &bandwidth_recorder
, max_bandwidth_estimate_kbytes_per_second
,
345 max_bandwidth_estimate_timestamp
);
346 // Queue up some pending data.
347 session_
->MarkConnectionLevelWriteBlocked(
348 kCryptoStreamId
, QuicWriteBlockedList::kHighestPriority
);
349 EXPECT_TRUE(session_
->HasDataToWrite());
351 // There will be no update sent yet - not enough time has passed.
352 QuicTime now
= QuicTime::Zero();
353 session_
->OnCongestionWindowChange(now
);
355 // Bandwidth estimate has now changed sufficiently but not enough time has
356 // passed to send a Server Config Update.
357 bandwidth_estimate_kbytes_per_second
=
358 bandwidth_estimate_kbytes_per_second
* 1.6;
359 session_
->OnCongestionWindowChange(now
);
361 // Bandwidth estimate has now changed sufficiently and enough time has passed,
362 // but not enough packets have been sent.
364 sent_packet_manager
->GetRttStats()->smoothed_rtt().ToMilliseconds();
365 now
= now
.Add(QuicTime::Delta::FromMilliseconds(
366 kMinIntervalBetweenServerConfigUpdatesRTTs
* srtt_ms
));
367 session_
->OnCongestionWindowChange(now
);
369 // The connection no longer has pending data to be written.
370 session_
->OnCanWrite();
371 EXPECT_FALSE(session_
->HasDataToWrite());
372 session_
->OnCongestionWindowChange(now
);
374 // Bandwidth estimate has now changed sufficiently, enough time has passed,
375 // and enough packets have been sent.
376 QuicConnectionPeer::SetPacketNumberOfLastSentPacket(
377 session_
->connection(), kMinPacketsBetweenServerConfigUpdates
);
379 // Verify that the proto has exactly the values we expect.
380 CachedNetworkParameters expected_network_params
;
381 expected_network_params
.set_bandwidth_estimate_bytes_per_second(
382 bandwidth_recorder
.BandwidthEstimate().ToBytesPerSecond());
383 expected_network_params
.set_max_bandwidth_estimate_bytes_per_second(
384 bandwidth_recorder
.MaxBandwidthEstimate().ToBytesPerSecond());
385 expected_network_params
.set_max_bandwidth_timestamp_seconds(
386 bandwidth_recorder
.MaxBandwidthTimestamp());
387 expected_network_params
.set_min_rtt_ms(session_
->connection()
388 ->sent_packet_manager()
392 expected_network_params
.set_previous_connection_state(
393 CachedNetworkParameters::CONGESTION_AVOIDANCE
);
394 expected_network_params
.set_timestamp(
395 session_
->connection()->clock()->WallNow().ToUNIXSeconds());
396 expected_network_params
.set_serving_region(serving_region
);
398 EXPECT_CALL(*crypto_stream
,
399 SendServerConfigUpdate(EqualsProto(expected_network_params
)))
401 EXPECT_CALL(*connection_
, OnSendConnectionState(_
)).Times(1);
402 session_
->OnCongestionWindowChange(now
);
405 TEST_P(QuicServerSessionTest
, BandwidthResumptionExperiment
) {
406 // Test that if a client provides a CachedNetworkParameters with the same
407 // serving region as the current server, and which was made within an hour of
408 // now, that this data is passed down to the send algorithm.
410 // Client has sent kBWRE connection option to trigger bandwidth resumption.
412 copt
.push_back(kBWRE
);
413 QuicConfigPeer::SetReceivedConnectionOptions(session_
->config(), copt
);
415 const string kTestServingRegion
= "a serving region";
416 session_
->set_serving_region(kTestServingRegion
);
418 // Set the time to be one hour + one second from the 0 baseline.
419 connection_
->AdvanceTime(
420 QuicTime::Delta::FromSeconds(kNumSecondsPerHour
+ 1));
422 QuicCryptoServerStream
* crypto_stream
=
423 static_cast<QuicCryptoServerStream
*>(
424 QuicSessionPeer::GetCryptoStream(session_
.get()));
426 // No effect if no CachedNetworkParameters provided.
427 EXPECT_CALL(*connection_
, ResumeConnectionState(_
, _
)).Times(0);
428 session_
->OnConfigNegotiated();
430 // No effect if CachedNetworkParameters provided, but different serving
432 CachedNetworkParameters cached_network_params
;
433 cached_network_params
.set_bandwidth_estimate_bytes_per_second(1);
434 cached_network_params
.set_serving_region("different serving region");
435 crypto_stream
->set_previous_cached_network_params(cached_network_params
);
436 EXPECT_CALL(*connection_
, ResumeConnectionState(_
, _
)).Times(0);
437 session_
->OnConfigNegotiated();
439 // Same serving region, but timestamp is too old, should have no effect.
440 cached_network_params
.set_serving_region(kTestServingRegion
);
441 cached_network_params
.set_timestamp(0);
442 crypto_stream
->set_previous_cached_network_params(cached_network_params
);
443 EXPECT_CALL(*connection_
, ResumeConnectionState(_
, _
)).Times(0);
444 session_
->OnConfigNegotiated();
446 // Same serving region, and timestamp is recent: estimate is stored.
447 cached_network_params
.set_timestamp(
448 connection_
->clock()->WallNow().ToUNIXSeconds());
449 crypto_stream
->set_previous_cached_network_params(cached_network_params
);
450 EXPECT_CALL(*connection_
, ResumeConnectionState(_
, _
)).Times(1);
451 session_
->OnConfigNegotiated();
454 TEST_P(QuicServerSessionTest
, BandwidthMaxEnablesResumption
) {
456 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_
.get()));
458 // Client has sent kBWMX connection option to trigger bandwidth resumption.
460 copt
.push_back(kBWMX
);
461 QuicConfigPeer::SetReceivedConnectionOptions(session_
->config(), copt
);
462 session_
->OnConfigNegotiated();
464 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_
.get()));
467 TEST_P(QuicServerSessionTest
, NoBandwidthResumptionByDefault
) {
469 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_
.get()));
470 session_
->OnConfigNegotiated();
472 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_
.get()));