• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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