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_sustained_bandwidth_recorder_peer.h"
20 #include "net/quic/test_tools/quic_test_utils.h"
21 #include "net/test/gtest_util.h"
22 #include "net/tools/quic/quic_spdy_server_stream.h"
23 #include "net/tools/quic/test_tools/quic_test_utils.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 using __gnu_cxx::vector
;
28 using net::test::MockConnection
;
29 using net::test::QuicConfigPeer
;
30 using net::test::QuicConnectionPeer
;
31 using net::test::QuicDataStreamPeer
;
32 using net::test::QuicSentPacketManagerPeer
;
33 using net::test::QuicSessionPeer
;
34 using net::test::QuicSustainedBandwidthRecorderPeer
;
35 using net::test::SupportedVersions
;
36 using net::test::ValueRestore
;
37 using net::test::kClientDataStreamId1
;
38 using net::test::kClientDataStreamId2
;
39 using net::test::kClientDataStreamId3
;
41 using testing::StrictMock
;
48 class QuicServerSessionPeer
{
50 static QuicDataStream
* GetIncomingDataStream(
51 QuicServerSession
* s
, QuicStreamId id
) {
52 return s
->GetIncomingDataStream(id
);
54 static void SetCryptoStream(QuicServerSession
* s
,
55 QuicCryptoServerStream
* crypto_stream
) {
56 s
->crypto_stream_
.reset(crypto_stream
);
58 static bool IsBandwidthResumptionEnabled(QuicServerSession
* s
) {
59 return s
->bandwidth_resumption_enabled_
;
65 const size_t kMaxStreamsForTest
= 10;
67 class QuicServerSessionTest
: public ::testing::TestWithParam
<QuicVersion
> {
69 QuicServerSessionTest()
70 : crypto_config_(QuicCryptoServerConfig::TESTING
,
71 QuicRandom::GetInstance()) {
72 config_
.SetMaxStreamsPerConnection(kMaxStreamsForTest
,
74 config_
.SetInitialStreamFlowControlWindowToSend(
75 kInitialStreamFlowControlWindowForTest
);
76 config_
.SetInitialSessionFlowControlWindowToSend(
77 kInitialSessionFlowControlWindowForTest
);
79 connection_
= new StrictMock
<MockConnection
>(Perspective::IS_SERVER
,
80 SupportedVersions(GetParam()));
82 new QuicServerSession(config_
, connection_
, &owner_
, &crypto_config_
));
84 handshake_message_
.reset(crypto_config_
.AddDefaultConfig(
85 QuicRandom::GetInstance(), &clock
,
86 QuicCryptoServerConfig::ConfigOptions()));
87 session_
->Initialize();
88 visitor_
= QuicConnectionPeer::GetVisitor(connection_
);
91 StrictMock
<MockQuicServerSessionVisitor
> owner_
;
92 StrictMock
<MockConnection
>* connection_
;
94 QuicCryptoServerConfig crypto_config_
;
95 scoped_ptr
<QuicServerSession
> session_
;
96 scoped_ptr
<CryptoHandshakeMessage
> handshake_message_
;
97 QuicConnectionVisitorInterface
* visitor_
;
100 // Compares CachedNetworkParameters.
101 MATCHER_P(EqualsProto
, network_params
, "") {
102 CachedNetworkParameters
reference(network_params
);
103 return (arg
->bandwidth_estimate_bytes_per_second() ==
104 reference
.bandwidth_estimate_bytes_per_second() &&
105 arg
->bandwidth_estimate_bytes_per_second() ==
106 reference
.bandwidth_estimate_bytes_per_second() &&
107 arg
->max_bandwidth_estimate_bytes_per_second() ==
108 reference
.max_bandwidth_estimate_bytes_per_second() &&
109 arg
->max_bandwidth_timestamp_seconds() ==
110 reference
.max_bandwidth_timestamp_seconds() &&
111 arg
->min_rtt_ms() == reference
.min_rtt_ms() &&
112 arg
->previous_connection_state() ==
113 reference
.previous_connection_state());
116 INSTANTIATE_TEST_CASE_P(Tests
, QuicServerSessionTest
,
117 ::testing::ValuesIn(QuicSupportedVersions()));
119 TEST_P(QuicServerSessionTest
, CloseStreamDueToReset
) {
120 // Open a stream, then reset it.
121 // Send two bytes of payload to open it.
122 QuicStreamFrame
data1(kClientDataStreamId1
, false, 0, StringPiece("HT"));
123 vector
<QuicStreamFrame
> frames
;
124 frames
.push_back(data1
);
125 session_
->OnStreamFrames(frames
);
126 EXPECT_EQ(1u, session_
->GetNumOpenStreams());
128 // Send a reset (and expect the peer to send a RST in response).
129 QuicRstStreamFrame
rst1(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
130 EXPECT_CALL(*connection_
,
131 SendRstStream(kClientDataStreamId1
, QUIC_RST_ACKNOWLEDGEMENT
, 0));
132 visitor_
->OnRstStream(rst1
);
133 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
135 // Send the same two bytes of payload in a new packet.
136 visitor_
->OnStreamFrames(frames
);
138 // The stream should not be re-opened.
139 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
140 EXPECT_TRUE(connection_
->connected());
143 TEST_P(QuicServerSessionTest
, NeverOpenStreamDueToReset
) {
144 // Send a reset (and expect the peer to send a RST in response).
145 QuicRstStreamFrame
rst1(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
146 EXPECT_CALL(*connection_
,
147 SendRstStream(kClientDataStreamId1
, QUIC_RST_ACKNOWLEDGEMENT
, 0));
148 visitor_
->OnRstStream(rst1
);
149 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
151 // Send two bytes of payload.
152 QuicStreamFrame
data1(kClientDataStreamId1
, false, 0, StringPiece("HT"));
153 vector
<QuicStreamFrame
> frames
;
154 frames
.push_back(data1
);
155 visitor_
->OnStreamFrames(frames
);
157 // The stream should never be opened, now that the reset is received.
158 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
159 EXPECT_TRUE(connection_
->connected());
162 TEST_P(QuicServerSessionTest
, AcceptClosedStream
) {
163 vector
<QuicStreamFrame
> frames
;
164 // Send (empty) compressed headers followed by two bytes of data.
165 frames
.push_back(QuicStreamFrame(kClientDataStreamId1
, false, 0,
166 StringPiece("\1\0\0\0\0\0\0\0HT")));
167 frames
.push_back(QuicStreamFrame(kClientDataStreamId2
, false, 0,
168 StringPiece("\2\0\0\0\0\0\0\0HT")));
169 visitor_
->OnStreamFrames(frames
);
170 EXPECT_EQ(2u, session_
->GetNumOpenStreams());
172 // Send a reset (and expect the peer to send a RST in response).
173 QuicRstStreamFrame
rst(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
174 EXPECT_CALL(*connection_
,
175 SendRstStream(kClientDataStreamId1
, QUIC_RST_ACKNOWLEDGEMENT
, 0));
176 visitor_
->OnRstStream(rst
);
178 // If we were tracking, we'd probably want to reject this because it's data
179 // past the reset point of stream 3. As it's a closed stream we just drop the
180 // data on the floor, but accept the packet because it has data for stream 5.
183 QuicStreamFrame(kClientDataStreamId1
, false, 2, StringPiece("TP")));
185 QuicStreamFrame(kClientDataStreamId2
, false, 2, StringPiece("TP")));
186 visitor_
->OnStreamFrames(frames
);
187 // The stream should never be opened, now that the reset is received.
188 EXPECT_EQ(1u, session_
->GetNumOpenStreams());
189 EXPECT_TRUE(connection_
->connected());
192 TEST_P(QuicServerSessionTest
, MaxOpenStreams
) {
193 // Test that the server closes the connection if a client attempts to open too
194 // many data streams. The server accepts slightly more than the negotiated
195 // stream limit to deal with rare cases where a client FIN/RST is lost.
197 // The slightly increased stream limit is set during config negotiation. It
198 // should be either an increase of 10 over negotiated limit, or a fixed
199 // percentage scaling, whichever is larger. Test both before continuing.
200 EXPECT_EQ(kMaxStreamsForTest
, session_
->get_max_open_streams());
201 session_
->OnConfigNegotiated();
202 EXPECT_LT(kMaxStreamsMultiplier
* kMaxStreamsForTest
,
203 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
);
204 EXPECT_EQ(kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
,
205 session_
->get_max_open_streams());
206 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
207 QuicStreamId stream_id
= kClientDataStreamId1
;
208 // Open the max configured number of streams, should be no problem.
209 for (size_t i
= 0; i
< kMaxStreamsForTest
; ++i
) {
210 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(session_
.get(),
215 // Open more streams: server should accept slightly more than the limit.
216 for (size_t i
= 0; i
< kMaxStreamsMinimumIncrement
; ++i
) {
217 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(session_
.get(),
222 // Now violate the server's internal stream limit.
223 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS
));
226 QuicServerSessionPeer::GetIncomingDataStream(session_
.get(), stream_id
));
229 TEST_P(QuicServerSessionTest
, MaxOpenStreamsImplicit
) {
230 // Test that the server closes the connection if a client attempts to open too
231 // many data streams implicitly. The server accepts slightly more than the
232 // negotiated stream limit to deal with rare cases where a client FIN/RST is
235 // The slightly increased stream limit is set during config negotiation.
236 EXPECT_EQ(kMaxStreamsForTest
, session_
->get_max_open_streams());
237 session_
->OnConfigNegotiated();
238 EXPECT_LT(kMaxStreamsMultiplier
* kMaxStreamsForTest
,
239 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
);
240 EXPECT_EQ(kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
,
241 session_
->get_max_open_streams());
243 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
244 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
245 session_
.get(), kClientDataStreamId1
));
246 // Implicitly open streams up to the server's limit.
247 const int kActualMaxStreams
=
248 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
;
249 const int kMaxValidStreamId
=
250 kClientDataStreamId1
+ (kActualMaxStreams
- 1) * 2;
251 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
252 session_
.get(), kMaxValidStreamId
));
254 // Opening a further stream will result in connection close.
255 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS
));
256 EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDataStream(
257 session_
.get(), kMaxValidStreamId
+ 2));
260 TEST_P(QuicServerSessionTest
, GetEvenIncomingError
) {
261 // Incoming streams on the server session must be odd.
262 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_INVALID_STREAM_ID
));
264 QuicServerSessionPeer::GetIncomingDataStream(session_
.get(), 4));
267 TEST_P(QuicServerSessionTest
, GetStreamDisconnected
) {
268 // Don't create new streams if the connection is disconnected.
269 QuicConnectionPeer::CloseConnection(connection_
);
270 EXPECT_DFATAL(QuicServerSessionPeer::GetIncomingDataStream(session_
.get(), 5),
271 "ShouldCreateIncomingDataStream 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
,
286 QuicSessionPeer::GetHeadersStream(session_
.get())->fec_policy());
287 QuicDataStream
* stream
= QuicServerSessionPeer::GetIncomingDataStream(
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_
->MarkWriteBlocked(kCryptoStreamId
,
348 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::SetSequenceNumberOfLastSentPacket(
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, that this data is passed down to the
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 QuicCryptoServerStream
* crypto_stream
=
419 static_cast<QuicCryptoServerStream
*>(
420 QuicSessionPeer::GetCryptoStream(session_
.get()));
422 // No effect if no CachedNetworkParameters provided.
423 EXPECT_CALL(*connection_
, ResumeConnectionState(_
, _
)).Times(0);
424 session_
->OnConfigNegotiated();
426 // No effect if CachedNetworkParameters provided, but different serving
428 CachedNetworkParameters cached_network_params
;
429 cached_network_params
.set_bandwidth_estimate_bytes_per_second(1);
430 cached_network_params
.set_serving_region("different serving region");
431 crypto_stream
->set_previous_cached_network_params(cached_network_params
);
432 EXPECT_CALL(*connection_
, ResumeConnectionState(_
, _
)).Times(0);
433 session_
->OnConfigNegotiated();
435 // Same serving region results in CachedNetworkParameters being stored.
436 cached_network_params
.set_serving_region(kTestServingRegion
);
437 crypto_stream
->set_previous_cached_network_params(cached_network_params
);
438 EXPECT_CALL(*connection_
, ResumeConnectionState(_
, _
)).Times(1);
439 session_
->OnConfigNegotiated();
442 TEST_P(QuicServerSessionTest
, BandwidthMaxEnablesResumption
) {
444 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_
.get()));
446 // Client has sent kBWMX connection option to trigger bandwidth resumption.
448 copt
.push_back(kBWMX
);
449 QuicConfigPeer::SetReceivedConnectionOptions(session_
->config(), copt
);
450 session_
->OnConfigNegotiated();
452 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_
.get()));
455 TEST_P(QuicServerSessionTest
, NoBandwidthResumptionByDefault
) {
457 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_
.get()));
458 session_
->OnConfigNegotiated();
460 QuicServerSessionPeer::IsBandwidthResumptionEnabled(session_
.get()));