xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/http/quic_receive_control_stream.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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