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/cached_network_parameters.h"
8 #include "net/quic/crypto/quic_crypto_server_config.h"
9 #include "net/quic/crypto/quic_random.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/tools/quic/quic_spdy_server_stream.h"
22 #include "net/tools/quic/test_tools/quic_test_utils.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using __gnu_cxx::vector
;
27 using net::test::MockConnection
;
28 using net::test::QuicConfigPeer
;
29 using net::test::QuicConnectionPeer
;
30 using net::test::QuicDataStreamPeer
;
31 using net::test::QuicSentPacketManagerPeer
;
32 using net::test::QuicSessionPeer
;
33 using net::test::QuicSustainedBandwidthRecorderPeer
;
34 using net::test::SupportedVersions
;
35 using net::test::ValueRestore
;
36 using net::test::kClientDataStreamId1
;
37 using net::test::kClientDataStreamId2
;
38 using net::test::kClientDataStreamId3
;
39 using net::test::kClientDataStreamId4
;
41 using testing::StrictMock
;
48 class QuicServerSessionPeer
{
50 static QuicDataStream
* GetIncomingDataStream(
51 QuicServerSession
* s
, QuicStreamId id
) {
52 return s
->GetIncomingDataStream(id
);
54 static QuicDataStream
* GetDataStream(QuicServerSession
* s
, QuicStreamId id
) {
55 return s
->GetDataStream(id
);
57 static void SetCryptoStream(QuicServerSession
* s
,
58 QuicCryptoServerStream
* crypto_stream
) {
59 s
->crypto_stream_
.reset(crypto_stream
);
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
);
80 new StrictMock
<MockConnection
>(true, SupportedVersions(GetParam()));
81 session_
.reset(new QuicServerSession(config_
, connection_
, &owner_
));
83 handshake_message_
.reset(crypto_config_
.AddDefaultConfig(
84 QuicRandom::GetInstance(), &clock
,
85 QuicCryptoServerConfig::ConfigOptions()));
86 session_
->InitializeSession(crypto_config_
);
87 visitor_
= QuicConnectionPeer::GetVisitor(connection_
);
90 QuicVersion
version() const { return connection_
->version(); }
92 StrictMock
<MockQuicServerSessionVisitor
> owner_
;
93 StrictMock
<MockConnection
>* connection_
;
95 QuicCryptoServerConfig crypto_config_
;
96 scoped_ptr
<QuicServerSession
> session_
;
97 scoped_ptr
<CryptoHandshakeMessage
> handshake_message_
;
98 QuicConnectionVisitorInterface
* visitor_
;
101 // Compares CachedNetworkParameters.
102 MATCHER_P(EqualsProto
, network_params
, "") {
103 CachedNetworkParameters
reference(network_params
);
104 return (arg
->bandwidth_estimate_bytes_per_second() ==
105 reference
.bandwidth_estimate_bytes_per_second() &&
106 arg
->bandwidth_estimate_bytes_per_second() ==
107 reference
.bandwidth_estimate_bytes_per_second() &&
108 arg
->max_bandwidth_estimate_bytes_per_second() ==
109 reference
.max_bandwidth_estimate_bytes_per_second() &&
110 arg
->max_bandwidth_timestamp_seconds() ==
111 reference
.max_bandwidth_timestamp_seconds() &&
112 arg
->min_rtt_ms() == reference
.min_rtt_ms() &&
113 arg
->previous_connection_state() ==
114 reference
.previous_connection_state());
117 INSTANTIATE_TEST_CASE_P(Tests
, QuicServerSessionTest
,
118 ::testing::ValuesIn(QuicSupportedVersions()));
120 TEST_P(QuicServerSessionTest
, CloseStreamDueToReset
) {
121 // Open a stream, then reset it.
122 // Send two bytes of payload to open it.
123 QuicStreamFrame
data1(kClientDataStreamId1
, false, 0, MakeIOVector("HT"));
124 vector
<QuicStreamFrame
> frames
;
125 frames
.push_back(data1
);
126 session_
->OnStreamFrames(frames
);
127 EXPECT_EQ(1u, session_
->GetNumOpenStreams());
129 // Send a reset (and expect the peer to send a RST in response).
130 QuicRstStreamFrame
rst1(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
131 EXPECT_CALL(*connection_
,
132 SendRstStream(kClientDataStreamId1
, QUIC_RST_ACKNOWLEDGEMENT
, 0));
133 visitor_
->OnRstStream(rst1
);
134 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
136 // Send the same two bytes of payload in a new packet.
137 visitor_
->OnStreamFrames(frames
);
139 // The stream should not be re-opened.
140 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
141 EXPECT_TRUE(connection_
->connected());
144 TEST_P(QuicServerSessionTest
, NeverOpenStreamDueToReset
) {
145 // Send a reset (and expect the peer to send a RST in response).
146 QuicRstStreamFrame
rst1(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
147 EXPECT_CALL(*connection_
,
148 SendRstStream(kClientDataStreamId1
, QUIC_RST_ACKNOWLEDGEMENT
, 0));
149 visitor_
->OnRstStream(rst1
);
150 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
152 // Send two bytes of payload.
153 QuicStreamFrame
data1(kClientDataStreamId1
, false, 0, MakeIOVector("HT"));
154 vector
<QuicStreamFrame
> frames
;
155 frames
.push_back(data1
);
156 visitor_
->OnStreamFrames(frames
);
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 vector
<QuicStreamFrame
> frames
;
165 // Send (empty) compressed headers followed by two bytes of data.
166 frames
.push_back(QuicStreamFrame(kClientDataStreamId1
, false, 0,
167 MakeIOVector("\1\0\0\0\0\0\0\0HT")));
168 frames
.push_back(QuicStreamFrame(kClientDataStreamId2
, false, 0,
169 MakeIOVector("\2\0\0\0\0\0\0\0HT")));
170 visitor_
->OnStreamFrames(frames
);
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.
184 QuicStreamFrame(kClientDataStreamId1
, false, 2, MakeIOVector("TP")));
186 QuicStreamFrame(kClientDataStreamId2
, false, 2, MakeIOVector("TP")));
187 visitor_
->OnStreamFrames(frames
);
188 // The stream should never be opened, now that the reset is received.
189 EXPECT_EQ(1u, session_
->GetNumOpenStreams());
190 EXPECT_TRUE(connection_
->connected());
193 TEST_P(QuicServerSessionTest
, MaxOpenStreams
) {
194 // Test that the server closes the connection if a client attempts to open too
195 // many data streams. The server accepts slightly more than the negotiated
196 // stream limit to deal with rare cases where a client FIN/RST is lost.
198 // The slightly increased stream limit is set during config negotiation. It
199 // should be either an increase of 10 over negotiated limit, or a fixed
200 // percentage scaling, whichever is larger. Test both before continuing.
201 EXPECT_EQ(kMaxStreamsForTest
, session_
->get_max_open_streams());
202 session_
->OnConfigNegotiated();
203 EXPECT_LT(kMaxStreamsMultiplier
* kMaxStreamsForTest
,
204 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
);
205 EXPECT_EQ(kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
,
206 session_
->get_max_open_streams());
207 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
208 QuicStreamId stream_id
= kClientDataStreamId1
;
209 // Open the max configured number of streams, should be no problem.
210 for (size_t i
= 0; i
< kMaxStreamsForTest
; ++i
) {
211 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(session_
.get(),
216 // Open more streams: server should accept slightly more than the limit.
217 for (size_t i
= 0; i
< kMaxStreamsMinimumIncrement
; ++i
) {
218 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(session_
.get(),
223 // Now violate the server's internal stream limit.
224 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS
));
227 QuicServerSessionPeer::GetIncomingDataStream(session_
.get(), stream_id
));
230 TEST_P(QuicServerSessionTest
, MaxOpenStreamsImplicit
) {
231 // Test that the server closes the connection if a client attempts to open too
232 // many data streams implicitly. The server accepts slightly more than the
233 // negotiated stream limit to deal with rare cases where a client FIN/RST is
236 // The slightly increased stream limit is set during config negotiation.
237 EXPECT_EQ(kMaxStreamsForTest
, session_
->get_max_open_streams());
238 session_
->OnConfigNegotiated();
239 EXPECT_LT(kMaxStreamsMultiplier
* kMaxStreamsForTest
,
240 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
);
241 EXPECT_EQ(kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
,
242 session_
->get_max_open_streams());
244 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
245 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
246 session_
.get(), kClientDataStreamId1
));
247 // Implicitly open streams up to the server's limit.
248 const int kActualMaxStreams
=
249 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
;
250 const int kMaxValidStreamId
=
251 kClientDataStreamId1
+ (kActualMaxStreams
- 1) * 2;
252 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
253 session_
.get(), kMaxValidStreamId
));
255 // Opening a further stream will result in connection close.
256 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS
));
257 EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDataStream(
258 session_
.get(), kMaxValidStreamId
+ 2));
261 TEST_P(QuicServerSessionTest
, GetEvenIncomingError
) {
262 // Incoming streams on the server session must be odd.
263 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_INVALID_STREAM_ID
));
265 QuicServerSessionPeer::GetIncomingDataStream(session_
.get(), 4));
268 TEST_P(QuicServerSessionTest
, SetFecProtectionFromConfig
) {
269 ValueRestore
<bool> old_flag(&FLAGS_enable_quic_fec
, true);
271 // Set received config to have FEC connection option.
273 copt
.push_back(kFHDR
);
274 QuicConfigPeer::SetReceivedConnectionOptions(session_
->config(), copt
);
275 session_
->OnConfigNegotiated();
277 // Verify that headers stream is always protected and data streams are
278 // optionally protected.
279 EXPECT_EQ(FEC_PROTECT_ALWAYS
,
280 QuicSessionPeer::GetHeadersStream(session_
.get())->fec_policy());
281 QuicDataStream
* stream
= QuicServerSessionPeer::GetIncomingDataStream(
282 session_
.get(), kClientDataStreamId1
);
284 EXPECT_EQ(FEC_PROTECT_OPTIONAL
, stream
->fec_policy());
287 class MockQuicCryptoServerStream
: public QuicCryptoServerStream
{
289 explicit MockQuicCryptoServerStream(
290 const QuicCryptoServerConfig
& crypto_config
, QuicSession
* session
)
291 : QuicCryptoServerStream(crypto_config
, session
) {}
292 ~MockQuicCryptoServerStream() override
{}
294 MOCK_METHOD1(SendServerConfigUpdate
,
295 void(const CachedNetworkParameters
* cached_network_parameters
));
298 DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream
);
301 TEST_P(QuicServerSessionTest
, BandwidthEstimates
) {
302 // Test that bandwidth estimate updates are sent to the client, only after the
303 // bandwidth estimate has changes sufficiently, and enough time has passed,
304 // and we don't have any other data to write.
306 int32 bandwidth_estimate_kbytes_per_second
= 123;
307 int32 max_bandwidth_estimate_kbytes_per_second
= 134;
308 int32 max_bandwidth_estimate_timestamp
= 1122334455;
309 const string serving_region
= "not a real region";
310 session_
->set_serving_region(serving_region
);
312 MockQuicCryptoServerStream
* crypto_stream
=
313 new MockQuicCryptoServerStream(crypto_config_
, session_
.get());
314 QuicServerSessionPeer::SetCryptoStream(session_
.get(), crypto_stream
);
316 // Set some initial bandwidth values.
317 QuicSentPacketManager
* sent_packet_manager
=
318 QuicConnectionPeer::GetSentPacketManager(session_
->connection());
319 QuicSustainedBandwidthRecorder
& bandwidth_recorder
=
320 QuicSentPacketManagerPeer::GetBandwidthRecorder(sent_packet_manager
);
321 // Seed an rtt measurement equal to the initial default rtt.
322 RttStats
* rtt_stats
=
323 QuicSentPacketManagerPeer::GetRttStats(sent_packet_manager
);
324 rtt_stats
->UpdateRtt(QuicTime::Delta::FromMicroseconds(
325 rtt_stats
->initial_rtt_us()), QuicTime::Delta::Zero(), QuicTime::Zero());
326 QuicSustainedBandwidthRecorderPeer::SetBandwidthEstimate(
327 &bandwidth_recorder
, bandwidth_estimate_kbytes_per_second
);
328 QuicSustainedBandwidthRecorderPeer::SetMaxBandwidthEstimate(
329 &bandwidth_recorder
, max_bandwidth_estimate_kbytes_per_second
,
330 max_bandwidth_estimate_timestamp
);
331 // Queue up some pending data.
332 session_
->MarkWriteBlocked(kCryptoStreamId
,
333 QuicWriteBlockedList::kHighestPriority
);
334 EXPECT_TRUE(session_
->HasDataToWrite());
336 // There will be no update sent yet - not enough time has passed.
337 QuicTime now
= QuicTime::Zero();
338 session_
->OnCongestionWindowChange(now
);
340 // Bandwidth estimate has now changed sufficiently but not enough time has
341 // passed to send a Server Config Update.
342 bandwidth_estimate_kbytes_per_second
=
343 bandwidth_estimate_kbytes_per_second
* 1.6;
344 session_
->OnCongestionWindowChange(now
);
346 // Bandwidth estimate has now changed sufficiently and enough time has passed,
347 // but not enough packets have been sent.
349 sent_packet_manager
->GetRttStats()->smoothed_rtt().ToMilliseconds();
350 now
= now
.Add(QuicTime::Delta::FromMilliseconds(
351 kMinIntervalBetweenServerConfigUpdatesRTTs
* srtt_ms
));
352 session_
->OnCongestionWindowChange(now
);
354 // The connection no longer has pending data to be written.
355 session_
->OnCanWrite();
356 EXPECT_FALSE(session_
->HasDataToWrite());
357 session_
->OnCongestionWindowChange(now
);
359 // Bandwidth estimate has now changed sufficiently, enough time has passed,
360 // and enough packets have been sent.
361 QuicConnectionPeer::SetSequenceNumberOfLastSentPacket(
362 session_
->connection(), kMinPacketsBetweenServerConfigUpdates
);
364 // Verify that the proto has exactly the values we expect.
365 CachedNetworkParameters expected_network_params
;
366 expected_network_params
.set_bandwidth_estimate_bytes_per_second(
367 bandwidth_recorder
.BandwidthEstimate().ToBytesPerSecond());
368 expected_network_params
.set_max_bandwidth_estimate_bytes_per_second(
369 bandwidth_recorder
.MaxBandwidthEstimate().ToBytesPerSecond());
370 expected_network_params
.set_max_bandwidth_timestamp_seconds(
371 bandwidth_recorder
.MaxBandwidthTimestamp());
372 expected_network_params
.set_min_rtt_ms(session_
->connection()
373 ->sent_packet_manager()
377 expected_network_params
.set_previous_connection_state(
378 CachedNetworkParameters::CONGESTION_AVOIDANCE
);
379 expected_network_params
.set_timestamp(
380 session_
->connection()->clock()->WallNow().ToUNIXSeconds());
381 expected_network_params
.set_serving_region(serving_region
);
383 EXPECT_CALL(*crypto_stream
,
384 SendServerConfigUpdate(EqualsProto(expected_network_params
)))
386 session_
->OnCongestionWindowChange(now
);
389 TEST_P(QuicServerSessionTest
, BandwidthResumptionExperiment
) {
390 ValueRestore
<bool> old_flag(
391 &FLAGS_quic_enable_bandwidth_resumption_experiment
, true);
393 // Test that if a client provides a CachedNetworkParameters with the same
394 // serving region as the current server, that this data is passed down to the
397 // Client has sent kBWRE connection option to trigger bandwidth resumption.
399 copt
.push_back(kBWRE
);
400 QuicConfigPeer::SetReceivedConnectionOptions(session_
->config(), copt
);
402 const string kTestServingRegion
= "a serving region";
403 session_
->set_serving_region(kTestServingRegion
);
405 QuicCryptoServerStream
* crypto_stream
=
406 static_cast<QuicCryptoServerStream
*>(
407 QuicSessionPeer::GetCryptoStream(session_
.get()));
409 // No effect if no CachedNetworkParameters provided.
410 EXPECT_CALL(*connection_
, ResumeConnectionState(_
)).Times(0);
411 session_
->OnConfigNegotiated();
413 // No effect if CachedNetworkParameters provided, but different serving
415 CachedNetworkParameters cached_network_params
;
416 cached_network_params
.set_bandwidth_estimate_bytes_per_second(1);
417 cached_network_params
.set_serving_region("different serving region");
418 crypto_stream
->set_previous_cached_network_params(cached_network_params
);
419 EXPECT_CALL(*connection_
, ResumeConnectionState(_
)).Times(0);
420 session_
->OnConfigNegotiated();
422 // Same serving region results in CachedNetworkParameters being stored.
423 cached_network_params
.set_serving_region(kTestServingRegion
);
424 crypto_stream
->set_previous_cached_network_params(cached_network_params
);
425 EXPECT_CALL(*connection_
, ResumeConnectionState(_
)).Times(1);
426 session_
->OnConfigNegotiated();