| Index: net/http2/decoder/frame_decoder_state.cc
 | 
| diff --git a/net/http2/decoder/frame_decoder_state.cc b/net/http2/decoder/frame_decoder_state.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..e2b44066056db4107fbb068abac2504b841e9a1f
 | 
| --- /dev/null
 | 
| +++ b/net/http2/decoder/frame_decoder_state.cc
 | 
| @@ -0,0 +1,81 @@
 | 
| +// Copyright 2016 The Chromium Authors. All rights reserved.
 | 
| +// Use of this source code is governed by a BSD-style license that can be
 | 
| +// found in the LICENSE file.
 | 
| +
 | 
| +#include "net/http2/decoder/frame_decoder_state.h"
 | 
| +
 | 
| +namespace net {
 | 
| +
 | 
| +DecodeStatus FrameDecoderState::ReadPadLength(DecodeBuffer* db,
 | 
| +                                              bool report_pad_length) {
 | 
| +  DVLOG(2) << "ReadPadLength db->Remaining=" << db->Remaining()
 | 
| +           << "; payload_length=" << frame_header().payload_length;
 | 
| +  DCHECK(IsPaddable());
 | 
| +  DCHECK(frame_header().IsPadded());
 | 
| +
 | 
| +  // Pad Length is always at the start of the frame, so remaining_payload_
 | 
| +  // should equal payload_length at this point.
 | 
| +  const uint32_t total_payload = frame_header().payload_length;
 | 
| +  DCHECK_EQ(total_payload, remaining_payload_);
 | 
| +  DCHECK_EQ(0u, remaining_padding_);
 | 
| +
 | 
| +  if (db->HasData()) {
 | 
| +    const uint32_t pad_length = db->DecodeUInt8();
 | 
| +    const uint32_t total_padding = pad_length + 1;
 | 
| +    if (total_padding <= total_payload) {
 | 
| +      remaining_padding_ = pad_length;
 | 
| +      remaining_payload_ = total_payload - total_padding;
 | 
| +      if (report_pad_length) {
 | 
| +        listener()->OnPadLength(pad_length);
 | 
| +      }
 | 
| +      return DecodeStatus::kDecodeDone;
 | 
| +    }
 | 
| +    const uint32_t missing_length = total_padding - total_payload;
 | 
| +    // To allow for the possibility of recovery, record the number of
 | 
| +    // remaining bytes of the frame's payload (invalid though it is)
 | 
| +    // in remaining_payload_.
 | 
| +    remaining_payload_ = total_payload - 1;  // 1 for sizeof(Pad Length).
 | 
| +    remaining_padding_ = 0;
 | 
| +    listener()->OnPaddingTooLong(frame_header(), missing_length);
 | 
| +    return DecodeStatus::kDecodeError;
 | 
| +  }
 | 
| +
 | 
| +  if (total_payload == 0) {
 | 
| +    remaining_payload_ = 0;
 | 
| +    remaining_padding_ = 0;
 | 
| +    listener()->OnPaddingTooLong(frame_header(), 1);
 | 
| +    return DecodeStatus::kDecodeError;
 | 
| +  }
 | 
| +  // Need to wait for another buffer.
 | 
| +  return DecodeStatus::kDecodeInProgress;
 | 
| +}
 | 
| +
 | 
| +bool FrameDecoderState::SkipPadding(DecodeBuffer* db) {
 | 
| +  DVLOG(2) << "SkipPadding remaining_padding_=" << remaining_padding_
 | 
| +           << ", db->Remaining=" << db->Remaining()
 | 
| +           << ", header: " << frame_header();
 | 
| +  DCHECK_EQ(remaining_payload_, 0u);
 | 
| +  DCHECK(IsPaddable()) << "header: " << frame_header();
 | 
| +  DCHECK_GE(remaining_padding_, 0u);
 | 
| +  DCHECK(remaining_padding_ == 0 || frame_header().IsPadded())
 | 
| +      << "remaining_padding_=" << remaining_padding_
 | 
| +      << ", header: " << frame_header();
 | 
| +  const size_t avail = AvailablePadding(db);
 | 
| +  if (avail > 0) {
 | 
| +    listener()->OnPadding(db->cursor(), avail);
 | 
| +    db->AdvanceCursor(avail);
 | 
| +    remaining_padding_ -= avail;
 | 
| +  }
 | 
| +  return remaining_padding_ == 0;
 | 
| +}
 | 
| +
 | 
| +DecodeStatus FrameDecoderState::ReportFrameSizeError() {
 | 
| +  DVLOG(2) << "FrameDecoderState::ReportFrameSizeError: "
 | 
| +           << " remaining_payload_=" << remaining_payload_
 | 
| +           << "; remaining_padding_=" << remaining_padding_
 | 
| +           << ", header: " << frame_header();
 | 
| +  listener()->OnFrameSizeError(frame_header());
 | 
| +  return DecodeStatus::kDecodeError;
 | 
| +}
 | 
| +
 | 
| +}  // namespace net
 | 
| 
 |