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/tools/quic/quic_server_session.h"
6
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"
25
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;
41 using testing::_;
42
43 namespace net {
44 namespace tools {
45 namespace test {
46
47 class QuicServerSessionPeer {
48 public:
GetIncomingDataStream(QuicServerSession * s,QuicStreamId id)49 static QuicDataStream* GetIncomingDataStream(
50 QuicServerSession* s, QuicStreamId id) {
51 return s->GetIncomingDataStream(id);
52 }
GetDataStream(QuicServerSession * s,QuicStreamId id)53 static QuicDataStream* GetDataStream(QuicServerSession* s, QuicStreamId id) {
54 return s->GetDataStream(id);
55 }
SetCryptoStream(QuicServerSession * s,QuicCryptoServerStream * crypto_stream)56 static void SetCryptoStream(QuicServerSession* s,
57 QuicCryptoServerStream* crypto_stream) {
58 s->crypto_stream_.reset(crypto_stream);
59 }
60 };
61
62 namespace {
63
64 const size_t kMaxStreamsForTest = 10;
65
66 class QuicServerSessionTest : public ::testing::TestWithParam<QuicVersion> {
67 protected:
QuicServerSessionTest()68 QuicServerSessionTest()
69 : crypto_config_(QuicCryptoServerConfig::TESTING,
70 QuicRandom::GetInstance()) {
71 config_.SetDefaults();
72 config_.set_max_streams_per_connection(kMaxStreamsForTest,
73 kMaxStreamsForTest);
74 config_.SetInitialFlowControlWindowToSend(
75 kInitialSessionFlowControlWindowForTest);
76 config_.SetInitialStreamFlowControlWindowToSend(
77 kInitialStreamFlowControlWindowForTest);
78 config_.SetInitialSessionFlowControlWindowToSend(
79 kInitialSessionFlowControlWindowForTest);
80
81 connection_ =
82 new StrictMock<MockConnection>(true, SupportedVersions(GetParam()));
83 session_.reset(new QuicServerSession(config_, connection_, &owner_));
84 MockClock clock;
85 handshake_message_.reset(crypto_config_.AddDefaultConfig(
86 QuicRandom::GetInstance(), &clock,
87 QuicCryptoServerConfig::ConfigOptions()));
88 session_->InitializeSession(crypto_config_);
89 visitor_ = QuicConnectionPeer::GetVisitor(connection_);
90 }
91
version() const92 QuicVersion version() const { return connection_->version(); }
93
94 StrictMock<MockQuicServerSessionVisitor> owner_;
95 StrictMock<MockConnection>* connection_;
96 QuicConfig config_;
97 QuicCryptoServerConfig crypto_config_;
98 scoped_ptr<QuicServerSession> session_;
99 scoped_ptr<CryptoHandshakeMessage> handshake_message_;
100 QuicConnectionVisitorInterface* visitor_;
101 };
102
103 // Compares CachedNetworkParameters.
104 MATCHER_P(EqualsProto, network_params, "") {
105 CachedNetworkParameters reference(network_params);
106 return (arg->bandwidth_estimate_bytes_per_second() ==
107 reference.bandwidth_estimate_bytes_per_second() &&
108 arg->bandwidth_estimate_bytes_per_second() ==
109 reference.bandwidth_estimate_bytes_per_second() &&
110 arg->max_bandwidth_estimate_bytes_per_second() ==
111 reference.max_bandwidth_estimate_bytes_per_second() &&
112 arg->max_bandwidth_timestamp_seconds() ==
113 reference.max_bandwidth_timestamp_seconds() &&
114 arg->min_rtt_ms() == reference.min_rtt_ms() &&
115 arg->previous_connection_state() ==
116 reference.previous_connection_state());
117 }
118
119 INSTANTIATE_TEST_CASE_P(Tests, QuicServerSessionTest,
120 ::testing::ValuesIn(QuicSupportedVersions()));
121
TEST_P(QuicServerSessionTest,CloseStreamDueToReset)122 TEST_P(QuicServerSessionTest, CloseStreamDueToReset) {
123 // Open a stream, then reset it.
124 // Send two bytes of payload to open it.
125 QuicStreamFrame data1(kClientDataStreamId1, false, 0, MakeIOVector("HT"));
126 vector<QuicStreamFrame> frames;
127 frames.push_back(data1);
128 session_->OnStreamFrames(frames);
129 EXPECT_EQ(1u, session_->GetNumOpenStreams());
130
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_, SendRstStream(kClientDataStreamId1,
134 QUIC_RST_FLOW_CONTROL_ACCOUNTING, 0));
135 visitor_->OnRstStream(rst1);
136 EXPECT_EQ(0u, session_->GetNumOpenStreams());
137
138 // Send the same two bytes of payload in a new packet.
139 visitor_->OnStreamFrames(frames);
140
141 // The stream should not be re-opened.
142 EXPECT_EQ(0u, session_->GetNumOpenStreams());
143 EXPECT_TRUE(connection_->connected());
144 }
145
TEST_P(QuicServerSessionTest,NeverOpenStreamDueToReset)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_, SendRstStream(kClientDataStreamId1,
150 QUIC_RST_FLOW_CONTROL_ACCOUNTING, 0));
151 visitor_->OnRstStream(rst1);
152 EXPECT_EQ(0u, session_->GetNumOpenStreams());
153
154 // Send two bytes of payload.
155 QuicStreamFrame data1(kClientDataStreamId1, false, 0, MakeIOVector("HT"));
156 vector<QuicStreamFrame> frames;
157 frames.push_back(data1);
158 visitor_->OnStreamFrames(frames);
159
160 // The stream should never be opened, now that the reset is received.
161 EXPECT_EQ(0u, session_->GetNumOpenStreams());
162 EXPECT_TRUE(connection_->connected());
163 }
164
TEST_P(QuicServerSessionTest,AcceptClosedStream)165 TEST_P(QuicServerSessionTest, AcceptClosedStream) {
166 vector<QuicStreamFrame> frames;
167 // Send (empty) compressed headers followed by two bytes of data.
168 frames.push_back(QuicStreamFrame(kClientDataStreamId1, false, 0,
169 MakeIOVector("\1\0\0\0\0\0\0\0HT")));
170 frames.push_back(QuicStreamFrame(kClientDataStreamId2, false, 0,
171 MakeIOVector("\2\0\0\0\0\0\0\0HT")));
172 visitor_->OnStreamFrames(frames);
173 EXPECT_EQ(2u, session_->GetNumOpenStreams());
174
175 // Send a reset (and expect the peer to send a RST in response).
176 QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_STREAM_NO_ERROR, 0);
177 EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1,
178 QUIC_RST_FLOW_CONTROL_ACCOUNTING, 0));
179 visitor_->OnRstStream(rst);
180
181 // If we were tracking, we'd probably want to reject this because it's data
182 // past the reset point of stream 3. As it's a closed stream we just drop the
183 // data on the floor, but accept the packet because it has data for stream 5.
184 frames.clear();
185 frames.push_back(
186 QuicStreamFrame(kClientDataStreamId1, false, 2, MakeIOVector("TP")));
187 frames.push_back(
188 QuicStreamFrame(kClientDataStreamId2, false, 2, MakeIOVector("TP")));
189 visitor_->OnStreamFrames(frames);
190 // The stream should never be opened, now that the reset is received.
191 EXPECT_EQ(1u, session_->GetNumOpenStreams());
192 EXPECT_TRUE(connection_->connected());
193 }
194
TEST_P(QuicServerSessionTest,MaxOpenStreams)195 TEST_P(QuicServerSessionTest, MaxOpenStreams) {
196 ValueRestore<bool> old_flag(&FLAGS_quic_allow_more_open_streams, true);
197 // Test that the server closes the connection if a client attempts to open too
198 // many data streams. The server accepts slightly more than the negotiated
199 // stream limit to deal with rare cases where a client FIN/RST is lost.
200
201 // The slightly increased stream limit is set during config negotiation.
202 EXPECT_EQ(kMaxStreamsForTest, session_->get_max_open_streams());
203 session_->OnConfigNegotiated();
204 EXPECT_EQ(kMaxStreamsMultiplier * kMaxStreamsForTest,
205 session_->get_max_open_streams());
206
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(),
212 stream_id));
213 stream_id += 2;
214 }
215
216 // Open one more stream: server should accept slightly more than the
217 // configured limit.
218 EXPECT_TRUE(
219 QuicServerSessionPeer::GetIncomingDataStream(session_.get(), stream_id));
220
221 // Now violate the server's internal stream limit.
222 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS));
223 stream_id += 2;
224 EXPECT_FALSE(
225 QuicServerSessionPeer::GetIncomingDataStream(session_.get(), stream_id));
226 }
227
TEST_P(QuicServerSessionTest,MaxOpenStreamsImplicit)228 TEST_P(QuicServerSessionTest, MaxOpenStreamsImplicit) {
229 ValueRestore<bool> old_flag(&FLAGS_quic_allow_more_open_streams, true);
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
233 // lost.
234
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_EQ(kMaxStreamsMultiplier * kMaxStreamsForTest,
239 session_->get_max_open_streams());
240
241 EXPECT_EQ(0u, session_->GetNumOpenStreams());
242 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
243 session_.get(), kClientDataStreamId1));
244 // Implicitly open streams up to the server's limit.
245 const int kActualMaxStreams = kMaxStreamsMultiplier * kMaxStreamsForTest;
246 const int kMaxValidStreamId =
247 kClientDataStreamId1 + (kActualMaxStreams - 1) * 2;
248 EXPECT_TRUE(QuicServerSessionPeer::GetIncomingDataStream(
249 session_.get(), kMaxValidStreamId));
250
251 // Opening a further stream will result in connection close.
252 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS));
253 EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDataStream(
254 session_.get(), kMaxValidStreamId + 2));
255 }
256
TEST_P(QuicServerSessionTest,GetEvenIncomingError)257 TEST_P(QuicServerSessionTest, GetEvenIncomingError) {
258 // Incoming streams on the server session must be odd.
259 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_STREAM_ID));
260 EXPECT_EQ(NULL,
261 QuicServerSessionPeer::GetIncomingDataStream(session_.get(), 4));
262 }
263
TEST_P(QuicServerSessionTest,SetFecProtectionFromConfig)264 TEST_P(QuicServerSessionTest, SetFecProtectionFromConfig) {
265 ValueRestore<bool> old_flag(&FLAGS_enable_quic_fec, true);
266
267 // Set received config to have FEC connection option.
268 QuicTagVector copt;
269 copt.push_back(kFHDR);
270 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
271 session_->OnConfigNegotiated();
272
273 // Verify that headers stream is always protected and data streams are
274 // optionally protected.
275 EXPECT_EQ(FEC_PROTECT_ALWAYS,
276 QuicSessionPeer::GetHeadersStream(session_.get())->fec_policy());
277 QuicDataStream* stream = QuicServerSessionPeer::GetIncomingDataStream(
278 session_.get(), kClientDataStreamId1);
279 ASSERT_TRUE(stream);
280 EXPECT_EQ(FEC_PROTECT_OPTIONAL, stream->fec_policy());
281 }
282
283 class MockQuicCryptoServerStream : public QuicCryptoServerStream {
284 public:
MockQuicCryptoServerStream(const QuicCryptoServerConfig & crypto_config,QuicSession * session)285 explicit MockQuicCryptoServerStream(
286 const QuicCryptoServerConfig& crypto_config, QuicSession* session)
287 : QuicCryptoServerStream(crypto_config, session) {}
~MockQuicCryptoServerStream()288 virtual ~MockQuicCryptoServerStream() {}
289
290 MOCK_METHOD1(SendServerConfigUpdate,
291 void(const CachedNetworkParameters* cached_network_parameters));
292 private:
293 DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream);
294 };
295
TEST_P(QuicServerSessionTest,BandwidthEstimates)296 TEST_P(QuicServerSessionTest, BandwidthEstimates) {
297 if (version() <= QUIC_VERSION_21) {
298 return;
299 }
300 // Test that bandwidth estimate updates are sent to the client, only after the
301 // bandwidth estimate has changes sufficiently, and enough time has passed.
302
303 int32 bandwidth_estimate_kbytes_per_second = 123;
304 int32 max_bandwidth_estimate_kbytes_per_second = 134;
305 int32 max_bandwidth_estimate_timestamp = 1122334455;
306 const string serving_region = "not a real region";
307 session_->set_serving_region(serving_region);
308
309 MockQuicCryptoServerStream* crypto_stream =
310 new MockQuicCryptoServerStream(crypto_config_, session_.get());
311 QuicServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
312
313 // Set some initial bandwidth values.
314 QuicSentPacketManager* sent_packet_manager =
315 QuicConnectionPeer::GetSentPacketManager(session_->connection());
316 QuicSustainedBandwidthRecorder& bandwidth_recorder =
317 QuicSentPacketManagerPeer::GetBandwidthRecorder(sent_packet_manager);
318 QuicSustainedBandwidthRecorderPeer::SetBandwidthEstimate(
319 &bandwidth_recorder, bandwidth_estimate_kbytes_per_second);
320 QuicSustainedBandwidthRecorderPeer::SetMaxBandwidthEstimate(
321 &bandwidth_recorder, max_bandwidth_estimate_kbytes_per_second,
322 max_bandwidth_estimate_timestamp);
323
324 // There will be no update sent yet - not enough time has passed.
325 QuicTime now = QuicTime::Zero();
326 session_->OnCongestionWindowChange(now);
327
328 // Bandwidth estimate has now changed sufficiently but not enough time has
329 // passed to send a Server Config Update.
330 bandwidth_estimate_kbytes_per_second =
331 bandwidth_estimate_kbytes_per_second * 1.6;
332 session_->OnCongestionWindowChange(now);
333
334 // Bandwidth estimate has now changed sufficiently and enough time has passed.
335 int64 srtt_ms =
336 sent_packet_manager->GetRttStats()->SmoothedRtt().ToMilliseconds();
337 now = now.Add(QuicTime::Delta::FromMilliseconds(
338 kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms));
339
340 // Verify that the proto has exactly the values we expect.
341 CachedNetworkParameters expected_network_params;
342 expected_network_params.set_bandwidth_estimate_bytes_per_second(
343 bandwidth_recorder.BandwidthEstimate().ToBytesPerSecond());
344 expected_network_params.set_max_bandwidth_estimate_bytes_per_second(
345 bandwidth_recorder.MaxBandwidthEstimate().ToBytesPerSecond());
346 expected_network_params.set_max_bandwidth_timestamp_seconds(
347 bandwidth_recorder.MaxBandwidthTimestamp());
348 expected_network_params.set_min_rtt_ms(session_->connection()
349 ->sent_packet_manager()
350 .GetRttStats()
351 ->min_rtt()
352 .ToMilliseconds());
353 expected_network_params.set_previous_connection_state(
354 CachedNetworkParameters::CONGESTION_AVOIDANCE);
355 expected_network_params.set_serving_region(serving_region);
356
357 EXPECT_CALL(*crypto_stream,
358 SendServerConfigUpdate(EqualsProto(expected_network_params)))
359 .Times(1);
360 session_->OnCongestionWindowChange(now);
361 }
362
363 } // namespace
364 } // namespace test
365 } // namespace tools
366 } // namespace net
367