Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(784)

Side by Side Diff: net/spdy/http2_frame_decoder_adapter.cc

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

Powered by Google App Engine
This is Rietveld 408576698