| // 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" |
| #include "quiche/quic/platform/api/quic_flags.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(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 |