blob: b9926167126939924ce9bd2339b0dd615346d172 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2018 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 "quic/core/qpack/qpack_decoder.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05006
bnc463f2352019-10-10 04:49:34 -07007#include <utility>
8
vasilvv7cac7b02020-10-08 12:32:10 -07009#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -050010#include "quic/core/qpack/qpack_index_conversions.h"
11#include "quic/platform/api/quic_flag_utils.h"
12#include "quic/platform/api/quic_flags.h"
13#include "quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050014
15namespace quic {
16
17QpackDecoder::QpackDecoder(
bnc4c664c52019-08-04 18:14:12 -070018 uint64_t maximum_dynamic_table_capacity,
bnc57b5f622019-08-21 14:07:44 -070019 uint64_t maximum_blocked_streams,
renjietang8a2df8f2019-08-07 10:43:52 -070020 EncoderStreamErrorDelegate* encoder_stream_error_delegate)
QUICHE teama6ef0a62019-03-07 20:34:33 -050021 : encoder_stream_error_delegate_(encoder_stream_error_delegate),
bnc57b5f622019-08-21 14:07:44 -070022 encoder_stream_receiver_(this),
bnc45af7512019-10-08 06:59:58 -070023 maximum_blocked_streams_(maximum_blocked_streams),
24 known_received_count_(0) {
vasilvvf8035162021-02-01 14:49:14 -080025 QUICHE_DCHECK(encoder_stream_error_delegate_);
bnc4c664c52019-08-04 18:14:12 -070026
27 header_table_.SetMaximumDynamicTableCapacity(maximum_dynamic_table_capacity);
QUICHE teama6ef0a62019-03-07 20:34:33 -050028}
29
30QpackDecoder::~QpackDecoder() {}
31
QUICHE teama6ef0a62019-03-07 20:34:33 -050032void QpackDecoder::OnStreamReset(QuicStreamId stream_id) {
bnc6f18a822019-11-27 17:50:38 -080033 if (header_table_.maximum_dynamic_table_capacity() > 0) {
34 decoder_stream_sender_.SendStreamCancellation(stream_id);
35 decoder_stream_sender_.Flush();
36 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050037}
38
bnc57b5f622019-08-21 14:07:44 -070039bool QpackDecoder::OnStreamBlocked(QuicStreamId stream_id) {
40 auto result = blocked_streams_.insert(stream_id);
vasilvvf8035162021-02-01 14:49:14 -080041 QUICHE_DCHECK(result.second);
bnc57b5f622019-08-21 14:07:44 -070042 return blocked_streams_.size() <= maximum_blocked_streams_;
43}
44
45void QpackDecoder::OnStreamUnblocked(QuicStreamId stream_id) {
46 size_t result = blocked_streams_.erase(stream_id);
vasilvvf8035162021-02-01 14:49:14 -080047 QUICHE_DCHECK_EQ(1u, result);
bnc57b5f622019-08-21 14:07:44 -070048}
49
bnc45af7512019-10-08 06:59:58 -070050void QpackDecoder::OnDecodingCompleted(QuicStreamId stream_id,
51 uint64_t required_insert_count) {
52 if (required_insert_count > 0) {
53 decoder_stream_sender_.SendHeaderAcknowledgement(stream_id);
54
55 if (known_received_count_ < required_insert_count) {
56 known_received_count_ = required_insert_count;
57 }
58 }
59
60 // Send an Insert Count Increment instruction if not all dynamic table entries
61 // have been acknowledged yet. This is necessary for efficient compression in
62 // case the encoder chooses not to reference unacknowledged dynamic table
63 // entries, otherwise inserted entries would never be acknowledged.
64 if (known_received_count_ < header_table_.inserted_entry_count()) {
65 decoder_stream_sender_.SendInsertCountIncrement(
66 header_table_.inserted_entry_count() - known_received_count_);
67 known_received_count_ = header_table_.inserted_entry_count();
68 }
bnc6b1fc8a2019-10-11 17:17:14 -070069
70 decoder_stream_sender_.Flush();
bnc45af7512019-10-08 06:59:58 -070071}
72
QUICHE teama6ef0a62019-03-07 20:34:33 -050073void QpackDecoder::OnInsertWithNameReference(bool is_static,
74 uint64_t name_index,
vasilvv7cac7b02020-10-08 12:32:10 -070075 absl::string_view value) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050076 if (is_static) {
77 auto entry = header_table_.LookupEntry(/* is_static = */ true, name_index);
78 if (!entry) {
bnc4e440102020-10-20 17:32:29 -070079 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INVALID_STATIC_ENTRY,
bnc34a26802020-10-17 05:09:54 -070080 "Invalid static table entry.");
QUICHE teama6ef0a62019-03-07 20:34:33 -050081 return;
82 }
83
bncc45c9762021-03-15 12:17:35 -070084 if (!header_table_.EntryFitsDynamicTableCapacity(entry->name(), value)) {
bnc4e440102020-10-20 17:32:29 -070085 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_ERROR_INSERTING_STATIC,
bnc34a26802020-10-17 05:09:54 -070086 "Error inserting entry with name reference.");
bncc45c9762021-03-15 12:17:35 -070087 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -050088 }
bncc45c9762021-03-15 12:17:35 -070089 header_table_.InsertEntry(entry->name(), value);
QUICHE teama6ef0a62019-03-07 20:34:33 -050090 return;
91 }
92
93 uint64_t absolute_index;
bnccd5ec3c2019-08-14 13:50:46 -070094 if (!QpackEncoderStreamRelativeIndexToAbsoluteIndex(
95 name_index, header_table_.inserted_entry_count(), &absolute_index)) {
bnc4e440102020-10-20 17:32:29 -070096 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INSERTION_INVALID_RELATIVE_INDEX,
97 "Invalid relative index.");
QUICHE teama6ef0a62019-03-07 20:34:33 -050098 return;
99 }
100
101 const QpackEntry* entry =
102 header_table_.LookupEntry(/* is_static = */ false, absolute_index);
103 if (!entry) {
bnc4e440102020-10-20 17:32:29 -0700104 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INSERTION_DYNAMIC_ENTRY_NOT_FOUND,
bnc34a26802020-10-17 05:09:54 -0700105 "Dynamic table entry not found.");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500106 return;
107 }
bncc45c9762021-03-15 12:17:35 -0700108 if (!header_table_.EntryFitsDynamicTableCapacity(entry->name(), value)) {
bnc4e440102020-10-20 17:32:29 -0700109 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_ERROR_INSERTING_DYNAMIC,
bnc34a26802020-10-17 05:09:54 -0700110 "Error inserting entry with name reference.");
bncc45c9762021-03-15 12:17:35 -0700111 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500112 }
bncc45c9762021-03-15 12:17:35 -0700113 header_table_.InsertEntry(entry->name(), value);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500114}
115
vasilvv7cac7b02020-10-08 12:32:10 -0700116void QpackDecoder::OnInsertWithoutNameReference(absl::string_view name,
117 absl::string_view value) {
bncc45c9762021-03-15 12:17:35 -0700118 if (!header_table_.EntryFitsDynamicTableCapacity(name, value)) {
bnc4e440102020-10-20 17:32:29 -0700119 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_ERROR_INSERTING_LITERAL,
bnc34a26802020-10-17 05:09:54 -0700120 "Error inserting literal entry.");
bncc45c9762021-03-15 12:17:35 -0700121 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500122 }
bncc45c9762021-03-15 12:17:35 -0700123 header_table_.InsertEntry(name, value);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500124}
125
126void QpackDecoder::OnDuplicate(uint64_t index) {
127 uint64_t absolute_index;
bnccd5ec3c2019-08-14 13:50:46 -0700128 if (!QpackEncoderStreamRelativeIndexToAbsoluteIndex(
129 index, header_table_.inserted_entry_count(), &absolute_index)) {
bnc4e440102020-10-20 17:32:29 -0700130 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_DUPLICATE_INVALID_RELATIVE_INDEX,
131 "Invalid relative index.");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500132 return;
133 }
134
135 const QpackEntry* entry =
136 header_table_.LookupEntry(/* is_static = */ false, absolute_index);
137 if (!entry) {
bnc4e440102020-10-20 17:32:29 -0700138 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_DUPLICATE_DYNAMIC_ENTRY_NOT_FOUND,
bnc34a26802020-10-17 05:09:54 -0700139 "Dynamic table entry not found.");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500140 return;
141 }
bncc45c9762021-03-15 12:17:35 -0700142 if (!header_table_.EntryFitsDynamicTableCapacity(entry->name(),
143 entry->value())) {
144 // This is impossible since entry was retrieved from the dynamic table.
bnc4e440102020-10-20 17:32:29 -0700145 OnErrorDetected(QUIC_INTERNAL_ERROR, "Error inserting duplicate entry.");
bncc45c9762021-03-15 12:17:35 -0700146 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500147 }
bncc45c9762021-03-15 12:17:35 -0700148 header_table_.InsertEntry(entry->name(), entry->value());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500149}
150
151void QpackDecoder::OnSetDynamicTableCapacity(uint64_t capacity) {
152 if (!header_table_.SetDynamicTableCapacity(capacity)) {
bnc4e440102020-10-20 17:32:29 -0700153 OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_SET_DYNAMIC_TABLE_CAPACITY,
bnc34a26802020-10-17 05:09:54 -0700154 "Error updating dynamic table capacity.");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500155 }
156}
157
bnc4e440102020-10-20 17:32:29 -0700158void QpackDecoder::OnErrorDetected(QuicErrorCode error_code,
bnc34a26802020-10-17 05:09:54 -0700159 absl::string_view error_message) {
bnc1fe972f2021-01-28 09:24:49 -0800160 encoder_stream_error_delegate_->OnEncoderStreamError(error_code,
161 error_message);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500162}
163
bnca904b052019-06-11 11:34:38 -0700164std::unique_ptr<QpackProgressiveDecoder> QpackDecoder::CreateProgressiveDecoder(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500165 QuicStreamId stream_id,
166 QpackProgressiveDecoder::HeadersHandlerInterface* handler) {
bnc45af7512019-10-08 06:59:58 -0700167 return std::make_unique<QpackProgressiveDecoder>(stream_id, this, this,
168 &header_table_, handler);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500169}
170
171} // namespace quic