1 // Copyright 2019 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_receive_control_stream.h"
6 
7 #include <string>
8 
9 #include "absl/memory/memory.h"
10 #include "absl/strings/escaping.h"
11 #include "absl/strings/string_view.h"
12 #include "quiche/quic/core/http/http_constants.h"
13 #include "quiche/quic/core/qpack/qpack_header_table.h"
14 #include "quiche/quic/core/quic_types.h"
15 #include "quiche/quic/core/quic_utils.h"
16 #include "quiche/quic/test_tools/qpack/qpack_encoder_peer.h"
17 #include "quiche/quic/test_tools/quic_spdy_session_peer.h"
18 #include "quiche/quic/test_tools/quic_stream_peer.h"
19 #include "quiche/quic/test_tools/quic_test_utils.h"
20 #include "quiche/common/simple_buffer_allocator.h"
21 
22 namespace quic {
23 
24 class QpackEncoder;
25 
26 namespace test {
27 
28 namespace {
29 using ::testing::_;
30 using ::testing::AnyNumber;
31 using ::testing::StrictMock;
32 
33 struct TestParams {
TestParamsquic::test::__anoncce22c3d0111::TestParams34   TestParams(const ParsedQuicVersion& version, Perspective perspective)
35       : version(version), perspective(perspective) {
36     QUIC_LOG(INFO) << "TestParams: " << *this;
37   }
38 
TestParamsquic::test::__anoncce22c3d0111::TestParams39   TestParams(const TestParams& other)
40       : version(other.version), perspective(other.perspective) {}
41 
operator <<(std::ostream & os,const TestParams & tp)42   friend std::ostream& operator<<(std::ostream& os, const TestParams& tp) {
43     os << "{ version: " << ParsedQuicVersionToString(tp.version)
44        << ", perspective: "
45        << (tp.perspective == Perspective::IS_CLIENT ? "client" : "server")
46        << "}";
47     return os;
48   }
49 
50   ParsedQuicVersion version;
51   Perspective perspective;
52 };
53 
54 // Used by ::testing::PrintToStringParamName().
PrintToString(const TestParams & tp)55 std::string PrintToString(const TestParams& tp) {
56   return absl::StrCat(
57       ParsedQuicVersionToString(tp.version), "_",
58       (tp.perspective == Perspective::IS_CLIENT ? "client" : "server"));
59 }
60 
GetTestParams()61 std::vector<TestParams> GetTestParams() {
62   std::vector<TestParams> params;
63   ParsedQuicVersionVector all_supported_versions = AllSupportedVersions();
64   for (const auto& version : AllSupportedVersions()) {
65     if (!VersionUsesHttp3(version.transport_version)) {
66       continue;
67     }
68     for (Perspective p : {Perspective::IS_SERVER, Perspective::IS_CLIENT}) {
69       params.emplace_back(version, p);
70     }
71   }
72   return params;
73 }
74 
75 class TestStream : public QuicSpdyStream {
76  public:
TestStream(QuicStreamId id,QuicSpdySession * session)77   TestStream(QuicStreamId id, QuicSpdySession* session)
78       : QuicSpdyStream(id, session, BIDIRECTIONAL) {}
79   ~TestStream() override = default;
80 
OnBodyAvailable()81   void OnBodyAvailable() override {}
82 };
83 
84 class QuicReceiveControlStreamTest : public QuicTestWithParam<TestParams> {
85  public:
QuicReceiveControlStreamTest()86   QuicReceiveControlStreamTest()
87       : connection_(new StrictMock<MockQuicConnection>(
88             &helper_, &alarm_factory_, perspective(),
89             SupportedVersions(GetParam().version))),
90         session_(connection_) {
91     EXPECT_CALL(session_, OnCongestionWindowChange(_)).Times(AnyNumber());
92     session_.Initialize();
93     EXPECT_CALL(
94         static_cast<const MockQuicCryptoStream&>(*session_.GetCryptoStream()),
95         encryption_established())
96         .WillRepeatedly(testing::Return(true));
97     QuicStreamId id = perspective() == Perspective::IS_SERVER
98                           ? GetNthClientInitiatedUnidirectionalStreamId(
99                                 session_.transport_version(), 3)
100                           : GetNthServerInitiatedUnidirectionalStreamId(
101                                 session_.transport_version(), 3);
102     char type[] = {kControlStream};
103 
104     QuicStreamFrame data1(id, false, 0, absl::string_view(type, 1));
105     session_.OnStreamFrame(data1);
106 
107     receive_control_stream_ =
108         QuicSpdySessionPeer::GetReceiveControlStream(&session_);
109 
110     stream_ = new TestStream(GetNthClientInitiatedBidirectionalStreamId(
111                                  GetParam().version.transport_version, 0),
112                              &session_);
113     session_.ActivateStream(absl::WrapUnique(stream_));
114   }
115 
perspective() const116   Perspective perspective() const { return GetParam().perspective; }
117 
NumBytesConsumed()118   QuicStreamOffset NumBytesConsumed() {
119     return QuicStreamPeer::sequencer(receive_control_stream_)
120         ->NumBytesConsumed();
121   }
122 
123   MockQuicConnectionHelper helper_;
124   MockAlarmFactory alarm_factory_;
125   StrictMock<MockQuicConnection>* connection_;
126   StrictMock<MockQuicSpdySession> session_;
127   QuicReceiveControlStream* receive_control_stream_;
128   TestStream* stream_;
129 };
130 
131 INSTANTIATE_TEST_SUITE_P(Tests, QuicReceiveControlStreamTest,
132                          ::testing::ValuesIn(GetTestParams()),
133                          ::testing::PrintToStringParamName());
134 
TEST_P(QuicReceiveControlStreamTest,ResetControlStream)135 TEST_P(QuicReceiveControlStreamTest, ResetControlStream) {
136   EXPECT_TRUE(receive_control_stream_->is_static());
137   QuicRstStreamFrame rst_frame(kInvalidControlFrameId,
138                                receive_control_stream_->id(),
139                                QUIC_STREAM_CANCELLED, 1234);
140   EXPECT_CALL(*connection_,
141               CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM, _, _));
142   receive_control_stream_->OnStreamReset(rst_frame);
143 }
144 
TEST_P(QuicReceiveControlStreamTest,ReceiveSettings)145 TEST_P(QuicReceiveControlStreamTest, ReceiveSettings) {
146   SettingsFrame settings;
147   settings.values[10] = 2;
148   settings.values[SETTINGS_MAX_FIELD_SECTION_SIZE] = 5;
149   settings.values[SETTINGS_QPACK_BLOCKED_STREAMS] = 12;
150   settings.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] = 37;
151   std::string data = HttpEncoder::SerializeSettingsFrame(settings);
152   QuicStreamFrame frame(receive_control_stream_->id(), false, 1, data);
153 
154   QpackEncoder* qpack_encoder = session_.qpack_encoder();
155   QpackEncoderHeaderTable* header_table =
156       QpackEncoderPeer::header_table(qpack_encoder);
157   EXPECT_EQ(std::numeric_limits<size_t>::max(),
158             session_.max_outbound_header_list_size());
159   EXPECT_EQ(0u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
160   EXPECT_EQ(0u, header_table->maximum_dynamic_table_capacity());
161 
162   receive_control_stream_->OnStreamFrame(frame);
163 
164   EXPECT_EQ(5u, session_.max_outbound_header_list_size());
165   EXPECT_EQ(12u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
166   EXPECT_EQ(37u, header_table->maximum_dynamic_table_capacity());
167 }
168 
169 // Regression test for https://crbug.com/982648.
170 // QuicReceiveControlStream::OnDataAvailable() must stop processing input as
171 // soon as OnSettingsFrameStart() is called by HttpDecoder for the second frame.
TEST_P(QuicReceiveControlStreamTest,ReceiveSettingsTwice)172 TEST_P(QuicReceiveControlStreamTest, ReceiveSettingsTwice) {
173   SettingsFrame settings;
174   // Reserved identifiers, must be ignored.
175   settings.values[0x21] = 100;
176   settings.values[0x40] = 200;
177 
178   std::string settings_frame = HttpEncoder::SerializeSettingsFrame(settings);
179 
180   QuicStreamOffset offset = 1;
181   EXPECT_EQ(offset, NumBytesConsumed());
182 
183   // Receive first SETTINGS frame.
184   receive_control_stream_->OnStreamFrame(
185       QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false, offset,
186                       settings_frame));
187   offset += settings_frame.length();
188 
189   // First SETTINGS frame is consumed.
190   EXPECT_EQ(offset, NumBytesConsumed());
191 
192   // Second SETTINGS frame causes the connection to be closed.
193   EXPECT_CALL(
194       *connection_,
195       CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_CONTROL_STREAM,
196                       "SETTINGS frame can only be received once.", _))
197       .WillOnce(
198           Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
199   EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
200   EXPECT_CALL(session_, OnConnectionClosed(_, _));
201 
202   // Receive second SETTINGS frame.
203   receive_control_stream_->OnStreamFrame(
204       QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false, offset,
205                       settings_frame));
206 
207   // Frame header of second SETTINGS frame is consumed, but not frame payload.
208   QuicByteCount settings_frame_header_length = 2;
209   EXPECT_EQ(offset + settings_frame_header_length, NumBytesConsumed());
210 }
211 
TEST_P(QuicReceiveControlStreamTest,ReceiveSettingsFragments)212 TEST_P(QuicReceiveControlStreamTest, ReceiveSettingsFragments) {
213   SettingsFrame settings;
214   settings.values[10] = 2;
215   settings.values[SETTINGS_MAX_FIELD_SECTION_SIZE] = 5;
216   std::string data = HttpEncoder::SerializeSettingsFrame(settings);
217   std::string data1 = data.substr(0, 1);
218   std::string data2 = data.substr(1, data.length() - 1);
219 
220   QuicStreamFrame frame(receive_control_stream_->id(), false, 1, data1);
221   QuicStreamFrame frame2(receive_control_stream_->id(), false, 2, data2);
222   EXPECT_NE(5u, session_.max_outbound_header_list_size());
223   receive_control_stream_->OnStreamFrame(frame);
224   receive_control_stream_->OnStreamFrame(frame2);
225   EXPECT_EQ(5u, session_.max_outbound_header_list_size());
226 }
227 
TEST_P(QuicReceiveControlStreamTest,ReceiveWrongFrame)228 TEST_P(QuicReceiveControlStreamTest, ReceiveWrongFrame) {
229   // DATA frame header without payload.
230   quiche::QuicheBuffer data = HttpEncoder::SerializeDataFrameHeader(
231       /* payload_length = */ 2, quiche::SimpleBufferAllocator::Get());
232 
233   QuicStreamFrame frame(receive_control_stream_->id(), false, 1,
234                         data.AsStringView());
235   EXPECT_CALL(
236       *connection_,
237       CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM, _, _));
238   receive_control_stream_->OnStreamFrame(frame);
239 }
240 
TEST_P(QuicReceiveControlStreamTest,ReceivePriorityUpdateFrameBeforeSettingsFrame)241 TEST_P(QuicReceiveControlStreamTest,
242        ReceivePriorityUpdateFrameBeforeSettingsFrame) {
243   std::string serialized_frame = HttpEncoder::SerializePriorityUpdateFrame({});
244   QuicStreamFrame data(receive_control_stream_->id(), /* fin = */ false,
245                        /* offset = */ 1, serialized_frame);
246 
247   EXPECT_CALL(*connection_,
248               CloseConnection(QUIC_HTTP_MISSING_SETTINGS_FRAME,
249                               "First frame received on control stream is type "
250                               "984832, but it must be SETTINGS.",
251                               _))
252       .WillOnce(
253           Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
254   EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
255   EXPECT_CALL(session_, OnConnectionClosed(_, _));
256 
257   receive_control_stream_->OnStreamFrame(data);
258 }
259 
TEST_P(QuicReceiveControlStreamTest,ReceiveGoAwayFrame)260 TEST_P(QuicReceiveControlStreamTest, ReceiveGoAwayFrame) {
261   StrictMock<MockHttp3DebugVisitor> debug_visitor;
262   session_.set_debug_visitor(&debug_visitor);
263 
264   QuicStreamOffset offset = 1;
265 
266   // Receive SETTINGS frame.
267   SettingsFrame settings;
268   std::string settings_frame = HttpEncoder::SerializeSettingsFrame(settings);
269   EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(settings));
270   receive_control_stream_->OnStreamFrame(
271       QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false, offset,
272                       settings_frame));
273   offset += settings_frame.length();
274 
275   GoAwayFrame goaway{/* id = */ 0};
276   std::string goaway_frame = HttpEncoder::SerializeGoAwayFrame(goaway);
277   QuicStreamFrame frame(receive_control_stream_->id(), false, offset,
278                         goaway_frame);
279 
280   EXPECT_FALSE(session_.goaway_received());
281 
282   EXPECT_CALL(debug_visitor, OnGoAwayFrameReceived(goaway));
283   receive_control_stream_->OnStreamFrame(frame);
284 
285   EXPECT_TRUE(session_.goaway_received());
286 }
287 
TEST_P(QuicReceiveControlStreamTest,PushPromiseOnControlStreamShouldClose)288 TEST_P(QuicReceiveControlStreamTest, PushPromiseOnControlStreamShouldClose) {
289   std::string push_promise_frame;
290   ASSERT_TRUE(
291       absl::HexStringToBytes("05"   // PUSH_PROMISE
292                              "01"   // length
293                              "00",  // push ID
294                              &push_promise_frame));
295   QuicStreamFrame frame(receive_control_stream_->id(), false, 1,
296                         push_promise_frame);
297   EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR, _, _))
298       .WillOnce(
299           Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
300   EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
301   EXPECT_CALL(session_, OnConnectionClosed(_, _));
302   receive_control_stream_->OnStreamFrame(frame);
303 }
304 
305 // Regression test for b/137554973: unknown frames should be consumed.
TEST_P(QuicReceiveControlStreamTest,ConsumeUnknownFrame)306 TEST_P(QuicReceiveControlStreamTest, ConsumeUnknownFrame) {
307   EXPECT_EQ(1u, NumBytesConsumed());
308 
309   QuicStreamOffset offset = 1;
310 
311   // Receive SETTINGS frame.
312   std::string settings_frame = HttpEncoder::SerializeSettingsFrame({});
313   receive_control_stream_->OnStreamFrame(
314       QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false, offset,
315                       settings_frame));
316   offset += settings_frame.length();
317 
318   // SETTINGS frame is consumed.
319   EXPECT_EQ(offset, NumBytesConsumed());
320 
321   // Receive unknown frame.
322   std::string unknown_frame;
323   ASSERT_TRUE(
324       absl::HexStringToBytes("21"       // reserved frame type
325                              "03"       // payload length
326                              "666f6f",  // payload "foo"
327                              &unknown_frame));
328 
329   receive_control_stream_->OnStreamFrame(QuicStreamFrame(
330       receive_control_stream_->id(), /* fin = */ false, offset, unknown_frame));
331   offset += unknown_frame.size();
332 
333   // Unknown frame is consumed.
334   EXPECT_EQ(offset, NumBytesConsumed());
335 }
336 
TEST_P(QuicReceiveControlStreamTest,ReceiveUnknownFrame)337 TEST_P(QuicReceiveControlStreamTest, ReceiveUnknownFrame) {
338   StrictMock<MockHttp3DebugVisitor> debug_visitor;
339   session_.set_debug_visitor(&debug_visitor);
340 
341   const QuicStreamId id = receive_control_stream_->id();
342   QuicStreamOffset offset = 1;
343 
344   // Receive SETTINGS frame.
345   SettingsFrame settings;
346   std::string settings_frame = HttpEncoder::SerializeSettingsFrame(settings);
347   EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(settings));
348   receive_control_stream_->OnStreamFrame(
349       QuicStreamFrame(id, /* fin = */ false, offset, settings_frame));
350   offset += settings_frame.length();
351 
352   // Receive unknown frame.
353   std::string unknown_frame;
354   ASSERT_TRUE(
355       absl::HexStringToBytes("21"       // reserved frame type
356                              "03"       // payload length
357                              "666f6f",  // payload "foo"
358                              &unknown_frame));
359 
360   EXPECT_CALL(debug_visitor, OnUnknownFrameReceived(id, /* frame_type = */ 0x21,
361                                                     /* payload_length = */ 3));
362   receive_control_stream_->OnStreamFrame(
363       QuicStreamFrame(id, /* fin = */ false, offset, unknown_frame));
364 }
365 
TEST_P(QuicReceiveControlStreamTest,CancelPushFrameBeforeSettings)366 TEST_P(QuicReceiveControlStreamTest, CancelPushFrameBeforeSettings) {
367   std::string cancel_push_frame;
368   ASSERT_TRUE(
369       absl::HexStringToBytes("03"   // type CANCEL_PUSH
370                              "01"   // payload length
371                              "01",  // push ID
372                              &cancel_push_frame));
373 
374   EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR,
375                                             "CANCEL_PUSH frame received.", _))
376       .WillOnce(
377           Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
378   EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
379   EXPECT_CALL(session_, OnConnectionClosed(_, _));
380 
381   receive_control_stream_->OnStreamFrame(
382       QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false,
383                       /* offset = */ 1, cancel_push_frame));
384 }
385 
TEST_P(QuicReceiveControlStreamTest,AcceptChFrameBeforeSettings)386 TEST_P(QuicReceiveControlStreamTest, AcceptChFrameBeforeSettings) {
387   std::string accept_ch_frame;
388   ASSERT_TRUE(
389       absl::HexStringToBytes("4089"  // type (ACCEPT_CH)
390                              "00",   // length
391                              &accept_ch_frame));
392 
393   if (perspective() == Perspective::IS_SERVER) {
394     EXPECT_CALL(*connection_,
395                 CloseConnection(
396                     QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM,
397                     "Invalid frame type 137 received on control stream.", _))
398         .WillOnce(
399             Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
400   } else {
401     EXPECT_CALL(*connection_,
402                 CloseConnection(QUIC_HTTP_MISSING_SETTINGS_FRAME,
403                                 "First frame received on control stream is "
404                                 "type 137, but it must be SETTINGS.",
405                                 _))
406         .WillOnce(
407             Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
408   }
409   EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
410   EXPECT_CALL(session_, OnConnectionClosed(_, _));
411 
412   receive_control_stream_->OnStreamFrame(
413       QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false,
414                       /* offset = */ 1, accept_ch_frame));
415 }
416 
TEST_P(QuicReceiveControlStreamTest,ReceiveAcceptChFrame)417 TEST_P(QuicReceiveControlStreamTest, ReceiveAcceptChFrame) {
418   StrictMock<MockHttp3DebugVisitor> debug_visitor;
419   session_.set_debug_visitor(&debug_visitor);
420 
421   const QuicStreamId id = receive_control_stream_->id();
422   QuicStreamOffset offset = 1;
423 
424   // Receive SETTINGS frame.
425   SettingsFrame settings;
426   std::string settings_frame = HttpEncoder::SerializeSettingsFrame(settings);
427   EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(settings));
428   receive_control_stream_->OnStreamFrame(
429       QuicStreamFrame(id, /* fin = */ false, offset, settings_frame));
430   offset += settings_frame.length();
431 
432   // Receive ACCEPT_CH frame.
433   std::string accept_ch_frame;
434   ASSERT_TRUE(
435       absl::HexStringToBytes("4089"  // type (ACCEPT_CH)
436                              "00",   // length
437                              &accept_ch_frame));
438 
439   if (perspective() == Perspective::IS_CLIENT) {
440     EXPECT_CALL(debug_visitor, OnAcceptChFrameReceived(_));
441   } else {
442     EXPECT_CALL(*connection_,
443                 CloseConnection(
444                     QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM,
445                     "Invalid frame type 137 received on control stream.", _))
446         .WillOnce(
447             Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
448     EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
449     EXPECT_CALL(session_, OnConnectionClosed(_, _));
450   }
451 
452   receive_control_stream_->OnStreamFrame(
453       QuicStreamFrame(id, /* fin = */ false, offset, accept_ch_frame));
454 }
455 
TEST_P(QuicReceiveControlStreamTest,UnknownFrameBeforeSettings)456 TEST_P(QuicReceiveControlStreamTest, UnknownFrameBeforeSettings) {
457   std::string unknown_frame;
458   ASSERT_TRUE(
459       absl::HexStringToBytes("21"       // reserved frame type
460                              "03"       // payload length
461                              "666f6f",  // payload "foo"
462                              &unknown_frame));
463 
464   EXPECT_CALL(*connection_,
465               CloseConnection(QUIC_HTTP_MISSING_SETTINGS_FRAME,
466                               "First frame received on control stream is type "
467                               "33, but it must be SETTINGS.",
468                               _))
469       .WillOnce(
470           Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
471   EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
472   EXPECT_CALL(session_, OnConnectionClosed(_, _));
473 
474   receive_control_stream_->OnStreamFrame(
475       QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false,
476                       /* offset = */ 1, unknown_frame));
477 }
478 
479 }  // namespace
480 }  // namespace test
481 }  // namespace quic
482