• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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