blob: b20d0032aff47eab310ff0f98f161a40d670d976 [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 team5be974e2020-12-29 18:35:24 -050033#include "spdy/platform/api/spdy_estimate_memory_usage.h"
QUICHE team5be974e2020-12-29 18:35:24 -050034#include "spdy/platform/api/spdy_string_utils.h"
QUICHE team82dee2f2019-01-18 12:35:12 -050035
36using ::spdy::ExtensionVisitorInterface;
37using ::spdy::HpackDecoderAdapter;
38using ::spdy::HpackHeaderTable;
39using ::spdy::ParseErrorCode;
40using ::spdy::ParseFrameType;
41using ::spdy::SpdyAltSvcWireFormat;
42using ::spdy::SpdyErrorCode;
43using ::spdy::SpdyEstimateMemoryUsage;
44using ::spdy::SpdyFramerDebugVisitorInterface;
45using ::spdy::SpdyFramerVisitorInterface;
46using ::spdy::SpdyFrameType;
47using ::spdy::SpdyHeadersHandlerInterface;
48using ::spdy::SpdyKnownSettingsId;
QUICHE team82dee2f2019-01-18 12:35:12 -050049using ::spdy::SpdySettingsId;
50
51namespace http2 {
52namespace {
53
54const bool kHasPriorityFields = true;
55const bool kNotHasPriorityFields = false;
56
57bool IsPaddable(Http2FrameType type) {
58 return type == Http2FrameType::DATA || type == Http2FrameType::HEADERS ||
59 type == Http2FrameType::PUSH_PROMISE;
60}
61
62SpdyFrameType ToSpdyFrameType(Http2FrameType type) {
63 return ParseFrameType(static_cast<uint8_t>(type));
64}
65
66uint64_t ToSpdyPingId(const Http2PingFields& ping) {
67 uint64_t v;
68 std::memcpy(&v, ping.opaque_bytes, Http2PingFields::EncodedSize());
bnc975c94c2020-10-17 05:08:58 -070069 return quiche::QuicheEndian::NetToHost64(v);
QUICHE team82dee2f2019-01-18 12:35:12 -050070}
71
72// Overwrites the fields of the header with invalid values, for the purpose
73// of identifying reading of unset fields. Only takes effect for debug builds.
74// In Address Sanatizer builds, it also marks the fields as un-readable.
QUICHE team82dee2f2019-01-18 12:35:12 -050075#ifndef NDEBUG
bnc77b46412020-02-21 08:09:09 -080076void CorruptFrameHeader(Http2FrameHeader* header) {
QUICHE team82dee2f2019-01-18 12:35:12 -050077 // Beyond a valid payload length, which is 2^24 - 1.
78 header->payload_length = 0x1010dead;
79 // An unsupported frame type.
80 header->type = Http2FrameType(0x80);
vasilvved4f3082021-02-01 14:29:40 -080081 QUICHE_DCHECK(!IsSupportedHttp2FrameType(header->type));
QUICHE team82dee2f2019-01-18 12:35:12 -050082 // Frame flag bits that aren't used by any supported frame type.
83 header->flags = Http2FrameFlag(0xd2);
84 // A stream id with the reserved high-bit (R in the RFC) set.
85 // 2129510127 when the high-bit is cleared.
86 header->stream_id = 0xfeedbeef;
bnc77b46412020-02-21 08:09:09 -080087}
danzh8f3a5762019-06-25 13:43:51 -070088#else
bnc77b46412020-02-21 08:09:09 -080089void CorruptFrameHeader(Http2FrameHeader* /*header*/) {}
QUICHE team82dee2f2019-01-18 12:35:12 -050090#endif
bnc77b46412020-02-21 08:09:09 -080091
92Http2DecoderAdapter::SpdyFramerError HpackDecodingErrorToSpdyFramerError(
93 HpackDecodingError error) {
bnc77b46412020-02-21 08:09:09 -080094 switch (error) {
95 case HpackDecodingError::kOk:
96 return Http2DecoderAdapter::SpdyFramerError::SPDY_NO_ERROR;
97 case HpackDecodingError::kIndexVarintError:
98 return Http2DecoderAdapter::SpdyFramerError::
99 SPDY_HPACK_INDEX_VARINT_ERROR;
100 case HpackDecodingError::kNameLengthVarintError:
101 return Http2DecoderAdapter::SpdyFramerError::
102 SPDY_HPACK_NAME_LENGTH_VARINT_ERROR;
103 case HpackDecodingError::kValueLengthVarintError:
104 return Http2DecoderAdapter::SpdyFramerError::
105 SPDY_HPACK_VALUE_LENGTH_VARINT_ERROR;
106 case HpackDecodingError::kNameTooLong:
107 return Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_NAME_TOO_LONG;
108 case HpackDecodingError::kValueTooLong:
109 return Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_VALUE_TOO_LONG;
110 case HpackDecodingError::kNameHuffmanError:
111 return Http2DecoderAdapter::SpdyFramerError::
112 SPDY_HPACK_NAME_HUFFMAN_ERROR;
113 case HpackDecodingError::kValueHuffmanError:
114 return Http2DecoderAdapter::SpdyFramerError::
115 SPDY_HPACK_VALUE_HUFFMAN_ERROR;
116 case HpackDecodingError::kMissingDynamicTableSizeUpdate:
117 return Http2DecoderAdapter::SpdyFramerError::
118 SPDY_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE;
119 case HpackDecodingError::kInvalidIndex:
120 return Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_INVALID_INDEX;
121 case HpackDecodingError::kInvalidNameIndex:
122 return Http2DecoderAdapter::SpdyFramerError::
123 SPDY_HPACK_INVALID_NAME_INDEX;
124 case HpackDecodingError::kDynamicTableSizeUpdateNotAllowed:
125 return Http2DecoderAdapter::SpdyFramerError::
126 SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED;
127 case HpackDecodingError::kInitialDynamicTableSizeUpdateIsAboveLowWaterMark:
128 return Http2DecoderAdapter::SpdyFramerError::
129 SPDY_HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK;
130 case HpackDecodingError::kDynamicTableSizeUpdateIsAboveAcknowledgedSetting:
131 return Http2DecoderAdapter::SpdyFramerError::
132 SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING;
133 case HpackDecodingError::kTruncatedBlock:
134 return Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_TRUNCATED_BLOCK;
135 case HpackDecodingError::kFragmentTooLong:
136 return Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_FRAGMENT_TOO_LONG;
137 case HpackDecodingError::kCompressedHeaderSizeExceedsLimit:
138 return Http2DecoderAdapter::SpdyFramerError::
139 SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT;
140 }
141
142 return Http2DecoderAdapter::SpdyFramerError::SPDY_DECOMPRESS_FAILURE;
QUICHE team82dee2f2019-01-18 12:35:12 -0500143}
144
145} // namespace
146
147const char* Http2DecoderAdapter::StateToString(int state) {
148 switch (state) {
149 case SPDY_ERROR:
150 return "ERROR";
151 case SPDY_FRAME_COMPLETE:
152 return "FRAME_COMPLETE";
153 case SPDY_READY_FOR_FRAME:
154 return "READY_FOR_FRAME";
155 case SPDY_READING_COMMON_HEADER:
156 return "READING_COMMON_HEADER";
157 case SPDY_CONTROL_FRAME_PAYLOAD:
158 return "CONTROL_FRAME_PAYLOAD";
159 case SPDY_READ_DATA_FRAME_PADDING_LENGTH:
160 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
161 case SPDY_CONSUME_PADDING:
162 return "SPDY_CONSUME_PADDING";
163 case SPDY_IGNORE_REMAINING_PAYLOAD:
164 return "IGNORE_REMAINING_PAYLOAD";
165 case SPDY_FORWARD_STREAM_FRAME:
166 return "FORWARD_STREAM_FRAME";
167 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
168 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
169 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
170 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
171 case SPDY_GOAWAY_FRAME_PAYLOAD:
172 return "SPDY_GOAWAY_FRAME_PAYLOAD";
173 case SPDY_SETTINGS_FRAME_HEADER:
174 return "SPDY_SETTINGS_FRAME_HEADER";
175 case SPDY_SETTINGS_FRAME_PAYLOAD:
176 return "SPDY_SETTINGS_FRAME_PAYLOAD";
177 case SPDY_ALTSVC_FRAME_PAYLOAD:
178 return "SPDY_ALTSVC_FRAME_PAYLOAD";
179 }
180 return "UNKNOWN_STATE";
181}
182
183const char* Http2DecoderAdapter::SpdyFramerErrorToString(
184 SpdyFramerError spdy_framer_error) {
185 switch (spdy_framer_error) {
186 case SPDY_NO_ERROR:
187 return "NO_ERROR";
188 case SPDY_INVALID_STREAM_ID:
189 return "INVALID_STREAM_ID";
190 case SPDY_INVALID_CONTROL_FRAME:
191 return "INVALID_CONTROL_FRAME";
192 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
193 return "CONTROL_PAYLOAD_TOO_LARGE";
194 case SPDY_ZLIB_INIT_FAILURE:
195 return "ZLIB_INIT_FAILURE";
196 case SPDY_UNSUPPORTED_VERSION:
197 return "UNSUPPORTED_VERSION";
198 case SPDY_DECOMPRESS_FAILURE:
199 return "DECOMPRESS_FAILURE";
200 case SPDY_COMPRESS_FAILURE:
201 return "COMPRESS_FAILURE";
202 case SPDY_GOAWAY_FRAME_CORRUPT:
203 return "GOAWAY_FRAME_CORRUPT";
204 case SPDY_RST_STREAM_FRAME_CORRUPT:
205 return "RST_STREAM_FRAME_CORRUPT";
206 case SPDY_INVALID_PADDING:
207 return "INVALID_PADDING";
208 case SPDY_INVALID_DATA_FRAME_FLAGS:
209 return "INVALID_DATA_FRAME_FLAGS";
210 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
211 return "INVALID_CONTROL_FRAME_FLAGS";
212 case SPDY_UNEXPECTED_FRAME:
213 return "UNEXPECTED_FRAME";
214 case SPDY_INTERNAL_FRAMER_ERROR:
215 return "INTERNAL_FRAMER_ERROR";
216 case SPDY_INVALID_CONTROL_FRAME_SIZE:
217 return "INVALID_CONTROL_FRAME_SIZE";
218 case SPDY_OVERSIZED_PAYLOAD:
219 return "OVERSIZED_PAYLOAD";
bnc77b46412020-02-21 08:09:09 -0800220 case SPDY_HPACK_INDEX_VARINT_ERROR:
221 return "HPACK_INDEX_VARINT_ERROR";
222 case SPDY_HPACK_NAME_LENGTH_VARINT_ERROR:
223 return "HPACK_NAME_LENGTH_VARINT_ERROR";
224 case SPDY_HPACK_VALUE_LENGTH_VARINT_ERROR:
225 return "HPACK_VALUE_LENGTH_VARINT_ERROR";
226 case SPDY_HPACK_NAME_TOO_LONG:
227 return "HPACK_NAME_TOO_LONG";
228 case SPDY_HPACK_VALUE_TOO_LONG:
229 return "HPACK_VALUE_TOO_LONG";
230 case SPDY_HPACK_NAME_HUFFMAN_ERROR:
231 return "HPACK_NAME_HUFFMAN_ERROR";
232 case SPDY_HPACK_VALUE_HUFFMAN_ERROR:
233 return "HPACK_VALUE_HUFFMAN_ERROR";
234 case SPDY_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE:
235 return "HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE";
236 case SPDY_HPACK_INVALID_INDEX:
237 return "HPACK_INVALID_INDEX";
238 case SPDY_HPACK_INVALID_NAME_INDEX:
239 return "HPACK_INVALID_NAME_INDEX";
240 case SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED:
241 return "HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED";
242 case SPDY_HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK:
243 return "HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK";
244 case SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING:
245 return "HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING";
246 case SPDY_HPACK_TRUNCATED_BLOCK:
247 return "HPACK_TRUNCATED_BLOCK";
248 case SPDY_HPACK_FRAGMENT_TOO_LONG:
249 return "HPACK_FRAGMENT_TOO_LONG";
250 case SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT:
251 return "HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT";
QUICHE team82dee2f2019-01-18 12:35:12 -0500252 case LAST_ERROR:
253 return "UNKNOWN_ERROR";
254 }
255 return "UNKNOWN_ERROR";
256}
257
258Http2DecoderAdapter::Http2DecoderAdapter() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700259 QUICHE_DVLOG(1) << "Http2DecoderAdapter ctor";
QUICHE team82dee2f2019-01-18 12:35:12 -0500260 ResetInternal();
261}
262
263Http2DecoderAdapter::~Http2DecoderAdapter() = default;
264
265void Http2DecoderAdapter::set_visitor(SpdyFramerVisitorInterface* visitor) {
266 visitor_ = visitor;
267}
268
269void Http2DecoderAdapter::set_debug_visitor(
270 SpdyFramerDebugVisitorInterface* debug_visitor) {
271 debug_visitor_ = debug_visitor;
272}
273
QUICHE team82dee2f2019-01-18 12:35:12 -0500274void Http2DecoderAdapter::set_extension_visitor(
275 ExtensionVisitorInterface* visitor) {
276 extension_ = visitor;
277}
278
QUICHE team82dee2f2019-01-18 12:35:12 -0500279size_t Http2DecoderAdapter::ProcessInput(const char* data, size_t len) {
280 size_t limit = recv_frame_size_limit_;
281 frame_decoder_->set_maximum_payload_size(limit);
282
283 size_t total_processed = 0;
284 while (len > 0 && spdy_state_ != SPDY_ERROR) {
285 // Process one at a time so that we update the adapter's internal
286 // state appropriately.
287 const size_t processed = ProcessInputFrame(data, len);
288
289 // We had some data, and weren't in an error state, so should have
290 // processed/consumed at least one byte of it, even if we then ended up
291 // in an error state.
vasilvved4f3082021-02-01 14:29:40 -0800292 QUICHE_DCHECK(processed > 0)
293 << "processed=" << processed << " spdy_state_=" << spdy_state_
294 << " spdy_framer_error_=" << spdy_framer_error_;
QUICHE team82dee2f2019-01-18 12:35:12 -0500295
296 data += processed;
297 len -= processed;
298 total_processed += processed;
bncbc49a3d2021-02-04 05:50:39 -0800299 if (processed == 0) {
QUICHE team82dee2f2019-01-18 12:35:12 -0500300 break;
301 }
302 }
303 return total_processed;
304}
305
306void Http2DecoderAdapter::Reset() {
307 ResetInternal();
308}
309
310Http2DecoderAdapter::SpdyState Http2DecoderAdapter::state() const {
311 return spdy_state_;
312}
313
314Http2DecoderAdapter::SpdyFramerError Http2DecoderAdapter::spdy_framer_error()
315 const {
316 return spdy_framer_error_;
317}
318
319bool Http2DecoderAdapter::probable_http_response() const {
320 return latched_probable_http_response_;
321}
322
323size_t Http2DecoderAdapter::EstimateMemoryUsage() const {
324 // Skip |frame_decoder_|, |frame_header_| and |hpack_first_frame_header_| as
325 // they don't allocate.
326 return SpdyEstimateMemoryUsage(alt_svc_origin_) +
327 SpdyEstimateMemoryUsage(alt_svc_value_);
328}
329
330// ===========================================================================
331// Implementations of the methods declared by Http2FrameDecoderListener.
332
333// Called once the common frame header has been decoded for any frame.
334// This function is largely based on Http2DecoderAdapter::ValidateFrameHeader
335// and some parts of Http2DecoderAdapter::ProcessCommonHeader.
336bool Http2DecoderAdapter::OnFrameHeader(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700337 QUICHE_DVLOG(1) << "OnFrameHeader: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500338 decoded_frame_header_ = true;
339 if (!latched_probable_http_response_) {
340 latched_probable_http_response_ = header.IsProbableHttpResponse();
341 }
342 const uint8_t raw_frame_type = static_cast<uint8_t>(header.type);
343 visitor()->OnCommonHeader(header.stream_id, header.payload_length,
344 raw_frame_type, header.flags);
345 if (has_expected_frame_type_ && header.type != expected_frame_type_) {
346 // Report an unexpected frame error and close the connection if we
347 // expect a known frame type (probably CONTINUATION) and receive an
348 // unknown frame.
QUICHE team1b5d09e2021-04-08 13:36:42 -0700349 QUICHE_VLOG(1) << "The framer was expecting to receive a "
350 << expected_frame_type_
351 << " frame, but instead received an unknown frame of type "
352 << header.type;
fayang80366682020-07-24 09:19:11 -0700353 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500354 return false;
355 }
356 if (!IsSupportedHttp2FrameType(header.type)) {
357 if (extension_ != nullptr) {
358 // Unknown frames will be passed to the registered extension.
359 return true;
360 }
361 // In HTTP2 we ignore unknown frame types for extensibility, as long as
362 // the rest of the control frame header is valid.
363 // We rely on the visitor to check validity of stream_id.
364 bool valid_stream =
365 visitor()->OnUnknownFrame(header.stream_id, raw_frame_type);
366 if (!valid_stream) {
367 // Report an invalid frame error if the stream_id is not valid.
QUICHE team1b5d09e2021-04-08 13:36:42 -0700368 QUICHE_VLOG(1) << "Unknown control frame type " << header.type
369 << " received on invalid stream " << header.stream_id;
fayang80366682020-07-24 09:19:11 -0700370 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500371 return false;
372 } else {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700373 QUICHE_DVLOG(1) << "Ignoring unknown frame type " << header.type;
QUICHE team82dee2f2019-01-18 12:35:12 -0500374 return true;
375 }
376 }
377
378 SpdyFrameType frame_type = ToSpdyFrameType(header.type);
379 if (!IsValidHTTP2FrameStreamId(header.stream_id, frame_type)) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700380 QUICHE_VLOG(1) << "The framer received an invalid streamID of "
381 << header.stream_id << " for a frame of type "
382 << header.type;
fayang80366682020-07-24 09:19:11 -0700383 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500384 return false;
385 }
386
387 if (has_expected_frame_type_ && header.type != expected_frame_type_) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700388 QUICHE_VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
389 << header.type;
fayang80366682020-07-24 09:19:11 -0700390 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500391 return false;
392 }
393
394 if (!has_expected_frame_type_ &&
395 header.type == Http2FrameType::CONTINUATION) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700396 QUICHE_VLOG(1) << "Got CONTINUATION frame when not expected.";
fayang80366682020-07-24 09:19:11 -0700397 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500398 return false;
399 }
400
401 if (header.type == Http2FrameType::DATA) {
402 // For some reason SpdyFramer still rejects invalid DATA frame flags.
403 uint8_t valid_flags = Http2FrameFlag::PADDED | Http2FrameFlag::END_STREAM;
404 if (header.HasAnyFlags(~valid_flags)) {
fayang80366682020-07-24 09:19:11 -0700405 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_DATA_FRAME_FLAGS, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500406 return false;
407 }
408 }
409
410 return true;
411}
412
413void Http2DecoderAdapter::OnDataStart(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700414 QUICHE_DVLOG(1) << "OnDataStart: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500415
416 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
417 frame_header_ = header;
418 has_frame_header_ = true;
419 visitor()->OnDataFrameHeader(header.stream_id, header.payload_length,
420 header.IsEndStream());
421 }
422}
423
424void Http2DecoderAdapter::OnDataPayload(const char* data, size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700425 QUICHE_DVLOG(1) << "OnDataPayload: len=" << len;
vasilvved4f3082021-02-01 14:29:40 -0800426 QUICHE_DCHECK(has_frame_header_);
427 QUICHE_DCHECK_EQ(frame_header_.type, Http2FrameType::DATA);
QUICHE team82dee2f2019-01-18 12:35:12 -0500428 visitor()->OnStreamFrameData(frame_header().stream_id, data, len);
429}
430
431void Http2DecoderAdapter::OnDataEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700432 QUICHE_DVLOG(1) << "OnDataEnd";
vasilvved4f3082021-02-01 14:29:40 -0800433 QUICHE_DCHECK(has_frame_header_);
434 QUICHE_DCHECK_EQ(frame_header_.type, Http2FrameType::DATA);
QUICHE team82dee2f2019-01-18 12:35:12 -0500435 if (frame_header().IsEndStream()) {
436 visitor()->OnStreamEnd(frame_header().stream_id);
437 }
438 opt_pad_length_.reset();
439}
440
441void Http2DecoderAdapter::OnHeadersStart(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700442 QUICHE_DVLOG(1) << "OnHeadersStart: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500443 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
444 frame_header_ = header;
445 has_frame_header_ = true;
446 if (header.HasPriority()) {
447 // Once we've got the priority fields, then we can report the arrival
448 // of this HEADERS frame.
449 on_headers_called_ = false;
450 return;
451 }
452 on_headers_called_ = true;
453 ReportReceiveCompressedFrame(header);
454 visitor()->OnHeaders(header.stream_id, kNotHasPriorityFields,
455 0, // priority
456 0, // parent_stream_id
457 false, // exclusive
458 header.IsEndStream(), header.IsEndHeaders());
459 CommonStartHpackBlock();
460 }
461}
462
463void Http2DecoderAdapter::OnHeadersPriority(
464 const Http2PriorityFields& priority) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700465 QUICHE_DVLOG(1) << "OnHeadersPriority: " << priority;
vasilvved4f3082021-02-01 14:29:40 -0800466 QUICHE_DCHECK(has_frame_header_);
467 QUICHE_DCHECK_EQ(frame_type(), Http2FrameType::HEADERS) << frame_header_;
468 QUICHE_DCHECK(frame_header_.HasPriority());
469 QUICHE_DCHECK(!on_headers_called_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500470 on_headers_called_ = true;
471 ReportReceiveCompressedFrame(frame_header_);
ianswett20362752019-07-08 19:34:27 -0700472 if (!visitor()) {
QUICHE team33a4aa62021-04-08 11:10:59 -0700473 QUICHE_BUG(spdy_bug_1_1)
QUICHE team16501202021-03-11 09:32:16 -0800474 << "Visitor is nullptr, handling priority in headers failed."
475 << " priority:" << priority << " frame_header:" << frame_header_;
ianswett20362752019-07-08 19:34:27 -0700476 return;
477 }
QUICHE team82dee2f2019-01-18 12:35:12 -0500478 visitor()->OnHeaders(frame_header_.stream_id, kHasPriorityFields,
479 priority.weight, priority.stream_dependency,
480 priority.is_exclusive, frame_header_.IsEndStream(),
481 frame_header_.IsEndHeaders());
482 CommonStartHpackBlock();
483}
484
485void Http2DecoderAdapter::OnHpackFragment(const char* data, size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700486 QUICHE_DVLOG(1) << "OnHpackFragment: len=" << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500487 on_hpack_fragment_called_ = true;
bnc77b46412020-02-21 08:09:09 -0800488 auto* decoder = GetHpackDecoder();
489 if (!decoder->HandleControlFrameHeadersData(data, len)) {
fayang80366682020-07-24 09:19:11 -0700490 SetSpdyErrorAndNotify(HpackDecodingErrorToSpdyFramerError(decoder->error()),
491 decoder->detailed_error());
QUICHE team82dee2f2019-01-18 12:35:12 -0500492 return;
493 }
494}
495
496void Http2DecoderAdapter::OnHeadersEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700497 QUICHE_DVLOG(1) << "OnHeadersEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500498 CommonHpackFragmentEnd();
499 opt_pad_length_.reset();
500}
501
502void Http2DecoderAdapter::OnPriorityFrame(const Http2FrameHeader& header,
503 const Http2PriorityFields& priority) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700504 QUICHE_DVLOG(1) << "OnPriorityFrame: " << header
505 << "; priority: " << priority;
QUICHE team82dee2f2019-01-18 12:35:12 -0500506 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
507 visitor()->OnPriority(header.stream_id, priority.stream_dependency,
508 priority.weight, priority.is_exclusive);
509 }
510}
511
512void Http2DecoderAdapter::OnContinuationStart(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700513 QUICHE_DVLOG(1) << "OnContinuationStart: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500514 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
vasilvved4f3082021-02-01 14:29:40 -0800515 QUICHE_DCHECK(has_hpack_first_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500516 if (header.stream_id != hpack_first_frame_header_.stream_id) {
fayang80366682020-07-24 09:19:11 -0700517 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500518 return;
519 }
520 frame_header_ = header;
521 has_frame_header_ = true;
522 ReportReceiveCompressedFrame(header);
523 visitor()->OnContinuation(header.stream_id, header.IsEndHeaders());
524 }
525}
526
527void Http2DecoderAdapter::OnContinuationEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700528 QUICHE_DVLOG(1) << "OnContinuationEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500529 CommonHpackFragmentEnd();
530}
531
532void Http2DecoderAdapter::OnPadLength(size_t trailing_length) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700533 QUICHE_DVLOG(1) << "OnPadLength: " << trailing_length;
QUICHE team82dee2f2019-01-18 12:35:12 -0500534 opt_pad_length_ = trailing_length;
vasilvved4f3082021-02-01 14:29:40 -0800535 QUICHE_DCHECK_LT(trailing_length, 256u);
QUICHE team82dee2f2019-01-18 12:35:12 -0500536 if (frame_header_.type == Http2FrameType::DATA) {
537 visitor()->OnStreamPadLength(stream_id(), trailing_length);
538 }
539}
540
danzh8f3a5762019-06-25 13:43:51 -0700541void Http2DecoderAdapter::OnPadding(const char* /*padding*/,
QUICHE team82dee2f2019-01-18 12:35:12 -0500542 size_t skipped_length) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700543 QUICHE_DVLOG(1) << "OnPadding: " << skipped_length;
QUICHE team82dee2f2019-01-18 12:35:12 -0500544 if (frame_header_.type == Http2FrameType::DATA) {
545 visitor()->OnStreamPadding(stream_id(), skipped_length);
546 } else {
547 MaybeAnnounceEmptyFirstHpackFragment();
548 }
549}
550
551void Http2DecoderAdapter::OnRstStream(const Http2FrameHeader& header,
552 Http2ErrorCode http2_error_code) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700553 QUICHE_DVLOG(1) << "OnRstStream: " << header << "; code=" << http2_error_code;
QUICHE team82dee2f2019-01-18 12:35:12 -0500554 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
555 SpdyErrorCode error_code =
556 ParseErrorCode(static_cast<uint32_t>(http2_error_code));
557 visitor()->OnRstStream(header.stream_id, error_code);
558 }
559}
560
561void Http2DecoderAdapter::OnSettingsStart(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700562 QUICHE_DVLOG(1) << "OnSettingsStart: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500563 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
564 frame_header_ = header;
565 has_frame_header_ = true;
566 visitor()->OnSettings();
567 }
568}
569
570void Http2DecoderAdapter::OnSetting(const Http2SettingFields& setting_fields) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700571 QUICHE_DVLOG(1) << "OnSetting: " << setting_fields;
QUICHE team82dee2f2019-01-18 12:35:12 -0500572 const auto parameter = static_cast<SpdySettingsId>(setting_fields.parameter);
573 visitor()->OnSetting(parameter, setting_fields.value);
574 if (extension_ != nullptr) {
575 extension_->OnSetting(parameter, setting_fields.value);
576 }
577}
578
579void Http2DecoderAdapter::OnSettingsEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700580 QUICHE_DVLOG(1) << "OnSettingsEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500581 visitor()->OnSettingsEnd();
582}
583
584void Http2DecoderAdapter::OnSettingsAck(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700585 QUICHE_DVLOG(1) << "OnSettingsAck: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500586 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
587 visitor()->OnSettingsAck();
588 }
589}
590
591void Http2DecoderAdapter::OnPushPromiseStart(
592 const Http2FrameHeader& header,
593 const Http2PushPromiseFields& promise,
594 size_t total_padding_length) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700595 QUICHE_DVLOG(1) << "OnPushPromiseStart: " << header
596 << "; promise: " << promise
597 << "; total_padding_length: " << total_padding_length;
QUICHE team82dee2f2019-01-18 12:35:12 -0500598 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
599 if (promise.promised_stream_id == 0) {
fayang80366682020-07-24 09:19:11 -0700600 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500601 return;
602 }
603 frame_header_ = header;
604 has_frame_header_ = true;
605 ReportReceiveCompressedFrame(header);
606 visitor()->OnPushPromise(header.stream_id, promise.promised_stream_id,
607 header.IsEndHeaders());
608 CommonStartHpackBlock();
609 }
610}
611
612void Http2DecoderAdapter::OnPushPromiseEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700613 QUICHE_DVLOG(1) << "OnPushPromiseEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500614 CommonHpackFragmentEnd();
615 opt_pad_length_.reset();
616}
617
618void Http2DecoderAdapter::OnPing(const Http2FrameHeader& header,
619 const Http2PingFields& ping) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700620 QUICHE_DVLOG(1) << "OnPing: " << header << "; ping: " << ping;
QUICHE team82dee2f2019-01-18 12:35:12 -0500621 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
622 visitor()->OnPing(ToSpdyPingId(ping), false);
623 }
624}
625
626void Http2DecoderAdapter::OnPingAck(const Http2FrameHeader& header,
627 const Http2PingFields& ping) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700628 QUICHE_DVLOG(1) << "OnPingAck: " << header << "; ping: " << ping;
QUICHE team82dee2f2019-01-18 12:35:12 -0500629 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
630 visitor()->OnPing(ToSpdyPingId(ping), true);
631 }
632}
633
634void Http2DecoderAdapter::OnGoAwayStart(const Http2FrameHeader& header,
635 const Http2GoAwayFields& goaway) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700636 QUICHE_DVLOG(1) << "OnGoAwayStart: " << header << "; goaway: " << goaway;
QUICHE team82dee2f2019-01-18 12:35:12 -0500637 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
638 frame_header_ = header;
639 has_frame_header_ = true;
640 SpdyErrorCode error_code =
641 ParseErrorCode(static_cast<uint32_t>(goaway.error_code));
642 visitor()->OnGoAway(goaway.last_stream_id, error_code);
643 }
644}
645
646void Http2DecoderAdapter::OnGoAwayOpaqueData(const char* data, size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700647 QUICHE_DVLOG(1) << "OnGoAwayOpaqueData: len=" << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500648 visitor()->OnGoAwayFrameData(data, len);
649}
650
651void Http2DecoderAdapter::OnGoAwayEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700652 QUICHE_DVLOG(1) << "OnGoAwayEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500653 visitor()->OnGoAwayFrameData(nullptr, 0);
654}
655
656void Http2DecoderAdapter::OnWindowUpdate(const Http2FrameHeader& header,
657 uint32_t increment) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700658 QUICHE_DVLOG(1) << "OnWindowUpdate: " << header
659 << "; increment=" << increment;
QUICHE team82dee2f2019-01-18 12:35:12 -0500660 if (IsOkToStartFrame(header)) {
661 visitor()->OnWindowUpdate(header.stream_id, increment);
662 }
663}
664
665// Per RFC7838, an ALTSVC frame on stream 0 with origin_length == 0, or one on
666// a stream other than stream 0 with origin_length != 0 MUST be ignored. All
667// frames are decoded by Http2DecoderAdapter, and it is left to the consumer
668// (listener) to implement this behavior.
669void Http2DecoderAdapter::OnAltSvcStart(const Http2FrameHeader& header,
670 size_t origin_length,
671 size_t value_length) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700672 QUICHE_DVLOG(1) << "OnAltSvcStart: " << header
673 << "; origin_length: " << origin_length
674 << "; value_length: " << value_length;
QUICHE team82dee2f2019-01-18 12:35:12 -0500675 if (!IsOkToStartFrame(header)) {
676 return;
677 }
678 frame_header_ = header;
679 has_frame_header_ = true;
680 alt_svc_origin_.clear();
681 alt_svc_value_.clear();
682}
683
684void Http2DecoderAdapter::OnAltSvcOriginData(const char* data, size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700685 QUICHE_DVLOG(1) << "OnAltSvcOriginData: len=" << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500686 alt_svc_origin_.append(data, len);
687}
688
689// Called when decoding the Alt-Svc-Field-Value of an ALTSVC;
690// the field is uninterpreted.
691void Http2DecoderAdapter::OnAltSvcValueData(const char* data, size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700692 QUICHE_DVLOG(1) << "OnAltSvcValueData: len=" << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500693 alt_svc_value_.append(data, len);
694}
695
696void Http2DecoderAdapter::OnAltSvcEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700697 QUICHE_DVLOG(1) << "OnAltSvcEnd: origin.size(): " << alt_svc_origin_.size()
698 << "; value.size(): " << alt_svc_value_.size();
QUICHE team82dee2f2019-01-18 12:35:12 -0500699 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
700 if (!SpdyAltSvcWireFormat::ParseHeaderFieldValue(alt_svc_value_,
701 &altsvc_vector)) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700702 QUICHE_DLOG(ERROR) << "SpdyAltSvcWireFormat::ParseHeaderFieldValue failed.";
fayang80366682020-07-24 09:19:11 -0700703 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500704 return;
705 }
706 visitor()->OnAltSvc(frame_header_.stream_id, alt_svc_origin_, altsvc_vector);
707 // We assume that ALTSVC frames are rare, so get rid of the storage.
708 alt_svc_origin_.clear();
709 alt_svc_origin_.shrink_to_fit();
710 alt_svc_value_.clear();
711 alt_svc_value_.shrink_to_fit();
712}
713
bncbea13b82021-01-08 08:46:09 -0800714void Http2DecoderAdapter::OnPriorityUpdateStart(
715 const Http2FrameHeader& header,
716 const Http2PriorityUpdateFields& priority_update) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700717 QUICHE_DVLOG(1) << "OnPriorityUpdateStart: " << header
718 << "; prioritized_stream_id: "
719 << priority_update.prioritized_stream_id;
bncbea13b82021-01-08 08:46:09 -0800720 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header) &&
721 HasRequiredStreamId(priority_update.prioritized_stream_id)) {
722 frame_header_ = header;
723 has_frame_header_ = true;
724 prioritized_stream_id_ = priority_update.prioritized_stream_id;
725 }
726}
727
728void Http2DecoderAdapter::OnPriorityUpdatePayload(const char* data,
729 size_t len) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700730 QUICHE_DVLOG(1) << "OnPriorityUpdatePayload: len=" << len;
bncbea13b82021-01-08 08:46:09 -0800731 priority_field_value_.append(data, len);
732}
733
734void Http2DecoderAdapter::OnPriorityUpdateEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700735 QUICHE_DVLOG(1) << "OnPriorityUpdateEnd: priority_field_value.size(): "
736 << priority_field_value_.size();
bncbea13b82021-01-08 08:46:09 -0800737 visitor()->OnPriorityUpdate(prioritized_stream_id_, priority_field_value_);
738 priority_field_value_.clear();
739}
740
QUICHE team82dee2f2019-01-18 12:35:12 -0500741// Except for BLOCKED frames, all other unknown frames are either dropped or
742// passed to a registered extension.
743void Http2DecoderAdapter::OnUnknownStart(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700744 QUICHE_DVLOG(1) << "OnUnknownStart: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500745 if (IsOkToStartFrame(header)) {
746 if (extension_ != nullptr) {
747 const uint8_t type = static_cast<uint8_t>(header.type);
748 const uint8_t flags = static_cast<uint8_t>(header.flags);
749 handling_extension_payload_ = extension_->OnFrameHeader(
750 header.stream_id, header.payload_length, type, flags);
751 }
752 }
753}
754
755void Http2DecoderAdapter::OnUnknownPayload(const char* data, size_t len) {
756 if (handling_extension_payload_) {
757 extension_->OnFramePayload(data, len);
758 } else {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700759 QUICHE_DVLOG(1) << "OnUnknownPayload: len=" << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500760 }
761}
762
763void Http2DecoderAdapter::OnUnknownEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700764 QUICHE_DVLOG(1) << "OnUnknownEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500765 handling_extension_payload_ = false;
766}
767
768void Http2DecoderAdapter::OnPaddingTooLong(const Http2FrameHeader& header,
769 size_t missing_length) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700770 QUICHE_DVLOG(1) << "OnPaddingTooLong: " << header
771 << "; missing_length: " << missing_length;
QUICHE team82dee2f2019-01-18 12:35:12 -0500772 if (header.type == Http2FrameType::DATA) {
773 if (header.payload_length == 0) {
vasilvved4f3082021-02-01 14:29:40 -0800774 QUICHE_DCHECK_EQ(1u, missing_length);
fayang80366682020-07-24 09:19:11 -0700775 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_DATA_FRAME_FLAGS, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500776 return;
777 }
778 visitor()->OnStreamPadding(header.stream_id, 1);
779 }
fayang80366682020-07-24 09:19:11 -0700780 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_PADDING, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500781}
782
783void Http2DecoderAdapter::OnFrameSizeError(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700784 QUICHE_DVLOG(1) << "OnFrameSizeError: " << header;
QUICHE team82dee2f2019-01-18 12:35:12 -0500785 size_t recv_limit = recv_frame_size_limit_;
786 if (header.payload_length > recv_limit) {
fayang80366682020-07-24 09:19:11 -0700787 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_OVERSIZED_PAYLOAD, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500788 return;
789 }
790 if (header.type != Http2FrameType::DATA &&
791 header.payload_length > recv_limit) {
fayang80366682020-07-24 09:19:11 -0700792 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_CONTROL_PAYLOAD_TOO_LARGE, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500793 return;
794 }
795 switch (header.type) {
796 case Http2FrameType::GOAWAY:
797 case Http2FrameType::ALTSVC:
fayang80366682020-07-24 09:19:11 -0700798 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500799 break;
800 default:
fayang80366682020-07-24 09:19:11 -0700801 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME_SIZE,
802 "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500803 }
804}
805
806// Decodes the input up to the next frame boundary (i.e. at most one frame),
807// stopping early if an error is detected.
808size_t Http2DecoderAdapter::ProcessInputFrame(const char* data, size_t len) {
vasilvved4f3082021-02-01 14:29:40 -0800809 QUICHE_DCHECK_NE(spdy_state_, SpdyState::SPDY_ERROR);
QUICHE team82dee2f2019-01-18 12:35:12 -0500810 DecodeBuffer db(data, len);
811 DecodeStatus status = frame_decoder_->DecodeFrame(&db);
812 if (spdy_state_ != SpdyState::SPDY_ERROR) {
813 DetermineSpdyState(status);
814 } else {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700815 QUICHE_VLOG(1) << "ProcessInputFrame spdy_framer_error_="
816 << SpdyFramerErrorToString(spdy_framer_error_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500817 if (spdy_framer_error_ == SpdyFramerError::SPDY_INVALID_PADDING &&
818 has_frame_header_ && frame_type() != Http2FrameType::DATA) {
819 // spdy_framer_test checks that all of the available frame payload
820 // has been consumed, so do that.
821 size_t total = remaining_total_payload();
822 if (total <= frame_header().payload_length) {
823 size_t avail = db.MinLengthRemaining(total);
QUICHE team1b5d09e2021-04-08 13:36:42 -0700824 QUICHE_VLOG(1) << "Skipping past " << avail << " bytes, of " << total
825 << " total remaining in the frame's payload.";
QUICHE team82dee2f2019-01-18 12:35:12 -0500826 db.AdvanceCursor(avail);
827 } else {
QUICHE team33a4aa62021-04-08 11:10:59 -0700828 QUICHE_BUG(spdy_bug_1_2)
QUICHE team16501202021-03-11 09:32:16 -0800829 << "Total remaining (" << total
830 << ") should not be greater than the payload length; "
831 << frame_header();
QUICHE team82dee2f2019-01-18 12:35:12 -0500832 }
833 }
834 }
835 return db.Offset();
836}
837
838// After decoding, determine the next SpdyState. Only called if the current
839// state is NOT SpdyState::SPDY_ERROR (i.e. if none of the callback methods
840// detected an error condition), because otherwise we assume that the callback
841// method has set spdy_framer_error_ appropriately.
842void Http2DecoderAdapter::DetermineSpdyState(DecodeStatus status) {
vasilvved4f3082021-02-01 14:29:40 -0800843 QUICHE_DCHECK_EQ(spdy_framer_error_, SPDY_NO_ERROR);
844 QUICHE_DCHECK(!HasError()) << spdy_framer_error_;
QUICHE team82dee2f2019-01-18 12:35:12 -0500845 switch (status) {
846 case DecodeStatus::kDecodeDone:
QUICHE team1b5d09e2021-04-08 13:36:42 -0700847 QUICHE_DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeDone";
QUICHE team82dee2f2019-01-18 12:35:12 -0500848 ResetBetweenFrames();
849 break;
850 case DecodeStatus::kDecodeInProgress:
QUICHE team1b5d09e2021-04-08 13:36:42 -0700851 QUICHE_DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeInProgress";
QUICHE team82dee2f2019-01-18 12:35:12 -0500852 if (decoded_frame_header_) {
853 if (IsDiscardingPayload()) {
854 set_spdy_state(SpdyState::SPDY_IGNORE_REMAINING_PAYLOAD);
855 } else if (has_frame_header_ && frame_type() == Http2FrameType::DATA) {
856 if (IsReadingPaddingLength()) {
857 set_spdy_state(SpdyState::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
858 } else if (IsSkippingPadding()) {
859 set_spdy_state(SpdyState::SPDY_CONSUME_PADDING);
860 } else {
861 set_spdy_state(SpdyState::SPDY_FORWARD_STREAM_FRAME);
862 }
863 } else {
864 set_spdy_state(SpdyState::SPDY_CONTROL_FRAME_PAYLOAD);
865 }
866 } else {
867 set_spdy_state(SpdyState::SPDY_READING_COMMON_HEADER);
868 }
869 break;
870 case DecodeStatus::kDecodeError:
QUICHE team1b5d09e2021-04-08 13:36:42 -0700871 QUICHE_VLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeError";
QUICHE team82dee2f2019-01-18 12:35:12 -0500872 if (IsDiscardingPayload()) {
873 if (remaining_total_payload() == 0) {
874 // Push the Http2FrameDecoder out of state kDiscardPayload now
875 // since doing so requires no input.
876 DecodeBuffer tmp("", 0);
877 DecodeStatus status = frame_decoder_->DecodeFrame(&tmp);
878 if (status != DecodeStatus::kDecodeDone) {
QUICHE team33a4aa62021-04-08 11:10:59 -0700879 QUICHE_BUG(spdy_bug_1_3)
QUICHE team16501202021-03-11 09:32:16 -0800880 << "Expected to be done decoding the frame, not " << status;
fayang80366682020-07-24 09:19:11 -0700881 SetSpdyErrorAndNotify(SPDY_INTERNAL_FRAMER_ERROR, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500882 } else if (spdy_framer_error_ != SPDY_NO_ERROR) {
QUICHE team33a4aa62021-04-08 11:10:59 -0700883 QUICHE_BUG(spdy_bug_1_4)
QUICHE team16501202021-03-11 09:32:16 -0800884 << "Expected to have no error, not "
885 << SpdyFramerErrorToString(spdy_framer_error_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500886 } else {
887 ResetBetweenFrames();
888 }
889 } else {
890 set_spdy_state(SpdyState::SPDY_IGNORE_REMAINING_PAYLOAD);
891 }
892 } else {
fayang80366682020-07-24 09:19:11 -0700893 SetSpdyErrorAndNotify(SPDY_INVALID_CONTROL_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -0500894 }
895 break;
896 }
897}
898
899void Http2DecoderAdapter::ResetBetweenFrames() {
900 CorruptFrameHeader(&frame_header_);
901 decoded_frame_header_ = false;
902 has_frame_header_ = false;
903 set_spdy_state(SpdyState::SPDY_READY_FOR_FRAME);
904}
905
906// ResetInternal is called from the constructor, and during tests, but not
907// otherwise (i.e. not between every frame).
908void Http2DecoderAdapter::ResetInternal() {
909 set_spdy_state(SpdyState::SPDY_READY_FOR_FRAME);
910 spdy_framer_error_ = SpdyFramerError::SPDY_NO_ERROR;
911
912 decoded_frame_header_ = false;
913 has_frame_header_ = false;
914 on_headers_called_ = false;
915 on_hpack_fragment_called_ = false;
916 latched_probable_http_response_ = false;
917 has_expected_frame_type_ = false;
918
919 CorruptFrameHeader(&frame_header_);
920 CorruptFrameHeader(&hpack_first_frame_header_);
921
bnc463f2352019-10-10 04:49:34 -0700922 frame_decoder_ = std::make_unique<Http2FrameDecoder>(this);
QUICHE team82dee2f2019-01-18 12:35:12 -0500923 hpack_decoder_ = nullptr;
924}
925
926void Http2DecoderAdapter::set_spdy_state(SpdyState v) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700927 QUICHE_DVLOG(2) << "set_spdy_state(" << StateToString(v) << ")";
QUICHE team82dee2f2019-01-18 12:35:12 -0500928 spdy_state_ = v;
929}
930
fayang80366682020-07-24 09:19:11 -0700931void Http2DecoderAdapter::SetSpdyErrorAndNotify(SpdyFramerError error,
932 std::string detailed_error) {
QUICHE team82dee2f2019-01-18 12:35:12 -0500933 if (HasError()) {
vasilvved4f3082021-02-01 14:29:40 -0800934 QUICHE_DCHECK_EQ(spdy_state_, SpdyState::SPDY_ERROR);
QUICHE team82dee2f2019-01-18 12:35:12 -0500935 } else {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700936 QUICHE_VLOG(2) << "SetSpdyErrorAndNotify(" << SpdyFramerErrorToString(error)
937 << ")";
vasilvved4f3082021-02-01 14:29:40 -0800938 QUICHE_DCHECK_NE(error, SpdyFramerError::SPDY_NO_ERROR);
QUICHE team82dee2f2019-01-18 12:35:12 -0500939 spdy_framer_error_ = error;
940 set_spdy_state(SpdyState::SPDY_ERROR);
941 frame_decoder_->set_listener(&no_op_listener_);
fayang80366682020-07-24 09:19:11 -0700942 visitor()->OnError(error, detailed_error);
QUICHE team82dee2f2019-01-18 12:35:12 -0500943 }
944}
945
946bool Http2DecoderAdapter::HasError() const {
947 if (spdy_state_ == SpdyState::SPDY_ERROR) {
vasilvved4f3082021-02-01 14:29:40 -0800948 QUICHE_DCHECK_NE(spdy_framer_error(), SpdyFramerError::SPDY_NO_ERROR);
QUICHE team82dee2f2019-01-18 12:35:12 -0500949 return true;
950 } else {
vasilvved4f3082021-02-01 14:29:40 -0800951 QUICHE_DCHECK_EQ(spdy_framer_error(), SpdyFramerError::SPDY_NO_ERROR);
QUICHE team82dee2f2019-01-18 12:35:12 -0500952 return false;
953 }
954}
955
956const Http2FrameHeader& Http2DecoderAdapter::frame_header() const {
vasilvved4f3082021-02-01 14:29:40 -0800957 QUICHE_DCHECK(has_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500958 return frame_header_;
959}
960
961uint32_t Http2DecoderAdapter::stream_id() const {
962 return frame_header().stream_id;
963}
964
965Http2FrameType Http2DecoderAdapter::frame_type() const {
966 return frame_header().type;
967}
968
969size_t Http2DecoderAdapter::remaining_total_payload() const {
vasilvved4f3082021-02-01 14:29:40 -0800970 QUICHE_DCHECK(has_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500971 size_t remaining = frame_decoder_->remaining_payload();
972 if (IsPaddable(frame_type()) && frame_header_.IsPadded()) {
973 remaining += frame_decoder_->remaining_padding();
974 }
975 return remaining;
976}
977
978bool Http2DecoderAdapter::IsReadingPaddingLength() {
979 bool result = frame_header_.IsPadded() && !opt_pad_length_;
QUICHE team1b5d09e2021-04-08 13:36:42 -0700980 QUICHE_DVLOG(2) << "Http2DecoderAdapter::IsReadingPaddingLength: " << result;
QUICHE team82dee2f2019-01-18 12:35:12 -0500981 return result;
982}
983bool Http2DecoderAdapter::IsSkippingPadding() {
984 bool result = frame_header_.IsPadded() && opt_pad_length_ &&
985 frame_decoder_->remaining_payload() == 0 &&
986 frame_decoder_->remaining_padding() > 0;
QUICHE team1b5d09e2021-04-08 13:36:42 -0700987 QUICHE_DVLOG(2) << "Http2DecoderAdapter::IsSkippingPadding: " << result;
QUICHE team82dee2f2019-01-18 12:35:12 -0500988 return result;
989}
990bool Http2DecoderAdapter::IsDiscardingPayload() {
991 bool result = decoded_frame_header_ && frame_decoder_->IsDiscardingPayload();
QUICHE team1b5d09e2021-04-08 13:36:42 -0700992 QUICHE_DVLOG(2) << "Http2DecoderAdapter::IsDiscardingPayload: " << result;
QUICHE team82dee2f2019-01-18 12:35:12 -0500993 return result;
994}
995// Called from OnXyz or OnXyzStart methods to decide whether it is OK to
996// handle the callback.
997bool Http2DecoderAdapter::IsOkToStartFrame(const Http2FrameHeader& header) {
QUICHE team1b5d09e2021-04-08 13:36:42 -0700998 QUICHE_DVLOG(3) << "IsOkToStartFrame";
QUICHE team82dee2f2019-01-18 12:35:12 -0500999 if (HasError()) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001000 QUICHE_VLOG(2) << "HasError()";
QUICHE team82dee2f2019-01-18 12:35:12 -05001001 return false;
1002 }
vasilvved4f3082021-02-01 14:29:40 -08001003 QUICHE_DCHECK(!has_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -05001004 if (has_expected_frame_type_ && header.type != expected_frame_type_) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001005 QUICHE_VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
1006 << header.type;
fayang80366682020-07-24 09:19:11 -07001007 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
QUICHE team82dee2f2019-01-18 12:35:12 -05001008 return false;
1009 }
1010
1011 return true;
1012}
1013
1014bool Http2DecoderAdapter::HasRequiredStreamId(uint32_t stream_id) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001015 QUICHE_DVLOG(3) << "HasRequiredStreamId: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -05001016 if (HasError()) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001017 QUICHE_VLOG(2) << "HasError()";
QUICHE team82dee2f2019-01-18 12:35:12 -05001018 return false;
1019 }
1020 if (stream_id != 0) {
1021 return true;
1022 }
QUICHE team1b5d09e2021-04-08 13:36:42 -07001023 QUICHE_VLOG(1) << "Stream Id is required, but zero provided";
fayang80366682020-07-24 09:19:11 -07001024 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID, "");
QUICHE team82dee2f2019-01-18 12:35:12 -05001025 return false;
1026}
1027
1028bool Http2DecoderAdapter::HasRequiredStreamId(const Http2FrameHeader& header) {
1029 return HasRequiredStreamId(header.stream_id);
1030}
1031
1032bool Http2DecoderAdapter::HasRequiredStreamIdZero(uint32_t stream_id) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001033 QUICHE_DVLOG(3) << "HasRequiredStreamIdZero: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -05001034 if (HasError()) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001035 QUICHE_VLOG(2) << "HasError()";
QUICHE team82dee2f2019-01-18 12:35:12 -05001036 return false;
1037 }
1038 if (stream_id == 0) {
1039 return true;
1040 }
QUICHE team1b5d09e2021-04-08 13:36:42 -07001041 QUICHE_VLOG(1) << "Stream Id was not zero, as required: " << stream_id;
fayang80366682020-07-24 09:19:11 -07001042 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID, "");
QUICHE team82dee2f2019-01-18 12:35:12 -05001043 return false;
1044}
1045
1046bool Http2DecoderAdapter::HasRequiredStreamIdZero(
1047 const Http2FrameHeader& header) {
1048 return HasRequiredStreamIdZero(header.stream_id);
1049}
1050
1051void Http2DecoderAdapter::ReportReceiveCompressedFrame(
1052 const Http2FrameHeader& header) {
1053 if (debug_visitor() != nullptr) {
1054 size_t total = header.payload_length + Http2FrameHeader::EncodedSize();
1055 debug_visitor()->OnReceiveCompressedFrame(
1056 header.stream_id, ToSpdyFrameType(header.type), total);
1057 }
1058}
1059
1060HpackDecoderAdapter* Http2DecoderAdapter::GetHpackDecoder() {
1061 if (hpack_decoder_ == nullptr) {
bnc463f2352019-10-10 04:49:34 -07001062 hpack_decoder_ = std::make_unique<HpackDecoderAdapter>();
QUICHE team82dee2f2019-01-18 12:35:12 -05001063 }
1064 return hpack_decoder_.get();
1065}
1066
1067void Http2DecoderAdapter::CommonStartHpackBlock() {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001068 QUICHE_DVLOG(1) << "CommonStartHpackBlock";
vasilvved4f3082021-02-01 14:29:40 -08001069 QUICHE_DCHECK(!has_hpack_first_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -05001070 if (!frame_header_.IsEndHeaders()) {
1071 hpack_first_frame_header_ = frame_header_;
1072 has_hpack_first_frame_header_ = true;
1073 } else {
1074 CorruptFrameHeader(&hpack_first_frame_header_);
1075 }
1076 on_hpack_fragment_called_ = false;
1077 SpdyHeadersHandlerInterface* handler =
1078 visitor()->OnHeaderFrameStart(stream_id());
1079 if (handler == nullptr) {
QUICHE team33a4aa62021-04-08 11:10:59 -07001080 QUICHE_BUG(spdy_bug_1_5) << "visitor_->OnHeaderFrameStart returned nullptr";
fayang80366682020-07-24 09:19:11 -07001081 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INTERNAL_FRAMER_ERROR, "");
QUICHE team82dee2f2019-01-18 12:35:12 -05001082 return;
1083 }
1084 GetHpackDecoder()->HandleControlFrameHeadersStart(handler);
1085}
1086
1087// SpdyFramer calls HandleControlFrameHeadersData even if there are zero
1088// fragment bytes in the first frame, so do the same.
1089void Http2DecoderAdapter::MaybeAnnounceEmptyFirstHpackFragment() {
1090 if (!on_hpack_fragment_called_) {
1091 OnHpackFragment(nullptr, 0);
vasilvved4f3082021-02-01 14:29:40 -08001092 QUICHE_DCHECK(on_hpack_fragment_called_);
QUICHE team82dee2f2019-01-18 12:35:12 -05001093 }
1094}
1095
1096void Http2DecoderAdapter::CommonHpackFragmentEnd() {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001097 QUICHE_DVLOG(1) << "CommonHpackFragmentEnd: stream_id=" << stream_id();
QUICHE team82dee2f2019-01-18 12:35:12 -05001098 if (HasError()) {
QUICHE team1b5d09e2021-04-08 13:36:42 -07001099 QUICHE_VLOG(1) << "HasError(), returning";
QUICHE team82dee2f2019-01-18 12:35:12 -05001100 return;
1101 }
vasilvved4f3082021-02-01 14:29:40 -08001102 QUICHE_DCHECK(has_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -05001103 MaybeAnnounceEmptyFirstHpackFragment();
1104 if (frame_header_.IsEndHeaders()) {
vasilvved4f3082021-02-01 14:29:40 -08001105 QUICHE_DCHECK_EQ(has_hpack_first_frame_header_,
1106 frame_type() == Http2FrameType::CONTINUATION)
QUICHE team82dee2f2019-01-18 12:35:12 -05001107 << frame_header();
1108 has_expected_frame_type_ = false;
bnc77b46412020-02-21 08:09:09 -08001109 auto* decoder = GetHpackDecoder();
1110 if (decoder->HandleControlFrameHeadersComplete(nullptr)) {
QUICHE team82dee2f2019-01-18 12:35:12 -05001111 visitor()->OnHeaderFrameEnd(stream_id());
1112 } else {
bnc77b46412020-02-21 08:09:09 -08001113 SetSpdyErrorAndNotify(
fayang80366682020-07-24 09:19:11 -07001114 HpackDecodingErrorToSpdyFramerError(decoder->error()), "");
QUICHE team82dee2f2019-01-18 12:35:12 -05001115 return;
1116 }
1117 const Http2FrameHeader& first = frame_type() == Http2FrameType::CONTINUATION
1118 ? hpack_first_frame_header_
1119 : frame_header_;
1120 if (first.type == Http2FrameType::HEADERS && first.IsEndStream()) {
1121 visitor()->OnStreamEnd(first.stream_id);
1122 }
1123 has_hpack_first_frame_header_ = false;
1124 CorruptFrameHeader(&hpack_first_frame_header_);
1125 } else {
vasilvved4f3082021-02-01 14:29:40 -08001126 QUICHE_DCHECK(has_hpack_first_frame_header_);
QUICHE team82dee2f2019-01-18 12:35:12 -05001127 has_expected_frame_type_ = true;
1128 expected_frame_type_ = Http2FrameType::CONTINUATION;
1129 }
1130}
1131
1132} // namespace http2
1133
1134namespace spdy {
1135
danzh8f3a5762019-06-25 13:43:51 -07001136bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* /*goaway_data*/,
1137 size_t /*len*/) {
QUICHE team82dee2f2019-01-18 12:35:12 -05001138 return true;
1139}
1140
1141} // namespace spdy