blob: 7e424a353c1e18ac45054b25d79a1f74c60e994d [file] [log] [blame]
QUICHE team82dee2f2019-01-18 12:35:12 -05001// Copyright 2016 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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "spdy/core/http2_frame_decoder_adapter.h"
QUICHE team82dee2f2019-01-18 12:35:12 -05006
QUICHE team1b5d09e2021-04-08 13:36:42 -07007// Logging policy: If an error in the input is detected, QUICHE_VLOG(n) is used
8// so that the option exists to debug the situation. Otherwise, this code mostly
9// uses QUICHE_DVLOG so that the logging does not slow down production code when
danzh520d4d72019-07-01 12:33:38 -070010// things are working OK.
QUICHE team82dee2f2019-01-18 12:35:12 -050011
12#include <stddef.h>
13
14#include <cstdint>
15#include <cstring>
16#include <utility>
17
QUICHE team5be974e2020-12-29 18:35:24 -050018#include "http2/decoder/decode_buffer.h"
19#include "http2/decoder/decode_status.h"
20#include "http2/decoder/http2_frame_decoder.h"
21#include "http2/decoder/http2_frame_decoder_listener.h"
22#include "http2/http2_constants.h"
23#include "http2/http2_structures.h"
QUICHE team33a4aa62021-04-08 11:10:59 -070024#include "common/platform/api/quiche_bug_tracker.h"
QUICHE team1b5d09e2021-04-08 13:36:42 -070025#include "common/platform/api/quiche_logging.h"
QUICHE team5be974e2020-12-29 18:35:24 -050026#include "common/quiche_endian.h"
27#include "spdy/core/hpack/hpack_decoder_adapter.h"
28#include "spdy/core/hpack/hpack_header_table.h"
29#include "spdy/core/spdy_alt_svc_wire_format.h"
30#include "spdy/core/spdy_header_block.h"
31#include "spdy/core/spdy_headers_handler_interface.h"
32#include "spdy/core/spdy_protocol.h"
QUICHE team82dee2f2019-01-18 12:35:12 -050033
34using ::spdy::ExtensionVisitorInterface;
35using ::spdy::HpackDecoderAdapter;
36using ::spdy::HpackHeaderTable;
37using ::spdy::ParseErrorCode;
38using ::spdy::ParseFrameType;
39using ::spdy::SpdyAltSvcWireFormat;
40using ::spdy::SpdyErrorCode;
QUICHE team82dee2f2019-01-18 12:35:12 -050041using ::spdy::SpdyFramerDebugVisitorInterface;
42using ::spdy::SpdyFramerVisitorInterface;
43using ::spdy::SpdyFrameType;
44using ::spdy::SpdyHeadersHandlerInterface;
45using ::spdy::SpdyKnownSettingsId;
QUICHE team82dee2f2019-01-18 12:35:12 -050046using ::spdy::SpdySettingsId;
47
48namespace http2 {
49namespace {
50
51const bool kHasPriorityFields = true;
52const bool kNotHasPriorityFields = false;
53
54bool IsPaddable(Http2FrameType type) {
55 return type == Http2FrameType::DATA || type == Http2FrameType::HEADERS ||
56 type == Http2FrameType::PUSH_PROMISE;
57}
58
59SpdyFrameType ToSpdyFrameType(Http2FrameType type) {
60 return ParseFrameType(static_cast<uint8_t>(type));
61}
62
63uint64_t ToSpdyPingId(const Http2PingFields& ping) {
64 uint64_t v;
65 std::memcpy(&v, ping.opaque_bytes, Http2PingFields::EncodedSize());
bnc975c94c2020-10-17 05:08:58 -070066 return quiche::QuicheEndian::NetToHost64(v);
QUICHE team82dee2f2019-01-18 12:35:12 -050067}
68
69// Overwrites the fields of the header with invalid values, for the purpose
70// of identifying reading of unset fields. Only takes effect for debug builds.
71// In Address Sanatizer builds, it also marks the fields as un-readable.
QUICHE team82dee2f2019-01-18 12:35:12 -050072#ifndef NDEBUG
bnc77b46412020-02-21 08:09:09 -080073void CorruptFrameHeader(Http2FrameHeader* header) {
QUICHE team82dee2f2019-01-18 12:35:12 -050074 // Beyond a valid payload length, which is 2^24 - 1.
75 header->payload_length = 0x1010dead;
76 // An unsupported frame type.
77 header->type = Http2FrameType(0x80);
vasilvved4f3082021-02-01 14:29:40 -080078 QUICHE_DCHECK(!IsSupportedHttp2FrameType(header->type));
QUICHE team82dee2f2019-01-18 12:35:12 -050079 // Frame flag bits that aren't used by any supported frame type.
80 header->flags = Http2FrameFlag(0xd2);
81 // A stream id with the reserved high-bit (R in the RFC) set.
82 // 2129510127 when the high-bit is cleared.
83 header->stream_id = 0xfeedbeef;
bnc77b46412020-02-21 08:09:09 -080084}
danzh8f3a5762019-06-25 13:43:51 -070085#else
bnc77b46412020-02-21 08:09:09 -080086void CorruptFrameHeader(Http2FrameHeader* /*header*/) {}
QUICHE team82dee2f2019-01-18 12:35:12 -050087#endif
bnc77b46412020-02-21 08:09:09 -080088
89Http2DecoderAdapter::SpdyFramerError HpackDecodingErrorToSpdyFramerError(
90 HpackDecodingError error) {
bnc77b46412020-02-21 08:09:09 -080091 switch (error) {
92 case HpackDecodingError::kOk:
93 return Http2DecoderAdapter::SpdyFramerError::SPDY_NO_ERROR;
94 case HpackDecodingError::kIndexVarintError:
95 return Http2DecoderAdapter::SpdyFramerError::
96 SPDY_HPACK_INDEX_VARINT_ERROR;
97 case HpackDecodingError::kNameLengthVarintError:
98 return Http2DecoderAdapter::SpdyFramerError::
99 SPDY_HPACK_NAME_LENGTH_VARINT_ERROR;
100 case HpackDecodingError::kValueLengthVarintError:
101 return Http2DecoderAdapter::SpdyFramerError::
102 SPDY_HPACK_VALUE_LENGTH_VARINT_ERROR;
103 case HpackDecodingError::kNameTooLong:
104 return Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_NAME_TOO_LONG;
105 case HpackDecodingError::kValueTooLong:
106 return Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_VALUE_TOO_LONG;
107 case HpackDecodingError::kNameHuffmanError:
108 return Http2DecoderAdapter::SpdyFramerError::
109 SPDY_HPACK_NAME_HUFFMAN_ERROR;
110 case HpackDecodingError::kValueHuffmanError:
111 return Http2DecoderAdapter::SpdyFramerError::
112 SPDY_HPACK_VALUE_HUFFMAN_ERROR;
113 case HpackDecodingError::kMissingDynamicTableSizeUpdate:
114 return Http2DecoderAdapter::SpdyFramerError::
115 SPDY_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE;
116 case HpackDecodingError::kInvalidIndex:
117 return Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_INVALID_INDEX;
118 case HpackDecodingError::kInvalidNameIndex:
119 return Http2DecoderAdapter::SpdyFramerError::
120 SPDY_HPACK_INVALID_NAME_INDEX;
121 case HpackDecodingError::kDynamicTableSizeUpdateNotAllowed:
122 return Http2DecoderAdapter::SpdyFramerError::
123 SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED;
124 case HpackDecodingError::kInitialDynamicTableSizeUpdateIsAboveLowWaterMark:
125 return Http2DecoderAdapter::SpdyFramerError::
126 SPDY_HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK;
127 case HpackDecodingError::kDynamicTableSizeUpdateIsAboveAcknowledgedSetting:
128 return Http2DecoderAdapter::SpdyFramerError::
129 SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING;
130 case HpackDecodingError::kTruncatedBlock:
131 return Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_TRUNCATED_BLOCK;
132 case HpackDecodingError::kFragmentTooLong:
133 return Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_FRAGMENT_TOO_LONG;
134 case HpackDecodingError::kCompressedHeaderSizeExceedsLimit:
135 return Http2DecoderAdapter::SpdyFramerError::
136 SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT;
137 }
138
139 return Http2DecoderAdapter::SpdyFramerError::SPDY_DECOMPRESS_FAILURE;
QUICHE team82dee2f2019-01-18 12:35:12 -0500140}
141
142} // namespace
143
144const char* Http2DecoderAdapter::StateToString(int state) {
145 switch (state) {
146 case SPDY_ERROR:
147 return "ERROR";
148 case SPDY_FRAME_COMPLETE:
149 return "FRAME_COMPLETE";
150 case SPDY_READY_FOR_FRAME:
151 return "READY_FOR_FRAME";
152 case SPDY_READING_COMMON_HEADER:
153 return "READING_COMMON_HEADER";
154 case SPDY_CONTROL_FRAME_PAYLOAD:
155 return "CONTROL_FRAME_PAYLOAD";
156 case SPDY_READ_DATA_FRAME_PADDING_LENGTH:
157 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
158 case SPDY_CONSUME_PADDING:
159 return "SPDY_CONSUME_PADDING";
160 case SPDY_IGNORE_REMAINING_PAYLOAD:
161 return "IGNORE_REMAINING_PAYLOAD";
162 case SPDY_FORWARD_STREAM_FRAME:
163 return "FORWARD_STREAM_FRAME";
164 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
165 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
166 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
167 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
168 case SPDY_GOAWAY_FRAME_PAYLOAD:
169 return "SPDY_GOAWAY_FRAME_PAYLOAD";
170 case SPDY_SETTINGS_FRAME_HEADER:
171 return "SPDY_SETTINGS_FRAME_HEADER";
172 case SPDY_SETTINGS_FRAME_PAYLOAD:
173 return "SPDY_SETTINGS_FRAME_PAYLOAD";
174 case SPDY_ALTSVC_FRAME_PAYLOAD:
175 return "SPDY_ALTSVC_FRAME_PAYLOAD";
176 }
177 return "UNKNOWN_STATE";
178}
179
180const char* Http2DecoderAdapter::SpdyFramerErrorToString(
181 SpdyFramerError spdy_framer_error) {
182 switch (spdy_framer_error) {
183 case SPDY_NO_ERROR:
184 return "NO_ERROR";
185 case SPDY_INVALID_STREAM_ID:
186 return "INVALID_STREAM_ID";
187 case SPDY_INVALID_CONTROL_FRAME:
188 return "INVALID_CONTROL_FRAME";
189 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
190 return "CONTROL_PAYLOAD_TOO_LARGE";
QUICHE team82dee2f2019-01-18 12:35:12 -0500191 case SPDY_DECOMPRESS_FAILURE:
192 return "DECOMPRESS_FAILURE";
QUICHE team82dee2f2019-01-18 12:35:12 -0500193 case SPDY_INVALID_PADDING:
194 return "INVALID_PADDING";
195 case SPDY_INVALID_DATA_FRAME_FLAGS:
196 return "INVALID_DATA_FRAME_FLAGS";
QUICHE team82dee2f2019-01-18 12:35:12 -0500197 case SPDY_UNEXPECTED_FRAME:
198 return "UNEXPECTED_FRAME";
199 case SPDY_INTERNAL_FRAMER_ERROR:
200 return "INTERNAL_FRAMER_ERROR";
201 case SPDY_INVALID_CONTROL_FRAME_SIZE:
202 return "INVALID_CONTROL_FRAME_SIZE";
203 case SPDY_OVERSIZED_PAYLOAD:
204 return "OVERSIZED_PAYLOAD";
bnc77b46412020-02-21 08:09:09 -0800205 case SPDY_HPACK_INDEX_VARINT_ERROR:
206 return "HPACK_INDEX_VARINT_ERROR";
207 case SPDY_HPACK_NAME_LENGTH_VARINT_ERROR:
208 return "HPACK_NAME_LENGTH_VARINT_ERROR";
209 case SPDY_HPACK_VALUE_LENGTH_VARINT_ERROR:
210 return "HPACK_VALUE_LENGTH_VARINT_ERROR";
211 case SPDY_HPACK_NAME_TOO_LONG:
212 return "HPACK_NAME_TOO_LONG";
213 case SPDY_HPACK_VALUE_TOO_LONG:
214 return "HPACK_VALUE_TOO_LONG";
215 case SPDY_HPACK_NAME_HUFFMAN_ERROR:
216 return "HPACK_NAME_HUFFMAN_ERROR";
217 case SPDY_HPACK_VALUE_HUFFMAN_ERROR:
218 return "HPACK_VALUE_HUFFMAN_ERROR";
219 case SPDY_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE:
220 return "HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE";
221 case SPDY_HPACK_INVALID_INDEX:
222 return "HPACK_INVALID_INDEX";
223 case SPDY_HPACK_INVALID_NAME_INDEX:
224 return "HPACK_INVALID_NAME_INDEX";
225 case SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED:
226 return "HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED";
227 case SPDY_HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK:
228 return "HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK";
229 case SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING:
230 return "HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING";
231 case SPDY_HPACK_TRUNCATED_BLOCK:
232 return "HPACK_TRUNCATED_BLOCK";
233 case SPDY_HPACK_FRAGMENT_TOO_LONG:
234 return "HPACK_FRAGMENT_TOO_LONG";
235 case SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT:
236 return "HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT";
QUICHE teamc39a40b2021-08-06 08:05:39 -0700237 case SPDY_STOP_PROCESSING:
238 return "STOP_PROCESSING";
QUICHE team82dee2f2019-01-18 12:35:12 -0500239 case LAST_ERROR:
240 return "UNKNOWN_ERROR";
241 }
242 return "UNKNOWN_ERROR";
243}
244
245Http2DecoderAdapter::Http2DecoderAdapter() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700246 QUICHE_DVLOG(1) << "Http2DecoderAdapter ctor";
QUICHE team82dee2f2019-01-18 12:35:12 -0500247 ResetInternal();
248}
249
250Http2DecoderAdapter::~Http2DecoderAdapter() = default;
251
252void Http2DecoderAdapter::set_visitor(SpdyFramerVisitorInterface* visitor) {
253 visitor_ = visitor;
254}
255
256void Http2DecoderAdapter::set_debug_visitor(
257 SpdyFramerDebugVisitorInterface* debug_visitor) {
258 debug_visitor_ = debug_visitor;
259}
260
QUICHE team82dee2f2019-01-18 12:35:12 -0500261void Http2DecoderAdapter::set_extension_visitor(
262 ExtensionVisitorInterface* visitor) {
263 extension_ = visitor;
264}
265
QUICHE team82dee2f2019-01-18 12:35:12 -0500266size_t Http2DecoderAdapter::ProcessInput(const char* data, size_t len) {
267 size_t limit = recv_frame_size_limit_;
268 frame_decoder_->set_maximum_payload_size(limit);
269
270 size_t total_processed = 0;
271 while (len > 0 && spdy_state_ != SPDY_ERROR) {
272 // Process one at a time so that we update the adapter's internal
273 // state appropriately.
274 const size_t processed = ProcessInputFrame(data, len);
275
276 // We had some data, and weren't in an error state, so should have
277 // processed/consumed at least one byte of it, even if we then ended up
278 // in an error state.
vasilvved4f3082021-02-01 14:29:40 -0800279 QUICHE_DCHECK(processed > 0)
280 << "processed=" << processed << " spdy_state_=" << spdy_state_
281 << " spdy_framer_error_=" << spdy_framer_error_;
QUICHE team82dee2f2019-01-18 12:35:12 -0500282
283 data += processed;
284 len -= processed;
285 total_processed += processed;
bncbc49a3d2021-02-04 05:50:39 -0800286 if (processed == 0) {
QUICHE team82dee2f2019-01-18 12:35:12 -0500287 break;
288 }
289 }
290 return total_processed;
291}
292
293void Http2DecoderAdapter::Reset() {
294 ResetInternal();
295}
296
297Http2DecoderAdapter::SpdyState Http2DecoderAdapter::state() const {
298 return spdy_state_;
299}
300
301Http2DecoderAdapter::SpdyFramerError Http2DecoderAdapter::spdy_framer_error()
302 const {
303 return spdy_framer_error_;
304}
305
306bool Http2DecoderAdapter::probable_http_response() const {
307 return latched_probable_http_response_;
308}
309
QUICHE teamc39a40b2021-08-06 08:05:39 -0700310void Http2DecoderAdapter::StopProcessing() {
311 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_STOP_PROCESSING,
312 "Ignoring further events on this connection.");
313}
314
QUICHE team82dee2f2019-01-18 12:35:12 -0500315// ===========================================================================
316// Implementations of the methods declared by Http2FrameDecoderListener.
317
318// Called once the common frame header has been decoded for any frame.
319// This function is largely based on Http2DecoderAdapter::ValidateFrameHeader
320// and some parts of Http2DecoderAdapter::ProcessCommonHeader.
321bool Http2DecoderAdapter::OnFrameHeader(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700322 QUICHE_DVLOG(1) << "OnFrameHeader: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500323 decoded_frame_header_ = true;
324 if (!latched_probable_http_response_) {
325 latched_probable_http_response_ = header.IsProbableHttpResponse();
326 }
327 const uint8_t raw_frame_type = static_cast<uint8_t>(header.type);
328 visitor()->OnCommonHeader(header.stream_id, header.payload_length,
329 raw_frame_type, header.flags);
330 if (has_expected_frame_type_ && header.type != expected_frame_type_) {
331 // Report an unexpected frame error and close the connection if we
332 // expect a known frame type (probably CONTINUATION) and receive an
333 // unknown frame.
QUICHE team1b5d09e2021-04-08 13:36:42 -0700334 QUICHE_VLOG(1) << "The framer was expecting to receive a "
335 << expected_frame_type_
336 << " frame, but instead received an unknown frame of type "
337 << header.type;
fayang80366682020-07-24 09:19:11 -0700338 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500339 return false;
340 }
341 if (!IsSupportedHttp2FrameType(header.type)) {
342 if (extension_ != nullptr) {
343 // Unknown frames will be passed to the registered extension.
344 return true;
345 }
346 // In HTTP2 we ignore unknown frame types for extensibility, as long as
347 // the rest of the control frame header is valid.
348 // We rely on the visitor to check validity of stream_id.
349 bool valid_stream =
350 visitor()->OnUnknownFrame(header.stream_id, raw_frame_type);
351 if (!valid_stream) {
352 // Report an invalid frame error if the stream_id is not valid.
QUICHE team1b5d09e2021-04-08 13:36:42 -0700353 QUICHE_VLOG(1) << "Unknown control frame type " << header.type
354 << " received on invalid stream " << header.stream_id;
fayang80366682020-07-24 09:19:11 -0700355 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500356 return false;
357 } else {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700358 QUICHE_DVLOG(1) << "Ignoring unknown frame type " << header.type;
QUICHE team82dee2f2019-01-18 12:35:12 -0500359 return true;
360 }
361 }
362
363 SpdyFrameType frame_type = ToSpdyFrameType(header.type);
364 if (!IsValidHTTP2FrameStreamId(header.stream_id, frame_type)) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700365 QUICHE_VLOG(1) << "The framer received an invalid streamID of "
366 << header.stream_id << " for a frame of type "
367 << header.type;
fayang80366682020-07-24 09:19:11 -0700368 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500369 return false;
370 }
371
372 if (has_expected_frame_type_ && header.type != expected_frame_type_) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700373 QUICHE_VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
374 << header.type;
fayang80366682020-07-24 09:19:11 -0700375 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500376 return false;
377 }
378
379 if (!has_expected_frame_type_ &&
380 header.type == Http2FrameType::CONTINUATION) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700381 QUICHE_VLOG(1) << "Got CONTINUATION frame when not expected.";
fayang80366682020-07-24 09:19:11 -0700382 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500383 return false;
384 }
385
386 if (header.type == Http2FrameType::DATA) {
387 // For some reason SpdyFramer still rejects invalid DATA frame flags.
388 uint8_t valid_flags = Http2FrameFlag::PADDED | Http2FrameFlag::END_STREAM;
389 if (header.HasAnyFlags(~valid_flags)) {
fayang80366682020-07-24 09:19:11 -0700390 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_DATA_FRAME_FLAGS, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500391 return false;
392 }
393 }
394
395 return true;
396}
397
398void Http2DecoderAdapter::OnDataStart(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700399 QUICHE_DVLOG(1) << "OnDataStart: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500400
401 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
402 frame_header_ = header;
403 has_frame_header_ = true;
404 visitor()->OnDataFrameHeader(header.stream_id, header.payload_length,
405 header.IsEndStream());
406 }
407}
408
409void Http2DecoderAdapter::OnDataPayload(const char* data, size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700410 QUICHE_DVLOG(1) << "OnDataPayload: len=" << len;
vasilvved4f3082021-02-01 14:29:40 -0800411 QUICHE_DCHECK(has_frame_header_);
412 QUICHE_DCHECK_EQ(frame_header_.type, Http2FrameType::DATA);
QUICHE team82dee2f2019-01-18 12:35:12 -0500413 visitor()->OnStreamFrameData(frame_header().stream_id, data, len);
414}
415
416void Http2DecoderAdapter::OnDataEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700417 QUICHE_DVLOG(1) << "OnDataEnd";
vasilvved4f3082021-02-01 14:29:40 -0800418 QUICHE_DCHECK(has_frame_header_);
419 QUICHE_DCHECK_EQ(frame_header_.type, Http2FrameType::DATA);
QUICHE team82dee2f2019-01-18 12:35:12 -0500420 if (frame_header().IsEndStream()) {
421 visitor()->OnStreamEnd(frame_header().stream_id);
422 }
423 opt_pad_length_.reset();
424}
425
426void Http2DecoderAdapter::OnHeadersStart(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700427 QUICHE_DVLOG(1) << "OnHeadersStart: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500428 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
429 frame_header_ = header;
430 has_frame_header_ = true;
431 if (header.HasPriority()) {
432 // Once we've got the priority fields, then we can report the arrival
433 // of this HEADERS frame.
434 on_headers_called_ = false;
435 return;
436 }
437 on_headers_called_ = true;
438 ReportReceiveCompressedFrame(header);
439 visitor()->OnHeaders(header.stream_id, kNotHasPriorityFields,
440 0, // priority
441 0, // parent_stream_id
442 false, // exclusive
443 header.IsEndStream(), header.IsEndHeaders());
444 CommonStartHpackBlock();
445 }
446}
447
448void Http2DecoderAdapter::OnHeadersPriority(
449 const Http2PriorityFields& priority) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700450 QUICHE_DVLOG(1) << "OnHeadersPriority: " << priority;
vasilvved4f3082021-02-01 14:29:40 -0800451 QUICHE_DCHECK(has_frame_header_);
452 QUICHE_DCHECK_EQ(frame_type(), Http2FrameType::HEADERS) << frame_header_;
453 QUICHE_DCHECK(frame_header_.HasPriority());
454 QUICHE_DCHECK(!on_headers_called_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500455 on_headers_called_ = true;
456 ReportReceiveCompressedFrame(frame_header_);
ianswett20362752019-07-08 19:34:27 -0700457 if (!visitor()) {
QUICHE team33a4aa62021-04-08 11:10:59 -0700458 QUICHE_BUG(spdy_bug_1_1)
QUICHE team16501202021-03-11 09:32:16 -0800459 << "Visitor is nullptr, handling priority in headers failed."
460 << " priority:" << priority << " frame_header:" << frame_header_;
ianswett20362752019-07-08 19:34:27 -0700461 return;
462 }
QUICHE team82dee2f2019-01-18 12:35:12 -0500463 visitor()->OnHeaders(frame_header_.stream_id, kHasPriorityFields,
464 priority.weight, priority.stream_dependency,
465 priority.is_exclusive, frame_header_.IsEndStream(),
466 frame_header_.IsEndHeaders());
467 CommonStartHpackBlock();
468}
469
470void Http2DecoderAdapter::OnHpackFragment(const char* data, size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700471 QUICHE_DVLOG(1) << "OnHpackFragment: len=" << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500472 on_hpack_fragment_called_ = true;
bnc77b46412020-02-21 08:09:09 -0800473 auto* decoder = GetHpackDecoder();
474 if (!decoder->HandleControlFrameHeadersData(data, len)) {
fayang80366682020-07-24 09:19:11 -0700475 SetSpdyErrorAndNotify(HpackDecodingErrorToSpdyFramerError(decoder->error()),
476 decoder->detailed_error());
QUICHE team82dee2f2019-01-18 12:35:12 -0500477 return;
478 }
479}
480
481void Http2DecoderAdapter::OnHeadersEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700482 QUICHE_DVLOG(1) << "OnHeadersEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500483 CommonHpackFragmentEnd();
484 opt_pad_length_.reset();
485}
486
487void Http2DecoderAdapter::OnPriorityFrame(const Http2FrameHeader& header,
488 const Http2PriorityFields& priority) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700489 QUICHE_DVLOG(1) << "OnPriorityFrame: " << header
490 << "; priority: " << priority;
QUICHE team82dee2f2019-01-18 12:35:12 -0500491 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
492 visitor()->OnPriority(header.stream_id, priority.stream_dependency,
493 priority.weight, priority.is_exclusive);
494 }
495}
496
497void Http2DecoderAdapter::OnContinuationStart(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700498 QUICHE_DVLOG(1) << "OnContinuationStart: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500499 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
vasilvved4f3082021-02-01 14:29:40 -0800500 QUICHE_DCHECK(has_hpack_first_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500501 if (header.stream_id != hpack_first_frame_header_.stream_id) {
fayang80366682020-07-24 09:19:11 -0700502 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500503 return;
504 }
505 frame_header_ = header;
506 has_frame_header_ = true;
507 ReportReceiveCompressedFrame(header);
508 visitor()->OnContinuation(header.stream_id, header.IsEndHeaders());
509 }
510}
511
512void Http2DecoderAdapter::OnContinuationEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700513 QUICHE_DVLOG(1) << "OnContinuationEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500514 CommonHpackFragmentEnd();
515}
516
517void Http2DecoderAdapter::OnPadLength(size_t trailing_length) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700518 QUICHE_DVLOG(1) << "OnPadLength: " << trailing_length;
QUICHE team82dee2f2019-01-18 12:35:12 -0500519 opt_pad_length_ = trailing_length;
vasilvved4f3082021-02-01 14:29:40 -0800520 QUICHE_DCHECK_LT(trailing_length, 256u);
QUICHE team82dee2f2019-01-18 12:35:12 -0500521 if (frame_header_.type == Http2FrameType::DATA) {
522 visitor()->OnStreamPadLength(stream_id(), trailing_length);
523 }
524}
525
danzh8f3a5762019-06-25 13:43:51 -0700526void Http2DecoderAdapter::OnPadding(const char* /*padding*/,
QUICHE team82dee2f2019-01-18 12:35:12 -0500527 size_t skipped_length) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700528 QUICHE_DVLOG(1) << "OnPadding: " << skipped_length;
QUICHE team82dee2f2019-01-18 12:35:12 -0500529 if (frame_header_.type == Http2FrameType::DATA) {
530 visitor()->OnStreamPadding(stream_id(), skipped_length);
531 } else {
532 MaybeAnnounceEmptyFirstHpackFragment();
533 }
534}
535
536void Http2DecoderAdapter::OnRstStream(const Http2FrameHeader& header,
537 Http2ErrorCode http2_error_code) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700538 QUICHE_DVLOG(1) << "OnRstStream: " << header << "; code=" << http2_error_code;
QUICHE team82dee2f2019-01-18 12:35:12 -0500539 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
540 SpdyErrorCode error_code =
541 ParseErrorCode(static_cast<uint32_t>(http2_error_code));
542 visitor()->OnRstStream(header.stream_id, error_code);
543 }
544}
545
546void Http2DecoderAdapter::OnSettingsStart(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700547 QUICHE_DVLOG(1) << "OnSettingsStart: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500548 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
549 frame_header_ = header;
550 has_frame_header_ = true;
551 visitor()->OnSettings();
552 }
553}
554
555void Http2DecoderAdapter::OnSetting(const Http2SettingFields& setting_fields) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700556 QUICHE_DVLOG(1) << "OnSetting: " << setting_fields;
QUICHE team82dee2f2019-01-18 12:35:12 -0500557 const auto parameter = static_cast<SpdySettingsId>(setting_fields.parameter);
558 visitor()->OnSetting(parameter, setting_fields.value);
559 if (extension_ != nullptr) {
560 extension_->OnSetting(parameter, setting_fields.value);
561 }
562}
563
564void Http2DecoderAdapter::OnSettingsEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700565 QUICHE_DVLOG(1) << "OnSettingsEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500566 visitor()->OnSettingsEnd();
567}
568
569void Http2DecoderAdapter::OnSettingsAck(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700570 QUICHE_DVLOG(1) << "OnSettingsAck: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500571 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
572 visitor()->OnSettingsAck();
573 }
574}
575
576void Http2DecoderAdapter::OnPushPromiseStart(
577 const Http2FrameHeader& header,
578 const Http2PushPromiseFields& promise,
579 size_t total_padding_length) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700580 QUICHE_DVLOG(1) << "OnPushPromiseStart: " << header
581 << "; promise: " << promise
582 << "; total_padding_length: " << total_padding_length;
QUICHE team82dee2f2019-01-18 12:35:12 -0500583 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
584 if (promise.promised_stream_id == 0) {
fayang80366682020-07-24 09:19:11 -0700585 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500586 return;
587 }
588 frame_header_ = header;
589 has_frame_header_ = true;
590 ReportReceiveCompressedFrame(header);
591 visitor()->OnPushPromise(header.stream_id, promise.promised_stream_id,
592 header.IsEndHeaders());
593 CommonStartHpackBlock();
594 }
595}
596
597void Http2DecoderAdapter::OnPushPromiseEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700598 QUICHE_DVLOG(1) << "OnPushPromiseEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500599 CommonHpackFragmentEnd();
600 opt_pad_length_.reset();
601}
602
603void Http2DecoderAdapter::OnPing(const Http2FrameHeader& header,
604 const Http2PingFields& ping) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700605 QUICHE_DVLOG(1) << "OnPing: " << header << "; ping: " << ping;
QUICHE team82dee2f2019-01-18 12:35:12 -0500606 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
607 visitor()->OnPing(ToSpdyPingId(ping), false);
608 }
609}
610
611void Http2DecoderAdapter::OnPingAck(const Http2FrameHeader& header,
612 const Http2PingFields& ping) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700613 QUICHE_DVLOG(1) << "OnPingAck: " << header << "; ping: " << ping;
QUICHE team82dee2f2019-01-18 12:35:12 -0500614 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
615 visitor()->OnPing(ToSpdyPingId(ping), true);
616 }
617}
618
619void Http2DecoderAdapter::OnGoAwayStart(const Http2FrameHeader& header,
620 const Http2GoAwayFields& goaway) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700621 QUICHE_DVLOG(1) << "OnGoAwayStart: " << header << "; goaway: " << goaway;
QUICHE team82dee2f2019-01-18 12:35:12 -0500622 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
623 frame_header_ = header;
624 has_frame_header_ = true;
625 SpdyErrorCode error_code =
626 ParseErrorCode(static_cast<uint32_t>(goaway.error_code));
627 visitor()->OnGoAway(goaway.last_stream_id, error_code);
628 }
629}
630
631void Http2DecoderAdapter::OnGoAwayOpaqueData(const char* data, size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700632 QUICHE_DVLOG(1) << "OnGoAwayOpaqueData: len=" << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500633 visitor()->OnGoAwayFrameData(data, len);
634}
635
636void Http2DecoderAdapter::OnGoAwayEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700637 QUICHE_DVLOG(1) << "OnGoAwayEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500638 visitor()->OnGoAwayFrameData(nullptr, 0);
639}
640
641void Http2DecoderAdapter::OnWindowUpdate(const Http2FrameHeader& header,
642 uint32_t increment) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700643 QUICHE_DVLOG(1) << "OnWindowUpdate: " << header
644 << "; increment=" << increment;
QUICHE team82dee2f2019-01-18 12:35:12 -0500645 if (IsOkToStartFrame(header)) {
646 visitor()->OnWindowUpdate(header.stream_id, increment);
647 }
648}
649
650// Per RFC7838, an ALTSVC frame on stream 0 with origin_length == 0, or one on
651// a stream other than stream 0 with origin_length != 0 MUST be ignored. All
652// frames are decoded by Http2DecoderAdapter, and it is left to the consumer
653// (listener) to implement this behavior.
654void Http2DecoderAdapter::OnAltSvcStart(const Http2FrameHeader& header,
655 size_t origin_length,
656 size_t value_length) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700657 QUICHE_DVLOG(1) << "OnAltSvcStart: " << header
658 << "; origin_length: " << origin_length
659 << "; value_length: " << value_length;
QUICHE team82dee2f2019-01-18 12:35:12 -0500660 if (!IsOkToStartFrame(header)) {
661 return;
662 }
663 frame_header_ = header;
664 has_frame_header_ = true;
665 alt_svc_origin_.clear();
666 alt_svc_value_.clear();
667}
668
669void Http2DecoderAdapter::OnAltSvcOriginData(const char* data, size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700670 QUICHE_DVLOG(1) << "OnAltSvcOriginData: len=" << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500671 alt_svc_origin_.append(data, len);
672}
673
674// Called when decoding the Alt-Svc-Field-Value of an ALTSVC;
675// the field is uninterpreted.
676void Http2DecoderAdapter::OnAltSvcValueData(const char* data, size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700677 QUICHE_DVLOG(1) << "OnAltSvcValueData: len=" << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500678 alt_svc_value_.append(data, len);
679}
680
681void Http2DecoderAdapter::OnAltSvcEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700682 QUICHE_DVLOG(1) << "OnAltSvcEnd: origin.size(): " << alt_svc_origin_.size()
683 << "; value.size(): " << alt_svc_value_.size();
QUICHE team82dee2f2019-01-18 12:35:12 -0500684 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
685 if (!SpdyAltSvcWireFormat::ParseHeaderFieldValue(alt_svc_value_,
686 &altsvc_vector)) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700687 QUICHE_DLOG(ERROR) << "SpdyAltSvcWireFormat::ParseHeaderFieldValue failed.";
fayang80366682020-07-24 09:19:11 -0700688 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500689 return;
690 }
691 visitor()->OnAltSvc(frame_header_.stream_id, alt_svc_origin_, altsvc_vector);
692 // We assume that ALTSVC frames are rare, so get rid of the storage.
693 alt_svc_origin_.clear();
694 alt_svc_origin_.shrink_to_fit();
695 alt_svc_value_.clear();
696 alt_svc_value_.shrink_to_fit();
697}
698
bncbea13b82021-01-08 08:46:09 -0800699void Http2DecoderAdapter::OnPriorityUpdateStart(
700 const Http2FrameHeader& header,
701 const Http2PriorityUpdateFields& priority_update) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700702 QUICHE_DVLOG(1) << "OnPriorityUpdateStart: " << header
703 << "; prioritized_stream_id: "
704 << priority_update.prioritized_stream_id;
bncbea13b82021-01-08 08:46:09 -0800705 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header) &&
706 HasRequiredStreamId(priority_update.prioritized_stream_id)) {
707 frame_header_ = header;
708 has_frame_header_ = true;
709 prioritized_stream_id_ = priority_update.prioritized_stream_id;
710 }
711}
712
713void Http2DecoderAdapter::OnPriorityUpdatePayload(const char* data,
714 size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700715 QUICHE_DVLOG(1) << "OnPriorityUpdatePayload: len=" << len;
bncbea13b82021-01-08 08:46:09 -0800716 priority_field_value_.append(data, len);
717}
718
719void Http2DecoderAdapter::OnPriorityUpdateEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700720 QUICHE_DVLOG(1) << "OnPriorityUpdateEnd: priority_field_value.size(): "
721 << priority_field_value_.size();
bncbea13b82021-01-08 08:46:09 -0800722 visitor()->OnPriorityUpdate(prioritized_stream_id_, priority_field_value_);
723 priority_field_value_.clear();
724}
725
QUICHE team82dee2f2019-01-18 12:35:12 -0500726// Except for BLOCKED frames, all other unknown frames are either dropped or
727// passed to a registered extension.
728void Http2DecoderAdapter::OnUnknownStart(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700729 QUICHE_DVLOG(1) << "OnUnknownStart: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500730 if (IsOkToStartFrame(header)) {
731 if (extension_ != nullptr) {
732 const uint8_t type = static_cast<uint8_t>(header.type);
733 const uint8_t flags = static_cast<uint8_t>(header.flags);
734 handling_extension_payload_ = extension_->OnFrameHeader(
735 header.stream_id, header.payload_length, type, flags);
736 }
737 }
738}
739
740void Http2DecoderAdapter::OnUnknownPayload(const char* data, size_t len) {
741 if (handling_extension_payload_) {
742 extension_->OnFramePayload(data, len);
743 } else {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700744 QUICHE_DVLOG(1) << "OnUnknownPayload: len=" << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500745 }
746}
747
748void Http2DecoderAdapter::OnUnknownEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700749 QUICHE_DVLOG(1) << "OnUnknownEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500750 handling_extension_payload_ = false;
751}
752
753void Http2DecoderAdapter::OnPaddingTooLong(const Http2FrameHeader& header,
754 size_t missing_length) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700755 QUICHE_DVLOG(1) << "OnPaddingTooLong: " << header
756 << "; missing_length: " << missing_length;
QUICHE team82dee2f2019-01-18 12:35:12 -0500757 if (header.type == Http2FrameType::DATA) {
758 if (header.payload_length == 0) {
vasilvved4f3082021-02-01 14:29:40 -0800759 QUICHE_DCHECK_EQ(1u, missing_length);
fayang80366682020-07-24 09:19:11 -0700760 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_DATA_FRAME_FLAGS, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500761 return;
762 }
763 visitor()->OnStreamPadding(header.stream_id, 1);
764 }
fayang80366682020-07-24 09:19:11 -0700765 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_PADDING, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500766}
767
768void Http2DecoderAdapter::OnFrameSizeError(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700769 QUICHE_DVLOG(1) << "OnFrameSizeError: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500770 size_t recv_limit = recv_frame_size_limit_;
771 if (header.payload_length > recv_limit) {
QUICHE teamc8a1ee02021-06-25 14:59:37 -0700772 if (header.type == Http2FrameType::DATA) {
773 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_OVERSIZED_PAYLOAD, "");
774 } else {
775 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
776 "");
777 }
QUICHE team82dee2f2019-01-18 12:35:12 -0500778 return;
779 }
780 switch (header.type) {
781 case Http2FrameType::GOAWAY:
782 case Http2FrameType::ALTSVC:
fayang80366682020-07-24 09:19:11 -0700783 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500784 break;
785 default:
fayang80366682020-07-24 09:19:11 -0700786 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME_SIZE,
787 "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500788 }
789}
790
791// Decodes the input up to the next frame boundary (i.e. at most one frame),
792// stopping early if an error is detected.
793size_t Http2DecoderAdapter::ProcessInputFrame(const char* data, size_t len) {
vasilvved4f3082021-02-01 14:29:40 -0800794 QUICHE_DCHECK_NE(spdy_state_, SpdyState::SPDY_ERROR);
QUICHE team82dee2f2019-01-18 12:35:12 -0500795 DecodeBuffer db(data, len);
796 DecodeStatus status = frame_decoder_->DecodeFrame(&db);
797 if (spdy_state_ != SpdyState::SPDY_ERROR) {
798 DetermineSpdyState(status);
799 } else {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700800 QUICHE_VLOG(1) << "ProcessInputFrame spdy_framer_error_="
801 << SpdyFramerErrorToString(spdy_framer_error_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500802 if (spdy_framer_error_ == SpdyFramerError::SPDY_INVALID_PADDING &&
803 has_frame_header_ && frame_type() != Http2FrameType::DATA) {
804 // spdy_framer_test checks that all of the available frame payload
805 // has been consumed, so do that.
806 size_t total = remaining_total_payload();
807 if (total <= frame_header().payload_length) {
808 size_t avail = db.MinLengthRemaining(total);
QUICHE team1b5d09e2021-04-08 13:36:42 -0700809 QUICHE_VLOG(1) << "Skipping past " << avail << " bytes, of " << total
810 << " total remaining in the frame's payload.";
QUICHE team82dee2f2019-01-18 12:35:12 -0500811 db.AdvanceCursor(avail);
812 } else {
QUICHE team33a4aa62021-04-08 11:10:59 -0700813 QUICHE_BUG(spdy_bug_1_2)
QUICHE team16501202021-03-11 09:32:16 -0800814 << "Total remaining (" << total
815 << ") should not be greater than the payload length; "
816 << frame_header();
QUICHE team82dee2f2019-01-18 12:35:12 -0500817 }
818 }
819 }
820 return db.Offset();
821}
822
823// After decoding, determine the next SpdyState. Only called if the current
824// state is NOT SpdyState::SPDY_ERROR (i.e. if none of the callback methods
825// detected an error condition), because otherwise we assume that the callback
826// method has set spdy_framer_error_ appropriately.
827void Http2DecoderAdapter::DetermineSpdyState(DecodeStatus status) {
vasilvved4f3082021-02-01 14:29:40 -0800828 QUICHE_DCHECK_EQ(spdy_framer_error_, SPDY_NO_ERROR);
829 QUICHE_DCHECK(!HasError()) << spdy_framer_error_;
QUICHE team82dee2f2019-01-18 12:35:12 -0500830 switch (status) {
831 case DecodeStatus::kDecodeDone:
QUICHE team1b5d09e2021-04-08 13:36:42 -0700832 QUICHE_DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeDone";
QUICHE team82dee2f2019-01-18 12:35:12 -0500833 ResetBetweenFrames();
834 break;
835 case DecodeStatus::kDecodeInProgress:
QUICHE team1b5d09e2021-04-08 13:36:42 -0700836 QUICHE_DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeInProgress";
QUICHE team82dee2f2019-01-18 12:35:12 -0500837 if (decoded_frame_header_) {
838 if (IsDiscardingPayload()) {
839 set_spdy_state(SpdyState::SPDY_IGNORE_REMAINING_PAYLOAD);
840 } else if (has_frame_header_ && frame_type() == Http2FrameType::DATA) {
841 if (IsReadingPaddingLength()) {
842 set_spdy_state(SpdyState::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
843 } else if (IsSkippingPadding()) {
844 set_spdy_state(SpdyState::SPDY_CONSUME_PADDING);
845 } else {
846 set_spdy_state(SpdyState::SPDY_FORWARD_STREAM_FRAME);
847 }
848 } else {
849 set_spdy_state(SpdyState::SPDY_CONTROL_FRAME_PAYLOAD);
850 }
851 } else {
852 set_spdy_state(SpdyState::SPDY_READING_COMMON_HEADER);
853 }
854 break;
855 case DecodeStatus::kDecodeError:
QUICHE team1b5d09e2021-04-08 13:36:42 -0700856 QUICHE_VLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeError";
QUICHE team82dee2f2019-01-18 12:35:12 -0500857 if (IsDiscardingPayload()) {
858 if (remaining_total_payload() == 0) {
859 // Push the Http2FrameDecoder out of state kDiscardPayload now
860 // since doing so requires no input.
861 DecodeBuffer tmp("", 0);
862 DecodeStatus status = frame_decoder_->DecodeFrame(&tmp);
863 if (status != DecodeStatus::kDecodeDone) {
QUICHE team33a4aa62021-04-08 11:10:59 -0700864 QUICHE_BUG(spdy_bug_1_3)
QUICHE team16501202021-03-11 09:32:16 -0800865 << "Expected to be done decoding the frame, not " << status;
fayang80366682020-07-24 09:19:11 -0700866 SetSpdyErrorAndNotify(SPDY_INTERNAL_FRAMER_ERROR, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500867 } else if (spdy_framer_error_ != SPDY_NO_ERROR) {
QUICHE team33a4aa62021-04-08 11:10:59 -0700868 QUICHE_BUG(spdy_bug_1_4)
QUICHE team16501202021-03-11 09:32:16 -0800869 << "Expected to have no error, not "
870 << SpdyFramerErrorToString(spdy_framer_error_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500871 } else {
872 ResetBetweenFrames();
873 }
874 } else {
875 set_spdy_state(SpdyState::SPDY_IGNORE_REMAINING_PAYLOAD);
876 }
877 } else {
fayang80366682020-07-24 09:19:11 -0700878 SetSpdyErrorAndNotify(SPDY_INVALID_CONTROL_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500879 }
880 break;
881 }
882}
883
884void Http2DecoderAdapter::ResetBetweenFrames() {
885 CorruptFrameHeader(&frame_header_);
886 decoded_frame_header_ = false;
887 has_frame_header_ = false;
888 set_spdy_state(SpdyState::SPDY_READY_FOR_FRAME);
889}
890
891// ResetInternal is called from the constructor, and during tests, but not
892// otherwise (i.e. not between every frame).
893void Http2DecoderAdapter::ResetInternal() {
894 set_spdy_state(SpdyState::SPDY_READY_FOR_FRAME);
895 spdy_framer_error_ = SpdyFramerError::SPDY_NO_ERROR;
896
897 decoded_frame_header_ = false;
898 has_frame_header_ = false;
899 on_headers_called_ = false;
900 on_hpack_fragment_called_ = false;
901 latched_probable_http_response_ = false;
902 has_expected_frame_type_ = false;
903
904 CorruptFrameHeader(&frame_header_);
905 CorruptFrameHeader(&hpack_first_frame_header_);
906
bnc463f2352019-10-10 04:49:34 -0700907 frame_decoder_ = std::make_unique<Http2FrameDecoder>(this);
QUICHE team82dee2f2019-01-18 12:35:12 -0500908 hpack_decoder_ = nullptr;
909}
910
911void Http2DecoderAdapter::set_spdy_state(SpdyState v) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700912 QUICHE_DVLOG(2) << "set_spdy_state(" << StateToString(v) << ")";
QUICHE team82dee2f2019-01-18 12:35:12 -0500913 spdy_state_ = v;
914}
915
fayang80366682020-07-24 09:19:11 -0700916void Http2DecoderAdapter::SetSpdyErrorAndNotify(SpdyFramerError error,
917 std::string detailed_error) {
QUICHE team82dee2f2019-01-18 12:35:12 -0500918 if (HasError()) {
vasilvved4f3082021-02-01 14:29:40 -0800919 QUICHE_DCHECK_EQ(spdy_state_, SpdyState::SPDY_ERROR);
QUICHE team82dee2f2019-01-18 12:35:12 -0500920 } else {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700921 QUICHE_VLOG(2) << "SetSpdyErrorAndNotify(" << SpdyFramerErrorToString(error)
922 << ")";
vasilvved4f3082021-02-01 14:29:40 -0800923 QUICHE_DCHECK_NE(error, SpdyFramerError::SPDY_NO_ERROR);
QUICHE team82dee2f2019-01-18 12:35:12 -0500924 spdy_framer_error_ = error;
925 set_spdy_state(SpdyState::SPDY_ERROR);
926 frame_decoder_->set_listener(&no_op_listener_);
fayang80366682020-07-24 09:19:11 -0700927 visitor()->OnError(error, detailed_error);
QUICHE team82dee2f2019-01-18 12:35:12 -0500928 }
929}
930
931bool Http2DecoderAdapter::HasError() const {
932 if (spdy_state_ == SpdyState::SPDY_ERROR) {
vasilvved4f3082021-02-01 14:29:40 -0800933 QUICHE_DCHECK_NE(spdy_framer_error(), SpdyFramerError::SPDY_NO_ERROR);
QUICHE team82dee2f2019-01-18 12:35:12 -0500934 return true;
935 } else {
vasilvved4f3082021-02-01 14:29:40 -0800936 QUICHE_DCHECK_EQ(spdy_framer_error(), SpdyFramerError::SPDY_NO_ERROR);
QUICHE team82dee2f2019-01-18 12:35:12 -0500937 return false;
938 }
939}
940
941const Http2FrameHeader& Http2DecoderAdapter::frame_header() const {
vasilvved4f3082021-02-01 14:29:40 -0800942 QUICHE_DCHECK(has_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500943 return frame_header_;
944}
945
946uint32_t Http2DecoderAdapter::stream_id() const {
947 return frame_header().stream_id;
948}
949
950Http2FrameType Http2DecoderAdapter::frame_type() const {
951 return frame_header().type;
952}
953
954size_t Http2DecoderAdapter::remaining_total_payload() const {
vasilvved4f3082021-02-01 14:29:40 -0800955 QUICHE_DCHECK(has_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500956 size_t remaining = frame_decoder_->remaining_payload();
957 if (IsPaddable(frame_type()) && frame_header_.IsPadded()) {
958 remaining += frame_decoder_->remaining_padding();
959 }
960 return remaining;
961}
962
963bool Http2DecoderAdapter::IsReadingPaddingLength() {
964 bool result = frame_header_.IsPadded() && !opt_pad_length_;
QUICHE team1b5d09e2021-04-08 13:36:42 -0700965 QUICHE_DVLOG(2) << "Http2DecoderAdapter::IsReadingPaddingLength: " << result;
QUICHE team82dee2f2019-01-18 12:35:12 -0500966 return result;
967}
968bool Http2DecoderAdapter::IsSkippingPadding() {
969 bool result = frame_header_.IsPadded() && opt_pad_length_ &&
970 frame_decoder_->remaining_payload() == 0 &&
971 frame_decoder_->remaining_padding() > 0;
QUICHE team1b5d09e2021-04-08 13:36:42 -0700972 QUICHE_DVLOG(2) << "Http2DecoderAdapter::IsSkippingPadding: " << result;
QUICHE team82dee2f2019-01-18 12:35:12 -0500973 return result;
974}
975bool Http2DecoderAdapter::IsDiscardingPayload() {
976 bool result = decoded_frame_header_ && frame_decoder_->IsDiscardingPayload();
QUICHE team1b5d09e2021-04-08 13:36:42 -0700977 QUICHE_DVLOG(2) << "Http2DecoderAdapter::IsDiscardingPayload: " << result;
QUICHE team82dee2f2019-01-18 12:35:12 -0500978 return result;
979}
980// Called from OnXyz or OnXyzStart methods to decide whether it is OK to
981// handle the callback.
982bool Http2DecoderAdapter::IsOkToStartFrame(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700983 QUICHE_DVLOG(3) << "IsOkToStartFrame";
QUICHE team82dee2f2019-01-18 12:35:12 -0500984 if (HasError()) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700985 QUICHE_VLOG(2) << "HasError()";
QUICHE team82dee2f2019-01-18 12:35:12 -0500986 return false;
987 }
vasilvved4f3082021-02-01 14:29:40 -0800988 QUICHE_DCHECK(!has_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500989 if (has_expected_frame_type_ && header.type != expected_frame_type_) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700990 QUICHE_VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
991 << header.type;
fayang80366682020-07-24 09:19:11 -0700992 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500993 return false;
994 }
995
996 return true;
997}
998
999bool Http2DecoderAdapter::HasRequiredStreamId(uint32_t stream_id) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001000 QUICHE_DVLOG(3) << "HasRequiredStreamId: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -05001001 if (HasError()) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001002 QUICHE_VLOG(2) << "HasError()";
QUICHE team82dee2f2019-01-18 12:35:12 -05001003 return false;
1004 }
1005 if (stream_id != 0) {
1006 return true;
1007 }
QUICHE team1b5d09e2021-04-08 13:36:42 -07001008 QUICHE_VLOG(1) << "Stream Id is required, but zero provided";
fayang80366682020-07-24 09:19:11 -07001009 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID, "");
QUICHE team82dee2f2019-01-18 12:35:12 -05001010 return false;
1011}
1012
1013bool Http2DecoderAdapter::HasRequiredStreamId(const Http2FrameHeader& header) {
1014 return HasRequiredStreamId(header.stream_id);
1015}
1016
1017bool Http2DecoderAdapter::HasRequiredStreamIdZero(uint32_t stream_id) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001018 QUICHE_DVLOG(3) << "HasRequiredStreamIdZero: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -05001019 if (HasError()) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001020 QUICHE_VLOG(2) << "HasError()";
QUICHE team82dee2f2019-01-18 12:35:12 -05001021 return false;
1022 }
1023 if (stream_id == 0) {
1024 return true;
1025 }
QUICHE team1b5d09e2021-04-08 13:36:42 -07001026 QUICHE_VLOG(1) << "Stream Id was not zero, as required: " << stream_id;
fayang80366682020-07-24 09:19:11 -07001027 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID, "");
QUICHE team82dee2f2019-01-18 12:35:12 -05001028 return false;
1029}
1030
1031bool Http2DecoderAdapter::HasRequiredStreamIdZero(
1032 const Http2FrameHeader& header) {
1033 return HasRequiredStreamIdZero(header.stream_id);
1034}
1035
1036void Http2DecoderAdapter::ReportReceiveCompressedFrame(
1037 const Http2FrameHeader& header) {
1038 if (debug_visitor() != nullptr) {
1039 size_t total = header.payload_length + Http2FrameHeader::EncodedSize();
1040 debug_visitor()->OnReceiveCompressedFrame(
1041 header.stream_id, ToSpdyFrameType(header.type), total);
1042 }
1043}
1044
1045HpackDecoderAdapter* Http2DecoderAdapter::GetHpackDecoder() {
1046 if (hpack_decoder_ == nullptr) {
bnc463f2352019-10-10 04:49:34 -07001047 hpack_decoder_ = std::make_unique<HpackDecoderAdapter>();
QUICHE team82dee2f2019-01-18 12:35:12 -05001048 }
1049 return hpack_decoder_.get();
1050}
1051
1052void Http2DecoderAdapter::CommonStartHpackBlock() {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001053 QUICHE_DVLOG(1) << "CommonStartHpackBlock";
vasilvved4f3082021-02-01 14:29:40 -08001054 QUICHE_DCHECK(!has_hpack_first_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -05001055 if (!frame_header_.IsEndHeaders()) {
1056 hpack_first_frame_header_ = frame_header_;
1057 has_hpack_first_frame_header_ = true;
1058 } else {
1059 CorruptFrameHeader(&hpack_first_frame_header_);
1060 }
1061 on_hpack_fragment_called_ = false;
1062 SpdyHeadersHandlerInterface* handler =
1063 visitor()->OnHeaderFrameStart(stream_id());
1064 if (handler == nullptr) {
QUICHE team33a4aa62021-04-08 11:10:59 -07001065 QUICHE_BUG(spdy_bug_1_5) << "visitor_->OnHeaderFrameStart returned nullptr";
fayang80366682020-07-24 09:19:11 -07001066 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INTERNAL_FRAMER_ERROR, "");
QUICHE team82dee2f2019-01-18 12:35:12 -05001067 return;
1068 }
1069 GetHpackDecoder()->HandleControlFrameHeadersStart(handler);
1070}
1071
1072// SpdyFramer calls HandleControlFrameHeadersData even if there are zero
1073// fragment bytes in the first frame, so do the same.
1074void Http2DecoderAdapter::MaybeAnnounceEmptyFirstHpackFragment() {
1075 if (!on_hpack_fragment_called_) {
1076 OnHpackFragment(nullptr, 0);
vasilvved4f3082021-02-01 14:29:40 -08001077 QUICHE_DCHECK(on_hpack_fragment_called_);
QUICHE team82dee2f2019-01-18 12:35:12 -05001078 }
1079}
1080
1081void Http2DecoderAdapter::CommonHpackFragmentEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001082 QUICHE_DVLOG(1) << "CommonHpackFragmentEnd: stream_id=" << stream_id();
QUICHE team82dee2f2019-01-18 12:35:12 -05001083 if (HasError()) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001084 QUICHE_VLOG(1) << "HasError(), returning";
QUICHE team82dee2f2019-01-18 12:35:12 -05001085 return;
1086 }
vasilvved4f3082021-02-01 14:29:40 -08001087 QUICHE_DCHECK(has_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -05001088 MaybeAnnounceEmptyFirstHpackFragment();
1089 if (frame_header_.IsEndHeaders()) {
vasilvved4f3082021-02-01 14:29:40 -08001090 QUICHE_DCHECK_EQ(has_hpack_first_frame_header_,
1091 frame_type() == Http2FrameType::CONTINUATION)
QUICHE team82dee2f2019-01-18 12:35:12 -05001092 << frame_header();
1093 has_expected_frame_type_ = false;
bnc77b46412020-02-21 08:09:09 -08001094 auto* decoder = GetHpackDecoder();
QUICHE team9b192c42021-08-18 08:59:33 -07001095 if (decoder->HandleControlFrameHeadersComplete()) {
QUICHE team82dee2f2019-01-18 12:35:12 -05001096 visitor()->OnHeaderFrameEnd(stream_id());
1097 } else {
bnc77b46412020-02-21 08:09:09 -08001098 SetSpdyErrorAndNotify(
fayang80366682020-07-24 09:19:11 -07001099 HpackDecodingErrorToSpdyFramerError(decoder->error()), "");
QUICHE team82dee2f2019-01-18 12:35:12 -05001100 return;
1101 }
1102 const Http2FrameHeader& first = frame_type() == Http2FrameType::CONTINUATION
1103 ? hpack_first_frame_header_
1104 : frame_header_;
1105 if (first.type == Http2FrameType::HEADERS && first.IsEndStream()) {
1106 visitor()->OnStreamEnd(first.stream_id);
1107 }
1108 has_hpack_first_frame_header_ = false;
1109 CorruptFrameHeader(&hpack_first_frame_header_);
1110 } else {
vasilvved4f3082021-02-01 14:29:40 -08001111 QUICHE_DCHECK(has_hpack_first_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -05001112 has_expected_frame_type_ = true;
1113 expected_frame_type_ = Http2FrameType::CONTINUATION;
1114 }
1115}
1116
1117} // namespace http2
1118
1119namespace spdy {
1120
danzh8f3a5762019-06-25 13:43:51 -07001121bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* /*goaway_data*/,
1122 size_t /*len*/) {
QUICHE team82dee2f2019-01-18 12:35:12 -05001123 return true;
1124}
1125
1126} // namespace spdy