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_spdy_stream.h"
6
7 #include <cstring>
8 #include <memory>
9 #include <string>
10 #include <utility>
11
12 #include "absl/base/macros.h"
13 #include "absl/memory/memory.h"
14 #include "absl/strings/escaping.h"
15 #include "absl/strings/str_cat.h"
16 #include "absl/strings/string_view.h"
17 #include "quiche/quic/core/crypto/null_encrypter.h"
18 #include "quiche/quic/core/http/http_constants.h"
19 #include "quiche/quic/core/http/http_encoder.h"
20 #include "quiche/quic/core/http/http_frames.h"
21 #include "quiche/quic/core/http/quic_spdy_session.h"
22 #include "quiche/quic/core/http/spdy_utils.h"
23 #include "quiche/quic/core/http/web_transport_http3.h"
24 #include "quiche/quic/core/quic_connection.h"
25 #include "quiche/quic/core/quic_stream_sequencer_buffer.h"
26 #include "quiche/quic/core/quic_utils.h"
27 #include "quiche/quic/core/quic_versions.h"
28 #include "quiche/quic/core/quic_write_blocked_list.h"
29 #include "quiche/quic/platform/api/quic_expect_bug.h"
30 #include "quiche/quic/platform/api/quic_flags.h"
31 #include "quiche/quic/platform/api/quic_test.h"
32 #include "quiche/quic/test_tools/qpack/qpack_test_utils.h"
33 #include "quiche/quic/test_tools/quic_config_peer.h"
34 #include "quiche/quic/test_tools/quic_connection_peer.h"
35 #include "quiche/quic/test_tools/quic_flow_controller_peer.h"
36 #include "quiche/quic/test_tools/quic_session_peer.h"
37 #include "quiche/quic/test_tools/quic_spdy_session_peer.h"
38 #include "quiche/quic/test_tools/quic_spdy_stream_peer.h"
39 #include "quiche/quic/test_tools/quic_stream_peer.h"
40 #include "quiche/quic/test_tools/quic_test_utils.h"
41 #include "quiche/common/capsule.h"
42 #include "quiche/common/quiche_ip_address.h"
43 #include "quiche/common/quiche_mem_slice_storage.h"
44 #include "quiche/common/simple_buffer_allocator.h"
45
46 using quiche::Capsule;
47 using quiche::IpAddressRange;
48 using spdy::Http2HeaderBlock;
49 using spdy::kV3HighestPriority;
50 using spdy::kV3LowestPriority;
51 using testing::_;
52 using testing::AnyNumber;
53 using testing::AtLeast;
54 using testing::DoAll;
55 using testing::ElementsAre;
56 using testing::HasSubstr;
57 using testing::Invoke;
58 using testing::InvokeWithoutArgs;
59 using testing::MatchesRegex;
60 using testing::Pair;
61 using testing::Return;
62 using testing::SaveArg;
63 using testing::StrictMock;
64
65 namespace quic {
66 namespace test {
67 namespace {
68
69 constexpr bool kShouldProcessData = true;
70 constexpr absl::string_view kDataFramePayload = "some data";
71
72 class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
73 public:
TestCryptoStream(QuicSession * session)74 explicit TestCryptoStream(QuicSession* session)
75 : QuicCryptoStream(session),
76 QuicCryptoHandshaker(this, session),
77 encryption_established_(false),
78 one_rtt_keys_available_(false),
79 params_(new QuicCryptoNegotiatedParameters) {
80 // Simulate a negotiated cipher_suite with a fake value.
81 params_->cipher_suite = 1;
82 }
83
OnHandshakeMessage(const CryptoHandshakeMessage &)84 void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
85 encryption_established_ = true;
86 one_rtt_keys_available_ = true;
87 QuicErrorCode error;
88 std::string error_details;
89 session()->config()->SetInitialStreamFlowControlWindowToSend(
90 kInitialStreamFlowControlWindowForTest);
91 session()->config()->SetInitialSessionFlowControlWindowToSend(
92 kInitialSessionFlowControlWindowForTest);
93 if (session()->version().UsesTls()) {
94 if (session()->perspective() == Perspective::IS_CLIENT) {
95 session()->config()->SetOriginalConnectionIdToSend(
96 session()->connection()->connection_id());
97 session()->config()->SetInitialSourceConnectionIdToSend(
98 session()->connection()->connection_id());
99 } else {
100 session()->config()->SetInitialSourceConnectionIdToSend(
101 session()->connection()->client_connection_id());
102 }
103 TransportParameters transport_parameters;
104 EXPECT_TRUE(
105 session()->config()->FillTransportParameters(&transport_parameters));
106 error = session()->config()->ProcessTransportParameters(
107 transport_parameters, /* is_resumption = */ false, &error_details);
108 } else {
109 CryptoHandshakeMessage msg;
110 session()->config()->ToHandshakeMessage(&msg, transport_version());
111 error =
112 session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
113 }
114 EXPECT_THAT(error, IsQuicNoError());
115 session()->OnNewEncryptionKeyAvailable(
116 ENCRYPTION_FORWARD_SECURE,
117 std::make_unique<NullEncrypter>(session()->perspective()));
118 session()->OnConfigNegotiated();
119 if (session()->version().UsesTls()) {
120 session()->OnTlsHandshakeComplete();
121 } else {
122 session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
123 }
124 if (session()->version().UsesTls()) {
125 // HANDSHAKE_DONE frame.
126 EXPECT_CALL(*this, HasPendingRetransmission());
127 }
128 session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
129 }
130
131 // QuicCryptoStream implementation
EarlyDataReason() const132 ssl_early_data_reason_t EarlyDataReason() const override {
133 return ssl_early_data_unknown;
134 }
encryption_established() const135 bool encryption_established() const override {
136 return encryption_established_;
137 }
one_rtt_keys_available() const138 bool one_rtt_keys_available() const override {
139 return one_rtt_keys_available_;
140 }
GetHandshakeState() const141 HandshakeState GetHandshakeState() const override {
142 return one_rtt_keys_available() ? HANDSHAKE_COMPLETE : HANDSHAKE_START;
143 }
SetServerApplicationStateForResumption(std::unique_ptr<ApplicationState>)144 void SetServerApplicationStateForResumption(
145 std::unique_ptr<ApplicationState> /*application_state*/) override {}
AdvanceKeysAndCreateCurrentOneRttDecrypter()146 std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
147 override {
148 return nullptr;
149 }
CreateCurrentOneRttEncrypter()150 std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override {
151 return nullptr;
152 }
crypto_negotiated_params() const153 const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
154 const override {
155 return *params_;
156 }
crypto_message_parser()157 CryptoMessageParser* crypto_message_parser() override {
158 return QuicCryptoHandshaker::crypto_message_parser();
159 }
OnPacketDecrypted(EncryptionLevel)160 void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
OnOneRttPacketAcknowledged()161 void OnOneRttPacketAcknowledged() override {}
OnHandshakePacketSent()162 void OnHandshakePacketSent() override {}
OnConnectionClosed(QuicErrorCode,ConnectionCloseSource)163 void OnConnectionClosed(QuicErrorCode /*error*/,
164 ConnectionCloseSource /*source*/) override {}
OnHandshakeDoneReceived()165 void OnHandshakeDoneReceived() override {}
OnNewTokenReceived(absl::string_view)166 void OnNewTokenReceived(absl::string_view /*token*/) override {}
GetAddressToken(const CachedNetworkParameters *) const167 std::string GetAddressToken(
168 const CachedNetworkParameters* /*cached_network_parameters*/)
169 const override {
170 return "";
171 }
ValidateAddressToken(absl::string_view) const172 bool ValidateAddressToken(absl::string_view /*token*/) const override {
173 return true;
174 }
PreviousCachedNetworkParams() const175 const CachedNetworkParameters* PreviousCachedNetworkParams() const override {
176 return nullptr;
177 }
SetPreviousCachedNetworkParams(CachedNetworkParameters)178 void SetPreviousCachedNetworkParams(
179 CachedNetworkParameters /*cached_network_params*/) override {}
180
181 MOCK_METHOD(void, OnCanWrite, (), (override));
182
HasPendingCryptoRetransmission() const183 bool HasPendingCryptoRetransmission() const override { return false; }
184
185 MOCK_METHOD(bool, HasPendingRetransmission, (), (const, override));
186
ExportKeyingMaterial(absl::string_view,absl::string_view,size_t,std::string *)187 bool ExportKeyingMaterial(absl::string_view /*label*/,
188 absl::string_view /*context*/,
189 size_t /*result_len*/,
190 std::string* /*result*/) override {
191 return false;
192 }
193
GetSsl() const194 SSL* GetSsl() const override { return nullptr; }
195
IsCryptoFrameExpectedForEncryptionLevel(EncryptionLevel level) const196 bool IsCryptoFrameExpectedForEncryptionLevel(
197 EncryptionLevel level) const override {
198 return level != ENCRYPTION_ZERO_RTT;
199 }
200
GetEncryptionLevelToSendCryptoDataOfSpace(PacketNumberSpace space) const201 EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace(
202 PacketNumberSpace space) const override {
203 switch (space) {
204 case INITIAL_DATA:
205 return ENCRYPTION_INITIAL;
206 case HANDSHAKE_DATA:
207 return ENCRYPTION_HANDSHAKE;
208 case APPLICATION_DATA:
209 return ENCRYPTION_FORWARD_SECURE;
210 default:
211 QUICHE_DCHECK(false);
212 return NUM_ENCRYPTION_LEVELS;
213 }
214 }
215
216 private:
217 using QuicCryptoStream::session;
218
219 bool encryption_established_;
220 bool one_rtt_keys_available_;
221 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
222 };
223
224 class TestStream : public QuicSpdyStream {
225 public:
TestStream(QuicStreamId id,QuicSpdySession * session,bool should_process_data)226 TestStream(QuicStreamId id, QuicSpdySession* session,
227 bool should_process_data)
228 : QuicSpdyStream(id, session, BIDIRECTIONAL),
229 should_process_data_(should_process_data),
230 headers_payload_length_(0) {}
231 ~TestStream() override = default;
232
233 using QuicSpdyStream::set_ack_listener;
234 using QuicSpdyStream::ValidateReceivedHeaders;
235 using QuicStream::CloseWriteSide;
236 using QuicStream::sequencer;
237 using QuicStream::WriteOrBufferData;
238
OnBodyAvailable()239 void OnBodyAvailable() override {
240 if (!should_process_data_) {
241 return;
242 }
243 char buffer[2048];
244 struct iovec vec;
245 vec.iov_base = buffer;
246 vec.iov_len = ABSL_ARRAYSIZE(buffer);
247 size_t bytes_read = Readv(&vec, 1);
248 data_ += std::string(buffer, bytes_read);
249 }
250
251 MOCK_METHOD(void, WriteHeadersMock, (bool fin), ());
252
WriteHeadersImpl(spdy::Http2HeaderBlock header_block,bool fin,quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>)253 size_t WriteHeadersImpl(
254 spdy::Http2HeaderBlock header_block, bool fin,
255 quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
256 /*ack_listener*/) override {
257 saved_headers_ = std::move(header_block);
258 WriteHeadersMock(fin);
259 if (VersionUsesHttp3(transport_version())) {
260 // In this case, call QuicSpdyStream::WriteHeadersImpl() that does the
261 // actual work of closing the stream.
262 return QuicSpdyStream::WriteHeadersImpl(saved_headers_.Clone(), fin,
263 nullptr);
264 }
265 return 0;
266 }
267
data() const268 const std::string& data() const { return data_; }
saved_headers() const269 const spdy::Http2HeaderBlock& saved_headers() const { return saved_headers_; }
270
OnStreamHeaderList(bool fin,size_t frame_len,const QuicHeaderList & header_list)271 void OnStreamHeaderList(bool fin, size_t frame_len,
272 const QuicHeaderList& header_list) override {
273 headers_payload_length_ = frame_len;
274 QuicSpdyStream::OnStreamHeaderList(fin, frame_len, header_list);
275 }
276
headers_payload_length() const277 size_t headers_payload_length() const { return headers_payload_length_; }
278
279 private:
280 bool should_process_data_;
281 spdy::Http2HeaderBlock saved_headers_;
282 std::string data_;
283 size_t headers_payload_length_;
284 };
285
286 class TestSession : public MockQuicSpdySession {
287 public:
TestSession(QuicConnection * connection)288 explicit TestSession(QuicConnection* connection)
289 : MockQuicSpdySession(connection, /*create_mock_crypto_stream=*/false),
290 crypto_stream_(this) {}
291
GetMutableCryptoStream()292 TestCryptoStream* GetMutableCryptoStream() override {
293 return &crypto_stream_;
294 }
295
GetCryptoStream() const296 const TestCryptoStream* GetCryptoStream() const override {
297 return &crypto_stream_;
298 }
299
LocallySupportedWebTransportVersions() const300 WebTransportHttp3VersionSet LocallySupportedWebTransportVersions()
301 const override {
302 return locally_supported_webtransport_versions_;
303 }
EnableWebTransport(WebTransportHttp3VersionSet versions=kDefaultSupportedWebTransportVersions)304 void EnableWebTransport(WebTransportHttp3VersionSet versions =
305 kDefaultSupportedWebTransportVersions) {
306 locally_supported_webtransport_versions_ = versions;
307 }
308
LocalHttpDatagramSupport()309 HttpDatagramSupport LocalHttpDatagramSupport() override {
310 return local_http_datagram_support_;
311 }
set_local_http_datagram_support(HttpDatagramSupport value)312 void set_local_http_datagram_support(HttpDatagramSupport value) {
313 local_http_datagram_support_ = value;
314 }
315
316 private:
317 WebTransportHttp3VersionSet locally_supported_webtransport_versions_;
318 HttpDatagramSupport local_http_datagram_support_ = HttpDatagramSupport::kNone;
319 StrictMock<TestCryptoStream> crypto_stream_;
320 };
321
322 class TestMockUpdateStreamSession : public MockQuicSpdySession {
323 public:
TestMockUpdateStreamSession(QuicConnection * connection)324 explicit TestMockUpdateStreamSession(QuicConnection* connection)
325 : MockQuicSpdySession(connection) {}
326
UpdateStreamPriority(QuicStreamId id,const QuicStreamPriority & new_priority)327 void UpdateStreamPriority(QuicStreamId id,
328 const QuicStreamPriority& new_priority) override {
329 EXPECT_EQ(id, expected_stream_->id());
330 EXPECT_EQ(expected_priority_, new_priority.http());
331 EXPECT_EQ(QuicStreamPriority(expected_priority_),
332 expected_stream_->priority());
333 }
334
SetExpectedStream(QuicSpdyStream * stream)335 void SetExpectedStream(QuicSpdyStream* stream) { expected_stream_ = stream; }
SetExpectedPriority(const HttpStreamPriority & priority)336 void SetExpectedPriority(const HttpStreamPriority& priority) {
337 expected_priority_ = priority;
338 }
339
340 private:
341 QuicSpdyStream* expected_stream_;
342 HttpStreamPriority expected_priority_;
343 };
344
345 class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
346 protected:
QuicSpdyStreamTest()347 QuicSpdyStreamTest() {
348 headers_[":host"] = "www.google.com";
349 headers_[":path"] = "/index.hml";
350 headers_[":scheme"] = "https";
351 headers_["cookie"] =
352 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
353 "__utmc=160408618; "
354 "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
355 "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
356 "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
357 "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
358 "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
359 "1zFMi5vzcns38-8_Sns; "
360 "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
361 "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
362 "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
363 "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
364 "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
365 "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
366 "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
367 "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
368 "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
369 "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
370 "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
371 "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
372 "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
373 "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
374 "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
375 }
376
377 ~QuicSpdyStreamTest() override = default;
378
379 // Return QPACK-encoded header block without using the dynamic table.
EncodeQpackHeaders(std::vector<std::pair<absl::string_view,absl::string_view>> headers)380 std::string EncodeQpackHeaders(
381 std::vector<std::pair<absl::string_view, absl::string_view>> headers) {
382 Http2HeaderBlock header_block;
383 for (const auto& header_field : headers) {
384 header_block.AppendValueOrAddHeader(header_field.first,
385 header_field.second);
386 }
387
388 return EncodeQpackHeaders(header_block);
389 }
390
391 // Return QPACK-encoded header block without using the dynamic table.
EncodeQpackHeaders(const Http2HeaderBlock & header)392 std::string EncodeQpackHeaders(const Http2HeaderBlock& header) {
393 NoopQpackStreamSenderDelegate encoder_stream_sender_delegate;
394 auto qpack_encoder = std::make_unique<QpackEncoder>(
395 session_.get(), HuffmanEncoding::kEnabled);
396 qpack_encoder->set_qpack_stream_sender_delegate(
397 &encoder_stream_sender_delegate);
398 // QpackEncoder does not use the dynamic table by default,
399 // therefore the value of |stream_id| does not matter.
400 return qpack_encoder->EncodeHeaderList(/* stream_id = */ 0, header,
401 nullptr);
402 }
403
Initialize(bool stream_should_process_data)404 void Initialize(bool stream_should_process_data) {
405 InitializeWithPerspective(stream_should_process_data,
406 Perspective::IS_SERVER);
407 }
408
InitializeWithPerspective(bool stream_should_process_data,Perspective perspective)409 void InitializeWithPerspective(bool stream_should_process_data,
410 Perspective perspective) {
411 connection_ = new StrictMock<MockQuicConnection>(
412 &helper_, &alarm_factory_, perspective, SupportedVersions(GetParam()));
413 session_ = std::make_unique<StrictMock<TestSession>>(connection_);
414 EXPECT_CALL(*session_, OnCongestionWindowChange(_)).Times(AnyNumber());
415 session_->Initialize();
416 if (connection_->version().SupportsAntiAmplificationLimit()) {
417 QuicConnectionPeer::SetAddressValidated(connection_);
418 }
419 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
420 ON_CALL(*session_, WritevData(_, _, _, _, _, _))
421 .WillByDefault(
422 Invoke(session_.get(), &MockQuicSpdySession::ConsumeData));
423
424 stream_ =
425 new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(0),
426 session_.get(), stream_should_process_data);
427 session_->ActivateStream(absl::WrapUnique(stream_));
428 stream2_ =
429 new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(1),
430 session_.get(), stream_should_process_data);
431 session_->ActivateStream(absl::WrapUnique(stream2_));
432 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
433 session_->config(), kMinimumFlowControlSendWindow);
434 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
435 session_->config(), kMinimumFlowControlSendWindow);
436 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesIncomingBidirectional(
437 session_->config(), kMinimumFlowControlSendWindow);
438 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
439 session_->config(), kMinimumFlowControlSendWindow);
440 QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_->config(), 10);
441 session_->OnConfigNegotiated();
442 if (UsesHttp3()) {
443 // The control stream will write the stream type, a greased frame, and
444 // SETTINGS frame.
445 int num_control_stream_writes = 3;
446 auto send_control_stream =
447 QuicSpdySessionPeer::GetSendControlStream(session_.get());
448 EXPECT_CALL(*session_,
449 WritevData(send_control_stream->id(), _, _, _, _, _))
450 .Times(num_control_stream_writes);
451 }
452 TestCryptoStream* crypto_stream = session_->GetMutableCryptoStream();
453 EXPECT_CALL(*crypto_stream, HasPendingRetransmission()).Times(AnyNumber());
454
455 if (connection_->version().UsesTls() &&
456 session_->perspective() == Perspective::IS_SERVER) {
457 // HANDSHAKE_DONE frame.
458 EXPECT_CALL(*connection_, SendControlFrame(_))
459 .WillOnce(Invoke(&ClearControlFrame));
460 }
461 CryptoHandshakeMessage message;
462 session_->GetMutableCryptoStream()->OnHandshakeMessage(message);
463 }
464
ProcessHeaders(bool fin,const Http2HeaderBlock & headers)465 QuicHeaderList ProcessHeaders(bool fin, const Http2HeaderBlock& headers) {
466 QuicHeaderList h = AsHeaderList(headers);
467 stream_->OnStreamHeaderList(fin, h.uncompressed_header_bytes(), h);
468 return h;
469 }
470
GetNthClientInitiatedBidirectionalId(int n)471 QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
472 return GetNthClientInitiatedBidirectionalStreamId(
473 connection_->transport_version(), n);
474 }
475
UsesHttp3() const476 bool UsesHttp3() const {
477 return VersionUsesHttp3(GetParam().transport_version);
478 }
479
480 // Construct HEADERS frame with QPACK-encoded |headers| without using the
481 // dynamic table.
HeadersFrame(std::vector<std::pair<absl::string_view,absl::string_view>> headers)482 std::string HeadersFrame(
483 std::vector<std::pair<absl::string_view, absl::string_view>> headers) {
484 return HeadersFrame(EncodeQpackHeaders(headers));
485 }
486
487 // Construct HEADERS frame with QPACK-encoded |headers| without using the
488 // dynamic table.
HeadersFrame(const Http2HeaderBlock & headers)489 std::string HeadersFrame(const Http2HeaderBlock& headers) {
490 return HeadersFrame(EncodeQpackHeaders(headers));
491 }
492
493 // Construct HEADERS frame with given payload.
HeadersFrame(absl::string_view payload)494 std::string HeadersFrame(absl::string_view payload) {
495 std::string headers_frame_header =
496 HttpEncoder::SerializeHeadersFrameHeader(payload.length());
497 return absl::StrCat(headers_frame_header, payload);
498 }
499
DataFrame(absl::string_view payload)500 std::string DataFrame(absl::string_view payload) {
501 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
502 payload.length(), quiche::SimpleBufferAllocator::Get());
503 return absl::StrCat(header.AsStringView(), payload);
504 }
505
UnknownFrame(uint64_t frame_type,absl::string_view payload)506 std::string UnknownFrame(uint64_t frame_type, absl::string_view payload) {
507 std::string frame;
508 const size_t length = QuicDataWriter::GetVarInt62Len(frame_type) +
509 QuicDataWriter::GetVarInt62Len(payload.size()) +
510 payload.size();
511 frame.resize(length);
512
513 QuicDataWriter writer(length, const_cast<char*>(frame.data()));
514 writer.WriteVarInt62(frame_type);
515 writer.WriteStringPieceVarInt62(payload);
516 // Even though integers can be encoded with different lengths,
517 // QuicDataWriter is expected to produce an encoding in Write*() of length
518 // promised in GetVarInt62Len().
519 QUICHE_DCHECK_EQ(length, writer.length());
520
521 return frame;
522 }
523
524 MockQuicConnectionHelper helper_;
525 MockAlarmFactory alarm_factory_;
526 MockQuicConnection* connection_;
527 std::unique_ptr<TestSession> session_;
528
529 // Owned by the |session_|.
530 TestStream* stream_;
531 TestStream* stream2_;
532
533 Http2HeaderBlock headers_;
534 };
535
536 INSTANTIATE_TEST_SUITE_P(Tests, QuicSpdyStreamTest,
537 ::testing::ValuesIn(AllSupportedVersions()),
538 ::testing::PrintToStringParamName());
539
TEST_P(QuicSpdyStreamTest,ProcessHeaderList)540 TEST_P(QuicSpdyStreamTest, ProcessHeaderList) {
541 Initialize(kShouldProcessData);
542
543 stream_->OnStreamHeadersPriority(
544 spdy::SpdyStreamPrecedence(kV3HighestPriority));
545 ProcessHeaders(false, headers_);
546 EXPECT_EQ("", stream_->data());
547 EXPECT_FALSE(stream_->header_list().empty());
548 EXPECT_FALSE(stream_->IsDoneReading());
549 }
550
TEST_P(QuicSpdyStreamTest,ProcessTooLargeHeaderList)551 TEST_P(QuicSpdyStreamTest, ProcessTooLargeHeaderList) {
552 Initialize(kShouldProcessData);
553
554 if (!UsesHttp3()) {
555 QuicHeaderList headers;
556 stream_->OnStreamHeadersPriority(
557 spdy::SpdyStreamPrecedence(kV3HighestPriority));
558
559 EXPECT_CALL(
560 *session_,
561 MaybeSendRstStreamFrame(
562 stream_->id(),
563 QuicResetStreamError::FromInternal(QUIC_HEADERS_TOO_LARGE), 0));
564 stream_->OnStreamHeaderList(false, 1 << 20, headers);
565
566 EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_HEADERS_TOO_LARGE));
567
568 return;
569 }
570
571 // Header list size includes 32 bytes for overhead per header field.
572 session_->set_max_inbound_header_list_size(40);
573 std::string headers =
574 HeadersFrame({std::make_pair("foo", "too long headers")});
575
576 QuicStreamFrame frame(stream_->id(), false, 0, headers);
577
578 EXPECT_CALL(*session_, MaybeSendStopSendingFrame(
579 stream_->id(), QuicResetStreamError::FromInternal(
580 QUIC_HEADERS_TOO_LARGE)));
581 EXPECT_CALL(
582 *session_,
583 MaybeSendRstStreamFrame(
584 stream_->id(),
585 QuicResetStreamError::FromInternal(QUIC_HEADERS_TOO_LARGE), 0));
586
587 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
588 auto qpack_decoder_stream =
589 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
590 // Stream type and stream cancellation.
591 EXPECT_CALL(*session_,
592 WritevData(qpack_decoder_stream->id(), _, _, NO_FIN, _, _))
593 .Times(2);
594 }
595
596 stream_->OnStreamFrame(frame);
597 EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_HEADERS_TOO_LARGE));
598 }
599
TEST_P(QuicSpdyStreamTest,QpackProcessLargeHeaderListDiscountOverhead)600 TEST_P(QuicSpdyStreamTest, QpackProcessLargeHeaderListDiscountOverhead) {
601 if (!UsesHttp3()) {
602 return;
603 }
604 // Setting this flag to false causes no per-entry overhead to be included
605 // in the header size.
606 SetQuicFlag(quic_header_size_limit_includes_overhead, false);
607 Initialize(kShouldProcessData);
608 session_->set_max_inbound_header_list_size(40);
609 std::string headers =
610 HeadersFrame({std::make_pair("foo", "too long headers")});
611
612 QuicStreamFrame frame(stream_->id(), false, 0, headers);
613 stream_->OnStreamFrame(frame);
614 EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_NO_ERROR));
615 }
616
TEST_P(QuicSpdyStreamTest,ProcessHeaderListWithFin)617 TEST_P(QuicSpdyStreamTest, ProcessHeaderListWithFin) {
618 Initialize(kShouldProcessData);
619
620 size_t total_bytes = 0;
621 QuicHeaderList headers;
622 for (auto p : headers_) {
623 headers.OnHeader(p.first, p.second);
624 total_bytes += p.first.size() + p.second.size();
625 }
626 stream_->OnStreamHeadersPriority(
627 spdy::SpdyStreamPrecedence(kV3HighestPriority));
628 stream_->OnStreamHeaderList(true, total_bytes, headers);
629 EXPECT_EQ("", stream_->data());
630 EXPECT_FALSE(stream_->header_list().empty());
631 EXPECT_FALSE(stream_->IsDoneReading());
632 EXPECT_TRUE(stream_->HasReceivedFinalOffset());
633 }
634
635 // A valid status code should be 3-digit integer. The first digit should be in
636 // the range of [1, 5]. All the others are invalid.
TEST_P(QuicSpdyStreamTest,ParseHeaderStatusCode)637 TEST_P(QuicSpdyStreamTest, ParseHeaderStatusCode) {
638 Initialize(kShouldProcessData);
639 int status_code = 0;
640
641 // Valid status codes.
642 headers_[":status"] = "404";
643 EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
644 EXPECT_EQ(404, status_code);
645
646 headers_[":status"] = "100";
647 EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
648 EXPECT_EQ(100, status_code);
649
650 headers_[":status"] = "599";
651 EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code));
652 EXPECT_EQ(599, status_code);
653
654 // Invalid status codes.
655 headers_[":status"] = "010";
656 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
657
658 headers_[":status"] = "600";
659 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
660
661 headers_[":status"] = "200 ok";
662 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
663
664 headers_[":status"] = "2000";
665 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
666
667 headers_[":status"] = "+200";
668 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
669
670 headers_[":status"] = "+20";
671 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
672
673 headers_[":status"] = "-10";
674 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
675
676 headers_[":status"] = "-100";
677 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
678
679 // Leading or trailing spaces are also invalid.
680 headers_[":status"] = " 200";
681 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
682
683 headers_[":status"] = "200 ";
684 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
685
686 headers_[":status"] = " 200 ";
687 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
688
689 headers_[":status"] = " ";
690 EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code));
691 }
692
TEST_P(QuicSpdyStreamTest,MarkHeadersConsumed)693 TEST_P(QuicSpdyStreamTest, MarkHeadersConsumed) {
694 Initialize(kShouldProcessData);
695
696 std::string body = "this is the body";
697 QuicHeaderList headers = ProcessHeaders(false, headers_);
698 EXPECT_EQ(headers, stream_->header_list());
699
700 stream_->ConsumeHeaderList();
701 EXPECT_EQ(QuicHeaderList(), stream_->header_list());
702 }
703
TEST_P(QuicSpdyStreamTest,ProcessWrongFramesOnSpdyStream)704 TEST_P(QuicSpdyStreamTest, ProcessWrongFramesOnSpdyStream) {
705 if (!UsesHttp3()) {
706 return;
707 }
708
709 Initialize(kShouldProcessData);
710 testing::InSequence s;
711 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
712 GoAwayFrame goaway;
713 goaway.id = 0x1;
714 std::string goaway_frame = HttpEncoder::SerializeGoAwayFrame(goaway);
715
716 EXPECT_EQ("", stream_->data());
717 QuicHeaderList headers = ProcessHeaders(false, headers_);
718 EXPECT_EQ(headers, stream_->header_list());
719 stream_->ConsumeHeaderList();
720 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
721 goaway_frame);
722
723 EXPECT_CALL(*connection_,
724 CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM, _, _))
725 .WillOnce(
726 (Invoke([this](QuicErrorCode error, const std::string& error_details,
727 ConnectionCloseBehavior connection_close_behavior) {
728 connection_->ReallyCloseConnection(error, error_details,
729 connection_close_behavior);
730 })));
731 EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
732 EXPECT_CALL(*session_, OnConnectionClosed(_, _))
733 .WillOnce(Invoke([this](const QuicConnectionCloseFrame& frame,
734 ConnectionCloseSource source) {
735 session_->ReallyOnConnectionClosed(frame, source);
736 }));
737 EXPECT_CALL(*session_, MaybeSendRstStreamFrame(_, _, _)).Times(2);
738
739 stream_->OnStreamFrame(frame);
740 }
741
TEST_P(QuicSpdyStreamTest,Http3FrameError)742 TEST_P(QuicSpdyStreamTest, Http3FrameError) {
743 if (!UsesHttp3()) {
744 return;
745 }
746
747 Initialize(kShouldProcessData);
748
749 // PUSH_PROMISE frame is considered invalid.
750 std::string invalid_http3_frame;
751 ASSERT_TRUE(absl::HexStringToBytes("0500", &invalid_http3_frame));
752 QuicStreamFrame stream_frame(stream_->id(), /* fin = */ false,
753 /* offset = */ 0, invalid_http3_frame);
754
755 EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR, _, _));
756 stream_->OnStreamFrame(stream_frame);
757 }
758
TEST_P(QuicSpdyStreamTest,UnexpectedHttp3Frame)759 TEST_P(QuicSpdyStreamTest, UnexpectedHttp3Frame) {
760 if (!UsesHttp3()) {
761 return;
762 }
763
764 Initialize(kShouldProcessData);
765
766 // SETTINGS frame with empty payload.
767 std::string settings;
768 ASSERT_TRUE(absl::HexStringToBytes("0400", &settings));
769 QuicStreamFrame stream_frame(stream_->id(), /* fin = */ false,
770 /* offset = */ 0, settings);
771
772 EXPECT_CALL(*connection_,
773 CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM, _, _));
774 stream_->OnStreamFrame(stream_frame);
775 }
776
TEST_P(QuicSpdyStreamTest,ProcessHeadersAndBody)777 TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBody) {
778 Initialize(kShouldProcessData);
779
780 std::string body = "this is the body";
781 std::string data = UsesHttp3() ? DataFrame(body) : body;
782
783 EXPECT_EQ("", stream_->data());
784 QuicHeaderList headers = ProcessHeaders(false, headers_);
785 EXPECT_EQ(headers, stream_->header_list());
786 stream_->ConsumeHeaderList();
787 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
788 absl::string_view(data));
789 stream_->OnStreamFrame(frame);
790 EXPECT_EQ(QuicHeaderList(), stream_->header_list());
791 EXPECT_EQ(body, stream_->data());
792 }
793
TEST_P(QuicSpdyStreamTest,ProcessHeadersAndBodyFragments)794 TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragments) {
795 std::string body = "this is the body";
796 std::string data = UsesHttp3() ? DataFrame(body) : body;
797
798 for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) {
799 Initialize(kShouldProcessData);
800 QuicHeaderList headers = ProcessHeaders(false, headers_);
801 ASSERT_EQ(headers, stream_->header_list());
802 stream_->ConsumeHeaderList();
803 for (size_t offset = 0; offset < data.size(); offset += fragment_size) {
804 size_t remaining_data = data.size() - offset;
805 absl::string_view fragment(data.data() + offset,
806 std::min(fragment_size, remaining_data));
807 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false,
808 offset, absl::string_view(fragment));
809 stream_->OnStreamFrame(frame);
810 }
811 ASSERT_EQ(body, stream_->data()) << "fragment_size: " << fragment_size;
812 }
813 }
814
TEST_P(QuicSpdyStreamTest,ProcessHeadersAndBodyFragmentsSplit)815 TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragmentsSplit) {
816 std::string body = "this is the body";
817 std::string data = UsesHttp3() ? DataFrame(body) : body;
818
819 for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) {
820 Initialize(kShouldProcessData);
821 QuicHeaderList headers = ProcessHeaders(false, headers_);
822 ASSERT_EQ(headers, stream_->header_list());
823 stream_->ConsumeHeaderList();
824
825 absl::string_view fragment1(data.data(), split_point);
826 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
827 absl::string_view(fragment1));
828 stream_->OnStreamFrame(frame1);
829
830 absl::string_view fragment2(data.data() + split_point,
831 data.size() - split_point);
832 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
833 split_point, absl::string_view(fragment2));
834 stream_->OnStreamFrame(frame2);
835
836 ASSERT_EQ(body, stream_->data()) << "split_point: " << split_point;
837 }
838 }
839
TEST_P(QuicSpdyStreamTest,ProcessHeadersAndBodyReadv)840 TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyReadv) {
841 Initialize(!kShouldProcessData);
842
843 std::string body = "this is the body";
844 std::string data = UsesHttp3() ? DataFrame(body) : body;
845
846 ProcessHeaders(false, headers_);
847 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
848 absl::string_view(data));
849 stream_->OnStreamFrame(frame);
850 stream_->ConsumeHeaderList();
851
852 char buffer[2048];
853 ASSERT_LT(data.length(), ABSL_ARRAYSIZE(buffer));
854 struct iovec vec;
855 vec.iov_base = buffer;
856 vec.iov_len = ABSL_ARRAYSIZE(buffer);
857
858 size_t bytes_read = stream_->Readv(&vec, 1);
859 QuicStreamPeer::CloseReadSide(stream_);
860 EXPECT_EQ(body.length(), bytes_read);
861 EXPECT_EQ(body, std::string(buffer, bytes_read));
862 }
863
TEST_P(QuicSpdyStreamTest,ProcessHeadersAndLargeBodySmallReadv)864 TEST_P(QuicSpdyStreamTest, ProcessHeadersAndLargeBodySmallReadv) {
865 Initialize(kShouldProcessData);
866 std::string body(12 * 1024, 'a');
867 std::string data = UsesHttp3() ? DataFrame(body) : body;
868
869 ProcessHeaders(false, headers_);
870 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
871 absl::string_view(data));
872 stream_->OnStreamFrame(frame);
873 stream_->ConsumeHeaderList();
874 char buffer[2048];
875 char buffer2[2048];
876 struct iovec vec[2];
877 vec[0].iov_base = buffer;
878 vec[0].iov_len = ABSL_ARRAYSIZE(buffer);
879 vec[1].iov_base = buffer2;
880 vec[1].iov_len = ABSL_ARRAYSIZE(buffer2);
881 size_t bytes_read = stream_->Readv(vec, 2);
882 EXPECT_EQ(2048u * 2, bytes_read);
883 EXPECT_EQ(body.substr(0, 2048), std::string(buffer, 2048));
884 EXPECT_EQ(body.substr(2048, 2048), std::string(buffer2, 2048));
885 }
886
TEST_P(QuicSpdyStreamTest,ProcessHeadersAndBodyMarkConsumed)887 TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyMarkConsumed) {
888 Initialize(!kShouldProcessData);
889
890 std::string body = "this is the body";
891 std::string data = UsesHttp3() ? DataFrame(body) : body;
892
893 ProcessHeaders(false, headers_);
894 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
895 absl::string_view(data));
896 stream_->OnStreamFrame(frame);
897 stream_->ConsumeHeaderList();
898
899 struct iovec vec;
900
901 EXPECT_EQ(1, stream_->GetReadableRegions(&vec, 1));
902 EXPECT_EQ(body.length(), vec.iov_len);
903 EXPECT_EQ(body, std::string(static_cast<char*>(vec.iov_base), vec.iov_len));
904
905 stream_->MarkConsumed(body.length());
906 EXPECT_EQ(data.length(), QuicStreamPeer::bytes_consumed(stream_));
907 }
908
TEST_P(QuicSpdyStreamTest,ProcessHeadersAndConsumeMultipleBody)909 TEST_P(QuicSpdyStreamTest, ProcessHeadersAndConsumeMultipleBody) {
910 Initialize(!kShouldProcessData);
911 std::string body1 = "this is body 1";
912 std::string data1 = UsesHttp3() ? DataFrame(body1) : body1;
913 std::string body2 = "body 2";
914 std::string data2 = UsesHttp3() ? DataFrame(body2) : body2;
915
916 ProcessHeaders(false, headers_);
917 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
918 absl::string_view(data1));
919 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
920 data1.length(), absl::string_view(data2));
921 stream_->OnStreamFrame(frame1);
922 stream_->OnStreamFrame(frame2);
923 stream_->ConsumeHeaderList();
924
925 stream_->MarkConsumed(body1.length() + body2.length());
926 EXPECT_EQ(data1.length() + data2.length(),
927 QuicStreamPeer::bytes_consumed(stream_));
928 }
929
TEST_P(QuicSpdyStreamTest,ProcessHeadersAndBodyIncrementalReadv)930 TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyIncrementalReadv) {
931 Initialize(!kShouldProcessData);
932
933 std::string body = "this is the body";
934 std::string data = UsesHttp3() ? DataFrame(body) : body;
935
936 ProcessHeaders(false, headers_);
937 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
938 absl::string_view(data));
939 stream_->OnStreamFrame(frame);
940 stream_->ConsumeHeaderList();
941
942 char buffer[1];
943 struct iovec vec;
944 vec.iov_base = buffer;
945 vec.iov_len = ABSL_ARRAYSIZE(buffer);
946
947 for (size_t i = 0; i < body.length(); ++i) {
948 size_t bytes_read = stream_->Readv(&vec, 1);
949 ASSERT_EQ(1u, bytes_read);
950 EXPECT_EQ(body.data()[i], buffer[0]);
951 }
952 }
953
TEST_P(QuicSpdyStreamTest,ProcessHeadersUsingReadvWithMultipleIovecs)954 TEST_P(QuicSpdyStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
955 Initialize(!kShouldProcessData);
956
957 std::string body = "this is the body";
958 std::string data = UsesHttp3() ? DataFrame(body) : body;
959
960 ProcessHeaders(false, headers_);
961 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
962 absl::string_view(data));
963 stream_->OnStreamFrame(frame);
964 stream_->ConsumeHeaderList();
965
966 char buffer1[1];
967 char buffer2[1];
968 struct iovec vec[2];
969 vec[0].iov_base = buffer1;
970 vec[0].iov_len = ABSL_ARRAYSIZE(buffer1);
971 vec[1].iov_base = buffer2;
972 vec[1].iov_len = ABSL_ARRAYSIZE(buffer2);
973
974 for (size_t i = 0; i < body.length(); i += 2) {
975 size_t bytes_read = stream_->Readv(vec, 2);
976 ASSERT_EQ(2u, bytes_read) << i;
977 ASSERT_EQ(body.data()[i], buffer1[0]) << i;
978 ASSERT_EQ(body.data()[i + 1], buffer2[0]) << i;
979 }
980 }
981
982 // Tests that we send a BLOCKED frame to the peer when we attempt to write, but
983 // are flow control blocked.
TEST_P(QuicSpdyStreamTest,StreamFlowControlBlocked)984 TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) {
985 Initialize(kShouldProcessData);
986 testing::InSequence seq;
987
988 // Set a small flow control limit.
989 const uint64_t kWindow = 36;
990 QuicStreamPeer::SetSendWindowOffset(stream_, kWindow);
991 EXPECT_EQ(kWindow, QuicStreamPeer::SendWindowOffset(stream_));
992
993 // Try to send more data than the flow control limit allows.
994 const uint64_t kOverflow = 15;
995 std::string body(kWindow + kOverflow, 'a');
996
997 const uint64_t kHeaderLength = UsesHttp3() ? 2 : 0;
998 if (UsesHttp3()) {
999 EXPECT_CALL(*session_, WritevData(_, kHeaderLength, _, NO_FIN, _, _));
1000 }
1001 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
1002 .WillOnce(Return(QuicConsumedData(kWindow - kHeaderLength, true)));
1003 EXPECT_CALL(*session_, SendBlocked(_, _));
1004 EXPECT_CALL(*connection_, SendControlFrame(_));
1005 stream_->WriteOrBufferBody(body, false);
1006
1007 // Should have sent as much as possible, resulting in no send window left.
1008 EXPECT_EQ(0u, QuicStreamPeer::SendWindowSize(stream_));
1009
1010 // And we should have queued the overflowed data.
1011 EXPECT_EQ(kOverflow + kHeaderLength, stream_->BufferedDataBytes());
1012 }
1013
1014 // The flow control receive window decreases whenever we add new bytes to the
1015 // sequencer, whether they are consumed immediately or buffered. However we only
1016 // send WINDOW_UPDATE frames based on increasing number of bytes consumed.
TEST_P(QuicSpdyStreamTest,StreamFlowControlNoWindowUpdateIfNotConsumed)1017 TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) {
1018 // Don't process data - it will be buffered instead.
1019 Initialize(!kShouldProcessData);
1020
1021 // Expect no WINDOW_UPDATE frames to be sent.
1022 EXPECT_CALL(*session_, SendWindowUpdate(_, _)).Times(0);
1023
1024 // Set a small flow control receive window.
1025 const uint64_t kWindow = 36;
1026 QuicStreamPeer::SetReceiveWindowOffset(stream_, kWindow);
1027 QuicStreamPeer::SetMaxReceiveWindow(stream_, kWindow);
1028
1029 // Stream receives enough data to fill a fraction of the receive window.
1030 std::string body(kWindow / 3, 'a');
1031 QuicByteCount header_length = 0;
1032 std::string data;
1033
1034 if (UsesHttp3()) {
1035 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
1036 body.length(), quiche::SimpleBufferAllocator::Get());
1037 data = absl::StrCat(header.AsStringView(), body);
1038 header_length = header.size();
1039 } else {
1040 data = body;
1041 }
1042
1043 ProcessHeaders(false, headers_);
1044
1045 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
1046 absl::string_view(data));
1047 stream_->OnStreamFrame(frame1);
1048 EXPECT_EQ(kWindow - (kWindow / 3) - header_length,
1049 QuicStreamPeer::ReceiveWindowSize(stream_));
1050
1051 // Now receive another frame which results in the receive window being over
1052 // half full. This should all be buffered, decreasing the receive window but
1053 // not sending WINDOW_UPDATE.
1054 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
1055 kWindow / 3 + header_length, absl::string_view(data));
1056 stream_->OnStreamFrame(frame2);
1057 EXPECT_EQ(kWindow - (2 * kWindow / 3) - 2 * header_length,
1058 QuicStreamPeer::ReceiveWindowSize(stream_));
1059 }
1060
1061 // Tests that on receipt of data, the stream updates its receive window offset
1062 // appropriately, and sends WINDOW_UPDATE frames when its receive window drops
1063 // too low.
TEST_P(QuicSpdyStreamTest,StreamFlowControlWindowUpdate)1064 TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) {
1065 Initialize(kShouldProcessData);
1066
1067 // Set a small flow control limit.
1068 const uint64_t kWindow = 36;
1069 QuicStreamPeer::SetReceiveWindowOffset(stream_, kWindow);
1070 QuicStreamPeer::SetMaxReceiveWindow(stream_, kWindow);
1071
1072 // Stream receives enough data to fill a fraction of the receive window.
1073 std::string body(kWindow / 3, 'a');
1074 QuicByteCount header_length = 0;
1075 std::string data;
1076
1077 if (UsesHttp3()) {
1078 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
1079 body.length(), quiche::SimpleBufferAllocator::Get());
1080 data = absl::StrCat(header.AsStringView(), body);
1081 header_length = header.size();
1082 } else {
1083 data = body;
1084 }
1085
1086 ProcessHeaders(false, headers_);
1087 stream_->ConsumeHeaderList();
1088
1089 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
1090 absl::string_view(data));
1091 stream_->OnStreamFrame(frame1);
1092 EXPECT_EQ(kWindow - (kWindow / 3) - header_length,
1093 QuicStreamPeer::ReceiveWindowSize(stream_));
1094
1095 // Now receive another frame which results in the receive window being over
1096 // half full. This will trigger the stream to increase its receive window
1097 // offset and send a WINDOW_UPDATE. The result will be again an available
1098 // window of kWindow bytes.
1099 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
1100 kWindow / 3 + header_length, absl::string_view(data));
1101 EXPECT_CALL(*session_, SendWindowUpdate(_, _));
1102 EXPECT_CALL(*connection_, SendControlFrame(_));
1103 stream_->OnStreamFrame(frame2);
1104 EXPECT_EQ(kWindow, QuicStreamPeer::ReceiveWindowSize(stream_));
1105 }
1106
1107 // Tests that on receipt of data, the connection updates its receive window
1108 // offset appropriately, and sends WINDOW_UPDATE frames when its receive window
1109 // drops too low.
TEST_P(QuicSpdyStreamTest,ConnectionFlowControlWindowUpdate)1110 TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) {
1111 Initialize(kShouldProcessData);
1112
1113 // Set a small flow control limit for streams and connection.
1114 const uint64_t kWindow = 36;
1115 QuicStreamPeer::SetReceiveWindowOffset(stream_, kWindow);
1116 QuicStreamPeer::SetMaxReceiveWindow(stream_, kWindow);
1117 QuicStreamPeer::SetReceiveWindowOffset(stream2_, kWindow);
1118 QuicStreamPeer::SetMaxReceiveWindow(stream2_, kWindow);
1119 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(),
1120 kWindow);
1121 QuicFlowControllerPeer::SetMaxReceiveWindow(session_->flow_controller(),
1122 kWindow);
1123
1124 // Supply headers to both streams so that they are happy to receive data.
1125 auto headers = AsHeaderList(headers_);
1126 stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
1127 headers);
1128 stream_->ConsumeHeaderList();
1129 stream2_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
1130 headers);
1131 stream2_->ConsumeHeaderList();
1132
1133 // Each stream gets a quarter window of data. This should not trigger a
1134 // WINDOW_UPDATE for either stream, nor for the connection.
1135 QuicByteCount header_length = 0;
1136 std::string body;
1137 std::string data;
1138 std::string data2;
1139 std::string body2(1, 'a');
1140
1141 if (UsesHttp3()) {
1142 body = std::string(kWindow / 4 - 2, 'a');
1143 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
1144 body.length(), quiche::SimpleBufferAllocator::Get());
1145 data = absl::StrCat(header.AsStringView(), body);
1146 header_length = header.size();
1147 quiche::QuicheBuffer header2 = HttpEncoder::SerializeDataFrameHeader(
1148 body.length(), quiche::SimpleBufferAllocator::Get());
1149 data2 = absl::StrCat(header2.AsStringView(), body2);
1150 } else {
1151 body = std::string(kWindow / 4, 'a');
1152 data = body;
1153 data2 = body2;
1154 }
1155
1156 QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
1157 absl::string_view(data));
1158 stream_->OnStreamFrame(frame1);
1159 QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
1160 absl::string_view(data));
1161 stream2_->OnStreamFrame(frame2);
1162
1163 // Now receive a further single byte on one stream - again this does not
1164 // trigger a stream WINDOW_UPDATE, but now the connection flow control window
1165 // is over half full and thus a connection WINDOW_UPDATE is sent.
1166 EXPECT_CALL(*session_, SendWindowUpdate(_, _));
1167 EXPECT_CALL(*connection_, SendControlFrame(_));
1168 QuicStreamFrame frame3(GetNthClientInitiatedBidirectionalId(0), false,
1169 body.length() + header_length,
1170 absl::string_view(data2));
1171 stream_->OnStreamFrame(frame3);
1172 }
1173
1174 // Tests that on if the peer sends too much data (i.e. violates the flow control
1175 // protocol), then we terminate the connection.
TEST_P(QuicSpdyStreamTest,StreamFlowControlViolation)1176 TEST_P(QuicSpdyStreamTest, StreamFlowControlViolation) {
1177 // Stream should not process data, so that data gets buffered in the
1178 // sequencer, triggering flow control limits.
1179 Initialize(!kShouldProcessData);
1180
1181 // Set a small flow control limit.
1182 const uint64_t kWindow = 50;
1183 QuicStreamPeer::SetReceiveWindowOffset(stream_, kWindow);
1184
1185 ProcessHeaders(false, headers_);
1186
1187 // Receive data to overflow the window, violating flow control.
1188 std::string body(kWindow + 1, 'a');
1189 std::string data = UsesHttp3() ? DataFrame(body) : body;
1190 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
1191 absl::string_view(data));
1192 EXPECT_CALL(*connection_,
1193 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
1194 stream_->OnStreamFrame(frame);
1195 }
1196
TEST_P(QuicSpdyStreamTest,TestHandlingQuicRstStreamNoError)1197 TEST_P(QuicSpdyStreamTest, TestHandlingQuicRstStreamNoError) {
1198 Initialize(kShouldProcessData);
1199 ProcessHeaders(false, headers_);
1200
1201 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber());
1202
1203 stream_->OnStreamReset(QuicRstStreamFrame(
1204 kInvalidControlFrameId, stream_->id(), QUIC_STREAM_NO_ERROR, 0));
1205
1206 if (UsesHttp3()) {
1207 // RESET_STREAM should close the read side but not the write side.
1208 EXPECT_TRUE(stream_->read_side_closed());
1209 EXPECT_FALSE(stream_->write_side_closed());
1210 } else {
1211 EXPECT_TRUE(stream_->write_side_closed());
1212 EXPECT_FALSE(stream_->reading_stopped());
1213 }
1214 }
1215
1216 // Tests that on if the peer sends too much data (i.e. violates the flow control
1217 // protocol), at the connection level (rather than the stream level) then we
1218 // terminate the connection.
TEST_P(QuicSpdyStreamTest,ConnectionFlowControlViolation)1219 TEST_P(QuicSpdyStreamTest, ConnectionFlowControlViolation) {
1220 // Stream should not process data, so that data gets buffered in the
1221 // sequencer, triggering flow control limits.
1222 Initialize(!kShouldProcessData);
1223
1224 // Set a small flow control window on streams, and connection.
1225 const uint64_t kStreamWindow = 50;
1226 const uint64_t kConnectionWindow = 10;
1227 QuicStreamPeer::SetReceiveWindowOffset(stream_, kStreamWindow);
1228 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(),
1229 kConnectionWindow);
1230
1231 ProcessHeaders(false, headers_);
1232
1233 // Send enough data to overflow the connection level flow control window.
1234 std::string body(kConnectionWindow + 1, 'a');
1235 std::string data = UsesHttp3() ? DataFrame(body) : body;
1236
1237 EXPECT_LT(data.size(), kStreamWindow);
1238 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
1239 absl::string_view(data));
1240
1241 EXPECT_CALL(*connection_,
1242 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
1243 stream_->OnStreamFrame(frame);
1244 }
1245
1246 // An attempt to write a FIN with no data should not be flow control blocked,
1247 // even if the send window is 0.
TEST_P(QuicSpdyStreamTest,StreamFlowControlFinNotBlocked)1248 TEST_P(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) {
1249 Initialize(kShouldProcessData);
1250
1251 // Set a flow control limit of zero.
1252 QuicStreamPeer::SetReceiveWindowOffset(stream_, 0);
1253
1254 // Send a frame with a FIN but no data. This should not be blocked.
1255 std::string body = "";
1256 bool fin = true;
1257
1258 EXPECT_CALL(*session_,
1259 SendBlocked(GetNthClientInitiatedBidirectionalId(0), _))
1260 .Times(0);
1261 EXPECT_CALL(*session_, WritevData(_, 0, _, FIN, _, _));
1262
1263 stream_->WriteOrBufferBody(body, fin);
1264 }
1265
1266 // Test that receiving trailing headers from the peer via OnStreamHeaderList()
1267 // works, and can be read from the stream and consumed.
TEST_P(QuicSpdyStreamTest,ReceivingTrailersViaHeaderList)1268 TEST_P(QuicSpdyStreamTest, ReceivingTrailersViaHeaderList) {
1269 Initialize(kShouldProcessData);
1270
1271 // Receive initial headers.
1272 size_t total_bytes = 0;
1273 QuicHeaderList headers;
1274 for (const auto& p : headers_) {
1275 headers.OnHeader(p.first, p.second);
1276 total_bytes += p.first.size() + p.second.size();
1277 }
1278
1279 stream_->OnStreamHeadersPriority(
1280 spdy::SpdyStreamPrecedence(kV3HighestPriority));
1281 stream_->OnStreamHeaderList(/*fin=*/false, total_bytes, headers);
1282 stream_->ConsumeHeaderList();
1283
1284 // Receive trailing headers.
1285 Http2HeaderBlock trailers_block;
1286 trailers_block["key1"] = "value1";
1287 trailers_block["key2"] = "value2";
1288 trailers_block["key3"] = "value3";
1289 Http2HeaderBlock trailers_block_with_final_offset = trailers_block.Clone();
1290 if (!UsesHttp3()) {
1291 // :final-offset pseudo-header is only added if trailers are sent
1292 // on the headers stream.
1293 trailers_block_with_final_offset[kFinalOffsetHeaderKey] = "0";
1294 }
1295 total_bytes = 0;
1296 QuicHeaderList trailers;
1297 for (const auto& p : trailers_block_with_final_offset) {
1298 trailers.OnHeader(p.first, p.second);
1299 total_bytes += p.first.size() + p.second.size();
1300 }
1301 stream_->OnStreamHeaderList(/*fin=*/true, total_bytes, trailers);
1302
1303 // The trailers should be decompressed, and readable from the stream.
1304 EXPECT_TRUE(stream_->trailers_decompressed());
1305 EXPECT_EQ(trailers_block, stream_->received_trailers());
1306
1307 // IsDoneReading() returns false until trailers marked consumed.
1308 EXPECT_FALSE(stream_->IsDoneReading());
1309 stream_->MarkTrailersConsumed();
1310 EXPECT_TRUE(stream_->IsDoneReading());
1311 }
1312
1313 // Test that when receiving trailing headers with an offset before response
1314 // body, stream is closed at the right offset.
TEST_P(QuicSpdyStreamTest,ReceivingTrailersWithOffset)1315 TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) {
1316 // kFinalOffsetHeaderKey is not used when HEADERS are sent on the
1317 // request/response stream.
1318 if (UsesHttp3()) {
1319 return;
1320 }
1321
1322 Initialize(kShouldProcessData);
1323
1324 // Receive initial headers.
1325 QuicHeaderList headers = ProcessHeaders(false, headers_);
1326 stream_->ConsumeHeaderList();
1327
1328 const std::string body = "this is the body";
1329 std::string data = UsesHttp3() ? DataFrame(body) : body;
1330
1331 // Receive trailing headers.
1332 Http2HeaderBlock trailers_block;
1333 trailers_block["key1"] = "value1";
1334 trailers_block["key2"] = "value2";
1335 trailers_block["key3"] = "value3";
1336 trailers_block[kFinalOffsetHeaderKey] = absl::StrCat(data.size());
1337
1338 QuicHeaderList trailers = ProcessHeaders(true, trailers_block);
1339
1340 // The trailers should be decompressed, and readable from the stream.
1341 EXPECT_TRUE(stream_->trailers_decompressed());
1342
1343 // The final offset trailer will be consumed by QUIC.
1344 trailers_block.erase(kFinalOffsetHeaderKey);
1345 EXPECT_EQ(trailers_block, stream_->received_trailers());
1346
1347 // Consuming the trailers erases them from the stream.
1348 stream_->MarkTrailersConsumed();
1349 EXPECT_TRUE(stream_->FinishedReadingTrailers());
1350
1351 EXPECT_FALSE(stream_->IsDoneReading());
1352 // Receive and consume body.
1353 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/false,
1354 0, data);
1355 stream_->OnStreamFrame(frame);
1356 EXPECT_EQ(body, stream_->data());
1357 EXPECT_TRUE(stream_->IsDoneReading());
1358 }
1359
1360 // Test that receiving trailers without a final offset field is an error.
TEST_P(QuicSpdyStreamTest,ReceivingTrailersWithoutOffset)1361 TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutOffset) {
1362 // kFinalOffsetHeaderKey is not used when HEADERS are sent on the
1363 // request/response stream.
1364 if (UsesHttp3()) {
1365 return;
1366 }
1367
1368 Initialize(kShouldProcessData);
1369
1370 // Receive initial headers.
1371 ProcessHeaders(false, headers_);
1372 stream_->ConsumeHeaderList();
1373
1374 // Receive trailing headers, without kFinalOffsetHeaderKey.
1375 Http2HeaderBlock trailers_block;
1376 trailers_block["key1"] = "value1";
1377 trailers_block["key2"] = "value2";
1378 trailers_block["key3"] = "value3";
1379 auto trailers = AsHeaderList(trailers_block);
1380
1381 // Verify that the trailers block didn't contain a final offset.
1382 EXPECT_EQ("", trailers_block[kFinalOffsetHeaderKey].as_string());
1383
1384 // Receipt of the malformed trailers will close the connection.
1385 EXPECT_CALL(*connection_,
1386 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1387 .Times(1);
1388 stream_->OnStreamHeaderList(/*fin=*/true,
1389 trailers.uncompressed_header_bytes(), trailers);
1390 }
1391
1392 // Test that received Trailers must always have the FIN set.
TEST_P(QuicSpdyStreamTest,ReceivingTrailersWithoutFin)1393 TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutFin) {
1394 // In IETF QUIC, there is no such thing as FIN flag on HTTP/3 frames like the
1395 // HEADERS frame.
1396 if (UsesHttp3()) {
1397 return;
1398 }
1399
1400 Initialize(kShouldProcessData);
1401
1402 // Receive initial headers.
1403 auto headers = AsHeaderList(headers_);
1404 stream_->OnStreamHeaderList(/*fin=*/false,
1405 headers.uncompressed_header_bytes(), headers);
1406 stream_->ConsumeHeaderList();
1407
1408 // Receive trailing headers with FIN deliberately set to false.
1409 Http2HeaderBlock trailers_block;
1410 trailers_block["foo"] = "bar";
1411 auto trailers = AsHeaderList(trailers_block);
1412
1413 EXPECT_CALL(*connection_,
1414 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1415 .Times(1);
1416 stream_->OnStreamHeaderList(/*fin=*/false,
1417 trailers.uncompressed_header_bytes(), trailers);
1418 }
1419
TEST_P(QuicSpdyStreamTest,ReceivingTrailersAfterHeadersWithFin)1420 TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterHeadersWithFin) {
1421 // If headers are received with a FIN, no trailers should then arrive.
1422 Initialize(kShouldProcessData);
1423
1424 // If HEADERS frames are sent on the request/response stream, then the
1425 // sequencer will signal an error if any stream data arrives after a FIN,
1426 // so QuicSpdyStream does not need to.
1427 if (UsesHttp3()) {
1428 return;
1429 }
1430
1431 // Receive initial headers with FIN set.
1432 ProcessHeaders(true, headers_);
1433 stream_->ConsumeHeaderList();
1434
1435 // Receive trailing headers after FIN already received.
1436 Http2HeaderBlock trailers_block;
1437 trailers_block["foo"] = "bar";
1438 EXPECT_CALL(*connection_,
1439 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1440 .Times(1);
1441 ProcessHeaders(true, trailers_block);
1442 }
1443
1444 // If body data are received with a FIN, no trailers should then arrive.
TEST_P(QuicSpdyStreamTest,ReceivingTrailersAfterBodyWithFin)1445 TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterBodyWithFin) {
1446 // If HEADERS frames are sent on the request/response stream,
1447 // then the sequencer will block them from reaching QuicSpdyStream
1448 // after the stream is closed.
1449 if (UsesHttp3()) {
1450 return;
1451 }
1452
1453 Initialize(kShouldProcessData);
1454
1455 // Receive initial headers without FIN set.
1456 ProcessHeaders(false, headers_);
1457 stream_->ConsumeHeaderList();
1458
1459 // Receive body data, with FIN.
1460 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/true,
1461 0, "body");
1462 stream_->OnStreamFrame(frame);
1463
1464 // Receive trailing headers after FIN already received.
1465 Http2HeaderBlock trailers_block;
1466 trailers_block["foo"] = "bar";
1467 EXPECT_CALL(*connection_,
1468 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
1469 .Times(1);
1470 ProcessHeaders(true, trailers_block);
1471 }
1472
TEST_P(QuicSpdyStreamTest,ClosingStreamWithNoTrailers)1473 TEST_P(QuicSpdyStreamTest, ClosingStreamWithNoTrailers) {
1474 // Verify that a stream receiving headers, body, and no trailers is correctly
1475 // marked as done reading on consumption of headers and body.
1476 Initialize(kShouldProcessData);
1477
1478 // Receive and consume initial headers with FIN not set.
1479 auto h = AsHeaderList(headers_);
1480 stream_->OnStreamHeaderList(/*fin=*/false, h.uncompressed_header_bytes(), h);
1481 stream_->ConsumeHeaderList();
1482
1483 // Receive and consume body with FIN set, and no trailers.
1484 std::string body(1024, 'x');
1485 std::string data = UsesHttp3() ? DataFrame(body) : body;
1486
1487 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/true,
1488 0, data);
1489 stream_->OnStreamFrame(frame);
1490
1491 EXPECT_TRUE(stream_->IsDoneReading());
1492 }
1493
1494 // Test that writing trailers will send a FIN, as Trailers are the last thing to
1495 // be sent on a stream.
TEST_P(QuicSpdyStreamTest,WritingTrailersSendsAFin)1496 TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) {
1497 Initialize(kShouldProcessData);
1498
1499 if (UsesHttp3()) {
1500 // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
1501 // Four writes on the request stream: HEADERS frame header and payload both
1502 // for headers and trailers.
1503 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(2);
1504 }
1505
1506 // Write the initial headers, without a FIN.
1507 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1508 stream_->WriteHeaders(Http2HeaderBlock(), /*fin=*/false, nullptr);
1509
1510 // Writing trailers implicitly sends a FIN.
1511 Http2HeaderBlock trailers;
1512 trailers["trailer key"] = "trailer value";
1513 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1514 stream_->WriteTrailers(std::move(trailers), nullptr);
1515 EXPECT_TRUE(stream_->fin_sent());
1516 }
1517
TEST_P(QuicSpdyStreamTest,DoNotSendPriorityUpdateWithDefaultUrgency)1518 TEST_P(QuicSpdyStreamTest, DoNotSendPriorityUpdateWithDefaultUrgency) {
1519 if (!UsesHttp3()) {
1520 return;
1521 }
1522
1523 InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
1524 StrictMock<MockHttp3DebugVisitor> debug_visitor;
1525 session_->set_debug_visitor(&debug_visitor);
1526
1527 // Four writes on the request stream: HEADERS frame header and payload both
1528 // for headers and trailers.
1529 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(2);
1530
1531 // No PRIORITY_UPDATE frames on the control stream,
1532 // because the stream has default priority.
1533 auto send_control_stream =
1534 QuicSpdySessionPeer::GetSendControlStream(session_.get());
1535 EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _))
1536 .Times(0);
1537
1538 // Write the initial headers, without a FIN.
1539 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1540 EXPECT_CALL(debug_visitor, OnHeadersFrameSent(stream_->id(), _));
1541 stream_->WriteHeaders(Http2HeaderBlock(), /*fin=*/false, nullptr);
1542
1543 // Writing trailers implicitly sends a FIN.
1544 Http2HeaderBlock trailers;
1545 trailers["trailer key"] = "trailer value";
1546 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1547 EXPECT_CALL(debug_visitor, OnHeadersFrameSent(stream_->id(), _));
1548 stream_->WriteTrailers(std::move(trailers), nullptr);
1549 EXPECT_TRUE(stream_->fin_sent());
1550 }
1551
TEST_P(QuicSpdyStreamTest,ChangePriority)1552 TEST_P(QuicSpdyStreamTest, ChangePriority) {
1553 if (!UsesHttp3()) {
1554 return;
1555 }
1556
1557 InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
1558 StrictMock<MockHttp3DebugVisitor> debug_visitor;
1559 session_->set_debug_visitor(&debug_visitor);
1560
1561 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(1);
1562 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1563 EXPECT_CALL(debug_visitor, OnHeadersFrameSent(stream_->id(), _));
1564 stream_->WriteHeaders(Http2HeaderBlock(), /*fin=*/false, nullptr);
1565 testing::Mock::VerifyAndClearExpectations(&debug_visitor);
1566
1567 // PRIORITY_UPDATE frame on the control stream.
1568 auto send_control_stream =
1569 QuicSpdySessionPeer::GetSendControlStream(session_.get());
1570 EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _));
1571 PriorityUpdateFrame priority_update1{stream_->id(), "u=0"};
1572 EXPECT_CALL(debug_visitor, OnPriorityUpdateFrameSent(priority_update1));
1573 const HttpStreamPriority priority1{kV3HighestPriority,
1574 HttpStreamPriority::kDefaultIncremental};
1575 stream_->SetPriority(QuicStreamPriority(priority1));
1576 testing::Mock::VerifyAndClearExpectations(&debug_visitor);
1577
1578 // Send another PRIORITY_UPDATE frame with incremental flag set to true.
1579 EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _));
1580 PriorityUpdateFrame priority_update2{stream_->id(), "u=2, i"};
1581 EXPECT_CALL(debug_visitor, OnPriorityUpdateFrameSent(priority_update2));
1582 const HttpStreamPriority priority2{2, true};
1583 stream_->SetPriority(QuicStreamPriority(priority2));
1584 testing::Mock::VerifyAndClearExpectations(&debug_visitor);
1585
1586 // Calling SetPriority() with the same priority does not trigger sending
1587 // another PRIORITY_UPDATE frame.
1588 stream_->SetPriority(QuicStreamPriority(priority2));
1589 }
1590
TEST_P(QuicSpdyStreamTest,ChangePriorityBeforeWritingHeaders)1591 TEST_P(QuicSpdyStreamTest, ChangePriorityBeforeWritingHeaders) {
1592 if (!UsesHttp3()) {
1593 return;
1594 }
1595
1596 InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
1597
1598 // PRIORITY_UPDATE frame sent on the control stream as soon as SetPriority()
1599 // is called, before HEADERS frame is sent.
1600 auto send_control_stream =
1601 QuicSpdySessionPeer::GetSendControlStream(session_.get());
1602 EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _));
1603
1604 stream_->SetPriority(QuicStreamPriority(HttpStreamPriority{
1605 kV3HighestPriority, HttpStreamPriority::kDefaultIncremental}));
1606 testing::Mock::VerifyAndClearExpectations(session_.get());
1607
1608 // Two writes on the request stream: HEADERS frame header and payload.
1609 // PRIORITY_UPDATE frame is not sent this time, because one is already sent.
1610 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(1);
1611 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1612 stream_->WriteHeaders(Http2HeaderBlock(), /*fin=*/true, nullptr);
1613 }
1614
1615 // Test that when writing trailers, the trailers that are actually sent to the
1616 // peer contain the final offset field indicating last byte of data.
TEST_P(QuicSpdyStreamTest,WritingTrailersFinalOffset)1617 TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
1618 Initialize(kShouldProcessData);
1619
1620 if (UsesHttp3()) {
1621 // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
1622 // HEADERS frame header and payload on the request stream.
1623 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(1);
1624 }
1625
1626 // Write the initial headers.
1627 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1628 stream_->WriteHeaders(Http2HeaderBlock(), /*fin=*/false, nullptr);
1629
1630 // Write non-zero body data to force a non-zero final offset.
1631 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
1632 std::string body(1024, 'x'); // 1 kB
1633 QuicByteCount header_length = 0;
1634 if (UsesHttp3()) {
1635 header_length = HttpEncoder::SerializeDataFrameHeader(
1636 body.length(), quiche::SimpleBufferAllocator::Get())
1637 .size();
1638 }
1639
1640 stream_->WriteOrBufferBody(body, false);
1641
1642 // The final offset field in the trailing headers is populated with the
1643 // number of body bytes written (including queued bytes).
1644 Http2HeaderBlock trailers;
1645 trailers["trailer key"] = "trailer value";
1646
1647 Http2HeaderBlock expected_trailers(trailers.Clone());
1648 // :final-offset pseudo-header is only added if trailers are sent
1649 // on the headers stream.
1650 if (!UsesHttp3()) {
1651 expected_trailers[kFinalOffsetHeaderKey] =
1652 absl::StrCat(body.length() + header_length);
1653 }
1654
1655 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1656 stream_->WriteTrailers(std::move(trailers), nullptr);
1657 EXPECT_EQ(expected_trailers, stream_->saved_headers());
1658 }
1659
1660 // Test that if trailers are written after all other data has been written
1661 // (headers and body), that this closes the stream for writing.
TEST_P(QuicSpdyStreamTest,WritingTrailersClosesWriteSide)1662 TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) {
1663 Initialize(kShouldProcessData);
1664
1665 // Expect data being written on the stream. In addition to that, headers are
1666 // also written on the stream in case of IETF QUIC.
1667 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _))
1668 .Times(AtLeast(1));
1669
1670 // Write the initial headers.
1671 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1672 stream_->WriteHeaders(Http2HeaderBlock(), /*fin=*/false, nullptr);
1673
1674 // Write non-zero body data.
1675 const int kBodySize = 1 * 1024; // 1 kB
1676 stream_->WriteOrBufferBody(std::string(kBodySize, 'x'), false);
1677 EXPECT_EQ(0u, stream_->BufferedDataBytes());
1678
1679 // Headers and body have been fully written, there is no queued data. Writing
1680 // trailers marks the end of this stream, and thus the write side is closed.
1681 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1682 stream_->WriteTrailers(Http2HeaderBlock(), nullptr);
1683 EXPECT_TRUE(stream_->write_side_closed());
1684 }
1685
1686 // Test that the stream is not closed for writing when trailers are sent while
1687 // there are still body bytes queued.
TEST_P(QuicSpdyStreamTest,WritingTrailersWithQueuedBytes)1688 TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) {
1689 // This test exercises sending trailers on the headers stream while data is
1690 // still queued on the response/request stream. In IETF QUIC, data and
1691 // trailers are sent on the same stream, so this test does not apply.
1692 if (UsesHttp3()) {
1693 return;
1694 }
1695
1696 testing::InSequence seq;
1697 Initialize(kShouldProcessData);
1698
1699 // Write the initial headers.
1700 EXPECT_CALL(*stream_, WriteHeadersMock(false));
1701 stream_->WriteHeaders(Http2HeaderBlock(), /*fin=*/false, nullptr);
1702
1703 // Write non-zero body data, but only consume partially, ensuring queueing.
1704 const int kBodySize = 1 * 1024; // 1 kB
1705 if (UsesHttp3()) {
1706 EXPECT_CALL(*session_, WritevData(_, 3, _, NO_FIN, _, _));
1707 }
1708 EXPECT_CALL(*session_, WritevData(_, kBodySize, _, NO_FIN, _, _))
1709 .WillOnce(Return(QuicConsumedData(kBodySize - 1, false)));
1710 stream_->WriteOrBufferBody(std::string(kBodySize, 'x'), false);
1711 EXPECT_EQ(1u, stream_->BufferedDataBytes());
1712
1713 // Writing trailers will send a FIN, but not close the write side of the
1714 // stream as there are queued bytes.
1715 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1716 stream_->WriteTrailers(Http2HeaderBlock(), nullptr);
1717 EXPECT_TRUE(stream_->fin_sent());
1718 EXPECT_FALSE(stream_->write_side_closed());
1719
1720 // Writing the queued bytes will close the write side of the stream.
1721 EXPECT_CALL(*session_, WritevData(_, 1, _, NO_FIN, _, _));
1722 stream_->OnCanWrite();
1723 EXPECT_TRUE(stream_->write_side_closed());
1724 }
1725
1726 // Test that it is not possible to write Trailers after a FIN has been sent.
TEST_P(QuicSpdyStreamTest,WritingTrailersAfterFIN)1727 TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) {
1728 // In IETF QUIC, there is no such thing as FIN flag on HTTP/3 frames like the
1729 // HEADERS frame.
1730 if (UsesHttp3()) {
1731 return;
1732 }
1733
1734 Initialize(kShouldProcessData);
1735
1736 // Write the initial headers, with a FIN.
1737 EXPECT_CALL(*stream_, WriteHeadersMock(true));
1738 stream_->WriteHeaders(Http2HeaderBlock(), /*fin=*/true, nullptr);
1739 EXPECT_TRUE(stream_->fin_sent());
1740
1741 // Writing Trailers should fail, as the FIN has already been sent.
1742 // populated with the number of body bytes written.
1743 EXPECT_QUIC_BUG(stream_->WriteTrailers(Http2HeaderBlock(), nullptr),
1744 "Trailers cannot be sent after a FIN");
1745 }
1746
TEST_P(QuicSpdyStreamTest,HeaderStreamNotiferCorrespondingSpdyStream)1747 TEST_P(QuicSpdyStreamTest, HeaderStreamNotiferCorrespondingSpdyStream) {
1748 // There is no headers stream if QPACK is used.
1749 if (UsesHttp3()) {
1750 return;
1751 }
1752
1753 const char kHeader1[] = "Header1";
1754 const char kHeader2[] = "Header2";
1755 const char kBody1[] = "Test1";
1756 const char kBody2[] = "Test2";
1757
1758 Initialize(kShouldProcessData);
1759 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
1760 testing::InSequence s;
1761 quiche::QuicheReferenceCountedPointer<MockAckListener> ack_listener1(
1762 new MockAckListener());
1763 quiche::QuicheReferenceCountedPointer<MockAckListener> ack_listener2(
1764 new MockAckListener());
1765 stream_->set_ack_listener(ack_listener1);
1766 stream2_->set_ack_listener(ack_listener2);
1767
1768 session_->headers_stream()->WriteOrBufferData(kHeader1, false, ack_listener1);
1769 stream_->WriteOrBufferBody(kBody1, true);
1770
1771 session_->headers_stream()->WriteOrBufferData(kHeader2, false, ack_listener2);
1772 stream2_->WriteOrBufferBody(kBody2, false);
1773
1774 QuicStreamFrame frame1(
1775 QuicUtils::GetHeadersStreamId(connection_->transport_version()), false, 0,
1776 kHeader1);
1777
1778 std::string data1 = UsesHttp3() ? DataFrame(kBody1) : kBody1;
1779 QuicStreamFrame frame2(stream_->id(), true, 0, data1);
1780 QuicStreamFrame frame3(
1781 QuicUtils::GetHeadersStreamId(connection_->transport_version()), false, 7,
1782 kHeader2);
1783 std::string data2 = UsesHttp3() ? DataFrame(kBody2) : kBody2;
1784 QuicStreamFrame frame4(stream2_->id(), false, 0, data2);
1785
1786 EXPECT_CALL(*ack_listener1, OnPacketRetransmitted(7));
1787 session_->OnStreamFrameRetransmitted(frame1);
1788
1789 EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
1790 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame1), QuicTime::Delta::Zero(),
1791 QuicTime::Zero()));
1792 EXPECT_CALL(*ack_listener1, OnPacketAcked(5, _));
1793 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame2), QuicTime::Delta::Zero(),
1794 QuicTime::Zero()));
1795 EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
1796 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame3), QuicTime::Delta::Zero(),
1797 QuicTime::Zero()));
1798 EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
1799 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame4), QuicTime::Delta::Zero(),
1800 QuicTime::Zero()));
1801 }
1802
TEST_P(QuicSpdyStreamTest,OnPriorityFrame)1803 TEST_P(QuicSpdyStreamTest, OnPriorityFrame) {
1804 Initialize(kShouldProcessData);
1805 stream_->OnPriorityFrame(spdy::SpdyStreamPrecedence(kV3HighestPriority));
1806 EXPECT_EQ(QuicStreamPriority(HttpStreamPriority{
1807 kV3HighestPriority, HttpStreamPriority::kDefaultIncremental}),
1808 stream_->priority());
1809 }
1810
TEST_P(QuicSpdyStreamTest,OnPriorityFrameAfterSendingData)1811 TEST_P(QuicSpdyStreamTest, OnPriorityFrameAfterSendingData) {
1812 Initialize(kShouldProcessData);
1813 testing::InSequence seq;
1814
1815 if (UsesHttp3()) {
1816 EXPECT_CALL(*session_, WritevData(_, 2, _, NO_FIN, _, _));
1817 }
1818 EXPECT_CALL(*session_, WritevData(_, 4, _, FIN, _, _));
1819 stream_->WriteOrBufferBody("data", true);
1820 stream_->OnPriorityFrame(spdy::SpdyStreamPrecedence(kV3HighestPriority));
1821 EXPECT_EQ(QuicStreamPriority(HttpStreamPriority{
1822 kV3HighestPriority, HttpStreamPriority::kDefaultIncremental}),
1823 stream_->priority());
1824 }
1825
TEST_P(QuicSpdyStreamTest,SetPriorityBeforeUpdateStreamPriority)1826 TEST_P(QuicSpdyStreamTest, SetPriorityBeforeUpdateStreamPriority) {
1827 MockQuicConnection* connection = new StrictMock<MockQuicConnection>(
1828 &helper_, &alarm_factory_, Perspective::IS_SERVER,
1829 SupportedVersions(GetParam()));
1830 std::unique_ptr<TestMockUpdateStreamSession> session(
1831 new StrictMock<TestMockUpdateStreamSession>(connection));
1832 auto stream =
1833 new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalStreamId(
1834 session->transport_version(), 0),
1835 session.get(),
1836 /*should_process_data=*/true);
1837 session->ActivateStream(absl::WrapUnique(stream));
1838
1839 // QuicSpdyStream::SetPriority() should eventually call UpdateStreamPriority()
1840 // on the session. Make sure stream->priority() returns the updated priority
1841 // if called within UpdateStreamPriority(). This expectation is enforced in
1842 // TestMockUpdateStreamSession::UpdateStreamPriority().
1843 session->SetExpectedStream(stream);
1844 session->SetExpectedPriority(HttpStreamPriority{kV3HighestPriority});
1845 stream->SetPriority(
1846 QuicStreamPriority(HttpStreamPriority{kV3HighestPriority}));
1847
1848 session->SetExpectedPriority(HttpStreamPriority{kV3LowestPriority});
1849 stream->SetPriority(
1850 QuicStreamPriority(HttpStreamPriority{kV3LowestPriority}));
1851 }
1852
TEST_P(QuicSpdyStreamTest,StreamWaitsForAcks)1853 TEST_P(QuicSpdyStreamTest, StreamWaitsForAcks) {
1854 Initialize(kShouldProcessData);
1855 quiche::QuicheReferenceCountedPointer<MockAckListener> mock_ack_listener(
1856 new StrictMock<MockAckListener>);
1857 stream_->set_ack_listener(mock_ack_listener);
1858 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
1859 // Stream is not waiting for acks initially.
1860 EXPECT_FALSE(stream_->IsWaitingForAcks());
1861 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1862
1863 // Send kData1.
1864 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1865 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1866 EXPECT_TRUE(stream_->IsWaitingForAcks());
1867 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
1868 QuicByteCount newly_acked_length = 0;
1869 EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
1870 QuicTime::Zero(),
1871 &newly_acked_length));
1872 // Stream is not waiting for acks as all sent data is acked.
1873 EXPECT_FALSE(stream_->IsWaitingForAcks());
1874 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1875
1876 // Send kData2.
1877 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1878 EXPECT_TRUE(stream_->IsWaitingForAcks());
1879 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1880 // Send FIN.
1881 stream_->WriteOrBufferData("", true, nullptr);
1882 // Fin only frame is not stored in send buffer.
1883 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1884
1885 // kData2 is retransmitted.
1886 EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(9));
1887 stream_->OnStreamFrameRetransmitted(9, 9, false);
1888
1889 // kData2 is acked.
1890 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
1891 EXPECT_TRUE(stream_->OnStreamFrameAcked(9, 9, false, QuicTime::Delta::Zero(),
1892 QuicTime::Zero(),
1893 &newly_acked_length));
1894 // Stream is waiting for acks as FIN is not acked.
1895 EXPECT_TRUE(stream_->IsWaitingForAcks());
1896 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1897
1898 // FIN is acked.
1899 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
1900 EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 0, true, QuicTime::Delta::Zero(),
1901 QuicTime::Zero(),
1902 &newly_acked_length));
1903 EXPECT_FALSE(stream_->IsWaitingForAcks());
1904 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1905 }
1906
TEST_P(QuicSpdyStreamTest,StreamDataGetAckedMultipleTimes)1907 TEST_P(QuicSpdyStreamTest, StreamDataGetAckedMultipleTimes) {
1908 Initialize(kShouldProcessData);
1909 quiche::QuicheReferenceCountedPointer<MockAckListener> mock_ack_listener(
1910 new StrictMock<MockAckListener>);
1911 stream_->set_ack_listener(mock_ack_listener);
1912 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
1913 // Send [0, 27) and fin.
1914 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1915 stream_->WriteOrBufferData("FooAndBar", false, nullptr);
1916 stream_->WriteOrBufferData("FooAndBar", true, nullptr);
1917
1918 // Ack [0, 9), [5, 22) and [18, 26)
1919 // Verify [0, 9) 9 bytes are acked.
1920 QuicByteCount newly_acked_length = 0;
1921 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
1922 EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
1923 QuicTime::Zero(),
1924 &newly_acked_length));
1925 EXPECT_EQ(2u, QuicStreamPeer::SendBuffer(stream_).size());
1926 // Verify [9, 22) 13 bytes are acked.
1927 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(13, _));
1928 EXPECT_TRUE(stream_->OnStreamFrameAcked(5, 17, false, QuicTime::Delta::Zero(),
1929 QuicTime::Zero(),
1930 &newly_acked_length));
1931 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1932 // Verify [22, 26) 4 bytes are acked.
1933 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(4, _));
1934 EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 8, false, QuicTime::Delta::Zero(),
1935 QuicTime::Zero(),
1936 &newly_acked_length));
1937 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
1938 EXPECT_TRUE(stream_->IsWaitingForAcks());
1939
1940 // Ack [0, 27).
1941 // Verify [26, 27) 1 byte is acked.
1942 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(1, _));
1943 EXPECT_TRUE(stream_->OnStreamFrameAcked(26, 1, false, QuicTime::Delta::Zero(),
1944 QuicTime::Zero(),
1945 &newly_acked_length));
1946 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1947 EXPECT_TRUE(stream_->IsWaitingForAcks());
1948
1949 // Ack Fin. Verify OnPacketAcked is called.
1950 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
1951 EXPECT_TRUE(stream_->OnStreamFrameAcked(27, 0, true, QuicTime::Delta::Zero(),
1952 QuicTime::Zero(),
1953 &newly_acked_length));
1954 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1955 EXPECT_FALSE(stream_->IsWaitingForAcks());
1956
1957 // Ack [10, 27) and fin.
1958 // No new data is acked, verify OnPacketAcked is not called.
1959 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(_, _)).Times(0);
1960 EXPECT_FALSE(
1961 stream_->OnStreamFrameAcked(10, 17, true, QuicTime::Delta::Zero(),
1962 QuicTime::Zero(), &newly_acked_length));
1963 EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
1964 EXPECT_FALSE(stream_->IsWaitingForAcks());
1965 }
1966
1967 // HTTP/3 only.
TEST_P(QuicSpdyStreamTest,HeadersAckNotReportedWriteOrBufferBody)1968 TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteOrBufferBody) {
1969 if (!UsesHttp3()) {
1970 return;
1971 }
1972
1973 Initialize(kShouldProcessData);
1974 quiche::QuicheReferenceCountedPointer<MockAckListener> mock_ack_listener(
1975 new StrictMock<MockAckListener>);
1976 stream_->set_ack_listener(mock_ack_listener);
1977 std::string body = "Test1";
1978 std::string body2(100, 'x');
1979
1980 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
1981 stream_->WriteOrBufferBody(body, false);
1982 stream_->WriteOrBufferBody(body2, true);
1983
1984 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
1985 body.length(), quiche::SimpleBufferAllocator::Get());
1986 quiche::QuicheBuffer header2 = HttpEncoder::SerializeDataFrameHeader(
1987 body2.length(), quiche::SimpleBufferAllocator::Get());
1988
1989 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body.length(), _));
1990 QuicStreamFrame frame(stream_->id(), false, 0,
1991 absl::StrCat(header.AsStringView(), body));
1992 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame), QuicTime::Delta::Zero(),
1993 QuicTime::Zero()));
1994
1995 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
1996 QuicStreamFrame frame2(stream_->id(), false, header.size() + body.length(),
1997 header2.AsStringView());
1998 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame2), QuicTime::Delta::Zero(),
1999 QuicTime::Zero()));
2000
2001 EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body2.length(), _));
2002 QuicStreamFrame frame3(stream_->id(), true,
2003 header.size() + body.length() + header2.size(), body2);
2004 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame3), QuicTime::Delta::Zero(),
2005 QuicTime::Zero()));
2006
2007 EXPECT_TRUE(
2008 QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
2009 }
2010
2011 // HTTP/3 only.
TEST_P(QuicSpdyStreamTest,HeadersAckNotReportedWriteBodySlices)2012 TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteBodySlices) {
2013 if (!UsesHttp3()) {
2014 return;
2015 }
2016
2017 Initialize(kShouldProcessData);
2018 quiche::QuicheReferenceCountedPointer<MockAckListener> mock_ack_listener(
2019 new StrictMock<MockAckListener>);
2020 stream_->set_ack_listener(mock_ack_listener);
2021 std::string body1 = "Test1";
2022 std::string body2(100, 'x');
2023 struct iovec body1_iov = {const_cast<char*>(body1.data()), body1.length()};
2024 struct iovec body2_iov = {const_cast<char*>(body2.data()), body2.length()};
2025 quiche::QuicheMemSliceStorage storage(
2026 &body1_iov, 1, helper_.GetStreamSendBufferAllocator(), 1024);
2027 quiche::QuicheMemSliceStorage storage2(
2028 &body2_iov, 1, helper_.GetStreamSendBufferAllocator(), 1024);
2029 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
2030 stream_->WriteBodySlices(storage.ToSpan(), false);
2031 stream_->WriteBodySlices(storage2.ToSpan(), true);
2032
2033 std::string data1 = DataFrame(body1);
2034 std::string data2 = DataFrame(body2);
2035
2036 EXPECT_CALL(*mock_ack_listener,
2037 OnPacketAcked(body1.length() + body2.length(), _));
2038 QuicStreamFrame frame(stream_->id(), true, 0, data1 + data2);
2039 EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame), QuicTime::Delta::Zero(),
2040 QuicTime::Zero()));
2041
2042 EXPECT_TRUE(
2043 QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
2044 }
2045
2046 // HTTP/3 only.
TEST_P(QuicSpdyStreamTest,HeaderBytesNotReportedOnRetransmission)2047 TEST_P(QuicSpdyStreamTest, HeaderBytesNotReportedOnRetransmission) {
2048 if (!UsesHttp3()) {
2049 return;
2050 }
2051
2052 Initialize(kShouldProcessData);
2053 quiche::QuicheReferenceCountedPointer<MockAckListener> mock_ack_listener(
2054 new StrictMock<MockAckListener>);
2055 stream_->set_ack_listener(mock_ack_listener);
2056 std::string body1 = "Test1";
2057 std::string body2(100, 'x');
2058
2059 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
2060 stream_->WriteOrBufferBody(body1, false);
2061 stream_->WriteOrBufferBody(body2, true);
2062
2063 std::string data1 = DataFrame(body1);
2064 std::string data2 = DataFrame(body2);
2065
2066 EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(body1.length()));
2067 QuicStreamFrame frame(stream_->id(), false, 0, data1);
2068 session_->OnStreamFrameRetransmitted(frame);
2069
2070 EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(body2.length()));
2071 QuicStreamFrame frame2(stream_->id(), true, data1.length(), data2);
2072 session_->OnStreamFrameRetransmitted(frame2);
2073
2074 EXPECT_FALSE(
2075 QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
2076 }
2077
TEST_P(QuicSpdyStreamTest,HeadersFrameOnRequestStream)2078 TEST_P(QuicSpdyStreamTest, HeadersFrameOnRequestStream) {
2079 if (!UsesHttp3()) {
2080 return;
2081 }
2082
2083 Initialize(kShouldProcessData);
2084
2085 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
2086 std::string data = DataFrame(kDataFramePayload);
2087 std::string trailers =
2088 HeadersFrame({std::make_pair("custom-key", "custom-value")});
2089
2090 std::string stream_frame_payload = absl::StrCat(headers, data, trailers);
2091 QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
2092 stream_->OnStreamFrame(frame);
2093
2094 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2095
2096 // QuicSpdyStream only calls OnBodyAvailable()
2097 // after the header list has been consumed.
2098 EXPECT_EQ("", stream_->data());
2099 stream_->ConsumeHeaderList();
2100 EXPECT_EQ(kDataFramePayload, stream_->data());
2101
2102 EXPECT_THAT(stream_->received_trailers(),
2103 ElementsAre(Pair("custom-key", "custom-value")));
2104 }
2105
TEST_P(QuicSpdyStreamTest,ProcessBodyAfterTrailers)2106 TEST_P(QuicSpdyStreamTest, ProcessBodyAfterTrailers) {
2107 if (!UsesHttp3()) {
2108 return;
2109 }
2110
2111 Initialize(!kShouldProcessData);
2112
2113 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
2114 std::string data = DataFrame(kDataFramePayload);
2115
2116 // A header block that will take more than one block of sequencer buffer.
2117 // This ensures that when the trailers are consumed, some buffer buckets will
2118 // be freed.
2119 Http2HeaderBlock trailers_block;
2120 trailers_block["key1"] = std::string(10000, 'x');
2121 std::string trailers = HeadersFrame(trailers_block);
2122
2123 // Feed all three HTTP/3 frames in a single stream frame.
2124 std::string stream_frame_payload = absl::StrCat(headers, data, trailers);
2125 QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
2126 stream_->OnStreamFrame(frame);
2127
2128 stream_->ConsumeHeaderList();
2129 stream_->MarkTrailersConsumed();
2130
2131 EXPECT_TRUE(stream_->trailers_decompressed());
2132 EXPECT_EQ(trailers_block, stream_->received_trailers());
2133
2134 EXPECT_TRUE(stream_->HasBytesToRead());
2135
2136 // Consume data.
2137 char buffer[2048];
2138 struct iovec vec;
2139 vec.iov_base = buffer;
2140 vec.iov_len = ABSL_ARRAYSIZE(buffer);
2141 size_t bytes_read = stream_->Readv(&vec, 1);
2142 EXPECT_EQ(kDataFramePayload, absl::string_view(buffer, bytes_read));
2143
2144 EXPECT_FALSE(stream_->HasBytesToRead());
2145 }
2146
2147 // The test stream will receive a stream frame containing malformed headers and
2148 // normal body. Make sure the http decoder stops processing body after the
2149 // connection shuts down.
TEST_P(QuicSpdyStreamTest,MalformedHeadersStopHttpDecoder)2150 TEST_P(QuicSpdyStreamTest, MalformedHeadersStopHttpDecoder) {
2151 if (!UsesHttp3()) {
2152 return;
2153 }
2154
2155 Initialize(kShouldProcessData);
2156 testing::InSequence s;
2157 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
2158
2159 // Random bad headers.
2160 std::string headers_bytes;
2161 ASSERT_TRUE(absl::HexStringToBytes("00002a94e7036261", &headers_bytes));
2162 std::string headers = HeadersFrame(headers_bytes);
2163 std::string data = DataFrame(kDataFramePayload);
2164
2165 std::string stream_frame_payload = absl::StrCat(headers, data);
2166 QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
2167
2168 EXPECT_CALL(
2169 *connection_,
2170 CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
2171 MatchesRegex("Error decoding headers on stream \\d+: "
2172 "Incomplete header block."),
2173 _))
2174 .WillOnce(
2175 (Invoke([this](QuicErrorCode error, const std::string& error_details,
2176 ConnectionCloseBehavior connection_close_behavior) {
2177 connection_->ReallyCloseConnection(error, error_details,
2178 connection_close_behavior);
2179 })));
2180 EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
2181 EXPECT_CALL(*session_, OnConnectionClosed(_, _))
2182 .WillOnce(Invoke([this](const QuicConnectionCloseFrame& frame,
2183 ConnectionCloseSource source) {
2184 session_->ReallyOnConnectionClosed(frame, source);
2185 }));
2186 EXPECT_CALL(*session_, MaybeSendRstStreamFrame(_, _, _)).Times(2);
2187 stream_->OnStreamFrame(frame);
2188 }
2189
2190 // Regression test for https://crbug.com/1027895: a HEADERS frame triggers an
2191 // error in QuicSpdyStream::OnHeadersFramePayload(). This closes the
2192 // connection, freeing the buffer of QuicStreamSequencer. Therefore
2193 // QuicStreamSequencer::MarkConsumed() must not be called from
2194 // QuicSpdyStream::OnHeadersFramePayload().
TEST_P(QuicSpdyStreamTest,DoNotMarkConsumedAfterQpackDecodingError)2195 TEST_P(QuicSpdyStreamTest, DoNotMarkConsumedAfterQpackDecodingError) {
2196 if (!UsesHttp3()) {
2197 return;
2198 }
2199
2200 Initialize(kShouldProcessData);
2201 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
2202
2203 {
2204 testing::InSequence s;
2205 EXPECT_CALL(
2206 *connection_,
2207 CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
2208 MatchesRegex("Error decoding headers on stream \\d+: "
2209 "Invalid relative index."),
2210 _))
2211 .WillOnce((
2212 Invoke([this](QuicErrorCode error, const std::string& error_details,
2213 ConnectionCloseBehavior connection_close_behavior) {
2214 connection_->ReallyCloseConnection(error, error_details,
2215 connection_close_behavior);
2216 })));
2217 EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
2218 EXPECT_CALL(*session_, OnConnectionClosed(_, _))
2219 .WillOnce(Invoke([this](const QuicConnectionCloseFrame& frame,
2220 ConnectionCloseSource source) {
2221 session_->ReallyOnConnectionClosed(frame, source);
2222 }));
2223 }
2224 EXPECT_CALL(*session_, MaybeSendRstStreamFrame(stream_->id(), _, _));
2225 EXPECT_CALL(*session_, MaybeSendRstStreamFrame(stream2_->id(), _, _));
2226
2227 // Invalid headers: Required Insert Count is zero, but the header block
2228 // contains a dynamic table reference.
2229 std::string headers_bytes;
2230 ASSERT_TRUE(absl::HexStringToBytes("000080", &headers_bytes));
2231 std::string headers = HeadersFrame(headers_bytes);
2232 QuicStreamFrame frame(stream_->id(), false, 0, headers);
2233 stream_->OnStreamFrame(frame);
2234 }
2235
TEST_P(QuicSpdyStreamTest,ImmediateHeaderDecodingWithDynamicTableEntries)2236 TEST_P(QuicSpdyStreamTest, ImmediateHeaderDecodingWithDynamicTableEntries) {
2237 if (!UsesHttp3()) {
2238 return;
2239 }
2240
2241 Initialize(kShouldProcessData);
2242 testing::InSequence s;
2243 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
2244 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2245 session_->set_debug_visitor(&debug_visitor);
2246
2247 auto decoder_send_stream =
2248 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
2249
2250 // Deliver dynamic table entry to decoder.
2251 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2252
2253 // HEADERS frame referencing first dynamic table entry.
2254 std::string encoded_headers;
2255 ASSERT_TRUE(absl::HexStringToBytes("020080", &encoded_headers));
2256 std::string headers = HeadersFrame(encoded_headers);
2257 EXPECT_CALL(debug_visitor,
2258 OnHeadersFrameReceived(stream_->id(), encoded_headers.length()));
2259 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
2260 // Decoder stream type.
2261 EXPECT_CALL(*session_,
2262 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2263 /* offset = */ 0, _, _, _));
2264 // Header acknowledgement.
2265 EXPECT_CALL(*session_,
2266 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2267 /* offset = */ 1, _, _, _));
2268 }
2269 EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
2270 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2271
2272 // Headers can be decoded immediately.
2273 EXPECT_TRUE(stream_->headers_decompressed());
2274
2275 // Verify headers.
2276 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2277 stream_->ConsumeHeaderList();
2278
2279 // DATA frame.
2280 std::string data = DataFrame(kDataFramePayload);
2281 EXPECT_CALL(debug_visitor,
2282 OnDataFrameReceived(stream_->id(), kDataFramePayload.length()));
2283 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, /* offset = */
2284 headers.length(), data));
2285 EXPECT_EQ(kDataFramePayload, stream_->data());
2286
2287 // Deliver second dynamic table entry to decoder.
2288 session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar");
2289
2290 // Trailing HEADERS frame referencing second dynamic table entry.
2291 std::string encoded_trailers;
2292 ASSERT_TRUE(absl::HexStringToBytes("030080", &encoded_trailers));
2293 std::string trailers = HeadersFrame(encoded_trailers);
2294 EXPECT_CALL(debug_visitor,
2295 OnHeadersFrameReceived(stream_->id(), encoded_trailers.length()));
2296 // Header acknowledgement.
2297 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
2298 EXPECT_CALL(*session_,
2299 WritevData(decoder_send_stream->id(), _, _, _, _, _));
2300 }
2301 EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
2302 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), true, /* offset = */
2303 headers.length() + data.length(),
2304 trailers));
2305
2306 // Trailers can be decoded immediately.
2307 EXPECT_TRUE(stream_->trailers_decompressed());
2308
2309 // Verify trailers.
2310 EXPECT_THAT(stream_->received_trailers(),
2311 ElementsAre(Pair("trailing", "foobar")));
2312 stream_->MarkTrailersConsumed();
2313 }
2314
TEST_P(QuicSpdyStreamTest,BlockedHeaderDecoding)2315 TEST_P(QuicSpdyStreamTest, BlockedHeaderDecoding) {
2316 if (!UsesHttp3()) {
2317 return;
2318 }
2319
2320 Initialize(kShouldProcessData);
2321 testing::InSequence s;
2322 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
2323 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2324 session_->set_debug_visitor(&debug_visitor);
2325
2326 // HEADERS frame referencing first dynamic table entry.
2327 std::string encoded_headers;
2328 ASSERT_TRUE(absl::HexStringToBytes("020080", &encoded_headers));
2329 std::string headers = HeadersFrame(encoded_headers);
2330 EXPECT_CALL(debug_visitor,
2331 OnHeadersFrameReceived(stream_->id(), encoded_headers.length()));
2332 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2333
2334 // Decoding is blocked because dynamic table entry has not been received yet.
2335 EXPECT_FALSE(stream_->headers_decompressed());
2336
2337 auto decoder_send_stream =
2338 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
2339
2340 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
2341 // Decoder stream type.
2342 EXPECT_CALL(*session_,
2343 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2344 /* offset = */ 0, _, _, _));
2345 // Header acknowledgement.
2346 EXPECT_CALL(*session_,
2347 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2348 /* offset = */ 1, _, _, _));
2349 }
2350 EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
2351 // Deliver dynamic table entry to decoder.
2352 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2353 EXPECT_TRUE(stream_->headers_decompressed());
2354
2355 // Verify headers.
2356 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2357 stream_->ConsumeHeaderList();
2358
2359 // DATA frame.
2360 std::string data = DataFrame(kDataFramePayload);
2361 EXPECT_CALL(debug_visitor,
2362 OnDataFrameReceived(stream_->id(), kDataFramePayload.length()));
2363 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, /* offset = */
2364 headers.length(), data));
2365 EXPECT_EQ(kDataFramePayload, stream_->data());
2366
2367 // Trailing HEADERS frame referencing second dynamic table entry.
2368 std::string encoded_trailers;
2369 ASSERT_TRUE(absl::HexStringToBytes("030080", &encoded_trailers));
2370 std::string trailers = HeadersFrame(encoded_trailers);
2371 EXPECT_CALL(debug_visitor,
2372 OnHeadersFrameReceived(stream_->id(), encoded_trailers.length()));
2373 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), true, /* offset = */
2374 headers.length() + data.length(),
2375 trailers));
2376
2377 // Decoding is blocked because dynamic table entry has not been received yet.
2378 EXPECT_FALSE(stream_->trailers_decompressed());
2379
2380 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
2381 // Header acknowledgement.
2382 EXPECT_CALL(*session_,
2383 WritevData(decoder_send_stream->id(), _, _, _, _, _));
2384 }
2385 EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
2386 // Deliver second dynamic table entry to decoder.
2387 session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar");
2388 EXPECT_TRUE(stream_->trailers_decompressed());
2389
2390 // Verify trailers.
2391 EXPECT_THAT(stream_->received_trailers(),
2392 ElementsAre(Pair("trailing", "foobar")));
2393 stream_->MarkTrailersConsumed();
2394 }
2395
TEST_P(QuicSpdyStreamTest,AsyncErrorDecodingHeaders)2396 TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingHeaders) {
2397 if (!UsesHttp3()) {
2398 return;
2399 }
2400
2401 Initialize(kShouldProcessData);
2402 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
2403
2404 // HEADERS frame only referencing entry with absolute index 0 but with
2405 // Required Insert Count = 2, which is incorrect.
2406 std::string headers_bytes;
2407 ASSERT_TRUE(absl::HexStringToBytes("030081", &headers_bytes));
2408 std::string headers = HeadersFrame(headers_bytes);
2409 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2410
2411 // Even though entire header block is received and every referenced entry is
2412 // available, decoding is blocked until insert count reaches the Required
2413 // Insert Count value advertised in the header block prefix.
2414 EXPECT_FALSE(stream_->headers_decompressed());
2415
2416 EXPECT_CALL(
2417 *connection_,
2418 CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
2419 MatchesRegex("Error decoding headers on stream \\d+: "
2420 "Required Insert Count too large."),
2421 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
2422
2423 // Deliver two dynamic table entries to decoder
2424 // to trigger decoding of header block.
2425 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2426 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2427 }
2428
2429 // Regression test for https://crbug.com/1024263 and for
2430 // https://crbug.com/1025209#c11.
TEST_P(QuicSpdyStreamTest,BlockedHeaderDecodingUnblockedWithBufferedError)2431 TEST_P(QuicSpdyStreamTest, BlockedHeaderDecodingUnblockedWithBufferedError) {
2432 if (!UsesHttp3()) {
2433 return;
2434 }
2435
2436 Initialize(kShouldProcessData);
2437 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
2438
2439 // Relative index 2 is invalid because it is larger than or equal to the Base.
2440 std::string headers_bytes;
2441 ASSERT_TRUE(absl::HexStringToBytes("020082", &headers_bytes));
2442 std::string headers = HeadersFrame(headers_bytes);
2443 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2444
2445 // Decoding is blocked.
2446 EXPECT_FALSE(stream_->headers_decompressed());
2447
2448 EXPECT_CALL(
2449 *connection_,
2450 CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
2451 MatchesRegex("Error decoding headers on stream \\d+: "
2452 "Invalid relative index."),
2453 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
2454
2455 // Deliver one dynamic table entry to decoder
2456 // to trigger decoding of header block.
2457 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2458 }
2459
TEST_P(QuicSpdyStreamTest,AsyncErrorDecodingTrailers)2460 TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingTrailers) {
2461 if (!UsesHttp3()) {
2462 return;
2463 }
2464
2465 Initialize(kShouldProcessData);
2466 testing::InSequence s;
2467 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
2468
2469 // HEADERS frame referencing first dynamic table entry.
2470 std::string headers_bytes;
2471 ASSERT_TRUE(absl::HexStringToBytes("020080", &headers_bytes));
2472 std::string headers = HeadersFrame(headers_bytes);
2473 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2474
2475 // Decoding is blocked because dynamic table entry has not been received yet.
2476 EXPECT_FALSE(stream_->headers_decompressed());
2477
2478 auto decoder_send_stream =
2479 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
2480
2481 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
2482 // Decoder stream type.
2483 EXPECT_CALL(*session_,
2484 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2485 /* offset = */ 0, _, _, _));
2486 // Header acknowledgement.
2487 EXPECT_CALL(*session_,
2488 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2489 /* offset = */ 1, _, _, _));
2490 }
2491 // Deliver dynamic table entry to decoder.
2492 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2493 EXPECT_TRUE(stream_->headers_decompressed());
2494
2495 // Verify headers.
2496 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2497 stream_->ConsumeHeaderList();
2498
2499 // DATA frame.
2500 std::string data = DataFrame(kDataFramePayload);
2501 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, /* offset = */
2502 headers.length(), data));
2503 EXPECT_EQ(kDataFramePayload, stream_->data());
2504
2505 // Trailing HEADERS frame only referencing entry with absolute index 0 but
2506 // with Required Insert Count = 2, which is incorrect.
2507 std::string trailers_bytes;
2508 ASSERT_TRUE(absl::HexStringToBytes("030081", &trailers_bytes));
2509 std::string trailers = HeadersFrame(trailers_bytes);
2510 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), true, /* offset = */
2511 headers.length() + data.length(),
2512 trailers));
2513
2514 // Even though entire header block is received and every referenced entry is
2515 // available, decoding is blocked until insert count reaches the Required
2516 // Insert Count value advertised in the header block prefix.
2517 EXPECT_FALSE(stream_->trailers_decompressed());
2518
2519 EXPECT_CALL(
2520 *connection_,
2521 CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
2522 MatchesRegex("Error decoding trailers on stream \\d+: "
2523 "Required Insert Count too large."),
2524 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
2525
2526 // Deliver second dynamic table entry to decoder
2527 // to trigger decoding of trailing header block.
2528 session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar");
2529 }
2530
2531 // Regression test for b/132603592: QPACK decoding unblocked after stream is
2532 // closed.
TEST_P(QuicSpdyStreamTest,HeaderDecodingUnblockedAfterStreamClosed)2533 TEST_P(QuicSpdyStreamTest, HeaderDecodingUnblockedAfterStreamClosed) {
2534 if (!UsesHttp3()) {
2535 return;
2536 }
2537
2538 Initialize(kShouldProcessData);
2539 testing::InSequence s;
2540 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
2541 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2542 session_->set_debug_visitor(&debug_visitor);
2543
2544 // HEADERS frame referencing first dynamic table entry.
2545 std::string encoded_headers;
2546 ASSERT_TRUE(absl::HexStringToBytes("020080", &encoded_headers));
2547 std::string headers = HeadersFrame(encoded_headers);
2548 EXPECT_CALL(debug_visitor,
2549 OnHeadersFrameReceived(stream_->id(), encoded_headers.length()));
2550 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2551
2552 // Decoding is blocked because dynamic table entry has not been received yet.
2553 EXPECT_FALSE(stream_->headers_decompressed());
2554
2555 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
2556 // Decoder stream type and stream cancellation instruction.
2557 auto decoder_send_stream =
2558 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
2559 EXPECT_CALL(*session_,
2560 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2561 /* offset = */ 0, _, _, _));
2562 EXPECT_CALL(*session_,
2563 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2564 /* offset = */ 1, _, _, _));
2565 }
2566
2567 // Reset stream by this endpoint, for example, due to stream cancellation.
2568 EXPECT_CALL(*session_, MaybeSendStopSendingFrame(
2569 stream_->id(), QuicResetStreamError::FromInternal(
2570 QUIC_STREAM_CANCELLED)));
2571 EXPECT_CALL(
2572 *session_,
2573 MaybeSendRstStreamFrame(
2574 stream_->id(),
2575 QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED), _));
2576 stream_->Reset(QUIC_STREAM_CANCELLED);
2577
2578 // Deliver dynamic table entry to decoder.
2579 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2580
2581 EXPECT_FALSE(stream_->headers_decompressed());
2582 }
2583
TEST_P(QuicSpdyStreamTest,HeaderDecodingUnblockedAfterResetReceived)2584 TEST_P(QuicSpdyStreamTest, HeaderDecodingUnblockedAfterResetReceived) {
2585 if (!UsesHttp3()) {
2586 return;
2587 }
2588
2589 Initialize(kShouldProcessData);
2590 testing::InSequence s;
2591 session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
2592 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2593 session_->set_debug_visitor(&debug_visitor);
2594
2595 // HEADERS frame referencing first dynamic table entry.
2596 std::string encoded_headers;
2597 ASSERT_TRUE(absl::HexStringToBytes("020080", &encoded_headers));
2598 std::string headers = HeadersFrame(encoded_headers);
2599 EXPECT_CALL(debug_visitor,
2600 OnHeadersFrameReceived(stream_->id(), encoded_headers.length()));
2601 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
2602
2603 // Decoding is blocked because dynamic table entry has not been received yet.
2604 EXPECT_FALSE(stream_->headers_decompressed());
2605
2606 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
2607 // Decoder stream type and stream cancellation instruction.
2608 auto decoder_send_stream =
2609 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
2610 EXPECT_CALL(*session_,
2611 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2612 /* offset = */ 0, _, _, _));
2613 EXPECT_CALL(*session_,
2614 WritevData(decoder_send_stream->id(), /* write_length = */ 1,
2615 /* offset = */ 1, _, _, _));
2616 }
2617
2618 // OnStreamReset() is called when RESET_STREAM frame is received from peer.
2619 // This aborts header decompression.
2620 stream_->OnStreamReset(QuicRstStreamFrame(
2621 kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 0));
2622
2623 // Deliver dynamic table entry to decoder.
2624 session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2625 EXPECT_FALSE(stream_->headers_decompressed());
2626 }
2627
2628 class QuicSpdyStreamIncrementalConsumptionTest : public QuicSpdyStreamTest {
2629 protected:
QuicSpdyStreamIncrementalConsumptionTest()2630 QuicSpdyStreamIncrementalConsumptionTest() : offset_(0), consumed_bytes_(0) {}
2631 ~QuicSpdyStreamIncrementalConsumptionTest() override = default;
2632
2633 // Create QuicStreamFrame with |payload|
2634 // and pass it to stream_->OnStreamFrame().
OnStreamFrame(absl::string_view payload)2635 void OnStreamFrame(absl::string_view payload) {
2636 QuicStreamFrame frame(stream_->id(), /* fin = */ false, offset_, payload);
2637 stream_->OnStreamFrame(frame);
2638 offset_ += payload.size();
2639 }
2640
2641 // Return number of bytes marked consumed with sequencer
2642 // since last NewlyConsumedBytes() call.
NewlyConsumedBytes()2643 QuicStreamOffset NewlyConsumedBytes() {
2644 QuicStreamOffset previously_consumed_bytes = consumed_bytes_;
2645 consumed_bytes_ = stream_->sequencer()->NumBytesConsumed();
2646 return consumed_bytes_ - previously_consumed_bytes;
2647 }
2648
2649 // Read |size| bytes from the stream.
ReadFromStream(QuicByteCount size)2650 std::string ReadFromStream(QuicByteCount size) {
2651 std::string buffer;
2652 buffer.resize(size);
2653
2654 struct iovec vec;
2655 vec.iov_base = const_cast<char*>(buffer.data());
2656 vec.iov_len = size;
2657
2658 size_t bytes_read = stream_->Readv(&vec, 1);
2659 EXPECT_EQ(bytes_read, size);
2660
2661 return buffer;
2662 }
2663
2664 private:
2665 QuicStreamOffset offset_;
2666 QuicStreamOffset consumed_bytes_;
2667 };
2668
2669 INSTANTIATE_TEST_SUITE_P(Tests, QuicSpdyStreamIncrementalConsumptionTest,
2670 ::testing::ValuesIn(AllSupportedVersions()),
2671 ::testing::PrintToStringParamName());
2672
2673 // Test that stream bytes are consumed (by calling
2674 // sequencer()->MarkConsumed()) incrementally, as soon as possible.
TEST_P(QuicSpdyStreamIncrementalConsumptionTest,OnlyKnownFrames)2675 TEST_P(QuicSpdyStreamIncrementalConsumptionTest, OnlyKnownFrames) {
2676 if (!UsesHttp3()) {
2677 return;
2678 }
2679
2680 Initialize(!kShouldProcessData);
2681
2682 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
2683
2684 // All HEADERS frame bytes are consumed even if the frame is not received
2685 // completely.
2686 OnStreamFrame(absl::string_view(headers).substr(0, headers.size() - 1));
2687 EXPECT_EQ(headers.size() - 1, NewlyConsumedBytes());
2688
2689 // The rest of the HEADERS frame is also consumed immediately.
2690 OnStreamFrame(absl::string_view(headers).substr(headers.size() - 1));
2691 EXPECT_EQ(1u, NewlyConsumedBytes());
2692
2693 // Verify headers.
2694 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2695 stream_->ConsumeHeaderList();
2696
2697 // DATA frame.
2698 absl::string_view data_payload(kDataFramePayload);
2699 std::string data_frame = DataFrame(data_payload);
2700 QuicByteCount data_frame_header_length =
2701 data_frame.size() - data_payload.size();
2702
2703 // DATA frame header is consumed.
2704 // DATA frame payload is not consumed because payload has to be buffered.
2705 OnStreamFrame(data_frame);
2706 EXPECT_EQ(data_frame_header_length, NewlyConsumedBytes());
2707
2708 // Consume all but last byte of data.
2709 EXPECT_EQ(data_payload.substr(0, data_payload.size() - 1),
2710 ReadFromStream(data_payload.size() - 1));
2711 EXPECT_EQ(data_payload.size() - 1, NewlyConsumedBytes());
2712
2713 std::string trailers =
2714 HeadersFrame({std::make_pair("custom-key", "custom-value")});
2715
2716 // No bytes are consumed, because last byte of DATA payload is still buffered.
2717 OnStreamFrame(absl::string_view(trailers).substr(0, trailers.size() - 1));
2718 EXPECT_EQ(0u, NewlyConsumedBytes());
2719
2720 // Reading last byte of DATA payload triggers consumption of all data received
2721 // so far, even though last HEADERS frame has not been received completely.
2722 EXPECT_EQ(data_payload.substr(data_payload.size() - 1), ReadFromStream(1));
2723 EXPECT_EQ(1 + trailers.size() - 1, NewlyConsumedBytes());
2724
2725 // Last byte of trailers is immediately consumed.
2726 OnStreamFrame(absl::string_view(trailers).substr(trailers.size() - 1));
2727 EXPECT_EQ(1u, NewlyConsumedBytes());
2728
2729 // Verify trailers.
2730 EXPECT_THAT(stream_->received_trailers(),
2731 ElementsAre(Pair("custom-key", "custom-value")));
2732 }
2733
TEST_P(QuicSpdyStreamIncrementalConsumptionTest,ReceiveUnknownFrame)2734 TEST_P(QuicSpdyStreamIncrementalConsumptionTest, ReceiveUnknownFrame) {
2735 if (!UsesHttp3()) {
2736 return;
2737 }
2738
2739 Initialize(kShouldProcessData);
2740 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2741 session_->set_debug_visitor(&debug_visitor);
2742
2743 EXPECT_CALL(debug_visitor,
2744 OnUnknownFrameReceived(stream_->id(), /* frame_type = */ 0x21,
2745 /* payload_length = */ 3));
2746 std::string unknown_frame = UnknownFrame(0x21, "foo");
2747 OnStreamFrame(unknown_frame);
2748 }
2749
TEST_P(QuicSpdyStreamIncrementalConsumptionTest,ReceiveUnsupportedMetadataFrame)2750 TEST_P(QuicSpdyStreamIncrementalConsumptionTest,
2751 ReceiveUnsupportedMetadataFrame) {
2752 if (!UsesHttp3()) {
2753 return;
2754 }
2755
2756 Initialize(kShouldProcessData);
2757 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2758 session_->set_debug_visitor(&debug_visitor);
2759
2760 quiche::HttpHeaderBlock headers;
2761 headers.AppendValueOrAddHeader("key1", "val1");
2762 headers.AppendValueOrAddHeader("key2", "val2");
2763 quic::NoopDecoderStreamErrorDelegate delegate;
2764 QpackEncoder qpack_encoder(&delegate, quic::HuffmanEncoding::kDisabled);
2765 std::string metadata_frame_payload = qpack_encoder.EncodeHeaderList(
2766 stream_->id(), headers,
2767 /* encoder_stream_sent_byte_count = */ nullptr);
2768 std::string metadata_frame_header =
2769 quic::HttpEncoder::SerializeMetadataFrameHeader(
2770 metadata_frame_payload.size());
2771 std::string metadata_frame = metadata_frame_header + metadata_frame_payload;
2772
2773 EXPECT_CALL(debug_visitor,
2774 OnUnknownFrameReceived(
2775 stream_->id(), /* frame_type = */ 0x4d,
2776 /* payload_length = */ metadata_frame_payload.length()));
2777 OnStreamFrame(metadata_frame);
2778 }
2779
2780 class MockMetadataVisitor : public QuicSpdyStream::MetadataVisitor {
2781 public:
2782 ~MockMetadataVisitor() override = default;
2783 MOCK_METHOD(void, OnMetadataComplete,
2784 (size_t frame_len, const QuicHeaderList& header_list),
2785 (override));
2786 };
2787
TEST_P(QuicSpdyStreamIncrementalConsumptionTest,ReceiveMetadataFrame)2788 TEST_P(QuicSpdyStreamIncrementalConsumptionTest, ReceiveMetadataFrame) {
2789 if (!UsesHttp3() ||
2790 !GetQuicReloadableFlag(quic_enable_http3_metadata_decoding)) {
2791 return;
2792 }
2793 StrictMock<MockMetadataVisitor> metadata_visitor;
2794 Initialize(kShouldProcessData);
2795 stream_->RegisterMetadataVisitor(&metadata_visitor);
2796 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2797 session_->set_debug_visitor(&debug_visitor);
2798
2799 quiche::HttpHeaderBlock headers;
2800 headers.AppendValueOrAddHeader("key1", "val1");
2801 headers.AppendValueOrAddHeader("key2", "val2");
2802 quic::NoopDecoderStreamErrorDelegate delegate;
2803 QpackEncoder qpack_encoder(&delegate, quic::HuffmanEncoding::kDisabled);
2804 std::string metadata_frame_payload = qpack_encoder.EncodeHeaderList(
2805 stream_->id(), headers,
2806 /* encoder_stream_sent_byte_count = */ nullptr);
2807 std::string metadata_frame_header =
2808 quic::HttpEncoder::SerializeMetadataFrameHeader(
2809 metadata_frame_payload.size());
2810 std::string metadata_frame = metadata_frame_header + metadata_frame_payload;
2811
2812 EXPECT_CALL(metadata_visitor, OnMetadataComplete(metadata_frame.size(), _))
2813 .WillOnce(testing::WithArgs<1>(
2814 Invoke([&headers](const QuicHeaderList& header_list) {
2815 quiche::HttpHeaderBlock actual_headers;
2816 for (const auto& header : header_list) {
2817 actual_headers.AppendValueOrAddHeader(header.first,
2818 header.second);
2819 }
2820 EXPECT_EQ(headers, actual_headers);
2821 })));
2822 OnStreamFrame(metadata_frame);
2823 }
2824
TEST_P(QuicSpdyStreamIncrementalConsumptionTest,ResetDuringMultipleMetadataFrames)2825 TEST_P(QuicSpdyStreamIncrementalConsumptionTest,
2826 ResetDuringMultipleMetadataFrames) {
2827 if (!UsesHttp3() ||
2828 !GetQuicReloadableFlag(quic_enable_http3_metadata_decoding)) {
2829 return;
2830 }
2831 StrictMock<MockMetadataVisitor> metadata_visitor;
2832 Initialize(kShouldProcessData);
2833 stream_->RegisterMetadataVisitor(&metadata_visitor);
2834 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2835 session_->set_debug_visitor(&debug_visitor);
2836
2837 quiche::HttpHeaderBlock headers;
2838 headers.AppendValueOrAddHeader("key1", "val1");
2839 headers.AppendValueOrAddHeader("key2", "val2");
2840 quic::NoopDecoderStreamErrorDelegate delegate;
2841 QpackEncoder qpack_encoder(&delegate, quic::HuffmanEncoding::kDisabled);
2842 std::string metadata_frame_payload = qpack_encoder.EncodeHeaderList(
2843 stream_->id(), headers,
2844 /* encoder_stream_sent_byte_count = */ nullptr);
2845 std::string metadata_frame_header =
2846 quic::HttpEncoder::SerializeMetadataFrameHeader(
2847 metadata_frame_payload.size());
2848 std::string metadata_frame = metadata_frame_header + metadata_frame_payload;
2849
2850 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber());
2851 EXPECT_CALL(*session_, MaybeSendStopSendingFrame(_, _));
2852 EXPECT_CALL(*session_, MaybeSendRstStreamFrame(_, _, _));
2853 // Reset the stream while processing the first frame and do not
2854 // receive a callback about the second.
2855 EXPECT_CALL(metadata_visitor, OnMetadataComplete(metadata_frame.size(), _))
2856 .WillOnce(testing::WithArgs<1>(
2857 Invoke([&headers, this](const QuicHeaderList& header_list) {
2858 quiche::HttpHeaderBlock actual_headers;
2859 for (const auto& header : header_list) {
2860 actual_headers.AppendValueOrAddHeader(header.first,
2861 header.second);
2862 }
2863 EXPECT_EQ(headers, actual_headers);
2864 stream_->Reset(QUIC_STREAM_CANCELLED);
2865 })));
2866 std::string data = metadata_frame + metadata_frame;
2867 OnStreamFrame(data);
2868 }
2869
TEST_P(QuicSpdyStreamIncrementalConsumptionTest,UnknownFramesInterleaved)2870 TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {
2871 if (!UsesHttp3()) {
2872 return;
2873 }
2874
2875 Initialize(!kShouldProcessData);
2876
2877 // Unknown frame of reserved type before HEADERS is consumed immediately.
2878 std::string unknown_frame1 = UnknownFrame(0x21, "foo");
2879 OnStreamFrame(unknown_frame1);
2880 EXPECT_EQ(unknown_frame1.size(), NewlyConsumedBytes());
2881
2882 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
2883
2884 // All HEADERS frame bytes are consumed even if the frame is not received
2885 // completely.
2886 OnStreamFrame(absl::string_view(headers).substr(0, headers.size() - 1));
2887 EXPECT_EQ(headers.size() - 1, NewlyConsumedBytes());
2888
2889 // The rest of the HEADERS frame is also consumed immediately.
2890 OnStreamFrame(absl::string_view(headers).substr(headers.size() - 1));
2891 EXPECT_EQ(1u, NewlyConsumedBytes());
2892
2893 // Verify headers.
2894 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2895 stream_->ConsumeHeaderList();
2896
2897 // Frame of unknown, not reserved type between HEADERS and DATA is consumed
2898 // immediately.
2899 std::string unknown_frame2 = UnknownFrame(0x3a, "");
2900 OnStreamFrame(unknown_frame2);
2901 EXPECT_EQ(unknown_frame2.size(), NewlyConsumedBytes());
2902
2903 // DATA frame.
2904 absl::string_view data_payload(kDataFramePayload);
2905 std::string data_frame = DataFrame(data_payload);
2906 QuicByteCount data_frame_header_length =
2907 data_frame.size() - data_payload.size();
2908
2909 // DATA frame header is consumed.
2910 // DATA frame payload is not consumed because payload has to be buffered.
2911 OnStreamFrame(data_frame);
2912 EXPECT_EQ(data_frame_header_length, NewlyConsumedBytes());
2913
2914 // Frame of unknown, not reserved type is not consumed because DATA payload is
2915 // still buffered.
2916 std::string unknown_frame3 = UnknownFrame(0x39, "bar");
2917 OnStreamFrame(unknown_frame3);
2918 EXPECT_EQ(0u, NewlyConsumedBytes());
2919
2920 // Consume all but last byte of data.
2921 EXPECT_EQ(data_payload.substr(0, data_payload.size() - 1),
2922 ReadFromStream(data_payload.size() - 1));
2923 EXPECT_EQ(data_payload.size() - 1, NewlyConsumedBytes());
2924
2925 std::string trailers =
2926 HeadersFrame({std::make_pair("custom-key", "custom-value")});
2927
2928 // No bytes are consumed, because last byte of DATA payload is still buffered.
2929 OnStreamFrame(absl::string_view(trailers).substr(0, trailers.size() - 1));
2930 EXPECT_EQ(0u, NewlyConsumedBytes());
2931
2932 // Reading last byte of DATA payload triggers consumption of all data received
2933 // so far, even though last HEADERS frame has not been received completely.
2934 EXPECT_EQ(data_payload.substr(data_payload.size() - 1), ReadFromStream(1));
2935 EXPECT_EQ(1 + unknown_frame3.size() + trailers.size() - 1,
2936 NewlyConsumedBytes());
2937
2938 // Last byte of trailers is immediately consumed.
2939 OnStreamFrame(absl::string_view(trailers).substr(trailers.size() - 1));
2940 EXPECT_EQ(1u, NewlyConsumedBytes());
2941
2942 // Verify trailers.
2943 EXPECT_THAT(stream_->received_trailers(),
2944 ElementsAre(Pair("custom-key", "custom-value")));
2945
2946 // Unknown frame of reserved type after trailers is consumed immediately.
2947 std::string unknown_frame4 = UnknownFrame(0x40, "");
2948 OnStreamFrame(unknown_frame4);
2949 EXPECT_EQ(unknown_frame4.size(), NewlyConsumedBytes());
2950 }
2951
2952 // Close connection if a DATA frame is received before a HEADERS frame.
TEST_P(QuicSpdyStreamTest,DataBeforeHeaders)2953 TEST_P(QuicSpdyStreamTest, DataBeforeHeaders) {
2954 if (!UsesHttp3()) {
2955 return;
2956 }
2957
2958 Initialize(kShouldProcessData);
2959
2960 // Closing the connection is mocked out in tests. Instead, simply stop
2961 // reading data at the stream level to prevent QuicSpdyStream from blowing up.
2962 EXPECT_CALL(
2963 *connection_,
2964 CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
2965 "Unexpected DATA frame received.",
2966 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
2967 .WillOnce(InvokeWithoutArgs([this]() { stream_->StopReading(); }));
2968
2969 std::string data = DataFrame(kDataFramePayload);
2970 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, data));
2971 }
2972
2973 // Close connection if a HEADERS frame is received after the trailing HEADERS.
TEST_P(QuicSpdyStreamTest,TrailersAfterTrailers)2974 TEST_P(QuicSpdyStreamTest, TrailersAfterTrailers) {
2975 if (!UsesHttp3()) {
2976 return;
2977 }
2978
2979 Initialize(kShouldProcessData);
2980
2981 // Receive and consume headers.
2982 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
2983 QuicStreamOffset offset = 0;
2984 stream_->OnStreamFrame(
2985 QuicStreamFrame(stream_->id(), false, offset, headers));
2986 offset += headers.size();
2987
2988 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
2989 stream_->ConsumeHeaderList();
2990
2991 // Receive data. It is consumed by TestStream.
2992 std::string data = DataFrame(kDataFramePayload);
2993 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, offset, data));
2994 offset += data.size();
2995
2996 EXPECT_EQ(kDataFramePayload, stream_->data());
2997
2998 // Receive and consume trailers.
2999 std::string trailers1 =
3000 HeadersFrame({std::make_pair("custom-key", "custom-value")});
3001 stream_->OnStreamFrame(
3002 QuicStreamFrame(stream_->id(), false, offset, trailers1));
3003 offset += trailers1.size();
3004
3005 EXPECT_TRUE(stream_->trailers_decompressed());
3006 EXPECT_THAT(stream_->received_trailers(),
3007 ElementsAre(Pair("custom-key", "custom-value")));
3008
3009 // Closing the connection is mocked out in tests. Instead, simply stop
3010 // reading data at the stream level to prevent QuicSpdyStream from blowing up.
3011 EXPECT_CALL(
3012 *connection_,
3013 CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
3014 "HEADERS frame received after trailing HEADERS.",
3015 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
3016 .WillOnce(InvokeWithoutArgs([this]() { stream_->StopReading(); }));
3017
3018 // Receive another HEADERS frame, with no header fields.
3019 std::string trailers2 = HeadersFrame(Http2HeaderBlock());
3020 stream_->OnStreamFrame(
3021 QuicStreamFrame(stream_->id(), false, offset, trailers2));
3022 }
3023
3024 // Regression test for https://crbug.com/978733.
3025 // Close connection if a DATA frame is received after the trailing HEADERS.
TEST_P(QuicSpdyStreamTest,DataAfterTrailers)3026 TEST_P(QuicSpdyStreamTest, DataAfterTrailers) {
3027 if (!UsesHttp3()) {
3028 return;
3029 }
3030
3031 Initialize(kShouldProcessData);
3032
3033 // Receive and consume headers.
3034 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
3035 QuicStreamOffset offset = 0;
3036 stream_->OnStreamFrame(
3037 QuicStreamFrame(stream_->id(), false, offset, headers));
3038 offset += headers.size();
3039
3040 EXPECT_THAT(stream_->header_list(), ElementsAre(Pair("foo", "bar")));
3041 stream_->ConsumeHeaderList();
3042
3043 // Receive data. It is consumed by TestStream.
3044 std::string data1 = DataFrame(kDataFramePayload);
3045 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, offset, data1));
3046 offset += data1.size();
3047 EXPECT_EQ(kDataFramePayload, stream_->data());
3048
3049 // Receive trailers, with single header field "custom-key: custom-value".
3050 std::string trailers =
3051 HeadersFrame({std::make_pair("custom-key", "custom-value")});
3052 stream_->OnStreamFrame(
3053 QuicStreamFrame(stream_->id(), false, offset, trailers));
3054 offset += trailers.size();
3055
3056 EXPECT_THAT(stream_->received_trailers(),
3057 ElementsAre(Pair("custom-key", "custom-value")));
3058
3059 // Closing the connection is mocked out in tests. Instead, simply stop
3060 // reading data at the stream level to prevent QuicSpdyStream from blowing up.
3061 EXPECT_CALL(
3062 *connection_,
3063 CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
3064 "Unexpected DATA frame received.",
3065 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
3066 .WillOnce(InvokeWithoutArgs([this]() { stream_->StopReading(); }));
3067
3068 // Receive more data.
3069 std::string data2 = DataFrame("This payload should not be proccessed.");
3070 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, offset, data2));
3071 }
3072
3073 // SETTINGS frames are invalid on bidirectional streams. If one is received,
3074 // the connection is closed. No more data should be processed.
TEST_P(QuicSpdyStreamTest,StopProcessingIfConnectionClosed)3075 TEST_P(QuicSpdyStreamTest, StopProcessingIfConnectionClosed) {
3076 if (!UsesHttp3()) {
3077 return;
3078 }
3079
3080 Initialize(kShouldProcessData);
3081
3082 // SETTINGS frame with empty payload.
3083 std::string settings;
3084 ASSERT_TRUE(absl::HexStringToBytes("0400", &settings));
3085
3086 // HEADERS frame.
3087 // Since it arrives after a SETTINGS frame, it should never be read.
3088 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
3089
3090 // Combine the two frames to make sure they are processed in a single
3091 // QuicSpdyStream::OnDataAvailable() call.
3092 std::string frames = absl::StrCat(settings, headers);
3093
3094 EXPECT_EQ(0u, stream_->sequencer()->NumBytesConsumed());
3095
3096 EXPECT_CALL(*connection_,
3097 CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM, _, _))
3098 .WillOnce(
3099 Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
3100 EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
3101 EXPECT_CALL(*session_, OnConnectionClosed(_, _));
3102
3103 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), /* fin = */ false,
3104 /* offset = */ 0, frames));
3105
3106 EXPECT_EQ(0u, stream_->sequencer()->NumBytesConsumed());
3107 }
3108
3109 // Stream Cancellation instruction is sent on QPACK decoder stream
3110 // when stream is reset.
TEST_P(QuicSpdyStreamTest,StreamCancellationWhenStreamReset)3111 TEST_P(QuicSpdyStreamTest, StreamCancellationWhenStreamReset) {
3112 if (!UsesHttp3()) {
3113 return;
3114 }
3115
3116 Initialize(kShouldProcessData);
3117
3118 auto qpack_decoder_stream =
3119 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
3120 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
3121 // Stream type.
3122 EXPECT_CALL(*session_,
3123 WritevData(qpack_decoder_stream->id(), /* write_length = */ 1,
3124 /* offset = */ 0, _, _, _));
3125 // Stream cancellation.
3126 EXPECT_CALL(*session_,
3127 WritevData(qpack_decoder_stream->id(), /* write_length = */ 1,
3128 /* offset = */ 1, _, _, _));
3129 }
3130 EXPECT_CALL(*session_, MaybeSendStopSendingFrame(
3131 stream_->id(), QuicResetStreamError::FromInternal(
3132 QUIC_STREAM_CANCELLED)));
3133 EXPECT_CALL(
3134 *session_,
3135 MaybeSendRstStreamFrame(
3136 stream_->id(),
3137 QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED), _));
3138
3139 stream_->Reset(QUIC_STREAM_CANCELLED);
3140 }
3141
3142 // Stream Cancellation instruction is sent on QPACK decoder stream
3143 // when RESET_STREAM frame is received.
TEST_P(QuicSpdyStreamTest,StreamCancellationOnResetReceived)3144 TEST_P(QuicSpdyStreamTest, StreamCancellationOnResetReceived) {
3145 if (!UsesHttp3()) {
3146 return;
3147 }
3148
3149 Initialize(kShouldProcessData);
3150
3151 auto qpack_decoder_stream =
3152 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
3153 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
3154 // Stream type.
3155 EXPECT_CALL(*session_,
3156 WritevData(qpack_decoder_stream->id(), /* write_length = */ 1,
3157 /* offset = */ 0, _, _, _));
3158 // Stream cancellation.
3159 EXPECT_CALL(*session_,
3160 WritevData(qpack_decoder_stream->id(), /* write_length = */ 1,
3161 /* offset = */ 1, _, _, _));
3162 }
3163
3164 stream_->OnStreamReset(QuicRstStreamFrame(
3165 kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 0));
3166 }
3167
TEST_P(QuicSpdyStreamTest,WriteHeadersReturnValue)3168 TEST_P(QuicSpdyStreamTest, WriteHeadersReturnValue) {
3169 if (!UsesHttp3()) {
3170 return;
3171 }
3172
3173 Initialize(kShouldProcessData);
3174 testing::InSequence s;
3175
3176 // Enable QPACK dynamic table.
3177 session_->OnSetting(SETTINGS_QPACK_MAX_TABLE_CAPACITY, 1024);
3178 session_->OnSetting(SETTINGS_QPACK_BLOCKED_STREAMS, 1);
3179
3180 EXPECT_CALL(*stream_, WriteHeadersMock(true));
3181
3182 QpackSendStream* encoder_stream =
3183 QuicSpdySessionPeer::GetQpackEncoderSendStream(session_.get());
3184 EXPECT_CALL(*session_, WritevData(encoder_stream->id(), _, _, _, _, _))
3185 .Times(AnyNumber());
3186
3187 size_t bytes_written = 0;
3188 EXPECT_CALL(*session_,
3189 WritevData(stream_->id(), _, /* offset = */ 0, _, _, _))
3190 .WillOnce(
3191 DoAll(SaveArg<1>(&bytes_written),
3192 Invoke(session_.get(), &MockQuicSpdySession::ConsumeData)));
3193
3194 Http2HeaderBlock request_headers;
3195 request_headers["foo"] = "bar";
3196 size_t write_headers_return_value =
3197 stream_->WriteHeaders(std::move(request_headers), /*fin=*/true, nullptr);
3198 EXPECT_TRUE(stream_->fin_sent());
3199 // bytes_written includes HEADERS frame header.
3200 EXPECT_GT(bytes_written, write_headers_return_value);
3201 }
3202
3203 // Regression test for https://crbug.com/1177662.
3204 // RESET_STREAM with QUIC_STREAM_NO_ERROR should not be treated in a special
3205 // way: it should close the read side but not the write side.
TEST_P(QuicSpdyStreamTest,TwoResetStreamFrames)3206 TEST_P(QuicSpdyStreamTest, TwoResetStreamFrames) {
3207 if (!UsesHttp3()) {
3208 return;
3209 }
3210
3211 Initialize(kShouldProcessData);
3212
3213 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber());
3214
3215 QuicRstStreamFrame rst_frame1(kInvalidControlFrameId, stream_->id(),
3216 QUIC_STREAM_CANCELLED, /* bytes_written = */ 0);
3217 stream_->OnStreamReset(rst_frame1);
3218 EXPECT_TRUE(stream_->read_side_closed());
3219 EXPECT_FALSE(stream_->write_side_closed());
3220
3221 QuicRstStreamFrame rst_frame2(kInvalidControlFrameId, stream_->id(),
3222 QUIC_STREAM_NO_ERROR, /* bytes_written = */ 0);
3223 stream_->OnStreamReset(rst_frame2);
3224 EXPECT_TRUE(stream_->read_side_closed());
3225 EXPECT_FALSE(stream_->write_side_closed());
3226 }
3227
TEST_P(QuicSpdyStreamTest,ProcessOutgoingWebTransportHeaders)3228 TEST_P(QuicSpdyStreamTest, ProcessOutgoingWebTransportHeaders) {
3229 if (!UsesHttp3()) {
3230 return;
3231 }
3232
3233 InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
3234 session_->set_local_http_datagram_support(HttpDatagramSupport::kRfc);
3235 session_->EnableWebTransport();
3236 session_->OnSetting(SETTINGS_ENABLE_CONNECT_PROTOCOL, 1);
3237 QuicSpdySessionPeer::EnableWebTransport(session_.get());
3238 QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(),
3239 HttpDatagramSupport::kRfc);
3240
3241 EXPECT_CALL(*stream_, WriteHeadersMock(false));
3242 EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _))
3243 .Times(AnyNumber());
3244
3245 spdy::Http2HeaderBlock headers;
3246 headers[":method"] = "CONNECT";
3247 headers[":protocol"] = "webtransport";
3248 stream_->WriteHeaders(std::move(headers), /*fin=*/false, nullptr);
3249 ASSERT_TRUE(stream_->web_transport() != nullptr);
3250 EXPECT_EQ(stream_->id(), stream_->web_transport()->id());
3251 }
3252
TEST_P(QuicSpdyStreamTest,ProcessIncomingWebTransportHeaders)3253 TEST_P(QuicSpdyStreamTest, ProcessIncomingWebTransportHeaders) {
3254 if (!UsesHttp3()) {
3255 return;
3256 }
3257
3258 Initialize(kShouldProcessData);
3259 session_->set_local_http_datagram_support(HttpDatagramSupport::kRfc);
3260 session_->EnableWebTransport();
3261 QuicSpdySessionPeer::EnableWebTransport(session_.get());
3262 QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(),
3263 HttpDatagramSupport::kRfc);
3264
3265 headers_[":method"] = "CONNECT";
3266 headers_[":protocol"] = "webtransport";
3267
3268 stream_->OnStreamHeadersPriority(
3269 spdy::SpdyStreamPrecedence(kV3HighestPriority));
3270 ProcessHeaders(false, headers_);
3271 EXPECT_EQ("", stream_->data());
3272 EXPECT_FALSE(stream_->header_list().empty());
3273 EXPECT_FALSE(stream_->IsDoneReading());
3274 ASSERT_TRUE(stream_->web_transport() != nullptr);
3275 EXPECT_EQ(stream_->id(), stream_->web_transport()->id());
3276 }
3277
TEST_P(QuicSpdyStreamTest,IncomingWebTransportStreamWhenUnsupported)3278 TEST_P(QuicSpdyStreamTest, IncomingWebTransportStreamWhenUnsupported) {
3279 if (!UsesHttp3()) {
3280 return;
3281 }
3282
3283 Initialize(kShouldProcessData);
3284 // Support WebTransport locally, but not by the peer.
3285 session_->set_local_http_datagram_support(HttpDatagramSupport::kRfc);
3286 session_->EnableWebTransport();
3287 session_->OnSettingsFrame(SettingsFrame());
3288
3289 StrictMock<MockHttp3DebugVisitor> debug_visitor;
3290 session_->set_debug_visitor(&debug_visitor);
3291
3292 std::string webtransport_stream_frame;
3293 ASSERT_TRUE(
3294 absl::HexStringToBytes("40410400000000", &webtransport_stream_frame));
3295 QuicStreamFrame stream_frame(stream_->id(), /* fin = */ false,
3296 /* offset = */ 0, webtransport_stream_frame);
3297
3298 EXPECT_CALL(debug_visitor, OnUnknownFrameReceived(stream_->id(), 0x41, 4));
3299 stream_->OnStreamFrame(stream_frame);
3300 EXPECT_TRUE(stream_->web_transport_stream() == nullptr);
3301 }
3302
TEST_P(QuicSpdyStreamTest,IncomingWebTransportStream)3303 TEST_P(QuicSpdyStreamTest, IncomingWebTransportStream) {
3304 if (!UsesHttp3()) {
3305 return;
3306 }
3307
3308 Initialize(kShouldProcessData);
3309 session_->set_local_http_datagram_support(HttpDatagramSupport::kRfc);
3310 session_->EnableWebTransport();
3311 SettingsFrame settings;
3312 settings.values[SETTINGS_WEBTRANS_MAX_SESSIONS_DRAFT07] = 10;
3313 settings.values[SETTINGS_H3_DATAGRAM] = 1;
3314 session_->OnSettingsFrame(settings);
3315
3316 std::string webtransport_stream_frame;
3317 ASSERT_TRUE(absl::HexStringToBytes("404110", &webtransport_stream_frame));
3318 QuicStreamFrame stream_frame(stream_->id(), /* fin = */ false,
3319 /* offset = */ 0, webtransport_stream_frame);
3320
3321 EXPECT_CALL(*session_, CreateIncomingStream(0x10));
3322 stream_->OnStreamFrame(stream_frame);
3323 EXPECT_TRUE(stream_->web_transport_stream() != nullptr);
3324 }
3325
TEST_P(QuicSpdyStreamTest,IncomingWebTransportStreamWithPaddingDraft02)3326 TEST_P(QuicSpdyStreamTest, IncomingWebTransportStreamWithPaddingDraft02) {
3327 if (!UsesHttp3()) {
3328 return;
3329 }
3330
3331 Initialize(kShouldProcessData);
3332 session_->set_local_http_datagram_support(HttpDatagramSupport::kRfc);
3333 session_->EnableWebTransport();
3334 SettingsFrame settings;
3335 settings.values[SETTINGS_WEBTRANS_DRAFT00] = 1;
3336 settings.values[SETTINGS_H3_DATAGRAM] = 1;
3337 session_->OnSettingsFrame(settings);
3338
3339 std::string webtransport_stream_frame;
3340 ASSERT_TRUE(absl::HexStringToBytes("2100404110", &webtransport_stream_frame));
3341 QuicStreamFrame stream_frame(stream_->id(), /* fin = */ false,
3342 /* offset = */ 0, webtransport_stream_frame);
3343
3344 EXPECT_CALL(*session_, CreateIncomingStream(0x10));
3345 stream_->OnStreamFrame(stream_frame);
3346 EXPECT_TRUE(stream_->web_transport_stream() != nullptr);
3347 }
3348
TEST_P(QuicSpdyStreamTest,IncomingWebTransportStreamWithPaddingDraft07)3349 TEST_P(QuicSpdyStreamTest, IncomingWebTransportStreamWithPaddingDraft07) {
3350 if (!UsesHttp3()) {
3351 return;
3352 }
3353
3354 Initialize(kShouldProcessData);
3355 session_->set_local_http_datagram_support(HttpDatagramSupport::kRfc);
3356 session_->EnableWebTransport();
3357 SettingsFrame settings;
3358 settings.values[SETTINGS_WEBTRANS_MAX_SESSIONS_DRAFT07] = 10;
3359 settings.values[SETTINGS_H3_DATAGRAM] = 1;
3360 session_->OnSettingsFrame(settings);
3361
3362 std::string webtransport_stream_frame;
3363 ASSERT_TRUE(absl::HexStringToBytes("2100404110", &webtransport_stream_frame));
3364 QuicStreamFrame stream_frame(stream_->id(), /* fin = */ false,
3365 /* offset = */ 0, webtransport_stream_frame);
3366
3367 EXPECT_CALL(*connection_,
3368 CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
3369 HasSubstr("non-zero offset"), _));
3370 stream_->OnStreamFrame(stream_frame);
3371 EXPECT_TRUE(stream_->web_transport_stream() == nullptr);
3372 }
3373
TEST_P(QuicSpdyStreamTest,ReceiveHttpDatagram)3374 TEST_P(QuicSpdyStreamTest, ReceiveHttpDatagram) {
3375 if (!UsesHttp3()) {
3376 return;
3377 }
3378 InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
3379 session_->set_local_http_datagram_support(HttpDatagramSupport::kRfc);
3380 QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(),
3381 HttpDatagramSupport::kRfc);
3382 headers_[":method"] = "CONNECT";
3383 headers_[":protocol"] = "webtransport";
3384 ProcessHeaders(false, headers_);
3385 SavingHttp3DatagramVisitor h3_datagram_visitor;
3386 ASSERT_EQ(QuicDataWriter::GetVarInt62Len(stream_->id()), 1);
3387 std::array<char, 256> datagram;
3388 datagram[0] = stream_->id();
3389 for (size_t i = 1; i < datagram.size(); i++) {
3390 datagram[i] = i;
3391 }
3392
3393 stream_->RegisterHttp3DatagramVisitor(&h3_datagram_visitor);
3394 session_->OnMessageReceived(
3395 absl::string_view(datagram.data(), datagram.size()));
3396 EXPECT_THAT(
3397 h3_datagram_visitor.received_h3_datagrams(),
3398 ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{
3399 stream_->id(), std::string(&datagram[1], datagram.size() - 1)}));
3400 // Test move.
3401 SavingHttp3DatagramVisitor h3_datagram_visitor2;
3402 stream_->ReplaceHttp3DatagramVisitor(&h3_datagram_visitor2);
3403 EXPECT_TRUE(h3_datagram_visitor2.received_h3_datagrams().empty());
3404 session_->OnMessageReceived(
3405 absl::string_view(datagram.data(), datagram.size()));
3406 EXPECT_THAT(
3407 h3_datagram_visitor2.received_h3_datagrams(),
3408 ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{
3409 stream_->id(), std::string(&datagram[1], datagram.size() - 1)}));
3410 // Cleanup.
3411 stream_->UnregisterHttp3DatagramVisitor();
3412 }
3413
TEST_P(QuicSpdyStreamTest,SendHttpDatagram)3414 TEST_P(QuicSpdyStreamTest, SendHttpDatagram) {
3415 if (!UsesHttp3()) {
3416 return;
3417 }
3418 Initialize(kShouldProcessData);
3419 session_->set_local_http_datagram_support(HttpDatagramSupport::kRfc);
3420 QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(),
3421 HttpDatagramSupport::kRfc);
3422 std::string http_datagram_payload = {1, 2, 3, 4, 5, 6};
3423 EXPECT_CALL(*connection_, SendMessage(1, _, false))
3424 .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
3425 EXPECT_EQ(stream_->SendHttp3Datagram(http_datagram_payload),
3426 MESSAGE_STATUS_SUCCESS);
3427 }
3428
TEST_P(QuicSpdyStreamTest,GetMaxDatagramSize)3429 TEST_P(QuicSpdyStreamTest, GetMaxDatagramSize) {
3430 if (!UsesHttp3()) {
3431 return;
3432 }
3433 Initialize(kShouldProcessData);
3434 session_->set_local_http_datagram_support(HttpDatagramSupport::kRfc);
3435 QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(),
3436 HttpDatagramSupport::kRfc);
3437 EXPECT_GT(stream_->GetMaxDatagramSize(), 512u);
3438 }
3439
TEST_P(QuicSpdyStreamTest,Capsules)3440 TEST_P(QuicSpdyStreamTest, Capsules) {
3441 if (!UsesHttp3()) {
3442 return;
3443 }
3444 Initialize(kShouldProcessData);
3445 session_->set_local_http_datagram_support(HttpDatagramSupport::kRfc);
3446 QuicSpdySessionPeer::SetHttpDatagramSupport(session_.get(),
3447 HttpDatagramSupport::kRfc);
3448 SavingHttp3DatagramVisitor h3_datagram_visitor;
3449 stream_->RegisterHttp3DatagramVisitor(&h3_datagram_visitor);
3450 SavingConnectIpVisitor connect_ip_visitor;
3451 stream_->RegisterConnectIpVisitor(&connect_ip_visitor);
3452 headers_[":method"] = "CONNECT";
3453 headers_[":protocol"] = "fake-capsule-protocol";
3454 ProcessHeaders(/*fin=*/false, headers_);
3455 // Datagram capsule.
3456 std::string http_datagram_payload = {1, 2, 3, 4, 5, 6};
3457 stream_->OnCapsule(Capsule::Datagram(http_datagram_payload));
3458 EXPECT_THAT(h3_datagram_visitor.received_h3_datagrams(),
3459 ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{
3460 stream_->id(), http_datagram_payload}));
3461 // Address assign capsule.
3462 quiche::PrefixWithId ip_prefix_with_id;
3463 ip_prefix_with_id.request_id = 1;
3464 quiche::QuicheIpAddress ip_address;
3465 ip_address.FromString("::");
3466 ip_prefix_with_id.ip_prefix =
3467 quiche::QuicheIpPrefix(ip_address, /*prefix_length=*/96);
3468 Capsule address_assign_capsule = Capsule::AddressAssign();
3469 address_assign_capsule.address_assign_capsule().assigned_addresses.push_back(
3470 ip_prefix_with_id);
3471 stream_->OnCapsule(address_assign_capsule);
3472 EXPECT_THAT(connect_ip_visitor.received_address_assign_capsules(),
3473 ElementsAre(address_assign_capsule.address_assign_capsule()));
3474 // Address request capsule.
3475 Capsule address_request_capsule = Capsule::AddressRequest();
3476 address_request_capsule.address_request_capsule()
3477 .requested_addresses.push_back(ip_prefix_with_id);
3478 stream_->OnCapsule(address_request_capsule);
3479 EXPECT_THAT(connect_ip_visitor.received_address_request_capsules(),
3480 ElementsAre(address_request_capsule.address_request_capsule()));
3481 // Route advertisement capsule.
3482 Capsule route_advertisement_capsule = Capsule::RouteAdvertisement();
3483 IpAddressRange ip_address_range;
3484 ip_address_range.start_ip_address.FromString("192.0.2.24");
3485 ip_address_range.end_ip_address.FromString("192.0.2.42");
3486 ip_address_range.ip_protocol = 0;
3487 route_advertisement_capsule.route_advertisement_capsule()
3488 .ip_address_ranges.push_back(ip_address_range);
3489 stream_->OnCapsule(route_advertisement_capsule);
3490 EXPECT_THAT(
3491 connect_ip_visitor.received_route_advertisement_capsules(),
3492 ElementsAre(route_advertisement_capsule.route_advertisement_capsule()));
3493 // Unknown capsule.
3494 uint64_t capsule_type = 0x17u;
3495 std::string capsule_payload = {1, 2, 3, 4};
3496 Capsule unknown_capsule = Capsule::Unknown(capsule_type, capsule_payload);
3497 stream_->OnCapsule(unknown_capsule);
3498 EXPECT_THAT(h3_datagram_visitor.received_unknown_capsules(),
3499 ElementsAre(SavingHttp3DatagramVisitor::SavedUnknownCapsule{
3500 stream_->id(), capsule_type, capsule_payload}));
3501 // Cleanup.
3502 stream_->UnregisterHttp3DatagramVisitor();
3503 stream_->UnregisterConnectIpVisitor();
3504 }
3505
TEST_P(QuicSpdyStreamTest,QUIC_TEST_DISABLED_IN_CHROME (HeadersAccumulatorNullptr))3506 TEST_P(QuicSpdyStreamTest,
3507 QUIC_TEST_DISABLED_IN_CHROME(HeadersAccumulatorNullptr)) {
3508 if (!UsesHttp3()) {
3509 return;
3510 }
3511
3512 Initialize(kShouldProcessData);
3513
3514 // Creates QpackDecodedHeadersAccumulator in
3515 // `qpack_decoded_headers_accumulator_`.
3516 std::string headers = HeadersFrame({std::make_pair("foo", "bar")});
3517 stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
3518
3519 // Resets `qpack_decoded_headers_accumulator_`.
3520 stream_->OnHeadersDecoded({}, false);
3521
3522 EXPECT_QUIC_BUG(
3523 {
3524 EXPECT_CALL(*connection_, CloseConnection(_, _, _));
3525 // This private method should never be called when
3526 // `qpack_decoded_headers_accumulator_` is nullptr.
3527 EXPECT_FALSE(QuicSpdyStreamPeer::OnHeadersFrameEnd(stream_));
3528 },
3529 "b215142466_OnHeadersFrameEnd");
3530 }
3531
3532 // Regression test for https://crbug.com/1465224.
TEST_P(QuicSpdyStreamTest,ReadAfterReset)3533 TEST_P(QuicSpdyStreamTest, ReadAfterReset) {
3534 if (!UsesHttp3()) {
3535 return;
3536 }
3537
3538 Initialize(!kShouldProcessData);
3539
3540 ProcessHeaders(false, headers_);
3541 stream_->ConsumeHeaderList();
3542
3543 std::string data_frame = DataFrame(kDataFramePayload);
3544 QuicStreamFrame frame(stream_->id(), /* fin = */ false, 0, data_frame);
3545 stream_->OnStreamFrame(frame);
3546
3547 if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
3548 // As a result of resetting the stream, stream type and stream cancellation
3549 // are sent on the QPACK decoder stream.
3550 auto qpack_decoder_stream =
3551 QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
3552 EXPECT_CALL(*session_,
3553 WritevData(qpack_decoder_stream->id(), _, _, NO_FIN, _, _))
3554 .Times(2);
3555 }
3556
3557 stream_->OnStreamReset(QuicRstStreamFrame(
3558 kInvalidControlFrameId, stream_->id(), QUIC_STREAM_NO_ERROR, 0));
3559
3560 char buffer[100];
3561 struct iovec vec;
3562 vec.iov_base = buffer;
3563 vec.iov_len = ABSL_ARRAYSIZE(buffer);
3564
3565 size_t bytes_read = stream_->Readv(&vec, 1);
3566 EXPECT_EQ(0u, bytes_read);
3567 }
3568
TEST_P(QuicSpdyStreamTest,ColonDisallowedInHeaderName)3569 TEST_P(QuicSpdyStreamTest, ColonDisallowedInHeaderName) {
3570 if (!UsesHttp3()) {
3571 return;
3572 }
3573
3574 Initialize(kShouldProcessData);
3575
3576 headers_["foo:bar"] = "invalid";
3577 EXPECT_FALSE(stream_->ValidateReceivedHeaders(AsHeaderList(headers_)));
3578 EXPECT_EQ("Invalid character in header name foo:bar",
3579 stream_->invalid_request_details());
3580 }
3581
3582 } // namespace
3583 } // namespace test
3584 } // namespace quic
3585