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