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/crypto/source_address_token.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
;
40 using testing::StrictMock
;
47 class QuicServerSessionPeer
{
49 static QuicDataStream
* GetIncomingDataStream(
50 QuicServerSession
* s
, QuicStreamId id
) {
51 return s
->GetIncomingDataStream(id
);
53 static QuicDataStream
* GetDataStream(QuicServerSession
* s
, QuicStreamId id
) {
54 return s
->GetDataStream(id
);
56 static void SetCryptoStream(QuicServerSession
* s
,
57 QuicCryptoServerStream
* crypto_stream
) {
58 s
->crypto_stream_
.reset(crypto_stream
);
64 const size_t kMaxStreamsForTest
= 10;
66 class QuicServerSessionTest
: public ::testing::TestWithParam
<QuicVersion
> {
68 QuicServerSessionTest()
69 : crypto_config_(QuicCryptoServerConfig::TESTING
,
70 QuicRandom::GetInstance()) {
71 config_
.SetMaxStreamsPerConnection(kMaxStreamsForTest
,
73 config_
.SetInitialFlowControlWindowToSend(
74 kInitialSessionFlowControlWindowForTest
);
75 config_
.SetInitialStreamFlowControlWindowToSend(
76 kInitialStreamFlowControlWindowForTest
);
77 config_
.SetInitialSessionFlowControlWindowToSend(
78 kInitialSessionFlowControlWindowForTest
);
81 new StrictMock
<MockConnection
>(true, SupportedVersions(GetParam()));
82 session_
.reset(new QuicServerSession(config_
, connection_
, &owner_
));
84 handshake_message_
.reset(crypto_config_
.AddDefaultConfig(
85 QuicRandom::GetInstance(), &clock
,
86 QuicCryptoServerConfig::ConfigOptions()));
87 session_
->InitializeSession(crypto_config_
);
88 visitor_
= QuicConnectionPeer::GetVisitor(connection_
);
91 QuicVersion
version() const { return connection_
->version(); }
93 StrictMock
<MockQuicServerSessionVisitor
> owner_
;
94 StrictMock
<MockConnection
>* connection_
;
96 QuicCryptoServerConfig crypto_config_
;
97 scoped_ptr
<QuicServerSession
> session_
;
98 scoped_ptr
<CryptoHandshakeMessage
> handshake_message_
;
99 QuicConnectionVisitorInterface
* visitor_
;
102 // Compares CachedNetworkParameters.
103 MATCHER_P(EqualsProto
, network_params
, "") {
104 CachedNetworkParameters
reference(network_params
);
105 return (arg
->bandwidth_estimate_bytes_per_second() ==
106 reference
.bandwidth_estimate_bytes_per_second() &&
107 arg
->bandwidth_estimate_bytes_per_second() ==
108 reference
.bandwidth_estimate_bytes_per_second() &&
109 arg
->max_bandwidth_estimate_bytes_per_second() ==
110 reference
.max_bandwidth_estimate_bytes_per_second() &&
111 arg
->max_bandwidth_timestamp_seconds() ==
112 reference
.max_bandwidth_timestamp_seconds() &&
113 arg
->min_rtt_ms() == reference
.min_rtt_ms() &&
114 arg
->previous_connection_state() ==
115 reference
.previous_connection_state());
118 INSTANTIATE_TEST_CASE_P(Tests
, QuicServerSessionTest
,
119 ::testing::ValuesIn(QuicSupportedVersions()));
121 TEST_P(QuicServerSessionTest
, CloseStreamDueToReset
) {
122 // Open a stream, then reset it.
123 // Send two bytes of payload to open it.
124 QuicStreamFrame
data1(kClientDataStreamId1
, false, 0, MakeIOVector("HT"));
125 vector
<QuicStreamFrame
> frames
;
126 frames
.push_back(data1
);
127 session_
->OnStreamFrames(frames
);
128 EXPECT_EQ(1u, session_
->GetNumOpenStreams());
130 // Send a reset (and expect the peer to send a RST in response).
131 QuicRstStreamFrame
rst1(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
132 EXPECT_CALL(*connection_
, SendRstStream(kClientDataStreamId1
,
133 QUIC_RST_FLOW_CONTROL_ACCOUNTING
, 0));
134 visitor_
->OnRstStream(rst1
);
135 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
137 // Send the same two bytes of payload in a new packet.
138 visitor_
->OnStreamFrames(frames
);
140 // The stream should not be re-opened.
141 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
142 EXPECT_TRUE(connection_
->connected());
145 TEST_P(QuicServerSessionTest
, NeverOpenStreamDueToReset
) {
146 // Send a reset (and expect the peer to send a RST in response).
147 QuicRstStreamFrame
rst1(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
148 EXPECT_CALL(*connection_
, SendRstStream(kClientDataStreamId1
,
149 QUIC_RST_FLOW_CONTROL_ACCOUNTING
, 0));
150 visitor_
->OnRstStream(rst1
);
151 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
153 // Send two bytes of payload.
154 QuicStreamFrame
data1(kClientDataStreamId1
, false, 0, MakeIOVector("HT"));
155 vector
<QuicStreamFrame
> frames
;
156 frames
.push_back(data1
);
157 visitor_
->OnStreamFrames(frames
);
159 // The stream should never be opened, now that the reset is received.
160 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
161 EXPECT_TRUE(connection_
->connected());
164 TEST_P(QuicServerSessionTest
, AcceptClosedStream
) {
165 vector
<QuicStreamFrame
> frames
;
166 // Send (empty) compressed headers followed by two bytes of data.
167 frames
.push_back(QuicStreamFrame(kClientDataStreamId1
, false, 0,
168 MakeIOVector("\1\0\0\0\0\0\0\0HT")));
169 frames
.push_back(QuicStreamFrame(kClientDataStreamId2
, false, 0,
170 MakeIOVector("\2\0\0\0\0\0\0\0HT")));
171 visitor_
->OnStreamFrames(frames
);
172 EXPECT_EQ(2u, session_
->GetNumOpenStreams());
174 // Send a reset (and expect the peer to send a RST in response).
175 QuicRstStreamFrame
rst(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
176 EXPECT_CALL(*connection_
, SendRstStream(kClientDataStreamId1
,
177 QUIC_RST_FLOW_CONTROL_ACCOUNTING
, 0));
178 visitor_
->OnRstStream(rst
);
180 // If we were tracking, we'd probably want to reject this because it's data
181 // past the reset point of stream 3. As it's a closed stream we just drop the
182 // data on the floor, but accept the packet because it has data for stream 5.
185 QuicStreamFrame(kClientDataStreamId1
, false, 2, MakeIOVector("TP")));
187 QuicStreamFrame(kClientDataStreamId2
, false, 2, MakeIOVector("TP")));
188 visitor_
->OnStreamFrames(frames
);
189 // The stream should never be opened, now that the reset is received.
190 EXPECT_EQ(1u, session_
->GetNumOpenStreams());
191 EXPECT_TRUE(connection_
->connected());
194 TEST_P(QuicServerSessionTest
, MaxOpenStreams
) {
195 ValueRestore
<bool> old_flag(&FLAGS_quic_allow_more_open_streams
, true);
196 // Test that the server closes the connection if a client attempts to open too
197 // many data streams. The server accepts slightly more than the negotiated
198 // stream limit to deal with rare cases where a client FIN/RST is lost.
200 // The slightly increased stream limit is set during config negotiation. It
201 // should be either an increase of 10 over negotiated limit, or a fixed
202 // percentage scaling, whichever is larger. Test both before continuing.
203 EXPECT_EQ(kMaxStreamsForTest
, session_
->get_max_open_streams());
204 session_
->OnConfigNegotiated();
205 EXPECT_LT(kMaxStreamsMultiplier
* kMaxStreamsForTest
,
206 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
);
207 EXPECT_EQ(kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
,
208 session_
->get_max_open_streams());
209 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
210 QuicStreamId stream_id
= kClientDataStreamId1
;
211 // Open the max configured number of streams, should be no problem.
212 for (size_t i
= 0; i
< kMaxStreamsForTest
; ++i
) {
213 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(session_
.get(),
218 // Open more streams: server should accept slightly more than the limit.
219 for (size_t i
= 0; i
< kMaxStreamsMinimumIncrement
; ++i
) {
220 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(session_
.get(),
225 // Now violate the server's internal stream limit.
226 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS
));
229 QuicServerSessionPeer::GetIncomingDataStream(session_
.get(), stream_id
));
232 TEST_P(QuicServerSessionTest
, MaxOpenStreamsImplicit
) {
233 ValueRestore
<bool> old_flag(&FLAGS_quic_allow_more_open_streams
, true);
234 // Test that the server closes the connection if a client attempts to open too
235 // many data streams implicitly. The server accepts slightly more than the
236 // negotiated stream limit to deal with rare cases where a client FIN/RST is
239 // The slightly increased stream limit is set during config negotiation.
240 EXPECT_EQ(kMaxStreamsForTest
, session_
->get_max_open_streams());
241 session_
->OnConfigNegotiated();
242 EXPECT_LT(kMaxStreamsMultiplier
* kMaxStreamsForTest
,
243 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
);
244 EXPECT_EQ(kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
,
245 session_
->get_max_open_streams());
247 EXPECT_EQ(0u, session_
->GetNumOpenStreams());
248 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
249 session_
.get(), kClientDataStreamId1
));
250 // Implicitly open streams up to the server's limit.
251 const int kActualMaxStreams
=
252 kMaxStreamsForTest
+ kMaxStreamsMinimumIncrement
;
253 const int kMaxValidStreamId
=
254 kClientDataStreamId1
+ (kActualMaxStreams
- 1) * 2;
255 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
256 session_
.get(), kMaxValidStreamId
));
258 // Opening a further stream will result in connection close.
259 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS
));
260 EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDataStream(
261 session_
.get(), kMaxValidStreamId
+ 2));
264 TEST_P(QuicServerSessionTest
, GetEvenIncomingError
) {
265 // Incoming streams on the server session must be odd.
266 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_INVALID_STREAM_ID
));
268 QuicServerSessionPeer::GetIncomingDataStream(session_
.get(), 4));
271 TEST_P(QuicServerSessionTest
, SetFecProtectionFromConfig
) {
272 ValueRestore
<bool> old_flag(&FLAGS_enable_quic_fec
, true);
274 // Set received config to have FEC connection option.
276 copt
.push_back(kFHDR
);
277 QuicConfigPeer::SetReceivedConnectionOptions(session_
->config(), copt
);
278 session_
->OnConfigNegotiated();
280 // Verify that headers stream is always protected and data streams are
281 // optionally protected.
282 EXPECT_EQ(FEC_PROTECT_ALWAYS
,
283 QuicSessionPeer::GetHeadersStream(session_
.get())->fec_policy());
284 QuicDataStream
* stream
= QuicServerSessionPeer::GetIncomingDataStream(
285 session_
.get(), kClientDataStreamId1
);
287 EXPECT_EQ(FEC_PROTECT_OPTIONAL
, stream
->fec_policy());
290 class MockQuicCryptoServerStream
: public QuicCryptoServerStream
{
292 explicit MockQuicCryptoServerStream(
293 const QuicCryptoServerConfig
& crypto_config
, QuicSession
* session
)
294 : QuicCryptoServerStream(crypto_config
, session
) {}
295 virtual ~MockQuicCryptoServerStream() {}
297 MOCK_METHOD2(SendServerConfigUpdate
,
298 void(const CachedNetworkParameters
* cached_network_parameters
,
299 bool on_handshake_complete
));
302 DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream
);
305 TEST_P(QuicServerSessionTest
, BandwidthEstimates
) {
306 if (version() <= QUIC_VERSION_21
) {
309 // Test that bandwidth estimate updates are sent to the client, only after the
310 // bandwidth estimate has changes sufficiently, and enough time has passed.
312 int32 bandwidth_estimate_kbytes_per_second
= 123;
313 int32 max_bandwidth_estimate_kbytes_per_second
= 134;
314 int32 max_bandwidth_estimate_timestamp
= 1122334455;
315 const string serving_region
= "not a real region";
316 session_
->set_serving_region(serving_region
);
318 MockQuicCryptoServerStream
* crypto_stream
=
319 new MockQuicCryptoServerStream(crypto_config_
, session_
.get());
320 QuicServerSessionPeer::SetCryptoStream(session_
.get(), crypto_stream
);
322 // Set some initial bandwidth values.
323 QuicSentPacketManager
* sent_packet_manager
=
324 QuicConnectionPeer::GetSentPacketManager(session_
->connection());
325 QuicSustainedBandwidthRecorder
& bandwidth_recorder
=
326 QuicSentPacketManagerPeer::GetBandwidthRecorder(sent_packet_manager
);
327 QuicSustainedBandwidthRecorderPeer::SetBandwidthEstimate(
328 &bandwidth_recorder
, bandwidth_estimate_kbytes_per_second
);
329 QuicSustainedBandwidthRecorderPeer::SetMaxBandwidthEstimate(
330 &bandwidth_recorder
, max_bandwidth_estimate_kbytes_per_second
,
331 max_bandwidth_estimate_timestamp
);
333 // There will be no update sent yet - not enough time has passed.
334 QuicTime now
= QuicTime::Zero();
335 session_
->OnCongestionWindowChange(now
);
337 // Bandwidth estimate has now changed sufficiently but not enough time has
338 // passed to send a Server Config Update.
339 bandwidth_estimate_kbytes_per_second
=
340 bandwidth_estimate_kbytes_per_second
* 1.6;
341 session_
->OnCongestionWindowChange(now
);
343 // Bandwidth estimate has now changed sufficiently and enough time has passed.
345 sent_packet_manager
->GetRttStats()->SmoothedRtt().ToMilliseconds();
346 now
= now
.Add(QuicTime::Delta::FromMilliseconds(
347 kMinIntervalBetweenServerConfigUpdatesRTTs
* srtt_ms
));
349 // Verify that the proto has exactly the values we expect.
350 CachedNetworkParameters expected_network_params
;
351 expected_network_params
.set_bandwidth_estimate_bytes_per_second(
352 bandwidth_recorder
.BandwidthEstimate().ToBytesPerSecond());
353 expected_network_params
.set_max_bandwidth_estimate_bytes_per_second(
354 bandwidth_recorder
.MaxBandwidthEstimate().ToBytesPerSecond());
355 expected_network_params
.set_max_bandwidth_timestamp_seconds(
356 bandwidth_recorder
.MaxBandwidthTimestamp());
357 expected_network_params
.set_min_rtt_ms(session_
->connection()
358 ->sent_packet_manager()
362 expected_network_params
.set_previous_connection_state(
363 CachedNetworkParameters::CONGESTION_AVOIDANCE
);
364 expected_network_params
.set_timestamp(
365 session_
->connection()->clock()->WallNow().ToUNIXSeconds());
366 expected_network_params
.set_serving_region(serving_region
);
368 EXPECT_CALL(*crypto_stream
,
369 SendServerConfigUpdate(EqualsProto(expected_network_params
), _
))
371 session_
->OnCongestionWindowChange(now
);