• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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