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