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