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 "quiche/quic/core/http/quic_server_session_base.h"
6
7 #include <cstdint>
8 #include <memory>
9 #include <string>
10 #include <utility>
11
12 #include "absl/memory/memory.h"
13 #include "quiche/quic/core/crypto/null_encrypter.h"
14 #include "quiche/quic/core/crypto/quic_crypto_server_config.h"
15 #include "quiche/quic/core/crypto/quic_random.h"
16 #include "quiche/quic/core/proto/cached_network_parameters_proto.h"
17 #include "quiche/quic/core/quic_connection.h"
18 #include "quiche/quic/core/quic_crypto_server_stream.h"
19 #include "quiche/quic/core/quic_crypto_server_stream_base.h"
20 #include "quiche/quic/core/quic_types.h"
21 #include "quiche/quic/core/quic_utils.h"
22 #include "quiche/quic/core/tls_server_handshaker.h"
23 #include "quiche/quic/platform/api/quic_expect_bug.h"
24 #include "quiche/quic/platform/api/quic_flags.h"
25 #include "quiche/quic/platform/api/quic_socket_address.h"
26 #include "quiche/quic/platform/api/quic_test.h"
27 #include "quiche/quic/test_tools/crypto_test_utils.h"
28 #include "quiche/quic/test_tools/fake_proof_source.h"
29 #include "quiche/quic/test_tools/mock_quic_session_visitor.h"
30 #include "quiche/quic/test_tools/quic_config_peer.h"
31 #include "quiche/quic/test_tools/quic_connection_peer.h"
32 #include "quiche/quic/test_tools/quic_crypto_server_config_peer.h"
33 #include "quiche/quic/test_tools/quic_sent_packet_manager_peer.h"
34 #include "quiche/quic/test_tools/quic_server_session_base_peer.h"
35 #include "quiche/quic/test_tools/quic_session_peer.h"
36 #include "quiche/quic/test_tools/quic_spdy_session_peer.h"
37 #include "quiche/quic/test_tools/quic_stream_id_manager_peer.h"
38 #include "quiche/quic/test_tools/quic_stream_peer.h"
39 #include "quiche/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h"
40 #include "quiche/quic/test_tools/quic_test_utils.h"
41 #include "quiche/quic/tools/quic_memory_cache_backend.h"
42 #include "quiche/quic/tools/quic_simple_server_stream.h"
43
44 using testing::_;
45 using testing::StrictMock;
46
47 using testing::AtLeast;
48
49 namespace quic {
50 namespace test {
51 namespace {
52
53 // Data to be sent on a request stream. In Google QUIC, this is interpreted as
54 // DATA payload (there is no framing on request streams). In IETF QUIC, this is
55 // interpreted as HEADERS frame (type 0x1) with payload length 122 ('z'). Since
56 // no payload is included, QPACK decoder will not be invoked.
57 const char* const kStreamData = "\1z";
58
59 class TestServerSession : public QuicServerSessionBase {
60 public:
TestServerSession(const QuicConfig & config,QuicConnection * connection,QuicSession::Visitor * visitor,QuicCryptoServerStreamBase::Helper * helper,const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache,QuicSimpleServerBackend * quic_simple_server_backend)61 TestServerSession(const QuicConfig& config, QuicConnection* connection,
62 QuicSession::Visitor* visitor,
63 QuicCryptoServerStreamBase::Helper* helper,
64 const QuicCryptoServerConfig* crypto_config,
65 QuicCompressedCertsCache* compressed_certs_cache,
66 QuicSimpleServerBackend* quic_simple_server_backend)
67 : QuicServerSessionBase(config, CurrentSupportedVersions(), connection,
68 visitor, helper, crypto_config,
69 compressed_certs_cache),
70 quic_simple_server_backend_(quic_simple_server_backend) {}
71
~TestServerSession()72 ~TestServerSession() override { DeleteConnection(); }
73
74 MOCK_METHOD(bool, WriteControlFrame,
75 (const QuicFrame& frame, TransmissionType type), (override));
76
77 protected:
CreateIncomingStream(QuicStreamId id)78 QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override {
79 if (!ShouldCreateIncomingStream(id)) {
80 return nullptr;
81 }
82 QuicSpdyStream* stream = new QuicSimpleServerStream(
83 id, this, BIDIRECTIONAL, quic_simple_server_backend_);
84 ActivateStream(absl::WrapUnique(stream));
85 return stream;
86 }
87
CreateIncomingStream(PendingStream * pending)88 QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override {
89 QuicSpdyStream* stream =
90 new QuicSimpleServerStream(pending, this, quic_simple_server_backend_);
91 ActivateStream(absl::WrapUnique(stream));
92 return stream;
93 }
94
CreateOutgoingBidirectionalStream()95 QuicSpdyStream* CreateOutgoingBidirectionalStream() override {
96 QUICHE_DCHECK(false);
97 return nullptr;
98 }
99
CreateOutgoingUnidirectionalStream()100 QuicSpdyStream* CreateOutgoingUnidirectionalStream() override {
101 if (!ShouldCreateOutgoingUnidirectionalStream()) {
102 return nullptr;
103 }
104
105 QuicSpdyStream* stream = new QuicSimpleServerStream(
106 GetNextOutgoingUnidirectionalStreamId(), this, WRITE_UNIDIRECTIONAL,
107 quic_simple_server_backend_);
108 ActivateStream(absl::WrapUnique(stream));
109 return stream;
110 }
111
CreateQuicCryptoServerStream(const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache)112 std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream(
113 const QuicCryptoServerConfig* crypto_config,
114 QuicCompressedCertsCache* compressed_certs_cache) override {
115 return CreateCryptoServerStream(crypto_config, compressed_certs_cache, this,
116 stream_helper());
117 }
118
119 private:
120 QuicSimpleServerBackend*
121 quic_simple_server_backend_; // Owned by QuicServerSessionBaseTest
122 };
123
124 const size_t kMaxStreamsForTest = 10;
125
126 class QuicServerSessionBaseTest : public QuicTestWithParam<ParsedQuicVersion> {
127 protected:
QuicServerSessionBaseTest()128 QuicServerSessionBaseTest()
129 : QuicServerSessionBaseTest(crypto_test_utils::ProofSourceForTesting()) {}
130
QuicServerSessionBaseTest(std::unique_ptr<ProofSource> proof_source)131 explicit QuicServerSessionBaseTest(std::unique_ptr<ProofSource> proof_source)
132 : crypto_config_(QuicCryptoServerConfig::TESTING,
133 QuicRandom::GetInstance(), std::move(proof_source),
134 KeyExchangeSource::Default()),
135 compressed_certs_cache_(
136 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
137 config_.SetMaxBidirectionalStreamsToSend(kMaxStreamsForTest);
138 config_.SetMaxUnidirectionalStreamsToSend(kMaxStreamsForTest);
139 QuicConfigPeer::SetReceivedMaxBidirectionalStreams(&config_,
140 kMaxStreamsForTest);
141 QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(&config_,
142 kMaxStreamsForTest);
143 config_.SetInitialStreamFlowControlWindowToSend(
144 kInitialStreamFlowControlWindowForTest);
145 config_.SetInitialSessionFlowControlWindowToSend(
146 kInitialSessionFlowControlWindowForTest);
147
148 ParsedQuicVersionVector supported_versions = SupportedVersions(version());
149 connection_ = new StrictMock<MockQuicConnection>(
150 &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions);
151 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
152 connection_->SetEncrypter(
153 ENCRYPTION_FORWARD_SECURE,
154 std::make_unique<NullEncrypter>(connection_->perspective()));
155 session_ = std::make_unique<TestServerSession>(
156 config_, connection_, &owner_, &stream_helper_, &crypto_config_,
157 &compressed_certs_cache_, &memory_cache_backend_);
158 MockClock clock;
159 handshake_message_ = crypto_config_.AddDefaultConfig(
160 QuicRandom::GetInstance(), &clock,
161 QuicCryptoServerConfig::ConfigOptions());
162 session_->Initialize();
163 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
164 session_->config(), kMinimumFlowControlSendWindow);
165 session_->OnConfigNegotiated();
166 if (version().SupportsAntiAmplificationLimit()) {
167 QuicConnectionPeer::SetAddressValidated(connection_);
168 }
169 }
170
GetNthClientInitiatedBidirectionalId(int n)171 QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
172 return GetNthClientInitiatedBidirectionalStreamId(transport_version(), n);
173 }
174
GetNthServerInitiatedUnidirectionalId(int n)175 QuicStreamId GetNthServerInitiatedUnidirectionalId(int n) {
176 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
177 transport_version(), n);
178 }
179
version() const180 ParsedQuicVersion version() const { return GetParam(); }
181
transport_version() const182 QuicTransportVersion transport_version() const {
183 return version().transport_version;
184 }
185
186 // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
187 // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
188 // one-way close. This method can be used to inject a STOP_SENDING, which
189 // would cause a close in the opposite direction. This allows tests to do the
190 // extra work to get a two-way (full) close where desired. Also sets up
191 // expects needed to ensure that the STOP_SENDING worked as expected.
InjectStopSendingFrame(QuicStreamId stream_id)192 void InjectStopSendingFrame(QuicStreamId stream_id) {
193 if (!VersionHasIetfQuicFrames(transport_version())) {
194 // Only needed for version 99/IETF QUIC. Noop otherwise.
195 return;
196 }
197 QuicStopSendingFrame stop_sending(kInvalidControlFrameId, stream_id,
198 QUIC_ERROR_PROCESSING_STREAM);
199 EXPECT_CALL(owner_, OnStopSendingReceived(_)).Times(1);
200 // Expect the RESET_STREAM that is generated in response to receiving a
201 // STOP_SENDING.
202 EXPECT_CALL(*session_, WriteControlFrame(_, _));
203 EXPECT_CALL(*connection_,
204 OnStreamReset(stream_id, QUIC_ERROR_PROCESSING_STREAM));
205 session_->OnStopSendingFrame(stop_sending);
206 }
207
208 StrictMock<MockQuicSessionVisitor> owner_;
209 StrictMock<MockQuicCryptoServerStreamHelper> stream_helper_;
210 MockQuicConnectionHelper helper_;
211 MockAlarmFactory alarm_factory_;
212 StrictMock<MockQuicConnection>* connection_;
213 QuicConfig config_;
214 QuicCryptoServerConfig crypto_config_;
215 QuicCompressedCertsCache compressed_certs_cache_;
216 QuicMemoryCacheBackend memory_cache_backend_;
217 std::unique_ptr<TestServerSession> session_;
218 std::unique_ptr<CryptoHandshakeMessage> handshake_message_;
219 };
220
221 // Compares CachedNetworkParameters.
222 MATCHER_P(EqualsProto, network_params, "") {
223 CachedNetworkParameters reference(network_params);
224 return (arg->bandwidth_estimate_bytes_per_second() ==
225 reference.bandwidth_estimate_bytes_per_second() &&
226 arg->bandwidth_estimate_bytes_per_second() ==
227 reference.bandwidth_estimate_bytes_per_second() &&
228 arg->max_bandwidth_estimate_bytes_per_second() ==
229 reference.max_bandwidth_estimate_bytes_per_second() &&
230 arg->max_bandwidth_timestamp_seconds() ==
231 reference.max_bandwidth_timestamp_seconds() &&
232 arg->min_rtt_ms() == reference.min_rtt_ms() &&
233 arg->previous_connection_state() ==
234 reference.previous_connection_state());
235 }
236
237 INSTANTIATE_TEST_SUITE_P(Tests, QuicServerSessionBaseTest,
238 ::testing::ValuesIn(AllSupportedVersions()),
239 ::testing::PrintToStringParamName());
240
TEST_P(QuicServerSessionBaseTest,CloseStreamDueToReset)241 TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) {
242 // Send some data open a stream, then reset it.
243 QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
244 kStreamData);
245 session_->OnStreamFrame(data1);
246 EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
247
248 // Send a reset (and expect the peer to send a RST in response).
249 QuicRstStreamFrame rst1(kInvalidControlFrameId,
250 GetNthClientInitiatedBidirectionalId(0),
251 QUIC_ERROR_PROCESSING_STREAM, 0);
252 EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
253 if (!VersionHasIetfQuicFrames(transport_version())) {
254 // For non-version 99, the RESET_STREAM will do the full close.
255 // Set up expects accordingly.
256 EXPECT_CALL(*session_, WriteControlFrame(_, _));
257 EXPECT_CALL(*connection_,
258 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
259 QUIC_RST_ACKNOWLEDGEMENT));
260 }
261 session_->OnRstStream(rst1);
262
263 // For version-99 will create and receive a stop-sending, completing
264 // the full-close expected by this test.
265 InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0));
266
267 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
268 // Send the same two bytes of payload in a new packet.
269 session_->OnStreamFrame(data1);
270
271 // The stream should not be re-opened.
272 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
273 EXPECT_TRUE(connection_->connected());
274 }
275
TEST_P(QuicServerSessionBaseTest,NeverOpenStreamDueToReset)276 TEST_P(QuicServerSessionBaseTest, NeverOpenStreamDueToReset) {
277 // Send a reset (and expect the peer to send a RST in response).
278 QuicRstStreamFrame rst1(kInvalidControlFrameId,
279 GetNthClientInitiatedBidirectionalId(0),
280 QUIC_ERROR_PROCESSING_STREAM, 0);
281 EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
282 if (!VersionHasIetfQuicFrames(transport_version())) {
283 // For non-version 99, the RESET_STREAM will do the full close.
284 // Set up expects accordingly.
285 EXPECT_CALL(*session_, WriteControlFrame(_, _));
286 EXPECT_CALL(*connection_,
287 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
288 QUIC_RST_ACKNOWLEDGEMENT));
289 }
290 session_->OnRstStream(rst1);
291
292 // For version-99 will create and receive a stop-sending, completing
293 // the full-close expected by this test.
294 InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0));
295
296 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
297
298 QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
299 kStreamData);
300 session_->OnStreamFrame(data1);
301
302 // The stream should never be opened, now that the reset is received.
303 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
304 EXPECT_TRUE(connection_->connected());
305 }
306
TEST_P(QuicServerSessionBaseTest,AcceptClosedStream)307 TEST_P(QuicServerSessionBaseTest, AcceptClosedStream) {
308 // Send some data to open two streams.
309 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
310 kStreamData);
311 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
312 kStreamData);
313 session_->OnStreamFrame(frame1);
314 session_->OnStreamFrame(frame2);
315 EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
316
317 // Send a reset (and expect the peer to send a RST in response).
318 QuicRstStreamFrame rst(kInvalidControlFrameId,
319 GetNthClientInitiatedBidirectionalId(0),
320 QUIC_ERROR_PROCESSING_STREAM, 0);
321 EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
322 if (!VersionHasIetfQuicFrames(transport_version())) {
323 // For non-version 99, the RESET_STREAM will do the full close.
324 // Set up expects accordingly.
325 EXPECT_CALL(*session_, WriteControlFrame(_, _));
326 EXPECT_CALL(*connection_,
327 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
328 QUIC_RST_ACKNOWLEDGEMENT));
329 }
330 session_->OnRstStream(rst);
331
332 // For version-99 will create and receive a stop-sending, completing
333 // the full-close expected by this test.
334 InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0));
335
336 // If we were tracking, we'd probably want to reject this because it's data
337 // past the reset point of stream 3. As it's a closed stream we just drop the
338 // data on the floor, but accept the packet because it has data for stream 5.
339 QuicStreamFrame frame3(GetNthClientInitiatedBidirectionalId(0), false, 2,
340 kStreamData);
341 QuicStreamFrame frame4(GetNthClientInitiatedBidirectionalId(1), false, 2,
342 kStreamData);
343 session_->OnStreamFrame(frame3);
344 session_->OnStreamFrame(frame4);
345 // The stream should never be opened, now that the reset is received.
346 EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
347 EXPECT_TRUE(connection_->connected());
348 }
349
TEST_P(QuicServerSessionBaseTest,MaxOpenStreams)350 TEST_P(QuicServerSessionBaseTest, MaxOpenStreams) {
351 // Test that the server refuses if a client attempts to open too many data
352 // streams. For versions other than version 99, the server accepts slightly
353 // more than the negotiated stream limit to deal with rare cases where a
354 // client FIN/RST is lost.
355 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
356 session_->OnConfigNegotiated();
357 if (!VersionHasIetfQuicFrames(transport_version())) {
358 // The slightly increased stream limit is set during config negotiation. It
359 // is either an increase of 10 over negotiated limit, or a fixed percentage
360 // scaling, whichever is larger. Test both before continuing.
361 EXPECT_LT(kMaxStreamsMultiplier * kMaxStreamsForTest,
362 kMaxStreamsForTest + kMaxStreamsMinimumIncrement);
363 EXPECT_EQ(kMaxStreamsForTest + kMaxStreamsMinimumIncrement,
364 session_->max_open_incoming_bidirectional_streams());
365 }
366 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
367 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
368 // Open the max configured number of streams, should be no problem.
369 for (size_t i = 0; i < kMaxStreamsForTest; ++i) {
370 EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateStream(session_.get(),
371 stream_id));
372 stream_id += QuicUtils::StreamIdDelta(transport_version());
373 }
374
375 if (!VersionHasIetfQuicFrames(transport_version())) {
376 // Open more streams: server should accept slightly more than the limit.
377 // Excess streams are for non-version-99 only.
378 for (size_t i = 0; i < kMaxStreamsMinimumIncrement; ++i) {
379 EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateStream(session_.get(),
380 stream_id));
381 stream_id += QuicUtils::StreamIdDelta(transport_version());
382 }
383 }
384 // Now violate the server's internal stream limit.
385 stream_id += QuicUtils::StreamIdDelta(transport_version());
386
387 if (!VersionHasIetfQuicFrames(transport_version())) {
388 // For non-version 99, QUIC responds to an attempt to exceed the stream
389 // limit by resetting the stream.
390 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
391 EXPECT_CALL(*session_, WriteControlFrame(_, _));
392 EXPECT_CALL(*connection_, OnStreamReset(stream_id, QUIC_REFUSED_STREAM));
393 } else {
394 // In version 99 QUIC responds to an attempt to exceed the stream limit by
395 // closing the connection.
396 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1);
397 }
398 // Even if the connection remains open, the stream creation should fail.
399 EXPECT_FALSE(
400 QuicServerSessionBasePeer::GetOrCreateStream(session_.get(), stream_id));
401 }
402
TEST_P(QuicServerSessionBaseTest,MaxAvailableBidirectionalStreams)403 TEST_P(QuicServerSessionBaseTest, MaxAvailableBidirectionalStreams) {
404 // Test that the server closes the connection if a client makes too many data
405 // streams available. The server accepts slightly more than the negotiated
406 // stream limit to deal with rare cases where a client FIN/RST is lost.
407 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
408 session_->OnConfigNegotiated();
409 const size_t kAvailableStreamLimit =
410 session_->MaxAvailableBidirectionalStreams();
411
412 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
413 EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateStream(
414 session_.get(), GetNthClientInitiatedBidirectionalId(0)));
415
416 // Establish available streams up to the server's limit.
417 QuicStreamId next_id = QuicUtils::StreamIdDelta(transport_version());
418 const int kLimitingStreamId =
419 GetNthClientInitiatedBidirectionalId(kAvailableStreamLimit + 1);
420 if (!VersionHasIetfQuicFrames(transport_version())) {
421 // This exceeds the stream limit. In versions other than 99
422 // this is allowed. Version 99 hews to the IETF spec and does
423 // not allow it.
424 EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateStream(
425 session_.get(), kLimitingStreamId));
426 // A further available stream will result in connection close.
427 EXPECT_CALL(*connection_,
428 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
429 } else {
430 // A further available stream will result in connection close.
431 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
432 }
433
434 // This forces stream kLimitingStreamId + 2 to become available, which
435 // violates the quota.
436 EXPECT_FALSE(QuicServerSessionBasePeer::GetOrCreateStream(
437 session_.get(), kLimitingStreamId + 2 * next_id));
438 }
439
TEST_P(QuicServerSessionBaseTest,GetEvenIncomingError)440 TEST_P(QuicServerSessionBaseTest, GetEvenIncomingError) {
441 // Incoming streams on the server session must be odd.
442 const QuicErrorCode expected_error =
443 VersionHasIetfQuicFrames(transport_version())
444 ? QUIC_HTTP_STREAM_WRONG_DIRECTION
445 : QUIC_INVALID_STREAM_ID;
446 EXPECT_CALL(*connection_, CloseConnection(expected_error, _, _));
447 EXPECT_EQ(nullptr, QuicServerSessionBasePeer::GetOrCreateStream(
448 session_.get(),
449 session_->next_outgoing_unidirectional_stream_id()));
450 }
451
TEST_P(QuicServerSessionBaseTest,GetStreamDisconnected)452 TEST_P(QuicServerSessionBaseTest, GetStreamDisconnected) {
453 // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
454 if (version() != AllSupportedVersions()[0]) {
455 return;
456 }
457
458 // Don't create new streams if the connection is disconnected.
459 QuicConnectionPeer::TearDownLocalConnectionState(connection_);
460 EXPECT_QUIC_BUG(QuicServerSessionBasePeer::GetOrCreateStream(
461 session_.get(), GetNthClientInitiatedBidirectionalId(0)),
462 "ShouldCreateIncomingStream called when disconnected");
463 }
464
465 class MockQuicCryptoServerStream : public QuicCryptoServerStream {
466 public:
MockQuicCryptoServerStream(const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache,QuicServerSessionBase * session,QuicCryptoServerStreamBase::Helper * helper)467 explicit MockQuicCryptoServerStream(
468 const QuicCryptoServerConfig* crypto_config,
469 QuicCompressedCertsCache* compressed_certs_cache,
470 QuicServerSessionBase* session,
471 QuicCryptoServerStreamBase::Helper* helper)
472 : QuicCryptoServerStream(crypto_config, compressed_certs_cache, session,
473 helper) {}
474 MockQuicCryptoServerStream(const MockQuicCryptoServerStream&) = delete;
475 MockQuicCryptoServerStream& operator=(const MockQuicCryptoServerStream&) =
476 delete;
~MockQuicCryptoServerStream()477 ~MockQuicCryptoServerStream() override {}
478
479 MOCK_METHOD(void, SendServerConfigUpdate, (const CachedNetworkParameters*),
480 (override));
481 };
482
483 class MockTlsServerHandshaker : public TlsServerHandshaker {
484 public:
MockTlsServerHandshaker(QuicServerSessionBase * session,const QuicCryptoServerConfig * crypto_config)485 explicit MockTlsServerHandshaker(QuicServerSessionBase* session,
486 const QuicCryptoServerConfig* crypto_config)
487 : TlsServerHandshaker(session, crypto_config) {}
488 MockTlsServerHandshaker(const MockTlsServerHandshaker&) = delete;
489 MockTlsServerHandshaker& operator=(const MockTlsServerHandshaker&) = delete;
~MockTlsServerHandshaker()490 ~MockTlsServerHandshaker() override {}
491
492 MOCK_METHOD(void, SendServerConfigUpdate, (const CachedNetworkParameters*),
493 (override));
494
495 MOCK_METHOD(std::string, GetAddressToken, (const CachedNetworkParameters*),
496 (const, override));
497 };
498
TEST_P(QuicServerSessionBaseTest,BandwidthEstimates)499 TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
500 if (version().UsesTls() && !version().HasIetfQuicFrames()) {
501 // Skip the Txxx versions.
502 return;
503 }
504
505 // Test that bandwidth estimate updates are sent to the client, only when
506 // bandwidth resumption is enabled, the bandwidth estimate has changed
507 // sufficiently, enough time has passed,
508 // and we don't have any other data to write.
509
510 // Client has sent kBWRE connection option to trigger bandwidth resumption.
511 QuicTagVector copt;
512 copt.push_back(kBWRE);
513 copt.push_back(kBWID);
514 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
515 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
516 session_->OnConfigNegotiated();
517 EXPECT_TRUE(
518 QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get()));
519
520 int32_t bandwidth_estimate_kbytes_per_second = 123;
521 int32_t max_bandwidth_estimate_kbytes_per_second = 134;
522 int32_t max_bandwidth_estimate_timestamp = 1122334455;
523 const std::string serving_region = "not a real region";
524 session_->set_serving_region(serving_region);
525
526 if (!VersionUsesHttp3(transport_version())) {
527 session_->UnregisterStreamPriority(
528 QuicUtils::GetHeadersStreamId(transport_version()));
529 }
530 QuicServerSessionBasePeer::SetCryptoStream(session_.get(), nullptr);
531 MockQuicCryptoServerStream* quic_crypto_stream = nullptr;
532 MockTlsServerHandshaker* tls_server_stream = nullptr;
533 if (version().handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
534 quic_crypto_stream = new MockQuicCryptoServerStream(
535 &crypto_config_, &compressed_certs_cache_, session_.get(),
536 &stream_helper_);
537 QuicServerSessionBasePeer::SetCryptoStream(session_.get(),
538 quic_crypto_stream);
539 } else {
540 tls_server_stream =
541 new MockTlsServerHandshaker(session_.get(), &crypto_config_);
542 QuicServerSessionBasePeer::SetCryptoStream(session_.get(),
543 tls_server_stream);
544 }
545 if (!VersionUsesHttp3(transport_version())) {
546 session_->RegisterStreamPriority(
547 QuicUtils::GetHeadersStreamId(transport_version()),
548 /*is_static=*/true,
549 QuicStreamPriority::Default(session_->priority_type()));
550 }
551
552 // Set some initial bandwidth values.
553 QuicSentPacketManager* sent_packet_manager =
554 QuicConnectionPeer::GetSentPacketManager(session_->connection());
555 QuicSustainedBandwidthRecorder& bandwidth_recorder =
556 QuicSentPacketManagerPeer::GetBandwidthRecorder(sent_packet_manager);
557 // Seed an rtt measurement equal to the initial default rtt.
558 RttStats* rtt_stats =
559 const_cast<RttStats*>(sent_packet_manager->GetRttStats());
560 rtt_stats->UpdateRtt(rtt_stats->initial_rtt(), QuicTime::Delta::Zero(),
561 QuicTime::Zero());
562 QuicSustainedBandwidthRecorderPeer::SetBandwidthEstimate(
563 &bandwidth_recorder, bandwidth_estimate_kbytes_per_second);
564 QuicSustainedBandwidthRecorderPeer::SetMaxBandwidthEstimate(
565 &bandwidth_recorder, max_bandwidth_estimate_kbytes_per_second,
566 max_bandwidth_estimate_timestamp);
567 // Queue up some pending data.
568 if (!VersionUsesHttp3(transport_version())) {
569 session_->MarkConnectionLevelWriteBlocked(
570 QuicUtils::GetHeadersStreamId(transport_version()));
571 } else {
572 session_->MarkConnectionLevelWriteBlocked(
573 QuicUtils::GetFirstUnidirectionalStreamId(transport_version(),
574 Perspective::IS_SERVER));
575 }
576 EXPECT_TRUE(session_->HasDataToWrite());
577
578 // There will be no update sent yet - not enough time has passed.
579 QuicTime now = QuicTime::Zero();
580 session_->OnCongestionWindowChange(now);
581
582 // Bandwidth estimate has now changed sufficiently but not enough time has
583 // passed to send a Server Config Update.
584 bandwidth_estimate_kbytes_per_second =
585 bandwidth_estimate_kbytes_per_second * 1.6;
586 session_->OnCongestionWindowChange(now);
587
588 // Bandwidth estimate has now changed sufficiently and enough time has passed,
589 // but not enough packets have been sent.
590 int64_t srtt_ms =
591 sent_packet_manager->GetRttStats()->smoothed_rtt().ToMilliseconds();
592 now = now + QuicTime::Delta::FromMilliseconds(
593 kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms);
594 session_->OnCongestionWindowChange(now);
595
596 // The connection no longer has pending data to be written.
597 session_->OnCanWrite();
598 EXPECT_FALSE(session_->HasDataToWrite());
599 session_->OnCongestionWindowChange(now);
600
601 // Bandwidth estimate has now changed sufficiently, enough time has passed,
602 // and enough packets have been sent.
603 SerializedPacket packet(
604 QuicPacketNumber(1) + kMinPacketsBetweenServerConfigUpdates,
605 PACKET_4BYTE_PACKET_NUMBER, nullptr, 1000, false, false);
606 sent_packet_manager->OnPacketSent(&packet, now, NOT_RETRANSMISSION,
607 HAS_RETRANSMITTABLE_DATA, true,
608 ECN_NOT_ECT);
609
610 // Verify that the proto has exactly the values we expect.
611 CachedNetworkParameters expected_network_params;
612 expected_network_params.set_bandwidth_estimate_bytes_per_second(
613 bandwidth_recorder.BandwidthEstimate().ToBytesPerSecond());
614 expected_network_params.set_max_bandwidth_estimate_bytes_per_second(
615 bandwidth_recorder.MaxBandwidthEstimate().ToBytesPerSecond());
616 expected_network_params.set_max_bandwidth_timestamp_seconds(
617 bandwidth_recorder.MaxBandwidthTimestamp());
618 expected_network_params.set_min_rtt_ms(session_->connection()
619 ->sent_packet_manager()
620 .GetRttStats()
621 ->min_rtt()
622 .ToMilliseconds());
623 expected_network_params.set_previous_connection_state(
624 CachedNetworkParameters::CONGESTION_AVOIDANCE);
625 expected_network_params.set_timestamp(
626 session_->connection()->clock()->WallNow().ToUNIXSeconds());
627 expected_network_params.set_serving_region(serving_region);
628
629 if (quic_crypto_stream) {
630 EXPECT_CALL(*quic_crypto_stream,
631 SendServerConfigUpdate(EqualsProto(expected_network_params)))
632 .Times(1);
633 } else {
634 EXPECT_CALL(*tls_server_stream,
635 GetAddressToken(EqualsProto(expected_network_params)))
636 .WillOnce(testing::Return("Test address token"));
637 }
638 EXPECT_CALL(*connection_, OnSendConnectionState(_)).Times(1);
639 session_->OnCongestionWindowChange(now);
640 }
641
TEST_P(QuicServerSessionBaseTest,BandwidthResumptionExperiment)642 TEST_P(QuicServerSessionBaseTest, BandwidthResumptionExperiment) {
643 if (version().UsesTls()) {
644 if (!version().HasIetfQuicFrames()) {
645 // Skip the Txxx versions.
646 return;
647 }
648 // Avoid a QUIC_BUG in QuicSession::OnConfigNegotiated.
649 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
650 }
651
652 // Test that if a client provides a CachedNetworkParameters with the same
653 // serving region as the current server, and which was made within an hour of
654 // now, that this data is passed down to the send algorithm.
655
656 // Client has sent kBWRE connection option to trigger bandwidth resumption.
657 QuicTagVector copt;
658 copt.push_back(kBWRE);
659 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
660
661 const std::string kTestServingRegion = "a serving region";
662 session_->set_serving_region(kTestServingRegion);
663
664 // Set the time to be one hour + one second from the 0 baseline.
665 connection_->AdvanceTime(
666 QuicTime::Delta::FromSeconds(kNumSecondsPerHour + 1));
667
668 QuicCryptoServerStreamBase* crypto_stream =
669 static_cast<QuicCryptoServerStreamBase*>(
670 QuicSessionPeer::GetMutableCryptoStream(session_.get()));
671
672 // No effect if no CachedNetworkParameters provided.
673 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0);
674 session_->OnConfigNegotiated();
675
676 // No effect if CachedNetworkParameters provided, but different serving
677 // regions.
678 CachedNetworkParameters cached_network_params;
679 cached_network_params.set_bandwidth_estimate_bytes_per_second(1);
680 cached_network_params.set_serving_region("different serving region");
681 crypto_stream->SetPreviousCachedNetworkParams(cached_network_params);
682 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0);
683 session_->OnConfigNegotiated();
684
685 // Same serving region, but timestamp is too old, should have no effect.
686 cached_network_params.set_serving_region(kTestServingRegion);
687 cached_network_params.set_timestamp(0);
688 crypto_stream->SetPreviousCachedNetworkParams(cached_network_params);
689 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0);
690 session_->OnConfigNegotiated();
691
692 // Same serving region, and timestamp is recent: estimate is stored.
693 cached_network_params.set_timestamp(
694 connection_->clock()->WallNow().ToUNIXSeconds());
695 crypto_stream->SetPreviousCachedNetworkParams(cached_network_params);
696 EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(1);
697 session_->OnConfigNegotiated();
698 }
699
TEST_P(QuicServerSessionBaseTest,BandwidthMaxEnablesResumption)700 TEST_P(QuicServerSessionBaseTest, BandwidthMaxEnablesResumption) {
701 EXPECT_FALSE(
702 QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get()));
703
704 // Client has sent kBWMX connection option to trigger bandwidth resumption.
705 QuicTagVector copt;
706 copt.push_back(kBWMX);
707 QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
708 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
709 session_->OnConfigNegotiated();
710 EXPECT_TRUE(
711 QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get()));
712 }
713
TEST_P(QuicServerSessionBaseTest,NoBandwidthResumptionByDefault)714 TEST_P(QuicServerSessionBaseTest, NoBandwidthResumptionByDefault) {
715 EXPECT_FALSE(
716 QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get()));
717 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
718 session_->OnConfigNegotiated();
719 EXPECT_FALSE(
720 QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get()));
721 }
722
723 // Tests which check the lifetime management of data members of
724 // QuicCryptoServerStream objects when async GetProof is in use.
725 class StreamMemberLifetimeTest : public QuicServerSessionBaseTest {
726 public:
StreamMemberLifetimeTest()727 StreamMemberLifetimeTest()
728 : QuicServerSessionBaseTest(
729 std::unique_ptr<FakeProofSource>(new FakeProofSource())),
730 crypto_config_peer_(&crypto_config_) {
731 GetFakeProofSource()->Activate();
732 }
733
GetFakeProofSource() const734 FakeProofSource* GetFakeProofSource() const {
735 return static_cast<FakeProofSource*>(crypto_config_peer_.GetProofSource());
736 }
737
738 private:
739 QuicCryptoServerConfigPeer crypto_config_peer_;
740 };
741
742 INSTANTIATE_TEST_SUITE_P(StreamMemberLifetimeTests, StreamMemberLifetimeTest,
743 ::testing::ValuesIn(AllSupportedVersions()),
744 ::testing::PrintToStringParamName());
745
746 // Trigger an operation which causes an async invocation of
747 // ProofSource::GetProof. Delay the completion of the operation until after the
748 // stream has been destroyed, and verify that there are no memory bugs.
TEST_P(StreamMemberLifetimeTest,Basic)749 TEST_P(StreamMemberLifetimeTest, Basic) {
750 if (version().handshake_protocol == PROTOCOL_TLS1_3) {
751 // This test depends on the QUIC crypto protocol, so it is disabled for the
752 // TLS handshake.
753 // TODO(nharper): Fix this test so it doesn't rely on QUIC crypto.
754 return;
755 }
756
757 const QuicClock* clock = helper_.GetClock();
758 CryptoHandshakeMessage chlo = crypto_test_utils::GenerateDefaultInchoateCHLO(
759 clock, transport_version(), &crypto_config_);
760 chlo.SetVector(kCOPT, QuicTagVector{kREJ});
761 std::vector<ParsedQuicVersion> packet_version_list = {version()};
762 std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
763 TestConnectionId(1), EmptyQuicConnectionId(), true, false, 1,
764 std::string(chlo.GetSerialized().AsStringPiece()), CONNECTION_ID_PRESENT,
765 CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER, &packet_version_list));
766
767 EXPECT_CALL(stream_helper_, CanAcceptClientHello(_, _, _, _, _))
768 .WillOnce(testing::Return(true));
769
770 // Set the current packet
771 QuicConnectionPeer::SetCurrentPacket(session_->connection(),
772 packet->AsStringPiece());
773
774 // Yes, this is horrible. But it's the easiest way to trigger the behavior we
775 // need to exercise.
776 QuicCryptoServerStreamBase* crypto_stream =
777 const_cast<QuicCryptoServerStreamBase*>(session_->crypto_stream());
778
779 // Feed the CHLO into the crypto stream, which will trigger a call to
780 // ProofSource::GetProof
781 crypto_test_utils::SendHandshakeMessageToStream(crypto_stream, chlo,
782 Perspective::IS_CLIENT);
783 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
784
785 // Destroy the stream
786 session_.reset();
787
788 // Allow the async ProofSource::GetProof call to complete. Verify (under
789 // memory access checkers) that this does not result in accesses to any
790 // freed memory from the session or its subobjects.
791 GetFakeProofSource()->InvokePendingCallback(0);
792 }
793
794 } // namespace
795 } // namespace test
796 } // namespace quic
797