1 // Copyright (c) 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/tools/quic_simple_server_stream.h"
6
7 #include <list>
8 #include <memory>
9 #include <optional>
10 #include <utility>
11
12 #include "absl/base/macros.h"
13 #include "absl/memory/memory.h"
14 #include "absl/strings/string_view.h"
15 #include "quiche/quic/core/crypto/null_encrypter.h"
16 #include "quiche/quic/core/http/http_encoder.h"
17 #include "quiche/quic/core/http/spdy_utils.h"
18 #include "quiche/quic/core/quic_alarm_factory.h"
19 #include "quiche/quic/core/quic_default_clock.h"
20 #include "quiche/quic/core/quic_error_codes.h"
21 #include "quiche/quic/core/quic_types.h"
22 #include "quiche/quic/core/quic_utils.h"
23 #include "quiche/quic/platform/api/quic_expect_bug.h"
24 #include "quiche/quic/platform/api/quic_flags.h"
25 #include "quiche/quic/platform/api/quic_socket_address.h"
26 #include "quiche/quic/platform/api/quic_test.h"
27 #include "quiche/quic/test_tools/crypto_test_utils.h"
28 #include "quiche/quic/test_tools/quic_config_peer.h"
29 #include "quiche/quic/test_tools/quic_connection_peer.h"
30 #include "quiche/quic/test_tools/quic_session_peer.h"
31 #include "quiche/quic/test_tools/quic_spdy_session_peer.h"
32 #include "quiche/quic/test_tools/quic_stream_peer.h"
33 #include "quiche/quic/test_tools/quic_test_utils.h"
34 #include "quiche/quic/test_tools/simulator/simulator.h"
35 #include "quiche/quic/tools/quic_backend_response.h"
36 #include "quiche/quic/tools/quic_memory_cache_backend.h"
37 #include "quiche/quic/tools/quic_simple_server_backend.h"
38 #include "quiche/quic/tools/quic_simple_server_session.h"
39 #include "quiche/common/simple_buffer_allocator.h"
40
41 using testing::_;
42 using testing::AnyNumber;
43 using testing::InSequence;
44 using testing::Invoke;
45 using testing::StrictMock;
46
47 namespace quic {
48 namespace test {
49
50 const size_t kFakeFrameLen = 60;
51 const size_t kErrorLength = strlen(QuicSimpleServerStream::kErrorResponseBody);
52 const size_t kDataFrameHeaderLength = 2;
53
54 class TestStream : public QuicSimpleServerStream {
55 public:
TestStream(QuicStreamId stream_id,QuicSpdySession * session,StreamType type,QuicSimpleServerBackend * quic_simple_server_backend)56 TestStream(QuicStreamId stream_id, QuicSpdySession* session, StreamType type,
57 QuicSimpleServerBackend* quic_simple_server_backend)
58 : QuicSimpleServerStream(stream_id, session, type,
59 quic_simple_server_backend) {
60 EXPECT_CALL(*this, WriteOrBufferBody(_, _))
61 .Times(AnyNumber())
62 .WillRepeatedly([this](absl::string_view data, bool fin) {
63 this->QuicSimpleServerStream::WriteOrBufferBody(data, fin);
64 });
65 }
66
67 ~TestStream() override = default;
68
69 MOCK_METHOD(void, FireAlarmMock, (), ());
70 MOCK_METHOD(void, WriteHeadersMock, (bool fin), ());
71 MOCK_METHOD(void, WriteEarlyHintsHeadersMock, (bool fin), ());
72 MOCK_METHOD(void, WriteOrBufferBody, (absl::string_view data, bool fin),
73 (override));
74
WriteHeaders(spdy::Http2HeaderBlock header_block,bool fin,quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>)75 size_t WriteHeaders(
76 spdy::Http2HeaderBlock header_block, bool fin,
77 quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
78 /*ack_listener*/) override {
79 if (header_block[":status"] == "103") {
80 WriteEarlyHintsHeadersMock(fin);
81 } else {
82 WriteHeadersMock(fin);
83 }
84 return 0;
85 }
86
87 // Expose protected QuicSimpleServerStream methods.
DoSendResponse()88 void DoSendResponse() { SendResponse(); }
DoSendErrorResponse()89 void DoSendErrorResponse() { QuicSimpleServerStream::SendErrorResponse(); }
90
mutable_headers()91 spdy::Http2HeaderBlock* mutable_headers() { return &request_headers_; }
set_body(std::string body)92 void set_body(std::string body) { body_ = std::move(body); }
body() const93 const std::string& body() const { return body_; }
content_length() const94 int content_length() const { return content_length_; }
send_response_was_called() const95 bool send_response_was_called() const { return send_response_was_called_; }
send_error_response_was_called() const96 bool send_error_response_was_called() const {
97 return send_error_response_was_called_;
98 }
99
GetHeader(absl::string_view key) const100 absl::string_view GetHeader(absl::string_view key) const {
101 auto it = request_headers_.find(key);
102 QUICHE_DCHECK(it != request_headers_.end());
103 return it->second;
104 }
105
ReplaceBackend(QuicSimpleServerBackend * backend)106 void ReplaceBackend(QuicSimpleServerBackend* backend) {
107 set_quic_simple_server_backend_for_test(backend);
108 }
109
110 protected:
SendResponse()111 void SendResponse() override {
112 send_response_was_called_ = true;
113 QuicSimpleServerStream::SendResponse();
114 }
115
SendErrorResponse(int resp_code)116 void SendErrorResponse(int resp_code) override {
117 send_error_response_was_called_ = true;
118 QuicSimpleServerStream::SendErrorResponse(resp_code);
119 }
120
121 private:
122 bool send_response_was_called_ = false;
123 bool send_error_response_was_called_ = false;
124 };
125
126 namespace {
127
128 class MockQuicSimpleServerSession : public QuicSimpleServerSession {
129 public:
130 const size_t kMaxStreamsForTest = 100;
131
MockQuicSimpleServerSession(QuicConnection * connection,MockQuicSessionVisitor * owner,MockQuicCryptoServerStreamHelper * helper,QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache,QuicSimpleServerBackend * quic_simple_server_backend)132 MockQuicSimpleServerSession(
133 QuicConnection* connection, MockQuicSessionVisitor* owner,
134 MockQuicCryptoServerStreamHelper* helper,
135 QuicCryptoServerConfig* crypto_config,
136 QuicCompressedCertsCache* compressed_certs_cache,
137 QuicSimpleServerBackend* quic_simple_server_backend)
138 : QuicSimpleServerSession(DefaultQuicConfig(), CurrentSupportedVersions(),
139 connection, owner, helper, crypto_config,
140 compressed_certs_cache,
141 quic_simple_server_backend) {
142 if (VersionHasIetfQuicFrames(connection->transport_version())) {
143 QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(
144 this, kMaxStreamsForTest);
145 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(
146 this, kMaxStreamsForTest);
147 } else {
148 QuicSessionPeer::SetMaxOpenIncomingStreams(this, kMaxStreamsForTest);
149 QuicSessionPeer::SetMaxOpenOutgoingStreams(this, kMaxStreamsForTest);
150 }
151 ON_CALL(*this, WritevData(_, _, _, _, _, _))
152 .WillByDefault(Invoke(this, &MockQuicSimpleServerSession::ConsumeData));
153 }
154
155 MockQuicSimpleServerSession(const MockQuicSimpleServerSession&) = delete;
156 MockQuicSimpleServerSession& operator=(const MockQuicSimpleServerSession&) =
157 delete;
158 ~MockQuicSimpleServerSession() override = default;
159
160 MOCK_METHOD(void, OnConnectionClosed,
161 (const QuicConnectionCloseFrame& frame,
162 ConnectionCloseSource source),
163 (override));
164 MOCK_METHOD(QuicSpdyStream*, CreateIncomingStream, (QuicStreamId id),
165 (override));
166 MOCK_METHOD(QuicConsumedData, WritevData,
167 (QuicStreamId id, size_t write_length, QuicStreamOffset offset,
168 StreamSendingState state, TransmissionType type,
169 EncryptionLevel level),
170 (override));
171 MOCK_METHOD(void, OnStreamHeaderList,
172 (QuicStreamId stream_id, bool fin, size_t frame_len,
173 const QuicHeaderList& header_list),
174 (override));
175 MOCK_METHOD(void, OnStreamHeadersPriority,
176 (QuicStreamId stream_id,
177 const spdy::SpdyStreamPrecedence& precedence),
178 (override));
179 MOCK_METHOD(void, MaybeSendRstStreamFrame,
180 (QuicStreamId stream_id, QuicResetStreamError error,
181 QuicStreamOffset bytes_written),
182 (override));
183 MOCK_METHOD(void, MaybeSendStopSendingFrame,
184 (QuicStreamId stream_id, QuicResetStreamError error), (override));
185
186 using QuicSession::ActivateStream;
187
ConsumeData(QuicStreamId id,size_t write_length,QuicStreamOffset offset,StreamSendingState state,TransmissionType,std::optional<EncryptionLevel>)188 QuicConsumedData ConsumeData(QuicStreamId id, size_t write_length,
189 QuicStreamOffset offset,
190 StreamSendingState state,
191 TransmissionType /*type*/,
192 std::optional<EncryptionLevel> /*level*/) {
193 if (write_length > 0) {
194 auto buf = std::make_unique<char[]>(write_length);
195 QuicStream* stream = GetOrCreateStream(id);
196 QUICHE_DCHECK(stream);
197 QuicDataWriter writer(write_length, buf.get(), quiche::HOST_BYTE_ORDER);
198 stream->WriteStreamData(offset, write_length, &writer);
199 } else {
200 QUICHE_DCHECK(state != NO_FIN);
201 }
202 return QuicConsumedData(write_length, state != NO_FIN);
203 }
204
205 spdy::Http2HeaderBlock original_request_headers_;
206 };
207
208 class QuicSimpleServerStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
209 public:
QuicSimpleServerStreamTest()210 QuicSimpleServerStreamTest()
211 : connection_(new StrictMock<MockQuicConnection>(
212 &simulator_, simulator_.GetAlarmFactory(), Perspective::IS_SERVER,
213 SupportedVersions(GetParam()))),
214 crypto_config_(new QuicCryptoServerConfig(
215 QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
216 crypto_test_utils::ProofSourceForTesting(),
217 KeyExchangeSource::Default())),
218 compressed_certs_cache_(
219 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
220 session_(connection_, &session_owner_, &session_helper_,
221 crypto_config_.get(), &compressed_certs_cache_,
222 &memory_cache_backend_),
223 quic_response_(new QuicBackendResponse),
224 body_("hello world") {
225 connection_->set_visitor(&session_);
226 header_list_.OnHeaderBlockStart();
227 header_list_.OnHeader(":authority", "www.google.com");
228 header_list_.OnHeader(":path", "/");
229 header_list_.OnHeader(":method", "POST");
230 header_list_.OnHeader(":scheme", "https");
231 header_list_.OnHeader("content-length", "11");
232
233 header_list_.OnHeaderBlockEnd(128, 128);
234
235 // New streams rely on having the peer's flow control receive window
236 // negotiated in the config.
237 session_.config()->SetInitialStreamFlowControlWindowToSend(
238 kInitialStreamFlowControlWindowForTest);
239 session_.config()->SetInitialSessionFlowControlWindowToSend(
240 kInitialSessionFlowControlWindowForTest);
241 session_.Initialize();
242 connection_->SetEncrypter(
243 quic::ENCRYPTION_FORWARD_SECURE,
244 std::make_unique<quic::NullEncrypter>(connection_->perspective()));
245 if (connection_->version().SupportsAntiAmplificationLimit()) {
246 QuicConnectionPeer::SetAddressValidated(connection_);
247 }
248 stream_ = new StrictMock<TestStream>(
249 GetNthClientInitiatedBidirectionalStreamId(
250 connection_->transport_version(), 0),
251 &session_, BIDIRECTIONAL, &memory_cache_backend_);
252 // Register stream_ in dynamic_stream_map_ and pass ownership to session_.
253 session_.ActivateStream(absl::WrapUnique(stream_));
254 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
255 session_.config(), kMinimumFlowControlSendWindow);
256 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
257 session_.config(), kMinimumFlowControlSendWindow);
258 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesIncomingBidirectional(
259 session_.config(), kMinimumFlowControlSendWindow);
260 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
261 session_.config(), kMinimumFlowControlSendWindow);
262 QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_.config(), 10);
263 session_.OnConfigNegotiated();
264 simulator_.RunFor(QuicTime::Delta::FromSeconds(1));
265 }
266
StreamBody()267 const std::string& StreamBody() { return stream_->body(); }
268
StreamHeadersValue(const std::string & key)269 std::string StreamHeadersValue(const std::string& key) {
270 return (*stream_->mutable_headers())[key].as_string();
271 }
272
UsesHttp3() const273 bool UsesHttp3() const {
274 return VersionUsesHttp3(connection_->transport_version());
275 }
276
ReplaceBackend(std::unique_ptr<QuicSimpleServerBackend> backend)277 void ReplaceBackend(std::unique_ptr<QuicSimpleServerBackend> backend) {
278 replacement_backend_ = std::move(backend);
279 stream_->ReplaceBackend(replacement_backend_.get());
280 }
281
282 quic::simulator::Simulator simulator_;
283 spdy::Http2HeaderBlock response_headers_;
284 MockQuicConnectionHelper helper_;
285 StrictMock<MockQuicConnection>* connection_;
286 StrictMock<MockQuicSessionVisitor> session_owner_;
287 StrictMock<MockQuicCryptoServerStreamHelper> session_helper_;
288 std::unique_ptr<QuicCryptoServerConfig> crypto_config_;
289 QuicCompressedCertsCache compressed_certs_cache_;
290 QuicMemoryCacheBackend memory_cache_backend_;
291 std::unique_ptr<QuicSimpleServerBackend> replacement_backend_;
292 StrictMock<MockQuicSimpleServerSession> session_;
293 StrictMock<TestStream>* stream_; // Owned by session_.
294 std::unique_ptr<QuicBackendResponse> quic_response_;
295 std::string body_;
296 QuicHeaderList header_list_;
297 };
298
299 INSTANTIATE_TEST_SUITE_P(Tests, QuicSimpleServerStreamTest,
300 ::testing::ValuesIn(AllSupportedVersions()),
301 ::testing::PrintToStringParamName());
302
TEST_P(QuicSimpleServerStreamTest,TestFraming)303 TEST_P(QuicSimpleServerStreamTest, TestFraming) {
304 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
305 .WillRepeatedly(
306 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
307 stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
308 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
309 body_.length(), quiche::SimpleBufferAllocator::Get());
310 std::string data =
311 UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
312 stream_->OnStreamFrame(
313 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
314 EXPECT_EQ("11", StreamHeadersValue("content-length"));
315 EXPECT_EQ("/", StreamHeadersValue(":path"));
316 EXPECT_EQ("POST", StreamHeadersValue(":method"));
317 EXPECT_EQ(body_, StreamBody());
318 }
319
TEST_P(QuicSimpleServerStreamTest,TestFramingOnePacket)320 TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) {
321 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
322 .WillRepeatedly(
323 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
324
325 stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
326 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
327 body_.length(), quiche::SimpleBufferAllocator::Get());
328 std::string data =
329 UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
330 stream_->OnStreamFrame(
331 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
332 EXPECT_EQ("11", StreamHeadersValue("content-length"));
333 EXPECT_EQ("/", StreamHeadersValue(":path"));
334 EXPECT_EQ("POST", StreamHeadersValue(":method"));
335 EXPECT_EQ(body_, StreamBody());
336 }
337
TEST_P(QuicSimpleServerStreamTest,SendQuicRstStreamNoErrorInStopReading)338 TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorInStopReading) {
339 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
340 .WillRepeatedly(
341 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
342
343 EXPECT_FALSE(stream_->fin_received());
344 EXPECT_FALSE(stream_->rst_received());
345
346 QuicStreamPeer::SetFinSent(stream_);
347 stream_->CloseWriteSide();
348
349 if (session_.version().UsesHttp3()) {
350 EXPECT_CALL(session_,
351 MaybeSendStopSendingFrame(_, QuicResetStreamError::FromInternal(
352 QUIC_STREAM_NO_ERROR)))
353 .Times(1);
354 } else {
355 EXPECT_CALL(
356 session_,
357 MaybeSendRstStreamFrame(
358 _, QuicResetStreamError::FromInternal(QUIC_STREAM_NO_ERROR), _))
359 .Times(1);
360 }
361 stream_->StopReading();
362 }
363
TEST_P(QuicSimpleServerStreamTest,TestFramingExtraData)364 TEST_P(QuicSimpleServerStreamTest, TestFramingExtraData) {
365 InSequence seq;
366 std::string large_body = "hello world!!!!!!";
367
368 // We'll automatically write out an error (headers + body)
369 EXPECT_CALL(*stream_, WriteHeadersMock(false));
370 if (UsesHttp3()) {
371 EXPECT_CALL(session_,
372 WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _, _));
373 }
374 EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
375
376 stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
377 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
378 body_.length(), quiche::SimpleBufferAllocator::Get());
379 std::string data =
380 UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
381
382 stream_->OnStreamFrame(
383 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
384 // Content length is still 11. This will register as an error and we won't
385 // accept the bytes.
386 header = HttpEncoder::SerializeDataFrameHeader(
387 large_body.length(), quiche::SimpleBufferAllocator::Get());
388 std::string data2 = UsesHttp3()
389 ? absl::StrCat(header.AsStringView(), large_body)
390 : large_body;
391 stream_->OnStreamFrame(
392 QuicStreamFrame(stream_->id(), /*fin=*/true, data.size(), data2));
393 EXPECT_EQ("11", StreamHeadersValue("content-length"));
394 EXPECT_EQ("/", StreamHeadersValue(":path"));
395 EXPECT_EQ("POST", StreamHeadersValue(":method"));
396 }
397
TEST_P(QuicSimpleServerStreamTest,SendResponseWithIllegalResponseStatus)398 TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) {
399 // Send an illegal response with response status not supported by HTTP/2.
400 spdy::Http2HeaderBlock* request_headers = stream_->mutable_headers();
401 (*request_headers)[":path"] = "/bar";
402 (*request_headers)[":authority"] = "www.google.com";
403 (*request_headers)[":method"] = "GET";
404
405 // HTTP/2 only supports integer responsecode, so "200 OK" is illegal.
406 response_headers_[":status"] = "200 OK";
407 response_headers_["content-length"] = "5";
408 std::string body = "Yummm";
409 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
410 body.length(), quiche::SimpleBufferAllocator::Get());
411
412 memory_cache_backend_.AddResponse("www.google.com", "/bar",
413 std::move(response_headers_), body);
414
415 QuicStreamPeer::SetFinReceived(stream_);
416
417 InSequence s;
418 EXPECT_CALL(*stream_, WriteHeadersMock(false));
419 if (UsesHttp3()) {
420 EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
421 }
422 EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
423
424 stream_->DoSendResponse();
425 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
426 EXPECT_TRUE(stream_->write_side_closed());
427 }
428
TEST_P(QuicSimpleServerStreamTest,SendResponseWithIllegalResponseStatus2)429 TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) {
430 // Send an illegal response with response status not supported by HTTP/2.
431 spdy::Http2HeaderBlock* request_headers = stream_->mutable_headers();
432 (*request_headers)[":path"] = "/bar";
433 (*request_headers)[":authority"] = "www.google.com";
434 (*request_headers)[":method"] = "GET";
435
436 // HTTP/2 only supports 3-digit-integer, so "+200" is illegal.
437 response_headers_[":status"] = "+200";
438 response_headers_["content-length"] = "5";
439 std::string body = "Yummm";
440
441 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
442 body.length(), quiche::SimpleBufferAllocator::Get());
443
444 memory_cache_backend_.AddResponse("www.google.com", "/bar",
445 std::move(response_headers_), body);
446
447 QuicStreamPeer::SetFinReceived(stream_);
448
449 InSequence s;
450 EXPECT_CALL(*stream_, WriteHeadersMock(false));
451 if (UsesHttp3()) {
452 EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
453 }
454 EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
455
456 stream_->DoSendResponse();
457 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
458 EXPECT_TRUE(stream_->write_side_closed());
459 }
460
TEST_P(QuicSimpleServerStreamTest,SendResponseWithValidHeaders)461 TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) {
462 // Add a request and response with valid headers.
463 spdy::Http2HeaderBlock* request_headers = stream_->mutable_headers();
464 (*request_headers)[":path"] = "/bar";
465 (*request_headers)[":authority"] = "www.google.com";
466 (*request_headers)[":method"] = "GET";
467
468 response_headers_[":status"] = "200";
469 response_headers_["content-length"] = "5";
470 std::string body = "Yummm";
471
472 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
473 body.length(), quiche::SimpleBufferAllocator::Get());
474
475 memory_cache_backend_.AddResponse("www.google.com", "/bar",
476 std::move(response_headers_), body);
477 QuicStreamPeer::SetFinReceived(stream_);
478
479 InSequence s;
480 EXPECT_CALL(*stream_, WriteHeadersMock(false));
481 if (UsesHttp3()) {
482 EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
483 }
484 EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
485
486 stream_->DoSendResponse();
487 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
488 EXPECT_TRUE(stream_->write_side_closed());
489 }
490
TEST_P(QuicSimpleServerStreamTest,SendResponseWithEarlyHints)491 TEST_P(QuicSimpleServerStreamTest, SendResponseWithEarlyHints) {
492 std::string host = "www.google.com";
493 std::string request_path = "/foo";
494 std::string body = "Yummm";
495
496 // Add a request and response with early hints.
497 spdy::Http2HeaderBlock* request_headers = stream_->mutable_headers();
498 (*request_headers)[":path"] = request_path;
499 (*request_headers)[":authority"] = host;
500 (*request_headers)[":method"] = "GET";
501
502 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
503 body.length(), quiche::SimpleBufferAllocator::Get());
504 std::vector<spdy::Http2HeaderBlock> early_hints;
505 // Add two Early Hints.
506 const size_t kNumEarlyHintsResponses = 2;
507 for (size_t i = 0; i < kNumEarlyHintsResponses; ++i) {
508 spdy::Http2HeaderBlock hints;
509 hints["link"] = "</image.png>; rel=preload; as=image";
510 early_hints.push_back(std::move(hints));
511 }
512
513 response_headers_[":status"] = "200";
514 response_headers_["content-length"] = "5";
515 memory_cache_backend_.AddResponseWithEarlyHints(
516 host, request_path, std::move(response_headers_), body, early_hints);
517 QuicStreamPeer::SetFinReceived(stream_);
518
519 InSequence s;
520 for (size_t i = 0; i < kNumEarlyHintsResponses; ++i) {
521 EXPECT_CALL(*stream_, WriteEarlyHintsHeadersMock(false));
522 }
523 EXPECT_CALL(*stream_, WriteHeadersMock(false));
524 if (UsesHttp3()) {
525 EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
526 }
527 EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
528
529 stream_->DoSendResponse();
530 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
531 EXPECT_TRUE(stream_->write_side_closed());
532 }
533
534 class AlarmTestDelegate : public QuicAlarm::DelegateWithoutContext {
535 public:
AlarmTestDelegate(TestStream * stream)536 AlarmTestDelegate(TestStream* stream) : stream_(stream) {}
537
OnAlarm()538 void OnAlarm() override { stream_->FireAlarmMock(); }
539
540 private:
541 TestStream* stream_;
542 };
543
TEST_P(QuicSimpleServerStreamTest,SendResponseWithDelay)544 TEST_P(QuicSimpleServerStreamTest, SendResponseWithDelay) {
545 // Add a request and response with valid headers.
546 spdy::Http2HeaderBlock* request_headers = stream_->mutable_headers();
547 std::string host = "www.google.com";
548 std::string path = "/bar";
549 (*request_headers)[":path"] = path;
550 (*request_headers)[":authority"] = host;
551 (*request_headers)[":method"] = "GET";
552
553 response_headers_[":status"] = "200";
554 response_headers_["content-length"] = "5";
555 std::string body = "Yummm";
556 QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(3000);
557
558 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
559 body.length(), quiche::SimpleBufferAllocator::Get());
560
561 memory_cache_backend_.AddResponse(host, path, std::move(response_headers_),
562 body);
563 auto did_delay_succeed =
564 memory_cache_backend_.SetResponseDelay(host, path, delay);
565 EXPECT_TRUE(did_delay_succeed);
566 auto did_invalid_delay_succeed =
567 memory_cache_backend_.SetResponseDelay(host, "nonsense", delay);
568 EXPECT_FALSE(did_invalid_delay_succeed);
569 std::unique_ptr<QuicAlarm> alarm(connection_->alarm_factory()->CreateAlarm(
570 new AlarmTestDelegate(stream_)));
571 alarm->Set(connection_->clock()->Now() + delay);
572 QuicStreamPeer::SetFinReceived(stream_);
573 InSequence s;
574 EXPECT_CALL(*stream_, FireAlarmMock());
575 EXPECT_CALL(*stream_, WriteHeadersMock(false));
576
577 if (UsesHttp3()) {
578 EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
579 }
580 EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
581
582 stream_->DoSendResponse();
583 simulator_.RunFor(delay);
584
585 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
586 EXPECT_TRUE(stream_->write_side_closed());
587 }
588
TEST_P(QuicSimpleServerStreamTest,TestSendErrorResponse)589 TEST_P(QuicSimpleServerStreamTest, TestSendErrorResponse) {
590 QuicStreamPeer::SetFinReceived(stream_);
591
592 InSequence s;
593 EXPECT_CALL(*stream_, WriteHeadersMock(false));
594 if (UsesHttp3()) {
595 EXPECT_CALL(session_,
596 WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _, _));
597 }
598 EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
599
600 stream_->DoSendErrorResponse();
601 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
602 EXPECT_TRUE(stream_->write_side_closed());
603 }
604
TEST_P(QuicSimpleServerStreamTest,InvalidMultipleContentLength)605 TEST_P(QuicSimpleServerStreamTest, InvalidMultipleContentLength) {
606 spdy::Http2HeaderBlock request_headers;
607 // \000 is a way to write the null byte when followed by a literal digit.
608 header_list_.OnHeader("content-length", absl::string_view("11\00012", 5));
609
610 if (session_.version().UsesHttp3()) {
611 EXPECT_CALL(session_,
612 MaybeSendStopSendingFrame(_, QuicResetStreamError::FromInternal(
613 QUIC_STREAM_NO_ERROR)));
614 }
615 EXPECT_CALL(*stream_, WriteHeadersMock(false));
616 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
617 .WillRepeatedly(
618 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
619 stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_);
620
621 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
622 EXPECT_TRUE(stream_->reading_stopped());
623 EXPECT_TRUE(stream_->write_side_closed());
624 }
625
TEST_P(QuicSimpleServerStreamTest,InvalidLeadingNullContentLength)626 TEST_P(QuicSimpleServerStreamTest, InvalidLeadingNullContentLength) {
627 spdy::Http2HeaderBlock request_headers;
628 // \000 is a way to write the null byte when followed by a literal digit.
629 header_list_.OnHeader("content-length", absl::string_view("\00012", 3));
630
631 if (session_.version().UsesHttp3()) {
632 EXPECT_CALL(session_,
633 MaybeSendStopSendingFrame(_, QuicResetStreamError::FromInternal(
634 QUIC_STREAM_NO_ERROR)));
635 }
636 EXPECT_CALL(*stream_, WriteHeadersMock(false));
637 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
638 .WillRepeatedly(
639 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
640 stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_);
641
642 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
643 EXPECT_TRUE(stream_->reading_stopped());
644 EXPECT_TRUE(stream_->write_side_closed());
645 }
646
TEST_P(QuicSimpleServerStreamTest,InvalidMultipleContentLengthII)647 TEST_P(QuicSimpleServerStreamTest, InvalidMultipleContentLengthII) {
648 spdy::Http2HeaderBlock request_headers;
649 // \000 is a way to write the null byte when followed by a literal digit.
650 header_list_.OnHeader("content-length", absl::string_view("11\00011", 5));
651
652 if (session_.version().UsesHttp3()) {
653 EXPECT_CALL(session_,
654 MaybeSendStopSendingFrame(_, QuicResetStreamError::FromInternal(
655 QUIC_STREAM_NO_ERROR)));
656 EXPECT_CALL(*stream_, WriteHeadersMock(false));
657 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
658 .WillRepeatedly(
659 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
660 }
661
662 stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
663
664 if (session_.version().UsesHttp3()) {
665 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
666 EXPECT_TRUE(stream_->reading_stopped());
667 EXPECT_TRUE(stream_->write_side_closed());
668 } else {
669 EXPECT_EQ(11, stream_->content_length());
670 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
671 EXPECT_FALSE(stream_->reading_stopped());
672 EXPECT_FALSE(stream_->write_side_closed());
673 }
674 }
675
TEST_P(QuicSimpleServerStreamTest,DoNotSendQuicRstStreamNoErrorWithRstReceived)676 TEST_P(QuicSimpleServerStreamTest,
677 DoNotSendQuicRstStreamNoErrorWithRstReceived) {
678 EXPECT_FALSE(stream_->reading_stopped());
679
680 if (VersionUsesHttp3(connection_->transport_version())) {
681 // Unidirectional stream type and then a Stream Cancellation instruction is
682 // sent on the QPACK decoder stream. Ignore these writes without any
683 // assumption on their number or size.
684 auto* qpack_decoder_stream =
685 QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_);
686 EXPECT_CALL(session_, WritevData(qpack_decoder_stream->id(), _, _, _, _, _))
687 .Times(AnyNumber());
688 }
689
690 EXPECT_CALL(
691 session_,
692 MaybeSendRstStreamFrame(
693 _,
694 session_.version().UsesHttp3()
695 ? QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED)
696 : QuicResetStreamError::FromInternal(QUIC_RST_ACKNOWLEDGEMENT),
697 _))
698 .Times(1);
699 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
700 QUIC_STREAM_CANCELLED, 1234);
701 stream_->OnStreamReset(rst_frame);
702 if (VersionHasIetfQuicFrames(connection_->transport_version())) {
703 EXPECT_CALL(session_owner_, OnStopSendingReceived(_));
704 // Create and inject a STOP SENDING frame to complete the close
705 // of the stream. This is only needed for version 99/IETF QUIC.
706 QuicStopSendingFrame stop_sending(kInvalidControlFrameId, stream_->id(),
707 QUIC_STREAM_CANCELLED);
708 session_.OnStopSendingFrame(stop_sending);
709 }
710 EXPECT_TRUE(stream_->reading_stopped());
711 EXPECT_TRUE(stream_->write_side_closed());
712 }
713
TEST_P(QuicSimpleServerStreamTest,InvalidHeadersWithFin)714 TEST_P(QuicSimpleServerStreamTest, InvalidHeadersWithFin) {
715 char arr[] = {
716 0x3a, 0x68, 0x6f, 0x73, // :hos
717 0x74, 0x00, 0x00, 0x00, // t...
718 0x00, 0x00, 0x00, 0x00, // ....
719 0x07, 0x3a, 0x6d, 0x65, // .:me
720 0x74, 0x68, 0x6f, 0x64, // thod
721 0x00, 0x00, 0x00, 0x03, // ....
722 0x47, 0x45, 0x54, 0x00, // GET.
723 0x00, 0x00, 0x05, 0x3a, // ...:
724 0x70, 0x61, 0x74, 0x68, // path
725 0x00, 0x00, 0x00, 0x04, // ....
726 0x2f, 0x66, 0x6f, 0x6f, // /foo
727 0x00, 0x00, 0x00, 0x07, // ....
728 0x3a, 0x73, 0x63, 0x68, // :sch
729 0x65, 0x6d, 0x65, 0x00, // eme.
730 0x00, 0x00, 0x00, 0x00, // ....
731 0x00, 0x00, 0x08, 0x3a, // ...:
732 0x76, 0x65, 0x72, 0x73, // vers
733 '\x96', 0x6f, 0x6e, 0x00, // <i(69)>on.
734 0x00, 0x00, 0x08, 0x48, // ...H
735 0x54, 0x54, 0x50, 0x2f, // TTP/
736 0x31, 0x2e, 0x31, // 1.1
737 };
738 absl::string_view data(arr, ABSL_ARRAYSIZE(arr));
739 QuicStreamFrame frame(stream_->id(), true, 0, data);
740 // Verify that we don't crash when we get a invalid headers in stream frame.
741 stream_->OnStreamFrame(frame);
742 }
743
744 // Basic QuicSimpleServerBackend that implements its behavior through mocking.
745 class TestQuicSimpleServerBackend : public QuicSimpleServerBackend {
746 public:
747 TestQuicSimpleServerBackend() = default;
748 ~TestQuicSimpleServerBackend() override = default;
749
750 // QuicSimpleServerBackend:
InitializeBackend(const std::string &)751 bool InitializeBackend(const std::string& /*backend_url*/) override {
752 return true;
753 }
IsBackendInitialized() const754 bool IsBackendInitialized() const override { return true; }
755 MOCK_METHOD(void, FetchResponseFromBackend,
756 (const spdy::Http2HeaderBlock&, const std::string&,
757 RequestHandler*),
758 (override));
759 MOCK_METHOD(void, HandleConnectHeaders,
760 (const spdy::Http2HeaderBlock&, RequestHandler*), (override));
761 MOCK_METHOD(void, HandleConnectData,
762 (absl::string_view, bool, RequestHandler*), (override));
CloseBackendResponseStream(RequestHandler *)763 void CloseBackendResponseStream(
764 RequestHandler* /*request_handler*/) override {}
765 };
766
ACTION_P(SendHeadersResponse,response_ptr)767 ACTION_P(SendHeadersResponse, response_ptr) {
768 arg1->OnResponseBackendComplete(response_ptr);
769 }
770
ACTION_P(SendStreamData,data,close_stream)771 ACTION_P(SendStreamData, data, close_stream) {
772 arg2->SendStreamData(data, close_stream);
773 }
774
ACTION_P(TerminateStream,error)775 ACTION_P(TerminateStream, error) { arg1->TerminateStreamWithError(error); }
776
TEST_P(QuicSimpleServerStreamTest,ConnectSendsIntermediateResponses)777 TEST_P(QuicSimpleServerStreamTest, ConnectSendsIntermediateResponses) {
778 auto test_backend = std::make_unique<TestQuicSimpleServerBackend>();
779 TestQuicSimpleServerBackend* test_backend_ptr = test_backend.get();
780 ReplaceBackend(std::move(test_backend));
781
782 constexpr absl::string_view kRequestBody = "\x11\x11";
783 spdy::Http2HeaderBlock response_headers;
784 response_headers[":status"] = "200";
785 QuicBackendResponse headers_response;
786 headers_response.set_headers(response_headers.Clone());
787 headers_response.set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE);
788 constexpr absl::string_view kBody1 = "\x22\x22";
789 constexpr absl::string_view kBody2 = "\x33\x33";
790
791 // Expect an initial headers-only request to result in a headers-only
792 // incomplete response. Then a data frame without fin, resulting in stream
793 // data. Then a data frame with fin, resulting in stream data with fin.
794 InSequence s;
795 EXPECT_CALL(*test_backend_ptr, HandleConnectHeaders(_, _))
796 .WillOnce(SendHeadersResponse(&headers_response));
797 EXPECT_CALL(*stream_, WriteHeadersMock(false));
798 EXPECT_CALL(*test_backend_ptr, HandleConnectData(kRequestBody, false, _))
799 .WillOnce(SendStreamData(kBody1,
800 /*close_stream=*/false));
801 EXPECT_CALL(*stream_, WriteOrBufferBody(kBody1, false));
802 EXPECT_CALL(*test_backend_ptr, HandleConnectData(kRequestBody, true, _))
803 .WillOnce(SendStreamData(kBody2,
804 /*close_stream=*/true));
805 EXPECT_CALL(*stream_, WriteOrBufferBody(kBody2, true));
806
807 QuicHeaderList header_list;
808 header_list.OnHeaderBlockStart();
809 header_list.OnHeader(":authority", "www.google.com:4433");
810 header_list.OnHeader(":method", "CONNECT");
811 header_list.OnHeaderBlockEnd(128, 128);
812
813 stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
814 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
815 kRequestBody.length(), quiche::SimpleBufferAllocator::Get());
816 std::string data = UsesHttp3()
817 ? absl::StrCat(header.AsStringView(), kRequestBody)
818 : std::string(kRequestBody);
819 stream_->OnStreamFrame(
820 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
821 stream_->OnStreamFrame(
822 QuicStreamFrame(stream_->id(), /*fin=*/true, data.length(), data));
823
824 // Expect to not go through SendResponse().
825 EXPECT_FALSE(stream_->send_response_was_called());
826 EXPECT_FALSE(stream_->send_error_response_was_called());
827 }
828
TEST_P(QuicSimpleServerStreamTest,ErrorOnUnhandledConnect)829 TEST_P(QuicSimpleServerStreamTest, ErrorOnUnhandledConnect) {
830 // Expect single set of failure response headers with FIN in response to the
831 // headers. Then, expect abrupt stream termination in response to the body.
832 EXPECT_CALL(*stream_, WriteHeadersMock(true));
833 EXPECT_CALL(session_, MaybeSendRstStreamFrame(stream_->id(), _, _));
834
835 QuicHeaderList header_list;
836 header_list.OnHeaderBlockStart();
837 header_list.OnHeader(":authority", "www.google.com:4433");
838 header_list.OnHeader(":method", "CONNECT");
839 header_list.OnHeaderBlockEnd(128, 128);
840 constexpr absl::string_view kRequestBody = "\x11\x11";
841
842 stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
843 quiche::QuicheBuffer header = HttpEncoder::SerializeDataFrameHeader(
844 kRequestBody.length(), quiche::SimpleBufferAllocator::Get());
845 std::string data = UsesHttp3()
846 ? absl::StrCat(header.AsStringView(), kRequestBody)
847 : std::string(kRequestBody);
848 stream_->OnStreamFrame(
849 QuicStreamFrame(stream_->id(), /*fin=*/true, /*offset=*/0, data));
850
851 // Expect failure to not go through SendResponse().
852 EXPECT_FALSE(stream_->send_response_was_called());
853 EXPECT_FALSE(stream_->send_error_response_was_called());
854 }
855
TEST_P(QuicSimpleServerStreamTest,ConnectWithInvalidHeader)856 TEST_P(QuicSimpleServerStreamTest, ConnectWithInvalidHeader) {
857 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
858 .WillRepeatedly(
859 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
860 QuicHeaderList header_list;
861 header_list.OnHeaderBlockStart();
862 header_list.OnHeader(":authority", "www.google.com:4433");
863 header_list.OnHeader(":method", "CONNECT");
864 // QUIC requires lower-case header names.
865 header_list.OnHeader("InVaLiD-HeAdEr", "Well that's just wrong!");
866 header_list.OnHeaderBlockEnd(128, 128);
867
868 if (UsesHttp3()) {
869 EXPECT_CALL(session_,
870 MaybeSendStopSendingFrame(_, QuicResetStreamError::FromInternal(
871 QUIC_STREAM_NO_ERROR)))
872 .Times(1);
873 } else {
874 EXPECT_CALL(
875 session_,
876 MaybeSendRstStreamFrame(
877 _, QuicResetStreamError::FromInternal(QUIC_STREAM_NO_ERROR), _))
878 .Times(1);
879 }
880 EXPECT_CALL(*stream_, WriteHeadersMock(/*fin=*/false));
881 stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
882 EXPECT_FALSE(stream_->send_response_was_called());
883 EXPECT_TRUE(stream_->send_error_response_was_called());
884 }
885
TEST_P(QuicSimpleServerStreamTest,BackendCanTerminateStream)886 TEST_P(QuicSimpleServerStreamTest, BackendCanTerminateStream) {
887 auto test_backend = std::make_unique<TestQuicSimpleServerBackend>();
888 TestQuicSimpleServerBackend* test_backend_ptr = test_backend.get();
889 ReplaceBackend(std::move(test_backend));
890
891 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
892 .WillRepeatedly(
893 Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
894
895 QuicResetStreamError expected_error =
896 QuicResetStreamError::FromInternal(QUIC_STREAM_CONNECT_ERROR);
897 EXPECT_CALL(*test_backend_ptr, HandleConnectHeaders(_, _))
898 .WillOnce(TerminateStream(expected_error));
899 EXPECT_CALL(session_,
900 MaybeSendRstStreamFrame(stream_->id(), expected_error, _));
901
902 QuicHeaderList header_list;
903 header_list.OnHeaderBlockStart();
904 header_list.OnHeader(":authority", "www.google.com:4433");
905 header_list.OnHeader(":method", "CONNECT");
906 header_list.OnHeaderBlockEnd(128, 128);
907 stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
908 }
909
910 } // namespace
911 } // namespace test
912 } // namespace quic
913