QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 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/third_party/quiche/src/http2/decoder/frame_decoder_state.h" |
| 6 | |
| 7 | namespace http2 { |
| 8 | |
| 9 | DecodeStatus FrameDecoderState::ReadPadLength(DecodeBuffer* db, |
| 10 | bool report_pad_length) { |
QUICHE team | 61940b4 | 2019-03-07 23:32:27 -0500 | [diff] [blame] | 11 | HTTP2_DVLOG(2) << "ReadPadLength db->Remaining=" << db->Remaining() |
| 12 | << "; payload_length=" << frame_header().payload_length; |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 13 | DCHECK(IsPaddable()); |
| 14 | DCHECK(frame_header().IsPadded()); |
| 15 | |
| 16 | // Pad Length is always at the start of the frame, so remaining_payload_ |
| 17 | // should equal payload_length at this point. |
| 18 | const uint32_t total_payload = frame_header().payload_length; |
| 19 | DCHECK_EQ(total_payload, remaining_payload_); |
| 20 | DCHECK_EQ(0u, remaining_padding_); |
| 21 | |
| 22 | if (db->HasData()) { |
| 23 | const uint32_t pad_length = db->DecodeUInt8(); |
| 24 | const uint32_t total_padding = pad_length + 1; |
| 25 | if (total_padding <= total_payload) { |
| 26 | remaining_padding_ = pad_length; |
| 27 | remaining_payload_ = total_payload - total_padding; |
| 28 | if (report_pad_length) { |
| 29 | listener()->OnPadLength(pad_length); |
| 30 | } |
| 31 | return DecodeStatus::kDecodeDone; |
| 32 | } |
| 33 | const uint32_t missing_length = total_padding - total_payload; |
| 34 | // To allow for the possibility of recovery, record the number of |
| 35 | // remaining bytes of the frame's payload (invalid though it is) |
| 36 | // in remaining_payload_. |
| 37 | remaining_payload_ = total_payload - 1; // 1 for sizeof(Pad Length). |
| 38 | remaining_padding_ = 0; |
| 39 | listener()->OnPaddingTooLong(frame_header(), missing_length); |
| 40 | return DecodeStatus::kDecodeError; |
| 41 | } |
| 42 | |
| 43 | if (total_payload == 0) { |
| 44 | remaining_payload_ = 0; |
| 45 | remaining_padding_ = 0; |
| 46 | listener()->OnPaddingTooLong(frame_header(), 1); |
| 47 | return DecodeStatus::kDecodeError; |
| 48 | } |
| 49 | // Need to wait for another buffer. |
| 50 | return DecodeStatus::kDecodeInProgress; |
| 51 | } |
| 52 | |
| 53 | bool FrameDecoderState::SkipPadding(DecodeBuffer* db) { |
QUICHE team | 61940b4 | 2019-03-07 23:32:27 -0500 | [diff] [blame] | 54 | HTTP2_DVLOG(2) << "SkipPadding remaining_padding_=" << remaining_padding_ |
| 55 | << ", db->Remaining=" << db->Remaining() |
| 56 | << ", header: " << frame_header(); |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 57 | DCHECK_EQ(remaining_payload_, 0u); |
| 58 | DCHECK(IsPaddable()) << "header: " << frame_header(); |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 59 | DCHECK(remaining_padding_ == 0 || frame_header().IsPadded()) |
| 60 | << "remaining_padding_=" << remaining_padding_ |
| 61 | << ", header: " << frame_header(); |
| 62 | const size_t avail = AvailablePadding(db); |
| 63 | if (avail > 0) { |
| 64 | listener()->OnPadding(db->cursor(), avail); |
| 65 | db->AdvanceCursor(avail); |
| 66 | remaining_padding_ -= avail; |
| 67 | } |
| 68 | return remaining_padding_ == 0; |
| 69 | } |
| 70 | |
| 71 | DecodeStatus FrameDecoderState::ReportFrameSizeError() { |
QUICHE team | 61940b4 | 2019-03-07 23:32:27 -0500 | [diff] [blame] | 72 | HTTP2_DVLOG(2) << "FrameDecoderState::ReportFrameSizeError: " |
| 73 | << " remaining_payload_=" << remaining_payload_ |
| 74 | << "; remaining_padding_=" << remaining_padding_ |
| 75 | << ", header: " << frame_header(); |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 76 | listener()->OnFrameSizeError(frame_header()); |
| 77 | return DecodeStatus::kDecodeError; |
| 78 | } |
| 79 | |
| 80 | } // namespace http2 |