blob: c4e728d2334ddc228943508e5a4136de7a822904 [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
5#include "net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h"
6
7// Logging policy: If an error in the input is detected, VLOG(n) is used so that
8// the option exists to debug the situation. Otherwise, this code mostly uses
9// DVLOG so that the logging does not slow down production code when things are
10// working OK.
11
12#include <stddef.h>
13
14#include <cstdint>
15#include <cstring>
16#include <utility>
17
18#include "base/logging.h"
19#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h"
20#include "net/third_party/quiche/src/http2/decoder/decode_status.h"
21#include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h"
22#include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.h"
23#include "net/third_party/quiche/src/http2/http2_constants.h"
24#include "net/third_party/quiche/src/http2/http2_structures.h"
25#include "net/third_party/quiche/src/http2/platform/api/http2_string.h"
26#include "net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h"
27#include "net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h"
28#include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h"
29#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
30#include "net/third_party/quiche/src/spdy/core/spdy_headers_handler_interface.h"
31#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
32#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h"
33#include "net/third_party/quiche/src/spdy/platform/api/spdy_endianness_util.h"
34#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h"
35#include "net/third_party/quiche/src/spdy/platform/api/spdy_flags.h"
36#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h"
37#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h"
38
39using ::spdy::ExtensionVisitorInterface;
40using ::spdy::HpackDecoderAdapter;
41using ::spdy::HpackHeaderTable;
42using ::spdy::ParseErrorCode;
43using ::spdy::ParseFrameType;
44using ::spdy::SpdyAltSvcWireFormat;
45using ::spdy::SpdyErrorCode;
46using ::spdy::SpdyEstimateMemoryUsage;
47using ::spdy::SpdyFramerDebugVisitorInterface;
48using ::spdy::SpdyFramerVisitorInterface;
49using ::spdy::SpdyFrameType;
50using ::spdy::SpdyHeadersHandlerInterface;
51using ::spdy::SpdyKnownSettingsId;
52using ::spdy::SpdyMakeUnique;
53using ::spdy::SpdySettingsId;
54
55namespace http2 {
56namespace {
57
58const bool kHasPriorityFields = true;
59const bool kNotHasPriorityFields = false;
60
61bool IsPaddable(Http2FrameType type) {
62 return type == Http2FrameType::DATA || type == Http2FrameType::HEADERS ||
63 type == Http2FrameType::PUSH_PROMISE;
64}
65
66SpdyFrameType ToSpdyFrameType(Http2FrameType type) {
67 return ParseFrameType(static_cast<uint8_t>(type));
68}
69
70uint64_t ToSpdyPingId(const Http2PingFields& ping) {
71 uint64_t v;
72 std::memcpy(&v, ping.opaque_bytes, Http2PingFields::EncodedSize());
73 return spdy::SpdyNetToHost64(v);
74}
75
76// Overwrites the fields of the header with invalid values, for the purpose
77// of identifying reading of unset fields. Only takes effect for debug builds.
78// In Address Sanatizer builds, it also marks the fields as un-readable.
79void CorruptFrameHeader(Http2FrameHeader* header) {
80#ifndef NDEBUG
81 // Beyond a valid payload length, which is 2^24 - 1.
82 header->payload_length = 0x1010dead;
83 // An unsupported frame type.
84 header->type = Http2FrameType(0x80);
85 DCHECK(!IsSupportedHttp2FrameType(header->type));
86 // Frame flag bits that aren't used by any supported frame type.
87 header->flags = Http2FrameFlag(0xd2);
88 // A stream id with the reserved high-bit (R in the RFC) set.
89 // 2129510127 when the high-bit is cleared.
90 header->stream_id = 0xfeedbeef;
91#endif
92}
93
94} // namespace
95
96const char* Http2DecoderAdapter::StateToString(int state) {
97 switch (state) {
98 case SPDY_ERROR:
99 return "ERROR";
100 case SPDY_FRAME_COMPLETE:
101 return "FRAME_COMPLETE";
102 case SPDY_READY_FOR_FRAME:
103 return "READY_FOR_FRAME";
104 case SPDY_READING_COMMON_HEADER:
105 return "READING_COMMON_HEADER";
106 case SPDY_CONTROL_FRAME_PAYLOAD:
107 return "CONTROL_FRAME_PAYLOAD";
108 case SPDY_READ_DATA_FRAME_PADDING_LENGTH:
109 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
110 case SPDY_CONSUME_PADDING:
111 return "SPDY_CONSUME_PADDING";
112 case SPDY_IGNORE_REMAINING_PAYLOAD:
113 return "IGNORE_REMAINING_PAYLOAD";
114 case SPDY_FORWARD_STREAM_FRAME:
115 return "FORWARD_STREAM_FRAME";
116 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
117 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
118 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
119 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
120 case SPDY_GOAWAY_FRAME_PAYLOAD:
121 return "SPDY_GOAWAY_FRAME_PAYLOAD";
122 case SPDY_SETTINGS_FRAME_HEADER:
123 return "SPDY_SETTINGS_FRAME_HEADER";
124 case SPDY_SETTINGS_FRAME_PAYLOAD:
125 return "SPDY_SETTINGS_FRAME_PAYLOAD";
126 case SPDY_ALTSVC_FRAME_PAYLOAD:
127 return "SPDY_ALTSVC_FRAME_PAYLOAD";
128 }
129 return "UNKNOWN_STATE";
130}
131
132const char* Http2DecoderAdapter::SpdyFramerErrorToString(
133 SpdyFramerError spdy_framer_error) {
134 switch (spdy_framer_error) {
135 case SPDY_NO_ERROR:
136 return "NO_ERROR";
137 case SPDY_INVALID_STREAM_ID:
138 return "INVALID_STREAM_ID";
139 case SPDY_INVALID_CONTROL_FRAME:
140 return "INVALID_CONTROL_FRAME";
141 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
142 return "CONTROL_PAYLOAD_TOO_LARGE";
143 case SPDY_ZLIB_INIT_FAILURE:
144 return "ZLIB_INIT_FAILURE";
145 case SPDY_UNSUPPORTED_VERSION:
146 return "UNSUPPORTED_VERSION";
147 case SPDY_DECOMPRESS_FAILURE:
148 return "DECOMPRESS_FAILURE";
149 case SPDY_COMPRESS_FAILURE:
150 return "COMPRESS_FAILURE";
151 case SPDY_GOAWAY_FRAME_CORRUPT:
152 return "GOAWAY_FRAME_CORRUPT";
153 case SPDY_RST_STREAM_FRAME_CORRUPT:
154 return "RST_STREAM_FRAME_CORRUPT";
155 case SPDY_INVALID_PADDING:
156 return "INVALID_PADDING";
157 case SPDY_INVALID_DATA_FRAME_FLAGS:
158 return "INVALID_DATA_FRAME_FLAGS";
159 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
160 return "INVALID_CONTROL_FRAME_FLAGS";
161 case SPDY_UNEXPECTED_FRAME:
162 return "UNEXPECTED_FRAME";
163 case SPDY_INTERNAL_FRAMER_ERROR:
164 return "INTERNAL_FRAMER_ERROR";
165 case SPDY_INVALID_CONTROL_FRAME_SIZE:
166 return "INVALID_CONTROL_FRAME_SIZE";
167 case SPDY_OVERSIZED_PAYLOAD:
168 return "OVERSIZED_PAYLOAD";
169 case LAST_ERROR:
170 return "UNKNOWN_ERROR";
171 }
172 return "UNKNOWN_ERROR";
173}
174
175Http2DecoderAdapter::Http2DecoderAdapter() {
176 DVLOG(1) << "Http2DecoderAdapter ctor";
177 ResetInternal();
178}
179
180Http2DecoderAdapter::~Http2DecoderAdapter() = default;
181
182void Http2DecoderAdapter::set_visitor(SpdyFramerVisitorInterface* visitor) {
183 visitor_ = visitor;
184}
185
186void Http2DecoderAdapter::set_debug_visitor(
187 SpdyFramerDebugVisitorInterface* debug_visitor) {
188 debug_visitor_ = debug_visitor;
189}
190
191void Http2DecoderAdapter::set_process_single_input_frame(bool v) {
192 process_single_input_frame_ = v;
193}
194
195void Http2DecoderAdapter::set_extension_visitor(
196 ExtensionVisitorInterface* visitor) {
197 extension_ = visitor;
198}
199
200// Passes the call on to the HPACK decoder.
201void Http2DecoderAdapter::SetDecoderHeaderTableDebugVisitor(
202 std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
203 GetHpackDecoder()->SetHeaderTableDebugVisitor(std::move(visitor));
204}
205
206size_t Http2DecoderAdapter::ProcessInput(const char* data, size_t len) {
207 size_t limit = recv_frame_size_limit_;
208 frame_decoder_->set_maximum_payload_size(limit);
209
210 size_t total_processed = 0;
211 while (len > 0 && spdy_state_ != SPDY_ERROR) {
212 // Process one at a time so that we update the adapter's internal
213 // state appropriately.
214 const size_t processed = ProcessInputFrame(data, len);
215
216 // We had some data, and weren't in an error state, so should have
217 // processed/consumed at least one byte of it, even if we then ended up
218 // in an error state.
219 DCHECK(processed > 0) << "processed=" << processed
220 << " spdy_state_=" << spdy_state_
221 << " spdy_framer_error_=" << spdy_framer_error_;
222
223 data += processed;
224 len -= processed;
225 total_processed += processed;
226 if (process_single_input_frame() || processed == 0) {
227 break;
228 }
229 }
230 return total_processed;
231}
232
233void Http2DecoderAdapter::Reset() {
234 ResetInternal();
235}
236
237Http2DecoderAdapter::SpdyState Http2DecoderAdapter::state() const {
238 return spdy_state_;
239}
240
241Http2DecoderAdapter::SpdyFramerError Http2DecoderAdapter::spdy_framer_error()
242 const {
243 return spdy_framer_error_;
244}
245
246bool Http2DecoderAdapter::probable_http_response() const {
247 return latched_probable_http_response_;
248}
249
250size_t Http2DecoderAdapter::EstimateMemoryUsage() const {
251 // Skip |frame_decoder_|, |frame_header_| and |hpack_first_frame_header_| as
252 // they don't allocate.
253 return SpdyEstimateMemoryUsage(alt_svc_origin_) +
254 SpdyEstimateMemoryUsage(alt_svc_value_);
255}
256
257// ===========================================================================
258// Implementations of the methods declared by Http2FrameDecoderListener.
259
260// Called once the common frame header has been decoded for any frame.
261// This function is largely based on Http2DecoderAdapter::ValidateFrameHeader
262// and some parts of Http2DecoderAdapter::ProcessCommonHeader.
263bool Http2DecoderAdapter::OnFrameHeader(const Http2FrameHeader& header) {
264 DVLOG(1) << "OnFrameHeader: " << header;
265 decoded_frame_header_ = true;
266 if (!latched_probable_http_response_) {
267 latched_probable_http_response_ = header.IsProbableHttpResponse();
268 }
269 const uint8_t raw_frame_type = static_cast<uint8_t>(header.type);
270 visitor()->OnCommonHeader(header.stream_id, header.payload_length,
271 raw_frame_type, header.flags);
272 if (has_expected_frame_type_ && header.type != expected_frame_type_) {
273 // Report an unexpected frame error and close the connection if we
274 // expect a known frame type (probably CONTINUATION) and receive an
275 // unknown frame.
276 VLOG(1) << "The framer was expecting to receive a " << expected_frame_type_
277 << " frame, but instead received an unknown frame of type "
278 << header.type;
279 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME);
280 return false;
281 }
282 if (!IsSupportedHttp2FrameType(header.type)) {
283 if (extension_ != nullptr) {
284 // Unknown frames will be passed to the registered extension.
285 return true;
286 }
287 // In HTTP2 we ignore unknown frame types for extensibility, as long as
288 // the rest of the control frame header is valid.
289 // We rely on the visitor to check validity of stream_id.
290 bool valid_stream =
291 visitor()->OnUnknownFrame(header.stream_id, raw_frame_type);
292 if (!valid_stream) {
293 // Report an invalid frame error if the stream_id is not valid.
294 VLOG(1) << "Unknown control frame type " << header.type
295 << " received on invalid stream " << header.stream_id;
296 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME);
297 return false;
298 } else {
299 DVLOG(1) << "Ignoring unknown frame type " << header.type;
300 return true;
301 }
302 }
303
304 SpdyFrameType frame_type = ToSpdyFrameType(header.type);
305 if (!IsValidHTTP2FrameStreamId(header.stream_id, frame_type)) {
306 VLOG(1) << "The framer received an invalid streamID of " << header.stream_id
307 << " for a frame of type " << header.type;
308 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID);
309 return false;
310 }
311
312 if (has_expected_frame_type_ && header.type != expected_frame_type_) {
313 VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
314 << header.type;
315 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME);
316 return false;
317 }
318
319 if (!has_expected_frame_type_ &&
320 header.type == Http2FrameType::CONTINUATION) {
321 VLOG(1) << "Got CONTINUATION frame when not expected.";
322 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME);
323 return false;
324 }
325
326 if (header.type == Http2FrameType::DATA) {
327 // For some reason SpdyFramer still rejects invalid DATA frame flags.
328 uint8_t valid_flags = Http2FrameFlag::PADDED | Http2FrameFlag::END_STREAM;
329 if (header.HasAnyFlags(~valid_flags)) {
330 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_DATA_FRAME_FLAGS);
331 return false;
332 }
333 }
334
335 return true;
336}
337
338void Http2DecoderAdapter::OnDataStart(const Http2FrameHeader& header) {
339 DVLOG(1) << "OnDataStart: " << header;
340
341 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
342 frame_header_ = header;
343 has_frame_header_ = true;
344 visitor()->OnDataFrameHeader(header.stream_id, header.payload_length,
345 header.IsEndStream());
346 }
347}
348
349void Http2DecoderAdapter::OnDataPayload(const char* data, size_t len) {
350 DVLOG(1) << "OnDataPayload: len=" << len;
351 DCHECK(has_frame_header_);
352 DCHECK_EQ(frame_header_.type, Http2FrameType::DATA);
353 visitor()->OnStreamFrameData(frame_header().stream_id, data, len);
354}
355
356void Http2DecoderAdapter::OnDataEnd() {
357 DVLOG(1) << "OnDataEnd";
358 DCHECK(has_frame_header_);
359 DCHECK_EQ(frame_header_.type, Http2FrameType::DATA);
360 if (frame_header().IsEndStream()) {
361 visitor()->OnStreamEnd(frame_header().stream_id);
362 }
363 opt_pad_length_.reset();
364}
365
366void Http2DecoderAdapter::OnHeadersStart(const Http2FrameHeader& header) {
367 DVLOG(1) << "OnHeadersStart: " << header;
368 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
369 frame_header_ = header;
370 has_frame_header_ = true;
371 if (header.HasPriority()) {
372 // Once we've got the priority fields, then we can report the arrival
373 // of this HEADERS frame.
374 on_headers_called_ = false;
375 return;
376 }
377 on_headers_called_ = true;
378 ReportReceiveCompressedFrame(header);
379 visitor()->OnHeaders(header.stream_id, kNotHasPriorityFields,
380 0, // priority
381 0, // parent_stream_id
382 false, // exclusive
383 header.IsEndStream(), header.IsEndHeaders());
384 CommonStartHpackBlock();
385 }
386}
387
388void Http2DecoderAdapter::OnHeadersPriority(
389 const Http2PriorityFields& priority) {
390 DVLOG(1) << "OnHeadersPriority: " << priority;
391 DCHECK(has_frame_header_);
392 DCHECK_EQ(frame_type(), Http2FrameType::HEADERS) << frame_header_;
393 DCHECK(frame_header_.HasPriority());
394 DCHECK(!on_headers_called_);
395 on_headers_called_ = true;
396 ReportReceiveCompressedFrame(frame_header_);
397 visitor()->OnHeaders(frame_header_.stream_id, kHasPriorityFields,
398 priority.weight, priority.stream_dependency,
399 priority.is_exclusive, frame_header_.IsEndStream(),
400 frame_header_.IsEndHeaders());
401 CommonStartHpackBlock();
402}
403
404void Http2DecoderAdapter::OnHpackFragment(const char* data, size_t len) {
405 DVLOG(1) << "OnHpackFragment: len=" << len;
406 on_hpack_fragment_called_ = true;
407 if (!GetHpackDecoder()->HandleControlFrameHeadersData(data, len)) {
408 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_DECOMPRESS_FAILURE);
409 return;
410 }
411}
412
413void Http2DecoderAdapter::OnHeadersEnd() {
414 DVLOG(1) << "OnHeadersEnd";
415 CommonHpackFragmentEnd();
416 opt_pad_length_.reset();
417}
418
419void Http2DecoderAdapter::OnPriorityFrame(const Http2FrameHeader& header,
420 const Http2PriorityFields& priority) {
421 DVLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority;
422 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
423 visitor()->OnPriority(header.stream_id, priority.stream_dependency,
424 priority.weight, priority.is_exclusive);
425 }
426}
427
428void Http2DecoderAdapter::OnContinuationStart(const Http2FrameHeader& header) {
429 DVLOG(1) << "OnContinuationStart: " << header;
430 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
431 DCHECK(has_hpack_first_frame_header_);
432 if (header.stream_id != hpack_first_frame_header_.stream_id) {
433 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME);
434 return;
435 }
436 frame_header_ = header;
437 has_frame_header_ = true;
438 ReportReceiveCompressedFrame(header);
439 visitor()->OnContinuation(header.stream_id, header.IsEndHeaders());
440 }
441}
442
443void Http2DecoderAdapter::OnContinuationEnd() {
444 DVLOG(1) << "OnContinuationEnd";
445 CommonHpackFragmentEnd();
446}
447
448void Http2DecoderAdapter::OnPadLength(size_t trailing_length) {
449 DVLOG(1) << "OnPadLength: " << trailing_length;
450 opt_pad_length_ = trailing_length;
451 DCHECK_LT(trailing_length, 256u);
452 if (frame_header_.type == Http2FrameType::DATA) {
453 visitor()->OnStreamPadLength(stream_id(), trailing_length);
454 }
455}
456
457void Http2DecoderAdapter::OnPadding(const char* padding,
458 size_t skipped_length) {
459 DVLOG(1) << "OnPadding: " << skipped_length;
460 if (frame_header_.type == Http2FrameType::DATA) {
461 visitor()->OnStreamPadding(stream_id(), skipped_length);
462 } else {
463 MaybeAnnounceEmptyFirstHpackFragment();
464 }
465}
466
467void Http2DecoderAdapter::OnRstStream(const Http2FrameHeader& header,
468 Http2ErrorCode http2_error_code) {
469 DVLOG(1) << "OnRstStream: " << header << "; code=" << http2_error_code;
470 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
471 SpdyErrorCode error_code =
472 ParseErrorCode(static_cast<uint32_t>(http2_error_code));
473 visitor()->OnRstStream(header.stream_id, error_code);
474 }
475}
476
477void Http2DecoderAdapter::OnSettingsStart(const Http2FrameHeader& header) {
478 DVLOG(1) << "OnSettingsStart: " << header;
479 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
480 frame_header_ = header;
481 has_frame_header_ = true;
482 visitor()->OnSettings();
483 }
484}
485
486void Http2DecoderAdapter::OnSetting(const Http2SettingFields& setting_fields) {
487 DVLOG(1) << "OnSetting: " << setting_fields;
488 const auto parameter = static_cast<SpdySettingsId>(setting_fields.parameter);
489 visitor()->OnSetting(parameter, setting_fields.value);
490 if (extension_ != nullptr) {
491 extension_->OnSetting(parameter, setting_fields.value);
492 }
493}
494
495void Http2DecoderAdapter::OnSettingsEnd() {
496 DVLOG(1) << "OnSettingsEnd";
497 visitor()->OnSettingsEnd();
498}
499
500void Http2DecoderAdapter::OnSettingsAck(const Http2FrameHeader& header) {
501 DVLOG(1) << "OnSettingsAck: " << header;
502 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
503 visitor()->OnSettingsAck();
504 }
505}
506
507void Http2DecoderAdapter::OnPushPromiseStart(
508 const Http2FrameHeader& header,
509 const Http2PushPromiseFields& promise,
510 size_t total_padding_length) {
511 DVLOG(1) << "OnPushPromiseStart: " << header << "; promise: " << promise
512 << "; total_padding_length: " << total_padding_length;
513 if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
514 if (promise.promised_stream_id == 0) {
515 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME);
516 return;
517 }
518 frame_header_ = header;
519 has_frame_header_ = true;
520 ReportReceiveCompressedFrame(header);
521 visitor()->OnPushPromise(header.stream_id, promise.promised_stream_id,
522 header.IsEndHeaders());
523 CommonStartHpackBlock();
524 }
525}
526
527void Http2DecoderAdapter::OnPushPromiseEnd() {
528 DVLOG(1) << "OnPushPromiseEnd";
529 CommonHpackFragmentEnd();
530 opt_pad_length_.reset();
531}
532
533void Http2DecoderAdapter::OnPing(const Http2FrameHeader& header,
534 const Http2PingFields& ping) {
535 DVLOG(1) << "OnPing: " << header << "; ping: " << ping;
536 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
537 visitor()->OnPing(ToSpdyPingId(ping), false);
538 }
539}
540
541void Http2DecoderAdapter::OnPingAck(const Http2FrameHeader& header,
542 const Http2PingFields& ping) {
543 DVLOG(1) << "OnPingAck: " << header << "; ping: " << ping;
544 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
545 visitor()->OnPing(ToSpdyPingId(ping), true);
546 }
547}
548
549void Http2DecoderAdapter::OnGoAwayStart(const Http2FrameHeader& header,
550 const Http2GoAwayFields& goaway) {
551 DVLOG(1) << "OnGoAwayStart: " << header << "; goaway: " << goaway;
552 if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
553 frame_header_ = header;
554 has_frame_header_ = true;
555 SpdyErrorCode error_code =
556 ParseErrorCode(static_cast<uint32_t>(goaway.error_code));
557 visitor()->OnGoAway(goaway.last_stream_id, error_code);
558 }
559}
560
561void Http2DecoderAdapter::OnGoAwayOpaqueData(const char* data, size_t len) {
562 DVLOG(1) << "OnGoAwayOpaqueData: len=" << len;
563 visitor()->OnGoAwayFrameData(data, len);
564}
565
566void Http2DecoderAdapter::OnGoAwayEnd() {
567 DVLOG(1) << "OnGoAwayEnd";
568 visitor()->OnGoAwayFrameData(nullptr, 0);
569}
570
571void Http2DecoderAdapter::OnWindowUpdate(const Http2FrameHeader& header,
572 uint32_t increment) {
573 DVLOG(1) << "OnWindowUpdate: " << header << "; increment=" << increment;
574 if (IsOkToStartFrame(header)) {
575 visitor()->OnWindowUpdate(header.stream_id, increment);
576 }
577}
578
579// Per RFC7838, an ALTSVC frame on stream 0 with origin_length == 0, or one on
580// a stream other than stream 0 with origin_length != 0 MUST be ignored. All
581// frames are decoded by Http2DecoderAdapter, and it is left to the consumer
582// (listener) to implement this behavior.
583void Http2DecoderAdapter::OnAltSvcStart(const Http2FrameHeader& header,
584 size_t origin_length,
585 size_t value_length) {
586 DVLOG(1) << "OnAltSvcStart: " << header
587 << "; origin_length: " << origin_length
588 << "; value_length: " << value_length;
589 if (!IsOkToStartFrame(header)) {
590 return;
591 }
592 frame_header_ = header;
593 has_frame_header_ = true;
594 alt_svc_origin_.clear();
595 alt_svc_value_.clear();
596}
597
598void Http2DecoderAdapter::OnAltSvcOriginData(const char* data, size_t len) {
599 DVLOG(1) << "OnAltSvcOriginData: len=" << len;
600 alt_svc_origin_.append(data, len);
601}
602
603// Called when decoding the Alt-Svc-Field-Value of an ALTSVC;
604// the field is uninterpreted.
605void Http2DecoderAdapter::OnAltSvcValueData(const char* data, size_t len) {
606 DVLOG(1) << "OnAltSvcValueData: len=" << len;
607 alt_svc_value_.append(data, len);
608}
609
610void Http2DecoderAdapter::OnAltSvcEnd() {
611 DVLOG(1) << "OnAltSvcEnd: origin.size(): " << alt_svc_origin_.size()
612 << "; value.size(): " << alt_svc_value_.size();
613 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
614 if (!SpdyAltSvcWireFormat::ParseHeaderFieldValue(alt_svc_value_,
615 &altsvc_vector)) {
616 DLOG(ERROR) << "SpdyAltSvcWireFormat::ParseHeaderFieldValue failed.";
617 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME);
618 return;
619 }
620 visitor()->OnAltSvc(frame_header_.stream_id, alt_svc_origin_, altsvc_vector);
621 // We assume that ALTSVC frames are rare, so get rid of the storage.
622 alt_svc_origin_.clear();
623 alt_svc_origin_.shrink_to_fit();
624 alt_svc_value_.clear();
625 alt_svc_value_.shrink_to_fit();
626}
627
628// Except for BLOCKED frames, all other unknown frames are either dropped or
629// passed to a registered extension.
630void Http2DecoderAdapter::OnUnknownStart(const Http2FrameHeader& header) {
631 DVLOG(1) << "OnUnknownStart: " << header;
632 if (IsOkToStartFrame(header)) {
633 if (extension_ != nullptr) {
634 const uint8_t type = static_cast<uint8_t>(header.type);
635 const uint8_t flags = static_cast<uint8_t>(header.flags);
636 handling_extension_payload_ = extension_->OnFrameHeader(
637 header.stream_id, header.payload_length, type, flags);
638 }
639 }
640}
641
642void Http2DecoderAdapter::OnUnknownPayload(const char* data, size_t len) {
643 if (handling_extension_payload_) {
644 extension_->OnFramePayload(data, len);
645 } else {
646 DVLOG(1) << "OnUnknownPayload: len=" << len;
647 }
648}
649
650void Http2DecoderAdapter::OnUnknownEnd() {
651 DVLOG(1) << "OnUnknownEnd";
652 handling_extension_payload_ = false;
653}
654
655void Http2DecoderAdapter::OnPaddingTooLong(const Http2FrameHeader& header,
656 size_t missing_length) {
657 DVLOG(1) << "OnPaddingTooLong: " << header
658 << "; missing_length: " << missing_length;
659 if (header.type == Http2FrameType::DATA) {
660 if (header.payload_length == 0) {
661 DCHECK_EQ(1u, missing_length);
662 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_DATA_FRAME_FLAGS);
663 return;
664 }
665 visitor()->OnStreamPadding(header.stream_id, 1);
666 }
667 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_PADDING);
668}
669
670void Http2DecoderAdapter::OnFrameSizeError(const Http2FrameHeader& header) {
671 DVLOG(1) << "OnFrameSizeError: " << header;
672 size_t recv_limit = recv_frame_size_limit_;
673 if (header.payload_length > recv_limit) {
674 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_OVERSIZED_PAYLOAD);
675 return;
676 }
677 if (header.type != Http2FrameType::DATA &&
678 header.payload_length > recv_limit) {
679 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_CONTROL_PAYLOAD_TOO_LARGE);
680 return;
681 }
682 switch (header.type) {
683 case Http2FrameType::GOAWAY:
684 case Http2FrameType::ALTSVC:
685 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME);
686 break;
687 default:
688 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME_SIZE);
689 }
690}
691
692// Decodes the input up to the next frame boundary (i.e. at most one frame),
693// stopping early if an error is detected.
694size_t Http2DecoderAdapter::ProcessInputFrame(const char* data, size_t len) {
695 DCHECK_NE(spdy_state_, SpdyState::SPDY_ERROR);
696 DecodeBuffer db(data, len);
697 DecodeStatus status = frame_decoder_->DecodeFrame(&db);
698 if (spdy_state_ != SpdyState::SPDY_ERROR) {
699 DetermineSpdyState(status);
700 } else {
701 VLOG(1) << "ProcessInputFrame spdy_framer_error_="
702 << SpdyFramerErrorToString(spdy_framer_error_);
703 if (spdy_framer_error_ == SpdyFramerError::SPDY_INVALID_PADDING &&
704 has_frame_header_ && frame_type() != Http2FrameType::DATA) {
705 // spdy_framer_test checks that all of the available frame payload
706 // has been consumed, so do that.
707 size_t total = remaining_total_payload();
708 if (total <= frame_header().payload_length) {
709 size_t avail = db.MinLengthRemaining(total);
710 VLOG(1) << "Skipping past " << avail << " bytes, of " << total
711 << " total remaining in the frame's payload.";
712 db.AdvanceCursor(avail);
713 } else {
714 SPDY_BUG << "Total remaining (" << total
715 << ") should not be greater than the payload length; "
716 << frame_header();
717 }
718 }
719 }
720 return db.Offset();
721}
722
723// After decoding, determine the next SpdyState. Only called if the current
724// state is NOT SpdyState::SPDY_ERROR (i.e. if none of the callback methods
725// detected an error condition), because otherwise we assume that the callback
726// method has set spdy_framer_error_ appropriately.
727void Http2DecoderAdapter::DetermineSpdyState(DecodeStatus status) {
728 DCHECK_EQ(spdy_framer_error_, SPDY_NO_ERROR);
729 DCHECK(!HasError()) << spdy_framer_error_;
730 switch (status) {
731 case DecodeStatus::kDecodeDone:
732 DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeDone";
733 ResetBetweenFrames();
734 break;
735 case DecodeStatus::kDecodeInProgress:
736 DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeInProgress";
737 if (decoded_frame_header_) {
738 if (IsDiscardingPayload()) {
739 set_spdy_state(SpdyState::SPDY_IGNORE_REMAINING_PAYLOAD);
740 } else if (has_frame_header_ && frame_type() == Http2FrameType::DATA) {
741 if (IsReadingPaddingLength()) {
742 set_spdy_state(SpdyState::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
743 } else if (IsSkippingPadding()) {
744 set_spdy_state(SpdyState::SPDY_CONSUME_PADDING);
745 } else {
746 set_spdy_state(SpdyState::SPDY_FORWARD_STREAM_FRAME);
747 }
748 } else {
749 set_spdy_state(SpdyState::SPDY_CONTROL_FRAME_PAYLOAD);
750 }
751 } else {
752 set_spdy_state(SpdyState::SPDY_READING_COMMON_HEADER);
753 }
754 break;
755 case DecodeStatus::kDecodeError:
756 VLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeError";
757 if (IsDiscardingPayload()) {
758 if (remaining_total_payload() == 0) {
759 // Push the Http2FrameDecoder out of state kDiscardPayload now
760 // since doing so requires no input.
761 DecodeBuffer tmp("", 0);
762 DecodeStatus status = frame_decoder_->DecodeFrame(&tmp);
763 if (status != DecodeStatus::kDecodeDone) {
764 SPDY_BUG << "Expected to be done decoding the frame, not "
765 << status;
766 SetSpdyErrorAndNotify(SPDY_INTERNAL_FRAMER_ERROR);
767 } else if (spdy_framer_error_ != SPDY_NO_ERROR) {
768 SPDY_BUG << "Expected to have no error, not "
769 << SpdyFramerErrorToString(spdy_framer_error_);
770 } else {
771 ResetBetweenFrames();
772 }
773 } else {
774 set_spdy_state(SpdyState::SPDY_IGNORE_REMAINING_PAYLOAD);
775 }
776 } else {
777 SetSpdyErrorAndNotify(SPDY_INVALID_CONTROL_FRAME);
778 }
779 break;
780 }
781}
782
783void Http2DecoderAdapter::ResetBetweenFrames() {
784 CorruptFrameHeader(&frame_header_);
785 decoded_frame_header_ = false;
786 has_frame_header_ = false;
787 set_spdy_state(SpdyState::SPDY_READY_FOR_FRAME);
788}
789
790// ResetInternal is called from the constructor, and during tests, but not
791// otherwise (i.e. not between every frame).
792void Http2DecoderAdapter::ResetInternal() {
793 set_spdy_state(SpdyState::SPDY_READY_FOR_FRAME);
794 spdy_framer_error_ = SpdyFramerError::SPDY_NO_ERROR;
795
796 decoded_frame_header_ = false;
797 has_frame_header_ = false;
798 on_headers_called_ = false;
799 on_hpack_fragment_called_ = false;
800 latched_probable_http_response_ = false;
801 has_expected_frame_type_ = false;
802
803 CorruptFrameHeader(&frame_header_);
804 CorruptFrameHeader(&hpack_first_frame_header_);
805
806 frame_decoder_ = SpdyMakeUnique<Http2FrameDecoder>(this);
807 hpack_decoder_ = nullptr;
808}
809
810void Http2DecoderAdapter::set_spdy_state(SpdyState v) {
811 DVLOG(2) << "set_spdy_state(" << StateToString(v) << ")";
812 spdy_state_ = v;
813}
814
815void Http2DecoderAdapter::SetSpdyErrorAndNotify(SpdyFramerError error) {
816 if (HasError()) {
817 DCHECK_EQ(spdy_state_, SpdyState::SPDY_ERROR);
818 } else {
819 VLOG(2) << "SetSpdyErrorAndNotify(" << SpdyFramerErrorToString(error)
820 << ")";
821 DCHECK_NE(error, SpdyFramerError::SPDY_NO_ERROR);
822 spdy_framer_error_ = error;
823 set_spdy_state(SpdyState::SPDY_ERROR);
824 frame_decoder_->set_listener(&no_op_listener_);
825 visitor()->OnError(error);
826 }
827}
828
829bool Http2DecoderAdapter::HasError() const {
830 if (spdy_state_ == SpdyState::SPDY_ERROR) {
831 DCHECK_NE(spdy_framer_error(), SpdyFramerError::SPDY_NO_ERROR);
832 return true;
833 } else {
834 DCHECK_EQ(spdy_framer_error(), SpdyFramerError::SPDY_NO_ERROR);
835 return false;
836 }
837}
838
839const Http2FrameHeader& Http2DecoderAdapter::frame_header() const {
840 DCHECK(has_frame_header_);
841 return frame_header_;
842}
843
844uint32_t Http2DecoderAdapter::stream_id() const {
845 return frame_header().stream_id;
846}
847
848Http2FrameType Http2DecoderAdapter::frame_type() const {
849 return frame_header().type;
850}
851
852size_t Http2DecoderAdapter::remaining_total_payload() const {
853 DCHECK(has_frame_header_);
854 size_t remaining = frame_decoder_->remaining_payload();
855 if (IsPaddable(frame_type()) && frame_header_.IsPadded()) {
856 remaining += frame_decoder_->remaining_padding();
857 }
858 return remaining;
859}
860
861bool Http2DecoderAdapter::IsReadingPaddingLength() {
862 bool result = frame_header_.IsPadded() && !opt_pad_length_;
863 DVLOG(2) << "Http2DecoderAdapter::IsReadingPaddingLength: " << result;
864 return result;
865}
866bool Http2DecoderAdapter::IsSkippingPadding() {
867 bool result = frame_header_.IsPadded() && opt_pad_length_ &&
868 frame_decoder_->remaining_payload() == 0 &&
869 frame_decoder_->remaining_padding() > 0;
870 DVLOG(2) << "Http2DecoderAdapter::IsSkippingPadding: " << result;
871 return result;
872}
873bool Http2DecoderAdapter::IsDiscardingPayload() {
874 bool result = decoded_frame_header_ && frame_decoder_->IsDiscardingPayload();
875 DVLOG(2) << "Http2DecoderAdapter::IsDiscardingPayload: " << result;
876 return result;
877}
878// Called from OnXyz or OnXyzStart methods to decide whether it is OK to
879// handle the callback.
880bool Http2DecoderAdapter::IsOkToStartFrame(const Http2FrameHeader& header) {
881 DVLOG(3) << "IsOkToStartFrame";
882 if (HasError()) {
883 VLOG(2) << "HasError()";
884 return false;
885 }
886 DCHECK(!has_frame_header_);
887 if (has_expected_frame_type_ && header.type != expected_frame_type_) {
888 VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
889 << header.type;
890 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME);
891 return false;
892 }
893
894 return true;
895}
896
897bool Http2DecoderAdapter::HasRequiredStreamId(uint32_t stream_id) {
898 DVLOG(3) << "HasRequiredStreamId: " << stream_id;
899 if (HasError()) {
900 VLOG(2) << "HasError()";
901 return false;
902 }
903 if (stream_id != 0) {
904 return true;
905 }
906 VLOG(1) << "Stream Id is required, but zero provided";
907 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID);
908 return false;
909}
910
911bool Http2DecoderAdapter::HasRequiredStreamId(const Http2FrameHeader& header) {
912 return HasRequiredStreamId(header.stream_id);
913}
914
915bool Http2DecoderAdapter::HasRequiredStreamIdZero(uint32_t stream_id) {
916 DVLOG(3) << "HasRequiredStreamIdZero: " << stream_id;
917 if (HasError()) {
918 VLOG(2) << "HasError()";
919 return false;
920 }
921 if (stream_id == 0) {
922 return true;
923 }
924 VLOG(1) << "Stream Id was not zero, as required: " << stream_id;
925 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID);
926 return false;
927}
928
929bool Http2DecoderAdapter::HasRequiredStreamIdZero(
930 const Http2FrameHeader& header) {
931 return HasRequiredStreamIdZero(header.stream_id);
932}
933
934void Http2DecoderAdapter::ReportReceiveCompressedFrame(
935 const Http2FrameHeader& header) {
936 if (debug_visitor() != nullptr) {
937 size_t total = header.payload_length + Http2FrameHeader::EncodedSize();
938 debug_visitor()->OnReceiveCompressedFrame(
939 header.stream_id, ToSpdyFrameType(header.type), total);
940 }
941}
942
943HpackDecoderAdapter* Http2DecoderAdapter::GetHpackDecoder() {
944 if (hpack_decoder_ == nullptr) {
945 hpack_decoder_ = SpdyMakeUnique<HpackDecoderAdapter>();
946 }
947 return hpack_decoder_.get();
948}
949
950void Http2DecoderAdapter::CommonStartHpackBlock() {
951 DVLOG(1) << "CommonStartHpackBlock";
952 DCHECK(!has_hpack_first_frame_header_);
953 if (!frame_header_.IsEndHeaders()) {
954 hpack_first_frame_header_ = frame_header_;
955 has_hpack_first_frame_header_ = true;
956 } else {
957 CorruptFrameHeader(&hpack_first_frame_header_);
958 }
959 on_hpack_fragment_called_ = false;
960 SpdyHeadersHandlerInterface* handler =
961 visitor()->OnHeaderFrameStart(stream_id());
962 if (handler == nullptr) {
963 SPDY_BUG << "visitor_->OnHeaderFrameStart returned nullptr";
964 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INTERNAL_FRAMER_ERROR);
965 return;
966 }
967 GetHpackDecoder()->HandleControlFrameHeadersStart(handler);
968}
969
970// SpdyFramer calls HandleControlFrameHeadersData even if there are zero
971// fragment bytes in the first frame, so do the same.
972void Http2DecoderAdapter::MaybeAnnounceEmptyFirstHpackFragment() {
973 if (!on_hpack_fragment_called_) {
974 OnHpackFragment(nullptr, 0);
975 DCHECK(on_hpack_fragment_called_);
976 }
977}
978
979void Http2DecoderAdapter::CommonHpackFragmentEnd() {
980 DVLOG(1) << "CommonHpackFragmentEnd: stream_id=" << stream_id();
981 if (HasError()) {
982 VLOG(1) << "HasError(), returning";
983 return;
984 }
985 DCHECK(has_frame_header_);
986 MaybeAnnounceEmptyFirstHpackFragment();
987 if (frame_header_.IsEndHeaders()) {
988 DCHECK_EQ(has_hpack_first_frame_header_,
989 frame_type() == Http2FrameType::CONTINUATION)
990 << frame_header();
991 has_expected_frame_type_ = false;
992 if (GetHpackDecoder()->HandleControlFrameHeadersComplete(nullptr)) {
993 visitor()->OnHeaderFrameEnd(stream_id());
994 } else {
995 SetSpdyErrorAndNotify(SpdyFramerError::SPDY_DECOMPRESS_FAILURE);
996 return;
997 }
998 const Http2FrameHeader& first = frame_type() == Http2FrameType::CONTINUATION
999 ? hpack_first_frame_header_
1000 : frame_header_;
1001 if (first.type == Http2FrameType::HEADERS && first.IsEndStream()) {
1002 visitor()->OnStreamEnd(first.stream_id);
1003 }
1004 has_hpack_first_frame_header_ = false;
1005 CorruptFrameHeader(&hpack_first_frame_header_);
1006 } else {
1007 DCHECK(has_hpack_first_frame_header_);
1008 has_expected_frame_type_ = true;
1009 expected_frame_type_ = Http2FrameType::CONTINUATION;
1010 }
1011}
1012
1013} // namespace http2
1014
1015namespace spdy {
1016
1017bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
1018 size_t len) {
1019 return true;
1020}
1021
1022} // namespace spdy