// Copyright (c) 2019 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 "quiche/quic/core/qpack/qpack_decoded_headers_accumulator.h"

#include "absl/strings/string_view.h"
#include "quiche/quic/core/qpack/qpack_decoder.h"
#include "quiche/quic/core/qpack/qpack_header_table.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"

namespace quic {

QpackDecodedHeadersAccumulator::QpackDecodedHeadersAccumulator(
    QuicStreamId id, QpackDecoder* qpack_decoder, Visitor* visitor,
    size_t max_header_list_size)
    : decoder_(qpack_decoder->CreateProgressiveDecoder(id, this)),
      visitor_(visitor),
      max_header_list_size_(max_header_list_size),
      uncompressed_header_bytes_including_overhead_(0),
      uncompressed_header_bytes_without_overhead_(0),
      compressed_header_bytes_(0),
      header_list_size_limit_exceeded_(false),
      headers_decoded_(false),
      error_detected_(false) {
  quic_header_list_.OnHeaderBlockStart();
}

void QpackDecodedHeadersAccumulator::OnHeaderDecoded(absl::string_view name,
                                                     absl::string_view value) {
  QUICHE_DCHECK(!error_detected_);

  uncompressed_header_bytes_without_overhead_ += name.size() + value.size();

  if (header_list_size_limit_exceeded_) {
    return;
  }

  uncompressed_header_bytes_including_overhead_ +=
      name.size() + value.size() + kQpackEntrySizeOverhead;

  const size_t uncompressed_header_bytes =
      GetQuicFlag(FLAGS_quic_header_size_limit_includes_overhead)
          ? uncompressed_header_bytes_including_overhead_
          : uncompressed_header_bytes_without_overhead_;
  if (uncompressed_header_bytes > max_header_list_size_) {
    header_list_size_limit_exceeded_ = true;
    quic_header_list_.Clear();
  } else {
    quic_header_list_.OnHeader(name, value);
  }
}

void QpackDecodedHeadersAccumulator::OnDecodingCompleted() {
  QUICHE_DCHECK(!headers_decoded_);
  QUICHE_DCHECK(!error_detected_);

  headers_decoded_ = true;

  quic_header_list_.OnHeaderBlockEnd(
      uncompressed_header_bytes_without_overhead_, compressed_header_bytes_);

  // Might destroy |this|.
  visitor_->OnHeadersDecoded(std::move(quic_header_list_),
                             header_list_size_limit_exceeded_);
}

void QpackDecodedHeadersAccumulator::OnDecodingErrorDetected(
    QuicErrorCode error_code, absl::string_view error_message) {
  QUICHE_DCHECK(!error_detected_);
  QUICHE_DCHECK(!headers_decoded_);

  error_detected_ = true;
  // Might destroy |this|.
  visitor_->OnHeaderDecodingError(error_code, error_message);
}

void QpackDecodedHeadersAccumulator::Decode(absl::string_view data) {
  QUICHE_DCHECK(!error_detected_);

  compressed_header_bytes_ += data.size();
  // Might destroy |this|.
  decoder_->Decode(data);
}

void QpackDecodedHeadersAccumulator::EndHeaderBlock() {
  QUICHE_DCHECK(!error_detected_);
  QUICHE_DCHECK(!headers_decoded_);

  if (!decoder_) {
    QUIC_BUG(b215142466_EndHeaderBlock);
    return;
  }

  // Might destroy |this|.
  decoder_->EndHeaderBlock();
}

}  // namespace quic
