blob: 76d1f31354ea78016dbdb6b88b03757939956b16 [file] [log] [blame]
QUICHE teamfd50a402018-12-07 22:54:05 -05001// 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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "http2/hpack/decoder/hpack_whole_entry_buffer.h"
QUICHE teamfd50a402018-12-07 22:54:05 -05006
vasilvv13aa6a02020-12-03 13:02:33 -08007#include "absl/strings/str_cat.h"
QUICHE team5be974e2020-12-29 18:35:24 -05008#include "http2/platform/api/http2_estimate_memory_usage.h"
9#include "http2/platform/api/http2_flag_utils.h"
10#include "http2/platform/api/http2_flags.h"
11#include "http2/platform/api/http2_logging.h"
12#include "http2/platform/api/http2_macros.h"
13#include "http2/platform/api/http2_string_utils.h"
QUICHE teamfd50a402018-12-07 22:54:05 -050014
15namespace http2 {
16
17HpackWholeEntryBuffer::HpackWholeEntryBuffer(HpackWholeEntryListener* listener,
18 size_t max_string_size_bytes)
19 : max_string_size_bytes_(max_string_size_bytes) {
20 set_listener(listener);
21}
22HpackWholeEntryBuffer::~HpackWholeEntryBuffer() = default;
23
24void HpackWholeEntryBuffer::set_listener(HpackWholeEntryListener* listener) {
25 listener_ = HTTP2_DIE_IF_NULL(listener);
26}
27
28void HpackWholeEntryBuffer::set_max_string_size_bytes(
29 size_t max_string_size_bytes) {
30 max_string_size_bytes_ = max_string_size_bytes;
31}
32
33void HpackWholeEntryBuffer::BufferStringsIfUnbuffered() {
34 name_.BufferStringIfUnbuffered();
35 value_.BufferStringIfUnbuffered();
36}
37
38size_t HpackWholeEntryBuffer::EstimateMemoryUsage() const {
39 return Http2EstimateMemoryUsage(name_) + Http2EstimateMemoryUsage(value_);
40}
41
42void HpackWholeEntryBuffer::OnIndexedHeader(size_t index) {
QUICHE team61940b42019-03-07 23:32:27 -050043 HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnIndexedHeader: index=" << index;
QUICHE teamfd50a402018-12-07 22:54:05 -050044 listener_->OnIndexedHeader(index);
45}
46
47void HpackWholeEntryBuffer::OnStartLiteralHeader(HpackEntryType entry_type,
48 size_t maybe_name_index) {
QUICHE team61940b42019-03-07 23:32:27 -050049 HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnStartLiteralHeader: entry_type="
50 << entry_type << ", maybe_name_index=" << maybe_name_index;
QUICHE teamfd50a402018-12-07 22:54:05 -050051 entry_type_ = entry_type;
52 maybe_name_index_ = maybe_name_index;
53}
54
55void HpackWholeEntryBuffer::OnNameStart(bool huffman_encoded, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -050056 HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnNameStart: huffman_encoded="
57 << (huffman_encoded ? "true" : "false") << ", len=" << len;
vasilvvafcc3172021-02-02 12:01:07 -080058 QUICHE_DCHECK_EQ(maybe_name_index_, 0u);
QUICHE teamfd50a402018-12-07 22:54:05 -050059 if (!error_detected_) {
60 if (len > max_string_size_bytes_) {
QUICHE team61940b42019-03-07 23:32:27 -050061 HTTP2_DVLOG(1) << "Name length (" << len << ") is longer than permitted ("
62 << max_string_size_bytes_ << ")";
fayang80366682020-07-24 09:19:11 -070063 ReportError(HpackDecodingError::kNameTooLong, "");
bnc1c3e2192020-01-30 08:38:24 -080064 HTTP2_CODE_COUNT_N(decompress_failure_3, 18, 23);
QUICHE teamfd50a402018-12-07 22:54:05 -050065 return;
66 }
67 name_.OnStart(huffman_encoded, len);
68 }
69}
70
71void HpackWholeEntryBuffer::OnNameData(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -050072 HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnNameData: len=" << len
73 << " data:\n"
vasilvvb16f7962020-10-13 10:48:38 -070074 << Http2HexDump(absl::string_view(data, len));
vasilvvafcc3172021-02-02 12:01:07 -080075 QUICHE_DCHECK_EQ(maybe_name_index_, 0u);
QUICHE teamfd50a402018-12-07 22:54:05 -050076 if (!error_detected_ && !name_.OnData(data, len)) {
fayang80366682020-07-24 09:19:11 -070077 ReportError(HpackDecodingError::kNameHuffmanError, "");
bnc1c3e2192020-01-30 08:38:24 -080078 HTTP2_CODE_COUNT_N(decompress_failure_3, 19, 23);
QUICHE teamfd50a402018-12-07 22:54:05 -050079 }
80}
81
82void HpackWholeEntryBuffer::OnNameEnd() {
QUICHE team61940b42019-03-07 23:32:27 -050083 HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnNameEnd";
vasilvvafcc3172021-02-02 12:01:07 -080084 QUICHE_DCHECK_EQ(maybe_name_index_, 0u);
QUICHE teamfd50a402018-12-07 22:54:05 -050085 if (!error_detected_ && !name_.OnEnd()) {
fayang80366682020-07-24 09:19:11 -070086 ReportError(HpackDecodingError::kNameHuffmanError, "");
bnc1c3e2192020-01-30 08:38:24 -080087 HTTP2_CODE_COUNT_N(decompress_failure_3, 20, 23);
QUICHE teamfd50a402018-12-07 22:54:05 -050088 }
89}
90
91void HpackWholeEntryBuffer::OnValueStart(bool huffman_encoded, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -050092 HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnValueStart: huffman_encoded="
93 << (huffman_encoded ? "true" : "false") << ", len=" << len;
QUICHE teamfd50a402018-12-07 22:54:05 -050094 if (!error_detected_) {
95 if (len > max_string_size_bytes_) {
vasilvv13aa6a02020-12-03 13:02:33 -080096 std::string detailed_error = absl::StrCat(
fayangf68be2c2020-07-29 06:53:59 -070097 "Value length (", len, ") of [", name_.GetStringIfComplete(),
fayang80366682020-07-24 09:19:11 -070098 "] is longer than permitted (", max_string_size_bytes_, ")");
99 HTTP2_DVLOG(1) << detailed_error;
100 ReportError(HpackDecodingError::kValueTooLong, detailed_error);
bnc1c3e2192020-01-30 08:38:24 -0800101 HTTP2_CODE_COUNT_N(decompress_failure_3, 21, 23);
QUICHE teamfd50a402018-12-07 22:54:05 -0500102 return;
103 }
104 value_.OnStart(huffman_encoded, len);
105 }
106}
107
108void HpackWholeEntryBuffer::OnValueData(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500109 HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnValueData: len=" << len
110 << " data:\n"
vasilvvb16f7962020-10-13 10:48:38 -0700111 << Http2HexDump(absl::string_view(data, len));
QUICHE teamfd50a402018-12-07 22:54:05 -0500112 if (!error_detected_ && !value_.OnData(data, len)) {
fayang80366682020-07-24 09:19:11 -0700113 ReportError(HpackDecodingError::kValueHuffmanError, "");
bnc1c3e2192020-01-30 08:38:24 -0800114 HTTP2_CODE_COUNT_N(decompress_failure_3, 22, 23);
QUICHE teamfd50a402018-12-07 22:54:05 -0500115 }
116}
117
118void HpackWholeEntryBuffer::OnValueEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500119 HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnValueEnd";
QUICHE teamfd50a402018-12-07 22:54:05 -0500120 if (error_detected_) {
121 return;
122 }
123 if (!value_.OnEnd()) {
fayang80366682020-07-24 09:19:11 -0700124 ReportError(HpackDecodingError::kValueHuffmanError, "");
bnc1c3e2192020-01-30 08:38:24 -0800125 HTTP2_CODE_COUNT_N(decompress_failure_3, 23, 23);
QUICHE teamfd50a402018-12-07 22:54:05 -0500126 return;
127 }
128 if (maybe_name_index_ == 0) {
129 listener_->OnLiteralNameAndValue(entry_type_, &name_, &value_);
130 name_.Reset();
131 } else {
132 listener_->OnNameIndexAndLiteralValue(entry_type_, maybe_name_index_,
133 &value_);
134 }
135 value_.Reset();
136}
137
138void HpackWholeEntryBuffer::OnDynamicTableSizeUpdate(size_t size) {
QUICHE team61940b42019-03-07 23:32:27 -0500139 HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnDynamicTableSizeUpdate: size="
140 << size;
QUICHE teamfd50a402018-12-07 22:54:05 -0500141 listener_->OnDynamicTableSizeUpdate(size);
142}
143
fayang80366682020-07-24 09:19:11 -0700144void HpackWholeEntryBuffer::ReportError(HpackDecodingError error,
145 std::string detailed_error) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500146 if (!error_detected_) {
bnc0ac0f722020-02-07 07:23:09 -0800147 HTTP2_DVLOG(1) << "HpackWholeEntryBuffer::ReportError: "
148 << HpackDecodingErrorToString(error);
QUICHE teamfd50a402018-12-07 22:54:05 -0500149 error_detected_ = true;
fayang80366682020-07-24 09:19:11 -0700150 listener_->OnHpackDecodeError(error, detailed_error);
QUICHE teamfd50a402018-12-07 22:54:05 -0500151 listener_ = HpackWholeEntryNoOpListener::NoOpListener();
152 }
153}
154
155} // namespace http2