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/tools/quic_simple_server_session.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <utility>
10
11 #include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
12 #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
13 #include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
14 #include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
15 #include "net/third_party/quiche/src/quic/core/quic_connection.h"
16 #include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
17 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
18 #include "net/third_party/quiche/src/quic/core/quic_versions.h"
19 #include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
20 #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
21 #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
22 #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
23 #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
24 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
25 #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
26 #include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
27 #include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
28 #include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
29 #include "net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h"
30 #include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
31 #include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
32 #include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
33 #include "net/third_party/quiche/src/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h"
34 #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
35 #include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
36 #include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
37 #include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h"
38 #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
39 #include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
40
41 using testing::_;
42 using testing::AnyNumber;
43 using testing::AtLeast;
44 using testing::InSequence;
45 using testing::Invoke;
46 using testing::Return;
47 using testing::StrictMock;
48
49 namespace quic {
50 namespace test {
51 namespace {
52
53 typedef QuicSimpleServerSession::PromisedStreamInfo PromisedStreamInfo;
54
55 const QuicByteCount kHeadersFrameHeaderLength = 2;
56 const QuicByteCount kHeadersFramePayloadLength = 9;
57
58 } // namespace
59
60 class QuicSimpleServerSessionPeer {
61 public:
SetCryptoStream(QuicSimpleServerSession * s,QuicCryptoServerStreamBase * crypto_stream)62 static void SetCryptoStream(QuicSimpleServerSession* s,
63 QuicCryptoServerStreamBase* crypto_stream) {
64 s->crypto_stream_.reset(crypto_stream);
65 }
66
CreateIncomingStream(QuicSimpleServerSession * s,QuicStreamId id)67 static QuicSpdyStream* CreateIncomingStream(QuicSimpleServerSession* s,
68 QuicStreamId id) {
69 return s->CreateIncomingStream(id);
70 }
71
CreateOutgoingUnidirectionalStream(QuicSimpleServerSession * s)72 static QuicSimpleServerStream* CreateOutgoingUnidirectionalStream(
73 QuicSimpleServerSession* s) {
74 return s->CreateOutgoingUnidirectionalStream();
75 }
76 };
77
78 namespace {
79
80 const size_t kMaxStreamsForTest = 10;
81
82 class MockQuicCryptoServerStream : public QuicCryptoServerStream {
83 public:
MockQuicCryptoServerStream(const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache,QuicSession * session,QuicCryptoServerStreamBase::Helper * helper)84 explicit MockQuicCryptoServerStream(
85 const QuicCryptoServerConfig* crypto_config,
86 QuicCompressedCertsCache* compressed_certs_cache,
87 QuicSession* session,
88 QuicCryptoServerStreamBase::Helper* helper)
89 : QuicCryptoServerStream(crypto_config,
90 compressed_certs_cache,
91 session,
92 helper) {}
93 MockQuicCryptoServerStream(const MockQuicCryptoServerStream&) = delete;
94 MockQuicCryptoServerStream& operator=(const MockQuicCryptoServerStream&) =
95 delete;
~MockQuicCryptoServerStream()96 ~MockQuicCryptoServerStream() override {}
97
98 MOCK_METHOD1(SendServerConfigUpdate,
99 void(const CachedNetworkParameters* cached_network_parameters));
100
encryption_established() const101 bool encryption_established() const override { return true; }
102 };
103
104 class MockTlsServerHandshaker : public TlsServerHandshaker {
105 public:
MockTlsServerHandshaker(QuicSession * session,SSL_CTX * ssl_ctx,ProofSource * proof_source)106 explicit MockTlsServerHandshaker(QuicSession* session,
107 SSL_CTX* ssl_ctx,
108 ProofSource* proof_source)
109 : TlsServerHandshaker(session, ssl_ctx, proof_source) {}
110 MockTlsServerHandshaker(const MockTlsServerHandshaker&) = delete;
111 MockTlsServerHandshaker& operator=(const MockTlsServerHandshaker&) = delete;
~MockTlsServerHandshaker()112 ~MockTlsServerHandshaker() override {}
113
114 MOCK_METHOD1(SendServerConfigUpdate,
115 void(const CachedNetworkParameters* cached_network_parameters));
116
encryption_established() const117 bool encryption_established() const override { return true; }
118 };
119
CreateMockCryptoServerStream(const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache,QuicSession * session,QuicCryptoServerStreamBase::Helper * helper)120 QuicCryptoServerStreamBase* CreateMockCryptoServerStream(
121 const QuicCryptoServerConfig* crypto_config,
122 QuicCompressedCertsCache* compressed_certs_cache,
123 QuicSession* session,
124 QuicCryptoServerStreamBase::Helper* helper) {
125 switch (session->connection()->version().handshake_protocol) {
126 case PROTOCOL_QUIC_CRYPTO:
127 return new MockQuicCryptoServerStream(
128 crypto_config, compressed_certs_cache, session, helper);
129 case PROTOCOL_TLS1_3:
130 return new MockTlsServerHandshaker(session, crypto_config->ssl_ctx(),
131 crypto_config->proof_source());
132 case PROTOCOL_UNSUPPORTED:
133 break;
134 }
135 QUIC_BUG << "Unknown handshake protocol: "
136 << static_cast<int>(
137 session->connection()->version().handshake_protocol);
138 return nullptr;
139 }
140
141 class MockQuicConnectionWithSendStreamData : public MockQuicConnection {
142 public:
MockQuicConnectionWithSendStreamData(MockQuicConnectionHelper * helper,MockAlarmFactory * alarm_factory,Perspective perspective,const ParsedQuicVersionVector & supported_versions)143 MockQuicConnectionWithSendStreamData(
144 MockQuicConnectionHelper* helper,
145 MockAlarmFactory* alarm_factory,
146 Perspective perspective,
147 const ParsedQuicVersionVector& supported_versions)
148 : MockQuicConnection(helper,
149 alarm_factory,
150 perspective,
151 supported_versions) {
152 auto consume_all_data = [](QuicStreamId /*id*/, size_t write_length,
153 QuicStreamOffset /*offset*/,
154 StreamSendingState state) {
155 return QuicConsumedData(write_length, state != NO_FIN);
156 };
157 ON_CALL(*this, SendStreamData(_, _, _, _))
158 .WillByDefault(Invoke(consume_all_data));
159 }
160
161 MOCK_METHOD4(SendStreamData,
162 QuicConsumedData(QuicStreamId id,
163 size_t write_length,
164 QuicStreamOffset offset,
165 StreamSendingState state));
166 };
167
168 class MockQuicSimpleServerSession : public QuicSimpleServerSession {
169 public:
MockQuicSimpleServerSession(const QuicConfig & config,QuicConnection * connection,QuicSession::Visitor * visitor,QuicCryptoServerStreamBase::Helper * helper,const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache,QuicSimpleServerBackend * quic_simple_server_backend)170 MockQuicSimpleServerSession(
171 const QuicConfig& config,
172 QuicConnection* connection,
173 QuicSession::Visitor* visitor,
174 QuicCryptoServerStreamBase::Helper* helper,
175 const QuicCryptoServerConfig* crypto_config,
176 QuicCompressedCertsCache* compressed_certs_cache,
177 QuicSimpleServerBackend* quic_simple_server_backend)
178 : QuicSimpleServerSession(config,
179 CurrentSupportedVersions(),
180 connection,
181 visitor,
182 helper,
183 crypto_config,
184 compressed_certs_cache,
185 quic_simple_server_backend) {}
186 // Methods taking non-copyable types like SpdyHeaderBlock by value cannot be
187 // mocked directly.
WritePushPromise(QuicStreamId original_stream_id,QuicStreamId promised_stream_id,spdy::SpdyHeaderBlock headers)188 void WritePushPromise(QuicStreamId original_stream_id,
189 QuicStreamId promised_stream_id,
190 spdy::SpdyHeaderBlock headers) override {
191 return WritePushPromiseMock(original_stream_id, promised_stream_id,
192 headers);
193 }
194 MOCK_METHOD3(WritePushPromiseMock,
195 void(QuicStreamId original_stream_id,
196 QuicStreamId promised_stream_id,
197 const spdy::SpdyHeaderBlock& headers));
198
199 MOCK_METHOD1(SendBlocked, void(QuicStreamId));
200 };
201
202 class QuicSimpleServerSessionTest
203 : public QuicTestWithParam<ParsedQuicVersion> {
204 public:
205 // The function ensures that A) the MAX_STREAMS frames get properly deleted
206 // (since the test uses a 'did we leak memory' check ... if we just lose the
207 // frame, the test fails) and B) returns true (instead of the default, false)
208 // which ensures that the rest of the system thinks that the frame actually
209 // was transmitted.
ClearMaxStreamsControlFrame(const QuicFrame & frame)210 bool ClearMaxStreamsControlFrame(const QuicFrame& frame) {
211 if (frame.type == MAX_STREAMS_FRAME) {
212 DeleteFrame(&const_cast<QuicFrame&>(frame));
213 return true;
214 }
215 return false;
216 }
217
218 protected:
QuicSimpleServerSessionTest()219 QuicSimpleServerSessionTest()
220 : crypto_config_(QuicCryptoServerConfig::TESTING,
221 QuicRandom::GetInstance(),
222 crypto_test_utils::ProofSourceForTesting(),
223 KeyExchangeSource::Default()),
224 compressed_certs_cache_(
225 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
226 config_.SetMaxBidirectionalStreamsToSend(kMaxStreamsForTest);
227 QuicConfigPeer::SetReceivedMaxBidirectionalStreams(&config_,
228 kMaxStreamsForTest);
229 config_.SetMaxUnidirectionalStreamsToSend(kMaxStreamsForTest);
230
231 config_.SetInitialStreamFlowControlWindowToSend(
232 kInitialStreamFlowControlWindowForTest);
233 config_.SetInitialMaxStreamDataBytesIncomingBidirectionalToSend(
234 kInitialStreamFlowControlWindowForTest);
235 config_.SetInitialMaxStreamDataBytesOutgoingBidirectionalToSend(
236 kInitialStreamFlowControlWindowForTest);
237 config_.SetInitialMaxStreamDataBytesUnidirectionalToSend(
238 kInitialStreamFlowControlWindowForTest);
239 config_.SetInitialSessionFlowControlWindowToSend(
240 kInitialSessionFlowControlWindowForTest);
241 if (VersionUsesHttp3(transport_version())) {
242 QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(
243 &config_, kMaxStreamsForTest + 3);
244 } else {
245 QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(&config_,
246 kMaxStreamsForTest);
247 }
248
249 ParsedQuicVersionVector supported_versions = SupportedVersions(GetParam());
250 connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>(
251 &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions);
252 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
253 session_ = std::make_unique<MockQuicSimpleServerSession>(
254 config_, connection_, &owner_, &stream_helper_, &crypto_config_,
255 &compressed_certs_cache_, &memory_cache_backend_);
256 MockClock clock;
257 handshake_message_ = crypto_config_.AddDefaultConfig(
258 QuicRandom::GetInstance(), &clock,
259 QuicCryptoServerConfig::ConfigOptions());
260 session_->Initialize();
261
262 if (VersionHasIetfQuicFrames(transport_version())) {
263 EXPECT_CALL(*connection_, SendControlFrame(_))
264 .WillRepeatedly(Invoke(
265 this, &QuicSimpleServerSessionTest::ClearMaxStreamsControlFrame));
266 }
267 session_->OnConfigNegotiated();
268 }
269
GetNthClientInitiatedBidirectionalId(int n)270 QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
271 return GetNthClientInitiatedBidirectionalStreamId(transport_version(), n);
272 }
273
GetNthServerInitiatedUnidirectionalId(int n)274 QuicStreamId GetNthServerInitiatedUnidirectionalId(int n) {
275 return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
276 transport_version(), n);
277 }
278
transport_version() const279 QuicTransportVersion transport_version() const {
280 return GetParam().transport_version;
281 }
282
InjectStopSending(QuicStreamId stream_id,QuicRstStreamErrorCode rst_stream_code)283 void InjectStopSending(QuicStreamId stream_id,
284 QuicRstStreamErrorCode rst_stream_code) {
285 // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
286 // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
287 // a one-way close.
288 if (!VersionHasIetfQuicFrames(transport_version())) {
289 // Only needed for version 99/IETF QUIC.
290 return;
291 }
292 EXPECT_CALL(owner_, OnStopSendingReceived(_)).Times(1);
293 QuicStopSendingFrame stop_sending(
294 kInvalidControlFrameId, stream_id,
295 static_cast<QuicApplicationErrorCode>(rst_stream_code));
296 // Expect the RESET_STREAM that is generated in response to receiving a
297 // STOP_SENDING.
298 EXPECT_CALL(*connection_, OnStreamReset(stream_id, rst_stream_code));
299 session_->OnStopSendingFrame(stop_sending);
300 }
301
302 StrictMock<MockQuicSessionVisitor> owner_;
303 StrictMock<MockQuicCryptoServerStreamHelper> stream_helper_;
304 MockQuicConnectionHelper helper_;
305 MockAlarmFactory alarm_factory_;
306 StrictMock<MockQuicConnectionWithSendStreamData>* connection_;
307 QuicConfig config_;
308 QuicCryptoServerConfig crypto_config_;
309 QuicCompressedCertsCache compressed_certs_cache_;
310 QuicMemoryCacheBackend memory_cache_backend_;
311 std::unique_ptr<MockQuicSimpleServerSession> session_;
312 std::unique_ptr<CryptoHandshakeMessage> handshake_message_;
313 };
314
315 INSTANTIATE_TEST_SUITE_P(Tests,
316 QuicSimpleServerSessionTest,
317 ::testing::ValuesIn(AllSupportedVersions()),
318 ::testing::PrintToStringParamName());
319
TEST_P(QuicSimpleServerSessionTest,CloseStreamDueToReset)320 TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) {
321 // Open a stream, then reset it.
322 // Send two bytes of payload to open it.
323 QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
324 quiche::QuicheStringPiece("HT"));
325 session_->OnStreamFrame(data1);
326 EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
327
328 // Receive a reset (and send a RST in response).
329 QuicRstStreamFrame rst1(kInvalidControlFrameId,
330 GetNthClientInitiatedBidirectionalId(0),
331 QUIC_ERROR_PROCESSING_STREAM, 0);
332 EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
333 EXPECT_CALL(*connection_, SendControlFrame(_));
334 if (!VersionHasIetfQuicFrames(transport_version())) {
335 // For version 99, this is covered in InjectStopSending()
336 EXPECT_CALL(*connection_,
337 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
338 QUIC_RST_ACKNOWLEDGEMENT));
339 }
340 session_->OnRstStream(rst1);
341 // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
342 // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
343 // a one-way close.
344 InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
345 QUIC_ERROR_PROCESSING_STREAM);
346 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
347
348 // Send the same two bytes of payload in a new packet.
349 session_->OnStreamFrame(data1);
350
351 // The stream should not be re-opened.
352 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
353 EXPECT_TRUE(connection_->connected());
354 }
355
TEST_P(QuicSimpleServerSessionTest,NeverOpenStreamDueToReset)356 TEST_P(QuicSimpleServerSessionTest, NeverOpenStreamDueToReset) {
357 // Send a reset (and expect the peer to send a RST in response).
358 QuicRstStreamFrame rst1(kInvalidControlFrameId,
359 GetNthClientInitiatedBidirectionalId(0),
360 QUIC_ERROR_PROCESSING_STREAM, 0);
361 EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
362 if (!VersionHasIetfQuicFrames(transport_version())) {
363 EXPECT_CALL(*connection_, SendControlFrame(_));
364 // For version 99, this is covered in InjectStopSending()
365 EXPECT_CALL(*connection_,
366 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
367 QUIC_RST_ACKNOWLEDGEMENT));
368 }
369 session_->OnRstStream(rst1);
370 // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
371 // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
372 // a one-way close.
373 InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
374 QUIC_ERROR_PROCESSING_STREAM);
375
376 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
377
378 // Send two bytes of payload.
379 QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
380 quiche::QuicheStringPiece("HT"));
381 session_->OnStreamFrame(data1);
382
383 // The stream should never be opened, now that the reset is received.
384 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
385 EXPECT_TRUE(connection_->connected());
386 }
387
TEST_P(QuicSimpleServerSessionTest,AcceptClosedStream)388 TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) {
389 // Send (empty) compressed headers followed by two bytes of data.
390 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
391 quiche::QuicheStringPiece("\1\0\0\0\0\0\0\0HT"));
392 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
393 quiche::QuicheStringPiece("\2\0\0\0\0\0\0\0HT"));
394 session_->OnStreamFrame(frame1);
395 session_->OnStreamFrame(frame2);
396 EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
397
398 // Send a reset (and expect the peer to send a RST in response).
399 QuicRstStreamFrame rst(kInvalidControlFrameId,
400 GetNthClientInitiatedBidirectionalId(0),
401 QUIC_ERROR_PROCESSING_STREAM, 0);
402 EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
403 if (!VersionHasIetfQuicFrames(transport_version())) {
404 EXPECT_CALL(*connection_, SendControlFrame(_));
405 // For version 99, this is covered in InjectStopSending()
406 EXPECT_CALL(*connection_,
407 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
408 QUIC_RST_ACKNOWLEDGEMENT));
409 }
410 session_->OnRstStream(rst);
411 // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
412 // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
413 // a one-way close.
414 InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
415 QUIC_ERROR_PROCESSING_STREAM);
416
417 // If we were tracking, we'd probably want to reject this because it's data
418 // past the reset point of stream 3. As it's a closed stream we just drop the
419 // data on the floor, but accept the packet because it has data for stream 5.
420 QuicStreamFrame frame3(GetNthClientInitiatedBidirectionalId(0), false, 2,
421 quiche::QuicheStringPiece("TP"));
422 QuicStreamFrame frame4(GetNthClientInitiatedBidirectionalId(1), false, 2,
423 quiche::QuicheStringPiece("TP"));
424 session_->OnStreamFrame(frame3);
425 session_->OnStreamFrame(frame4);
426 // The stream should never be opened, now that the reset is received.
427 EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
428 EXPECT_TRUE(connection_->connected());
429 }
430
TEST_P(QuicSimpleServerSessionTest,CreateIncomingStreamDisconnected)431 TEST_P(QuicSimpleServerSessionTest, CreateIncomingStreamDisconnected) {
432 // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
433 if (GetParam() != AllSupportedVersions()[0]) {
434 return;
435 }
436
437 // Tests that incoming stream creation fails when connection is not connected.
438 size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams();
439 QuicConnectionPeer::TearDownLocalConnectionState(connection_);
440 EXPECT_QUIC_BUG(QuicSimpleServerSessionPeer::CreateIncomingStream(
441 session_.get(), GetNthClientInitiatedBidirectionalId(0)),
442 "ShouldCreateIncomingStream called when disconnected");
443 EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams());
444 }
445
TEST_P(QuicSimpleServerSessionTest,CreateIncomingStream)446 TEST_P(QuicSimpleServerSessionTest, CreateIncomingStream) {
447 QuicSpdyStream* stream = QuicSimpleServerSessionPeer::CreateIncomingStream(
448 session_.get(), GetNthClientInitiatedBidirectionalId(0));
449 EXPECT_NE(nullptr, stream);
450 EXPECT_EQ(GetNthClientInitiatedBidirectionalId(0), stream->id());
451 }
452
TEST_P(QuicSimpleServerSessionTest,CreateOutgoingDynamicStreamDisconnected)453 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamDisconnected) {
454 // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
455 if (GetParam() != AllSupportedVersions()[0]) {
456 return;
457 }
458
459 // Tests that outgoing stream creation fails when connection is not connected.
460 size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams();
461 QuicConnectionPeer::TearDownLocalConnectionState(connection_);
462 EXPECT_QUIC_BUG(
463 QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
464 session_.get()),
465 "ShouldCreateOutgoingUnidirectionalStream called when disconnected");
466
467 EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams());
468 }
469
TEST_P(QuicSimpleServerSessionTest,CreateOutgoingDynamicStreamUnencrypted)470 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUnencrypted) {
471 // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
472 if (GetParam() != AllSupportedVersions()[0]) {
473 return;
474 }
475
476 // Tests that outgoing stream creation fails when encryption has not yet been
477 // established.
478 size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams();
479 EXPECT_QUIC_BUG(
480 QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
481 session_.get()),
482 "Encryption not established so no outgoing stream created.");
483 EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams());
484 }
485
TEST_P(QuicSimpleServerSessionTest,CreateOutgoingDynamicStreamUptoLimit)486 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) {
487 // Tests that outgoing stream creation should not be affected by existing
488 // incoming stream and vice-versa. But when reaching the limit of max outgoing
489 // stream allowed, creation should fail.
490
491 // Receive some data to initiate a incoming stream which should not effect
492 // creating outgoing streams.
493 QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
494 quiche::QuicheStringPiece("HT"));
495 session_->OnStreamFrame(data1);
496 EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
497 EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
498
499 if (!VersionUsesHttp3(transport_version())) {
500 session_->UnregisterStreamPriority(
501 QuicUtils::GetHeadersStreamId(transport_version()),
502 /*is_static=*/true);
503 }
504 // Assume encryption already established.
505 QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), nullptr);
506 QuicCryptoServerStreamBase* crypto_stream =
507 CreateMockCryptoServerStream(&crypto_config_, &compressed_certs_cache_,
508 session_.get(), &stream_helper_);
509 QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
510 if (!VersionUsesHttp3(transport_version())) {
511 session_->RegisterStreamPriority(
512 QuicUtils::GetHeadersStreamId(transport_version()),
513 /*is_static=*/true,
514 spdy::SpdyStreamPrecedence(QuicStream::kDefaultPriority));
515 }
516
517 // Create push streams till reaching the upper limit of allowed open streams.
518 for (size_t i = 0; i < kMaxStreamsForTest; ++i) {
519 QuicSpdyStream* created_stream =
520 QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
521 session_.get());
522 if (VersionUsesHttp3(transport_version())) {
523 EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(i + 3),
524 created_stream->id());
525 } else {
526 EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(i), created_stream->id());
527 }
528 EXPECT_EQ(i + 1, session_->GetNumOpenOutgoingStreams());
529 }
530
531 // Continuing creating push stream would fail.
532 EXPECT_EQ(nullptr,
533 QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
534 session_.get()));
535 EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
536
537 // Create peer initiated stream should have no problem.
538 QuicStreamFrame data2(GetNthClientInitiatedBidirectionalId(1), false, 0,
539 quiche::QuicheStringPiece("HT"));
540 session_->OnStreamFrame(data2);
541 EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
542 }
543
TEST_P(QuicSimpleServerSessionTest,OnStreamFrameWithEvenStreamId)544 TEST_P(QuicSimpleServerSessionTest, OnStreamFrameWithEvenStreamId) {
545 QuicStreamFrame frame(GetNthServerInitiatedUnidirectionalId(0), false, 0,
546 quiche::QuicheStringPiece());
547 EXPECT_CALL(*connection_,
548 CloseConnection(QUIC_INVALID_STREAM_ID,
549 "Client sent data on server push stream", _));
550 session_->OnStreamFrame(frame);
551 }
552
553 // Tests that calling GetOrCreateStream() on an outgoing stream not promised yet
554 // should result close connection.
TEST_P(QuicSimpleServerSessionTest,GetEvenIncomingError)555 TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) {
556 const size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams();
557 const QuicErrorCode expected_error = VersionUsesHttp3(transport_version())
558 ? QUIC_HTTP_STREAM_WRONG_DIRECTION
559 : QUIC_INVALID_STREAM_ID;
560 EXPECT_CALL(*connection_, CloseConnection(expected_error,
561 "Data for nonexistent stream", _));
562 EXPECT_EQ(nullptr,
563 QuicSessionPeer::GetOrCreateStream(
564 session_.get(), GetNthServerInitiatedUnidirectionalId(3)));
565 EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams());
566 }
567
568 // In order to test the case where server push stream creation goes beyond
569 // limit, server push streams need to be hanging there instead of
570 // immediately closing after sending back response.
571 // To achieve this goal, this class resets flow control windows so that large
572 // responses will not be sent fully in order to prevent push streams from being
573 // closed immediately.
574 // Also adjust connection-level flow control window to ensure a large response
575 // can cause stream-level flow control blocked but not connection-level.
576 class QuicSimpleServerSessionServerPushTest
577 : public QuicSimpleServerSessionTest {
578 protected:
579 const size_t kStreamFlowControlWindowSize = 32 * 1024; // 32KB.
580
QuicSimpleServerSessionServerPushTest()581 QuicSimpleServerSessionServerPushTest() {
582 // Reset stream level flow control window to be 32KB.
583 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
584 if (VersionHasIetfQuicFrames(transport_version())) {
585 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
586 &config_, kStreamFlowControlWindowSize);
587 } else {
588 // In this version, push streams are server-initiated bidirectional
589 // streams, which are outgoing since we are the server here.
590 QuicConfigPeer::
591 SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
592 &config_, kStreamFlowControlWindowSize);
593 }
594 } else {
595 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(
596 &config_, kStreamFlowControlWindowSize);
597 }
598 // Reset connection level flow control window to be 1.5 MB which is large
599 // enough that it won't block any stream to write before stream level flow
600 // control blocks it.
601 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
602 &config_, kInitialSessionFlowControlWindowForTest);
603
604 ParsedQuicVersionVector supported_versions = SupportedVersions(GetParam());
605 connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>(
606 &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions);
607 session_ = std::make_unique<MockQuicSimpleServerSession>(
608 config_, connection_, &owner_, &stream_helper_, &crypto_config_,
609 &compressed_certs_cache_, &memory_cache_backend_);
610 session_->Initialize();
611 // Needed to make new session flow control window and server push work.
612
613 if (VersionHasIetfQuicFrames(transport_version())) {
614 EXPECT_CALL(*connection_, SendControlFrame(_))
615 .WillRepeatedly(Invoke(this, &QuicSimpleServerSessionServerPushTest::
616 ClearMaxStreamsControlFrame));
617 }
618 session_->OnConfigNegotiated();
619
620 if (!VersionUsesHttp3(transport_version())) {
621 session_->UnregisterStreamPriority(
622 QuicUtils::GetHeadersStreamId(transport_version()),
623 /*is_static=*/true);
624 }
625 QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), nullptr);
626 // Assume encryption already established.
627 QuicCryptoServerStreamBase* crypto_stream =
628 CreateMockCryptoServerStream(&crypto_config_, &compressed_certs_cache_,
629 session_.get(), &stream_helper_);
630
631 QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
632 if (!VersionUsesHttp3(transport_version())) {
633 session_->RegisterStreamPriority(
634 QuicUtils::GetHeadersStreamId(transport_version()),
635 /*is_static=*/true,
636 spdy::SpdyStreamPrecedence(QuicStream::kDefaultPriority));
637 }
638 if (VersionUsesHttp3(transport_version())) {
639 // Ignore writes on the control stream.
640 auto send_control_stream =
641 QuicSpdySessionPeer::GetSendControlStream(session_.get());
642 EXPECT_CALL(*connection_,
643 SendStreamData(send_control_stream->id(), _, _, NO_FIN))
644 .Times(AnyNumber());
645 }
646 }
647
648 // Given |num_resources|, create this number of fake push resources and push
649 // them by sending PUSH_PROMISE for all and sending push responses for as much
650 // as possible(limited by kMaxStreamsForTest).
651 // If |num_resources| > kMaxStreamsForTest, the left over will be queued.
652 // Returns the length of the DATA frame header, or 0 if the version does not
653 // use DATA frames.
PromisePushResources(size_t num_resources)654 QuicByteCount PromisePushResources(size_t num_resources) {
655 // testing::InSequence seq;
656 // To prevent push streams from being closed the response need to be larger
657 // than stream flow control window so stream won't send the full body.
658 size_t body_size = 2 * kStreamFlowControlWindowSize; // 64KB.
659
660 std::string request_url = "mail.google.com/";
661 spdy::SpdyHeaderBlock request_headers;
662 std::string resource_host = "www.google.com";
663 std::string partial_push_resource_path = "/server_push_src";
664 std::list<QuicBackendResponse::ServerPushInfo> push_resources;
665 std::string scheme = "http";
666 QuicByteCount data_frame_header_length = 0;
667 for (unsigned int i = 1; i <= num_resources; ++i) {
668 QuicStreamId stream_id;
669 if (VersionUsesHttp3(transport_version())) {
670 stream_id = GetNthServerInitiatedUnidirectionalId(i + 2);
671 } else {
672 stream_id = GetNthServerInitiatedUnidirectionalId(i - 1);
673 }
674 std::string path = partial_push_resource_path +
675 quiche::QuicheTextUtils::Uint64ToString(i);
676 std::string url = scheme + "://" + resource_host + path;
677 QuicUrl resource_url = QuicUrl(url);
678 std::string body(body_size, 'a');
679 std::string data;
680 data_frame_header_length = 0;
681 if (VersionUsesHttp3(transport_version())) {
682 std::unique_ptr<char[]> buffer;
683 data_frame_header_length =
684 HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
685 std::string header(buffer.get(), data_frame_header_length);
686 data = header + body;
687 } else {
688 data = body;
689 }
690
691 memory_cache_backend_.AddSimpleResponse(resource_host, path, 200, data);
692 push_resources.push_back(QuicBackendResponse::ServerPushInfo(
693 resource_url, spdy::SpdyHeaderBlock(), QuicStream::kDefaultPriority,
694 body));
695 // PUSH_PROMISED are sent for all the resources.
696 EXPECT_CALL(*session_,
697 WritePushPromiseMock(GetNthClientInitiatedBidirectionalId(0),
698 stream_id, _));
699 if (i <= kMaxStreamsForTest) {
700 // |kMaxStreamsForTest| promised responses should be sent.
701 // Since flow control window is smaller than response body, not the
702 // whole body will be sent.
703 QuicStreamOffset offset = 0;
704 if (VersionUsesHttp3(transport_version())) {
705 EXPECT_CALL(*connection_,
706 SendStreamData(stream_id, 1, offset, NO_FIN));
707 offset++;
708 }
709
710 if (VersionUsesHttp3(transport_version())) {
711 EXPECT_CALL(*connection_,
712 SendStreamData(stream_id, kHeadersFrameHeaderLength,
713 offset, NO_FIN));
714 offset += kHeadersFrameHeaderLength;
715 EXPECT_CALL(*connection_,
716 SendStreamData(stream_id, kHeadersFramePayloadLength,
717 offset, NO_FIN));
718 offset += kHeadersFramePayloadLength;
719 }
720 if (VersionUsesHttp3(transport_version())) {
721 EXPECT_CALL(*connection_,
722 SendStreamData(stream_id, data_frame_header_length,
723 offset, NO_FIN));
724 offset += data_frame_header_length;
725 }
726 EXPECT_CALL(*connection_, SendStreamData(stream_id, _, offset, NO_FIN))
727 .WillOnce(Return(QuicConsumedData(
728 kStreamFlowControlWindowSize - offset, false)));
729 EXPECT_CALL(*session_, SendBlocked(stream_id));
730 }
731 }
732 session_->PromisePushResources(
733 request_url, push_resources, GetNthClientInitiatedBidirectionalId(0),
734 spdy::SpdyStreamPrecedence(0, spdy::kHttp2DefaultStreamWeight, false),
735 request_headers);
736 return data_frame_header_length;
737 }
738
MaybeConsumeHeadersStreamData()739 void MaybeConsumeHeadersStreamData() {
740 if (!VersionUsesHttp3(transport_version())) {
741 QuicStreamId headers_stream_id =
742 QuicUtils::GetHeadersStreamId(transport_version());
743 EXPECT_CALL(*connection_, SendStreamData(headers_stream_id, _, _, _))
744 .Times(AtLeast(1));
745 }
746 }
747 };
748
749 INSTANTIATE_TEST_SUITE_P(Tests,
750 QuicSimpleServerSessionServerPushTest,
751 ::testing::ValuesIn(AllSupportedVersions()));
752
753 // Tests that given more than kMaxStreamsForTest resources, all their
754 // PUSH_PROMISE's will be sent out and only kMaxStreamsForTest streams will be
755 // opened and send push response.
TEST_P(QuicSimpleServerSessionServerPushTest,TestPromisePushResources)756 TEST_P(QuicSimpleServerSessionServerPushTest, TestPromisePushResources) {
757 MaybeConsumeHeadersStreamData();
758 if (VersionUsesHttp3(transport_version())) {
759 session_->EnableServerPush();
760 session_->OnMaxPushIdFrame(kMaxQuicStreamId);
761 }
762 size_t num_resources = kMaxStreamsForTest + 5;
763 PromisePushResources(num_resources);
764 EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
765 }
766
767 // Tests that after promised stream queued up, when an opened stream is marked
768 // draining, a queued promised stream will become open and send push response.
TEST_P(QuicSimpleServerSessionServerPushTest,HandlePromisedPushRequestsAfterStreamDraining)769 TEST_P(QuicSimpleServerSessionServerPushTest,
770 HandlePromisedPushRequestsAfterStreamDraining) {
771 MaybeConsumeHeadersStreamData();
772 if (VersionUsesHttp3(transport_version())) {
773 session_->EnableServerPush();
774 session_->OnMaxPushIdFrame(kMaxQuicStreamId);
775 }
776 size_t num_resources = kMaxStreamsForTest + 1;
777 QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
778 QuicStreamId next_out_going_stream_id;
779 if (VersionUsesHttp3(transport_version())) {
780 next_out_going_stream_id =
781 GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
782 } else {
783 next_out_going_stream_id =
784 GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest);
785 }
786
787 // After an open stream is marked draining, a new stream is expected to be
788 // created and a response sent on the stream.
789 QuicStreamOffset offset = 0;
790 if (VersionUsesHttp3(transport_version())) {
791 EXPECT_CALL(*connection_,
792 SendStreamData(next_out_going_stream_id, 1, offset, NO_FIN));
793 offset++;
794 }
795 if (VersionUsesHttp3(transport_version())) {
796 EXPECT_CALL(*connection_,
797 SendStreamData(next_out_going_stream_id,
798 kHeadersFrameHeaderLength, offset, NO_FIN));
799 offset += kHeadersFrameHeaderLength;
800 EXPECT_CALL(*connection_,
801 SendStreamData(next_out_going_stream_id,
802 kHeadersFramePayloadLength, offset, NO_FIN));
803 offset += kHeadersFramePayloadLength;
804 }
805 if (VersionUsesHttp3(transport_version())) {
806 EXPECT_CALL(*connection_,
807 SendStreamData(next_out_going_stream_id,
808 data_frame_header_length, offset, NO_FIN));
809 offset += data_frame_header_length;
810 }
811 EXPECT_CALL(*connection_,
812 SendStreamData(next_out_going_stream_id, _, offset, NO_FIN))
813 .WillOnce(Return(
814 QuicConsumedData(kStreamFlowControlWindowSize - offset, false)));
815 EXPECT_CALL(*session_, SendBlocked(next_out_going_stream_id));
816
817 if (VersionHasIetfQuicFrames(transport_version())) {
818 // The PromisePushedResources call, above, will have used all available
819 // stream ids. For version 99, stream ids are not made available until
820 // a MAX_STREAMS frame is received. This emulates the reception of one.
821 // For pre-v-99, the node monitors its own stream usage and makes streams
822 // available as it closes/etc them.
823 // Version 99 also has unidirectional static streams, so we need to send
824 // MaxStreamFrame of the number of resources + number of static streams.
825 session_->OnMaxStreamsFrame(
826 QuicMaxStreamsFrame(0, num_resources + 3, /*unidirectional=*/true));
827 }
828
829 if (VersionUsesHttp3(transport_version())) {
830 session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(3));
831 } else {
832 session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(0));
833 }
834 // Number of open outgoing streams should still be the same, because a new
835 // stream is opened. And the queue should be empty.
836 EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
837 }
838
839 // Tests that after all resources are promised, a RST frame from client can
840 // prevent a promised resource to be send out.
TEST_P(QuicSimpleServerSessionServerPushTest,ResetPromisedStreamToCancelServerPush)841 TEST_P(QuicSimpleServerSessionServerPushTest,
842 ResetPromisedStreamToCancelServerPush) {
843 if (VersionHasIetfQuicFrames(transport_version())) {
844 // This test is resetting a stream that is not opened yet. IETF QUIC has no
845 // way to handle this. Some similar tests can be added once CANCEL_PUSH is
846 // supported.
847 return;
848 }
849 MaybeConsumeHeadersStreamData();
850 if (VersionUsesHttp3(transport_version())) {
851 session_->EnableServerPush();
852 session_->OnMaxPushIdFrame(kMaxQuicStreamId);
853 }
854
855 // Having two extra resources to be send later. One of them will be reset, so
856 // when opened stream become close, only one will become open.
857 size_t num_resources = kMaxStreamsForTest + 2;
858 if (VersionHasIetfQuicFrames(transport_version())) {
859 // V99 will send out a STREAMS_BLOCKED frame when it tries to exceed the
860 // limit. This will clear the frames so that they do not block the later
861 // rst-stream frame.
862 EXPECT_CALL(*connection_, SendControlFrame(_))
863 .WillOnce(Invoke(&ClearControlFrame));
864 }
865 QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
866
867 // Reset the last stream in the queue. It should be marked cancelled.
868 QuicStreamId stream_got_reset;
869 if (VersionUsesHttp3(transport_version())) {
870 stream_got_reset =
871 GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 4);
872 } else {
873 stream_got_reset =
874 GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 1);
875 }
876 QuicRstStreamFrame rst(kInvalidControlFrameId, stream_got_reset,
877 QUIC_STREAM_CANCELLED, 0);
878 EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
879 EXPECT_CALL(*connection_, SendControlFrame(_))
880 .WillOnce(Invoke(&ClearControlFrame));
881 EXPECT_CALL(*connection_,
882 OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT));
883 session_->OnRstStream(rst);
884
885 // When the first 2 streams becomes draining, the two queued up stream could
886 // be created. But since one of them was marked cancelled due to RST frame,
887 // only one queued resource will be sent out.
888 QuicStreamId stream_not_reset;
889 if (VersionUsesHttp3(transport_version())) {
890 stream_not_reset =
891 GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
892 } else {
893 stream_not_reset =
894 GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest);
895 }
896 InSequence s;
897 QuicStreamOffset offset = 0;
898 if (VersionUsesHttp3(transport_version())) {
899 EXPECT_CALL(*connection_,
900 SendStreamData(stream_not_reset, 1, offset, NO_FIN));
901 offset++;
902 EXPECT_CALL(*connection_,
903 SendStreamData(stream_not_reset, kHeadersFrameHeaderLength,
904 offset, NO_FIN));
905 offset += kHeadersFrameHeaderLength;
906 EXPECT_CALL(*connection_,
907 SendStreamData(stream_not_reset, kHeadersFramePayloadLength,
908 offset, NO_FIN));
909 offset += kHeadersFramePayloadLength;
910 EXPECT_CALL(*connection_,
911 SendStreamData(stream_not_reset, data_frame_header_length,
912 offset, NO_FIN));
913 offset += data_frame_header_length;
914 }
915 EXPECT_CALL(*connection_, SendStreamData(stream_not_reset, _, offset, NO_FIN))
916 .WillOnce(Return(
917 QuicConsumedData(kStreamFlowControlWindowSize - offset, false)));
918 EXPECT_CALL(*session_, SendBlocked(stream_not_reset));
919
920 if (VersionHasIetfQuicFrames(transport_version())) {
921 // The PromisePushedResources call, above, will have used all available
922 // stream ids. For version 99, stream ids are not made available until
923 // a MAX_STREAMS frame is received. This emulates the reception of one.
924 // For pre-v-99, the node monitors its own stream usage and makes streams
925 // available as it closes/etc them.
926 session_->OnMaxStreamsFrame(
927 QuicMaxStreamsFrame(0, num_resources + 3, /*unidirectional=*/true));
928 }
929 session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(3));
930 session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(4));
931 }
932
933 // Tests that closing a open outgoing stream can trigger a promised resource in
934 // the queue to be send out.
TEST_P(QuicSimpleServerSessionServerPushTest,CloseStreamToHandleMorePromisedStream)935 TEST_P(QuicSimpleServerSessionServerPushTest,
936 CloseStreamToHandleMorePromisedStream) {
937 MaybeConsumeHeadersStreamData();
938 if (VersionUsesHttp3(transport_version())) {
939 session_->EnableServerPush();
940 session_->OnMaxPushIdFrame(kMaxQuicStreamId);
941 }
942 size_t num_resources = kMaxStreamsForTest + 1;
943 if (VersionHasIetfQuicFrames(transport_version())) {
944 // V99 will send out a stream-id-blocked frame when the we desired to exceed
945 // the limit. This will clear the frames so that they do not block the later
946 // rst-stream frame.
947 EXPECT_CALL(*connection_, SendControlFrame(_))
948 .WillOnce(Invoke(&ClearControlFrame));
949 }
950 QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
951 QuicStreamId stream_to_open;
952 if (VersionUsesHttp3(transport_version())) {
953 stream_to_open =
954 GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
955 } else {
956 stream_to_open = GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest);
957 }
958
959 // Resetting an open stream will close the stream and give space for extra
960 // stream to be opened.
961 QuicStreamId stream_got_reset = GetNthServerInitiatedUnidirectionalId(3);
962 EXPECT_CALL(*connection_, SendControlFrame(_));
963 if (!VersionHasIetfQuicFrames(transport_version())) {
964 EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
965 // For version 99, this is covered in InjectStopSending()
966 EXPECT_CALL(*connection_,
967 OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT));
968 }
969 QuicStreamOffset offset = 0;
970 if (VersionUsesHttp3(transport_version())) {
971 EXPECT_CALL(*connection_,
972 SendStreamData(stream_to_open, 1, offset, NO_FIN));
973 offset++;
974 EXPECT_CALL(*connection_,
975 SendStreamData(stream_to_open, kHeadersFrameHeaderLength,
976 offset, NO_FIN));
977 offset += kHeadersFrameHeaderLength;
978 EXPECT_CALL(*connection_,
979 SendStreamData(stream_to_open, kHeadersFramePayloadLength,
980 offset, NO_FIN));
981 offset += kHeadersFramePayloadLength;
982 EXPECT_CALL(*connection_,
983 SendStreamData(stream_to_open, data_frame_header_length, offset,
984 NO_FIN));
985 offset += data_frame_header_length;
986 }
987 EXPECT_CALL(*connection_, SendStreamData(stream_to_open, _, offset, NO_FIN))
988 .WillOnce(Return(
989 QuicConsumedData(kStreamFlowControlWindowSize - offset, false)));
990
991 EXPECT_CALL(*session_, SendBlocked(stream_to_open));
992 QuicRstStreamFrame rst(kInvalidControlFrameId, stream_got_reset,
993 QUIC_STREAM_CANCELLED, 0);
994 if (VersionHasIetfQuicFrames(transport_version())) {
995 // The PromisePushedResources call, above, will have used all available
996 // stream ids. For version 99, stream ids are not made available until
997 // a MAX_STREAMS frame is received. This emulates the reception of one.
998 // For pre-v-99, the node monitors its own stream usage and makes streams
999 // available as it closes/etc them.
1000 session_->OnMaxStreamsFrame(
1001 QuicMaxStreamsFrame(0, num_resources + 3, /*unidirectional=*/true));
1002 } else {
1003 session_->OnRstStream(rst);
1004 }
1005 // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
1006 // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
1007 // a one-way close.
1008 InjectStopSending(stream_got_reset, QUIC_STREAM_CANCELLED);
1009 }
1010
1011 } // namespace
1012 } // namespace test
1013 } // namespace quic
1014