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 <utility>
8
9 #include "absl/strings/numbers.h"
10 #include "absl/strings/str_split.h"
11 #include "absl/strings/string_view.h"
12 #include "absl/types/optional.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 absl::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
OnUnknownFrameStart(uint64_t frame_type,QuicByteCount,QuicByteCount payload_length)175 bool QuicReceiveControlStream::OnUnknownFrameStart(
176 uint64_t frame_type, QuicByteCount /*header_length*/,
177 QuicByteCount payload_length) {
178 if (spdy_session()->debug_visitor()) {
179 spdy_session()->debug_visitor()->OnUnknownFrameReceived(id(), frame_type,
180 payload_length);
181 }
182
183 return ValidateFrameType(static_cast<HttpFrameType>(frame_type));
184 }
185
OnUnknownFramePayload(absl::string_view)186 bool QuicReceiveControlStream::OnUnknownFramePayload(
187 absl::string_view /*payload*/) {
188 // Ignore unknown frame types.
189 return true;
190 }
191
OnUnknownFrameEnd()192 bool QuicReceiveControlStream::OnUnknownFrameEnd() {
193 // Ignore unknown frame types.
194 return true;
195 }
196
ValidateFrameType(HttpFrameType frame_type)197 bool QuicReceiveControlStream::ValidateFrameType(HttpFrameType frame_type) {
198 // Certain frame types are forbidden.
199 if (frame_type == HttpFrameType::DATA ||
200 frame_type == HttpFrameType::HEADERS ||
201 (spdy_session()->perspective() == Perspective::IS_CLIENT &&
202 frame_type == HttpFrameType::MAX_PUSH_ID) ||
203 (spdy_session()->perspective() == Perspective::IS_SERVER &&
204 frame_type == HttpFrameType::ACCEPT_CH)) {
205 stream_delegate()->OnStreamError(
206 QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM,
207 absl::StrCat("Invalid frame type ", static_cast<int>(frame_type),
208 " received on control stream."));
209 return false;
210 }
211
212 if (settings_frame_received_) {
213 if (frame_type == HttpFrameType::SETTINGS) {
214 // SETTINGS frame may only be the first frame on the control stream.
215 stream_delegate()->OnStreamError(
216 QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_CONTROL_STREAM,
217 "SETTINGS frame can only be received once.");
218 return false;
219 }
220 return true;
221 }
222
223 if (frame_type == HttpFrameType::SETTINGS) {
224 settings_frame_received_ = true;
225 return true;
226 }
227 stream_delegate()->OnStreamError(
228 QUIC_HTTP_MISSING_SETTINGS_FRAME,
229 absl::StrCat("First frame received on control stream is type ",
230 static_cast<int>(frame_type), ", but it must be SETTINGS."));
231 return false;
232 }
233
234 } // namespace quic
235