| Index: net/spdy/hpack/hpack_decoder2.cc
|
| diff --git a/net/spdy/hpack/hpack_decoder2.cc b/net/spdy/hpack/hpack_decoder2.cc
|
| deleted file mode 100644
|
| index 14ff94e990f38afd6bee7c271f251cf73c5c81a7..0000000000000000000000000000000000000000
|
| --- a/net/spdy/hpack/hpack_decoder2.cc
|
| +++ /dev/null
|
| @@ -1,337 +0,0 @@
|
| -// 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/spdy/hpack/hpack_decoder2.h"
|
| -
|
| -#include <list>
|
| -#include <utility>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/strings/string_piece.h"
|
| -#include "net/http2/decoder/decode_buffer.h"
|
| -#include "net/http2/decoder/decode_status.h"
|
| -#include "net/spdy/hpack/hpack_entry.h"
|
| -#include "net/spdy/platform/api/spdy_estimate_memory_usage.h"
|
| -
|
| -using base::StringPiece;
|
| -
|
| -namespace net {
|
| -
|
| -HpackDecoder2::HpackDecoder2() : hpack_block_decoder_(this) {
|
| - Reset();
|
| -}
|
| -
|
| -HpackDecoder2::~HpackDecoder2() {}
|
| -
|
| -void HpackDecoder2::Reset() {
|
| - DVLOG(2) << "HpackDecoder2::Reset";
|
| - handler_ = nullptr;
|
| -
|
| - hpack_block_decoder_.Reset();
|
| - hpack_block_decoder_.set_listener(this);
|
| -
|
| - total_hpack_bytes_ = 0;
|
| - total_header_bytes_ = 0;
|
| - size_update_count_ = 0;
|
| - header_seen_ = false;
|
| - in_progress_ = false;
|
| - error_detected_ = false;
|
| - header_block_started_ = false;
|
| -
|
| - name_.Reset();
|
| - value_.Reset();
|
| -}
|
| -
|
| -void HpackDecoder2::SetErrorDetected() {
|
| - if (!error_detected_) {
|
| - DVLOG(2) << "HpackDecoder2::SetErrorDetected";
|
| - hpack_block_decoder_.set_listener(&no_op_listener_);
|
| - error_detected_ = true;
|
| - }
|
| -}
|
| -
|
| -void HpackDecoder2::ApplyHeaderTableSizeSetting(size_t size_setting) {
|
| - DVLOG(2) << "HpackDecoder2::ApplyHeaderTableSizeSetting";
|
| - header_table_.SetSettingsHeaderTableSize(size_setting);
|
| -}
|
| -
|
| -// If a SpdyHeadersHandlerInterface is provided, the decoder will emit
|
| -// headers to it rather than accumulating them in a SpdyHeaderBlock.
|
| -void HpackDecoder2::HandleControlFrameHeadersStart(
|
| - SpdyHeadersHandlerInterface* handler) {
|
| - DVLOG(2) << "HpackDecoder2::HandleControlFrameHeadersStart";
|
| - DCHECK(!header_block_started_);
|
| - handler_ = handler;
|
| -}
|
| -
|
| -// Called as HPACK block fragments arrive. Returns false
|
| -// if an error occurred while decoding the block.
|
| -bool HpackDecoder2::HandleControlFrameHeadersData(const char* headers_data,
|
| - size_t headers_data_length) {
|
| - DVLOG(2) << "HpackDecoder2::HandleControlFrameHeadersData: len="
|
| - << headers_data_length;
|
| - if (!header_block_started_) {
|
| - DCHECK_EQ(total_hpack_bytes_, 0u);
|
| - // Clear the SpdyHeaderBlock here rather than in Reset so that it is NOT
|
| - // cleared in HandleControlFrameHeadersComplete, which would be before it
|
| - // could be used.
|
| - decoded_block_.clear();
|
| - header_block_started_ = true;
|
| - if (handler_ != nullptr) {
|
| - handler_->OnHeaderBlockStart();
|
| - }
|
| - }
|
| -
|
| - // Sometimes we get a call with headers_data==nullptr and
|
| - // headers_data_length==0, in which case we need to avoid creating
|
| - // a DecodeBuffer, which would otherwise complain.
|
| - if (headers_data_length > 0) {
|
| - DCHECK_NE(headers_data, nullptr);
|
| - total_hpack_bytes_ += headers_data_length;
|
| - DecodeBuffer db(headers_data, headers_data_length);
|
| - DecodeStatus status = hpack_block_decoder_.Decode(&db);
|
| - switch (status) {
|
| - case DecodeStatus::kDecodeDone:
|
| - // We've completed the decoding of headers_data, and it ended at the
|
| - // boundary between two HPACK block entries, so name_ and value_ are
|
| - // currently reset.
|
| - DCHECK_EQ(0u, db.Remaining());
|
| - in_progress_ = false;
|
| - break;
|
| -
|
| - case DecodeStatus::kDecodeInProgress:
|
| - DCHECK_EQ(0u, db.Remaining());
|
| - in_progress_ = true;
|
| - if (!error_detected_) {
|
| - name_.BufferStringIfUnbuffered();
|
| - value_.BufferStringIfUnbuffered();
|
| - EnforceMaxDecodeBufferSize();
|
| - }
|
| - break;
|
| -
|
| - case DecodeStatus::kDecodeError:
|
| - SetErrorDetected();
|
| - break;
|
| - }
|
| - }
|
| - return !error_detected_;
|
| -}
|
| -
|
| -// Called after a HPACK block has been completely delivered via
|
| -// HandleControlFrameHeadersData(). Returns false if an error occurred.
|
| -// |compressed_len| if non-null will be set to the size of the encoded
|
| -// buffered block that was accumulated in HandleControlFrameHeadersData(),
|
| -// to support subsequent calculation of compression percentage.
|
| -// Discards the handler supplied at the start of decoding the block.
|
| -// TODO(jamessynge): Determine if compressed_len is needed; it is used to
|
| -// produce UUMA stat Net.SpdyHpackDecompressionPercentage, but only for
|
| -// SPDY3, not HTTP2.
|
| -bool HpackDecoder2::HandleControlFrameHeadersComplete(size_t* compressed_len) {
|
| - DVLOG(2) << "HpackDecoder2::HandleControlFrameHeadersComplete";
|
| - if (error_detected_ || in_progress_) {
|
| - DVLOG(2) << "error_detected_=" << error_detected_
|
| - << ", in_progress_=" << in_progress_;
|
| - return false;
|
| - }
|
| - if (compressed_len != nullptr) {
|
| - *compressed_len = total_hpack_bytes_;
|
| - }
|
| - if (handler_ != nullptr) {
|
| - handler_->OnHeaderBlockEnd(total_header_bytes_);
|
| - }
|
| - Reset();
|
| - return true;
|
| -}
|
| -
|
| -const SpdyHeaderBlock& HpackDecoder2::decoded_block() const {
|
| - return decoded_block_;
|
| -}
|
| -
|
| -void HpackDecoder2::SetHeaderTableDebugVisitor(
|
| - std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
|
| - DVLOG(2) << "HpackDecoder2::SetHeaderTableDebugVisitor";
|
| - header_table_.set_debug_visitor(std::move(visitor));
|
| -}
|
| -
|
| -void HpackDecoder2::set_max_decode_buffer_size_bytes(
|
| - size_t max_decode_buffer_size_bytes) {
|
| - DVLOG(2) << "HpackDecoder2::set_max_decode_buffer_size_bytes";
|
| - max_decode_buffer_size_bytes_ = max_decode_buffer_size_bytes;
|
| -}
|
| -
|
| -size_t HpackDecoder2::EstimateMemoryUsage() const {
|
| - return SpdyEstimateMemoryUsage(header_table_) +
|
| - SpdyEstimateMemoryUsage(decoded_block_) +
|
| - SpdyEstimateMemoryUsage(name_) + SpdyEstimateMemoryUsage(value_);
|
| -}
|
| -
|
| -void HpackDecoder2::OnIndexedHeader(size_t index) {
|
| - DVLOG(2) << "HpackDecoder2::OnIndexedHeader: index=" << index;
|
| - DCHECK(!error_detected_);
|
| - const HpackEntry* entry = header_table_.GetByIndex(index);
|
| - if (entry == nullptr) {
|
| - SetErrorDetected();
|
| - return;
|
| - }
|
| - HandleHeaderRepresentation(entry->name(), entry->value());
|
| -}
|
| -
|
| -void HpackDecoder2::OnStartLiteralHeader(HpackEntryType entry_type,
|
| - size_t maybe_name_index) {
|
| - DVLOG(2) << "HpackDecoder2::OnStartLiteralHeader: entry_type=" << entry_type
|
| - << ", maybe_name_index=" << maybe_name_index;
|
| - DCHECK(!error_detected_);
|
| - entry_type_ = entry_type;
|
| - if (maybe_name_index > 0) {
|
| - const HpackEntry* entry = header_table_.GetByIndex(maybe_name_index);
|
| - if (entry == nullptr) {
|
| - SetErrorDetected();
|
| - return;
|
| - } else {
|
| - // Non-static entries could be evicted, leaving us with a dangling
|
| - // pointer, so we preemptively copy. This could be avoided if
|
| - // TryAddEntry would copy the strings prior to performing eviction.
|
| - name_.Set(entry->name(), entry->IsStatic());
|
| - name_.BufferStringIfUnbuffered();
|
| - }
|
| - }
|
| -}
|
| -
|
| -void HpackDecoder2::OnNameStart(bool huffman_encoded, size_t len) {
|
| - DVLOG(2) << "HpackDecoder2::OnNameStart: huffman_encoded="
|
| - << (huffman_encoded ? "true" : "false") << ", len=" << len;
|
| - if (len > max_decode_buffer_size_bytes_) {
|
| - DVLOG(1) << "Name length (" << len << ") is longer than permitted ("
|
| - << max_decode_buffer_size_bytes_ << ")";
|
| - SetErrorDetected();
|
| - return;
|
| - }
|
| - name_.OnStart(huffman_encoded, len);
|
| -}
|
| -
|
| -void HpackDecoder2::OnNameData(const char* data, size_t len) {
|
| - DVLOG(2) << "HpackDecoder2::OnNameData: len=" << len
|
| - << "\n data: " << StringPiece(data, len);
|
| - if (error_detected_) {
|
| - return;
|
| - }
|
| - if (!name_.OnData(data, len)) {
|
| - SetErrorDetected();
|
| - }
|
| -}
|
| -
|
| -void HpackDecoder2::OnNameEnd() {
|
| - DVLOG(2) << "HpackDecoder2::OnNameEnd";
|
| - if (error_detected_) {
|
| - return;
|
| - }
|
| - if (!name_.OnEnd()) {
|
| - SetErrorDetected();
|
| - }
|
| -}
|
| -
|
| -void HpackDecoder2::OnValueStart(bool huffman_encoded, size_t len) {
|
| - DVLOG(2) << "HpackDecoder2::OnValueStart: huffman_encoded="
|
| - << (huffman_encoded ? "true" : "false") << ", len=" << len;
|
| - if (len > max_decode_buffer_size_bytes_) {
|
| - DVLOG(1) << "Value length (" << len << ") is longer than permitted ("
|
| - << max_decode_buffer_size_bytes_ << ")";
|
| - SetErrorDetected();
|
| - return;
|
| - }
|
| - value_.OnStart(huffman_encoded, len);
|
| -}
|
| -
|
| -void HpackDecoder2::OnValueData(const char* data, size_t len) {
|
| - DVLOG(2) << "HpackDecoder2::OnValueData: len=" << len
|
| - << "\n data: " << StringPiece(data, len);
|
| - if (error_detected_) {
|
| - return;
|
| - }
|
| - if (!value_.OnData(data, len)) {
|
| - SetErrorDetected();
|
| - }
|
| -}
|
| -
|
| -void HpackDecoder2::OnValueEnd() {
|
| - DVLOG(2) << "HpackDecoder2::OnValueEnd";
|
| - if (error_detected_) {
|
| - return;
|
| - }
|
| - if (!value_.OnEnd()) {
|
| - SetErrorDetected();
|
| - return;
|
| - }
|
| - if (EnforceMaxDecodeBufferSize()) {
|
| - // All is well.
|
| - HandleHeaderRepresentation(name_.str(), value_.str());
|
| - if (entry_type_ == HpackEntryType::kIndexedLiteralHeader) {
|
| - header_table_.TryAddEntry(name_.str(), value_.str());
|
| - }
|
| - name_.Reset();
|
| - value_.Reset();
|
| - }
|
| -}
|
| -
|
| -void HpackDecoder2::OnDynamicTableSizeUpdate(size_t size) {
|
| - DVLOG(2) << "HpackDecoder2::OnDynamicTableSizeUpdate: size=" << size;
|
| - if (error_detected_) {
|
| - return;
|
| - }
|
| - if (size > header_table_.settings_size_bound()) {
|
| - DVLOG(1) << "Dynamic Table Size Update with too large a size: " << size
|
| - << " > " << header_table_.settings_size_bound();
|
| - SetErrorDetected();
|
| - return;
|
| - }
|
| - if (header_seen_) {
|
| - DVLOG(1) << "Dynamic Table Size Update seen after a Header";
|
| - SetErrorDetected();
|
| - return;
|
| - }
|
| - ++size_update_count_;
|
| - if (size_update_count_ > 2) {
|
| - DVLOG(1) << "Too many (" << size_update_count_
|
| - << ") Dynamic Table Size Updates";
|
| - SetErrorDetected();
|
| - return;
|
| - }
|
| - header_table_.SetMaxSize(size);
|
| - return;
|
| -}
|
| -
|
| -bool HpackDecoder2::EnforceMaxDecodeBufferSize() {
|
| - if (!error_detected_) {
|
| - size_t buffered_length = name_.BufferedLength() + value_.BufferedLength();
|
| - DVLOG(2) << "buffered_length=" << buffered_length
|
| - << "; max=" << max_decode_buffer_size_bytes_;
|
| - if (buffered_length > max_decode_buffer_size_bytes_) {
|
| - DVLOG(1) << "Header length (" << buffered_length
|
| - << ") is longer than permitted ("
|
| - << max_decode_buffer_size_bytes_ << ")";
|
| - SetErrorDetected();
|
| - }
|
| - }
|
| - return !error_detected_;
|
| -}
|
| -
|
| -void HpackDecoder2::HandleHeaderRepresentation(StringPiece name,
|
| - StringPiece value) {
|
| - DVLOG(2) << "HpackDecoder2::HandleHeaderRepresentation:\n name: " << name
|
| - << "\n value: " << value;
|
| - total_header_bytes_ += name.size() + value.size();
|
| - header_seen_ = true;
|
| - if (handler_ == nullptr) {
|
| - DVLOG(3) << "HpackDecoder2::HandleHeaderRepresentation "
|
| - << "adding to decoded_block";
|
| - decoded_block_.AppendValueOrAddHeader(name, value);
|
| - } else {
|
| - DVLOG(3) << "HpackDecoder2::HandleHeaderRepresentation "
|
| - << "passing to handler";
|
| - DCHECK(decoded_block_.empty());
|
| - handler_->OnHeader(name, value);
|
| - }
|
| -}
|
| -
|
| -} // namespace net
|
|
|