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