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 <optional>
8 #include <utility>
9
10 #include "absl/strings/numbers.h"
11 #include "absl/strings/str_split.h"
12 #include "absl/strings/string_view.h"
13 #include "quiche/quic/core/http/http_constants.h"
14 #include "quiche/quic/core/http/http_decoder.h"
15 #include "quiche/quic/core/http/quic_spdy_session.h"
16 #include "quiche/quic/core/quic_stream_priority.h"
17 #include "quiche/quic/core/quic_types.h"
18 #include "quiche/quic/platform/api/quic_flag_utils.h"
19 #include "quiche/quic/platform/api/quic_flags.h"
20 #include "quiche/common/quiche_text_utils.h"
21
22 namespace quic {
23
QuicReceiveControlStream(PendingStream * pending,QuicSpdySession * spdy_session)24 QuicReceiveControlStream::QuicReceiveControlStream(
25 PendingStream* pending, QuicSpdySession* spdy_session)
26 : QuicStream(pending, spdy_session,
27 /*is_static=*/true),
28 settings_frame_received_(false),
29 decoder_(this),
30 spdy_session_(spdy_session) {
31 sequencer()->set_level_triggered(true);
32 }
33
~QuicReceiveControlStream()34 QuicReceiveControlStream::~QuicReceiveControlStream() {}
35
OnStreamReset(const QuicRstStreamFrame &)36 void QuicReceiveControlStream::OnStreamReset(
37 const QuicRstStreamFrame& /*frame*/) {
38 stream_delegate()->OnStreamError(
39 QUIC_HTTP_CLOSED_CRITICAL_STREAM,
40 "RESET_STREAM received for receive control stream");
41 }
42
OnDataAvailable()43 void QuicReceiveControlStream::OnDataAvailable() {
44 iovec iov;
45 while (!reading_stopped() && decoder_.error() == QUIC_NO_ERROR &&
46 sequencer()->GetReadableRegion(&iov)) {
47 QUICHE_DCHECK(!sequencer()->IsClosed());
48
49 QuicByteCount processed_bytes = decoder_.ProcessInput(
50 reinterpret_cast<const char*>(iov.iov_base), iov.iov_len);
51 sequencer()->MarkConsumed(processed_bytes);
52
53 if (!session()->connection()->connected()) {
54 return;
55 }
56
57 // The only reason QuicReceiveControlStream pauses HttpDecoder is an error,
58 // in which case the connection would have already been closed.
59 QUICHE_DCHECK_EQ(iov.iov_len, processed_bytes);
60 }
61 }
62
OnError(HttpDecoder * decoder)63 void QuicReceiveControlStream::OnError(HttpDecoder* decoder) {
64 stream_delegate()->OnStreamError(decoder->error(), decoder->error_detail());
65 }
66
OnMaxPushIdFrame()67 bool QuicReceiveControlStream::OnMaxPushIdFrame() {
68 return ValidateFrameType(HttpFrameType::MAX_PUSH_ID);
69 }
70
OnGoAwayFrame(const GoAwayFrame & frame)71 bool QuicReceiveControlStream::OnGoAwayFrame(const GoAwayFrame& frame) {
72 if (spdy_session()->debug_visitor()) {
73 spdy_session()->debug_visitor()->OnGoAwayFrameReceived(frame);
74 }
75
76 if (!ValidateFrameType(HttpFrameType::GOAWAY)) {
77 return false;
78 }
79
80 spdy_session()->OnHttp3GoAway(frame.id);
81 return true;
82 }
83
OnSettingsFrameStart(QuicByteCount)84 bool QuicReceiveControlStream::OnSettingsFrameStart(
85 QuicByteCount /*header_length*/) {
86 return ValidateFrameType(HttpFrameType::SETTINGS);
87 }
88
OnSettingsFrame(const SettingsFrame & frame)89 bool QuicReceiveControlStream::OnSettingsFrame(const SettingsFrame& frame) {
90 QUIC_DVLOG(1) << "Control Stream " << id()
91 << " received settings frame: " << frame;
92 return spdy_session_->OnSettingsFrame(frame);
93 }
94
OnDataFrameStart(QuicByteCount,QuicByteCount)95 bool QuicReceiveControlStream::OnDataFrameStart(QuicByteCount /*header_length*/,
96 QuicByteCount
97 /*payload_length*/) {
98 return ValidateFrameType(HttpFrameType::DATA);
99 }
100
OnDataFramePayload(absl::string_view)101 bool QuicReceiveControlStream::OnDataFramePayload(
102 absl::string_view /*payload*/) {
103 QUICHE_NOTREACHED();
104 return false;
105 }
106
OnDataFrameEnd()107 bool QuicReceiveControlStream::OnDataFrameEnd() {
108 QUICHE_NOTREACHED();
109 return false;
110 }
111
OnHeadersFrameStart(QuicByteCount,QuicByteCount)112 bool QuicReceiveControlStream::OnHeadersFrameStart(
113 QuicByteCount /*header_length*/, QuicByteCount
114 /*payload_length*/) {
115 return ValidateFrameType(HttpFrameType::HEADERS);
116 }
117
OnHeadersFramePayload(absl::string_view)118 bool QuicReceiveControlStream::OnHeadersFramePayload(
119 absl::string_view /*payload*/) {
120 QUICHE_NOTREACHED();
121 return false;
122 }
123
OnHeadersFrameEnd()124 bool QuicReceiveControlStream::OnHeadersFrameEnd() {
125 QUICHE_NOTREACHED();
126 return false;
127 }
128
OnPriorityUpdateFrameStart(QuicByteCount)129 bool QuicReceiveControlStream::OnPriorityUpdateFrameStart(
130 QuicByteCount /*header_length*/) {
131 return ValidateFrameType(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM);
132 }
133
OnPriorityUpdateFrame(const PriorityUpdateFrame & frame)134 bool QuicReceiveControlStream::OnPriorityUpdateFrame(
135 const PriorityUpdateFrame& frame) {
136 if (spdy_session()->debug_visitor()) {
137 spdy_session()->debug_visitor()->OnPriorityUpdateFrameReceived(frame);
138 }
139
140 std::optional<HttpStreamPriority> priority =
141 ParsePriorityFieldValue(frame.priority_field_value);
142
143 if (!priority.has_value()) {
144 stream_delegate()->OnStreamError(QUIC_INVALID_PRIORITY_UPDATE,
145 "Invalid PRIORITY_UPDATE frame payload.");
146 return false;
147 }
148
149 const QuicStreamId stream_id = frame.prioritized_element_id;
150 return spdy_session_->OnPriorityUpdateForRequestStream(stream_id, *priority);
151 }
152
OnAcceptChFrameStart(QuicByteCount)153 bool QuicReceiveControlStream::OnAcceptChFrameStart(
154 QuicByteCount /* header_length */) {
155 return ValidateFrameType(HttpFrameType::ACCEPT_CH);
156 }
157
OnAcceptChFrame(const AcceptChFrame & frame)158 bool QuicReceiveControlStream::OnAcceptChFrame(const AcceptChFrame& frame) {
159 QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, spdy_session()->perspective());
160
161 if (spdy_session()->debug_visitor()) {
162 spdy_session()->debug_visitor()->OnAcceptChFrameReceived(frame);
163 }
164
165 spdy_session()->OnAcceptChFrame(frame);
166 return true;
167 }
168
OnWebTransportStreamFrameType(QuicByteCount,WebTransportSessionId)169 void QuicReceiveControlStream::OnWebTransportStreamFrameType(
170 QuicByteCount /*header_length*/, WebTransportSessionId /*session_id*/) {
171 QUIC_BUG(WEBTRANSPORT_STREAM on Control Stream)
172 << "Parsed WEBTRANSPORT_STREAM on a control stream.";
173 }
174
OnMetadataFrameStart(QuicByteCount,QuicByteCount)175 bool QuicReceiveControlStream::OnMetadataFrameStart(
176 QuicByteCount /*header_length*/, QuicByteCount /*payload_length*/) {
177 return ValidateFrameType(HttpFrameType::METADATA);
178 }
179
OnMetadataFramePayload(absl::string_view)180 bool QuicReceiveControlStream::OnMetadataFramePayload(
181 absl::string_view /*payload*/) {
182 // Ignore METADATA frames.
183 return true;
184 }
185
OnMetadataFrameEnd()186 bool QuicReceiveControlStream::OnMetadataFrameEnd() {
187 // Ignore METADATA frames.
188 return true;
189 }
190
OnUnknownFrameStart(uint64_t frame_type,QuicByteCount,QuicByteCount payload_length)191 bool QuicReceiveControlStream::OnUnknownFrameStart(
192 uint64_t frame_type, QuicByteCount /*header_length*/,
193 QuicByteCount payload_length) {
194 if (spdy_session()->debug_visitor()) {
195 spdy_session()->debug_visitor()->OnUnknownFrameReceived(id(), frame_type,
196 payload_length);
197 }
198
199 return ValidateFrameType(static_cast<HttpFrameType>(frame_type));
200 }
201
OnUnknownFramePayload(absl::string_view)202 bool QuicReceiveControlStream::OnUnknownFramePayload(
203 absl::string_view /*payload*/) {
204 // Ignore unknown frame types.
205 return true;
206 }
207
OnUnknownFrameEnd()208 bool QuicReceiveControlStream::OnUnknownFrameEnd() {
209 // Ignore unknown frame types.
210 return true;
211 }
212
ValidateFrameType(HttpFrameType frame_type)213 bool QuicReceiveControlStream::ValidateFrameType(HttpFrameType frame_type) {
214 // Certain frame types are forbidden.
215 if (frame_type == HttpFrameType::DATA ||
216 frame_type == HttpFrameType::HEADERS ||
217 (spdy_session()->perspective() == Perspective::IS_CLIENT &&
218 frame_type == HttpFrameType::MAX_PUSH_ID) ||
219 (spdy_session()->perspective() == Perspective::IS_SERVER &&
220 frame_type == HttpFrameType::ACCEPT_CH)) {
221 stream_delegate()->OnStreamError(
222 QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM,
223 absl::StrCat("Invalid frame type ", static_cast<int>(frame_type),
224 " received on control stream."));
225 return false;
226 }
227
228 if (settings_frame_received_) {
229 if (frame_type == HttpFrameType::SETTINGS) {
230 // SETTINGS frame may only be the first frame on the control stream.
231 stream_delegate()->OnStreamError(
232 QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_CONTROL_STREAM,
233 "SETTINGS frame can only be received once.");
234 return false;
235 }
236 return true;
237 }
238
239 if (frame_type == HttpFrameType::SETTINGS) {
240 settings_frame_received_ = true;
241 return true;
242 }
243 stream_delegate()->OnStreamError(
244 QUIC_HTTP_MISSING_SETTINGS_FRAME,
245 absl::StrCat("First frame received on control stream is type ",
246 static_cast<int>(frame_type), ", but it must be SETTINGS."));
247 return false;
248 }
249
250 } // namespace quic
251