xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // 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 
5 #include "quiche/quic/core/qpack/qpack_decoder.h"
6 
7 #include <utility>
8 
9 #include "absl/strings/string_view.h"
10 #include "quiche/quic/core/qpack/qpack_index_conversions.h"
11 #include "quiche/quic/platform/api/quic_flag_utils.h"
12 #include "quiche/quic/platform/api/quic_flags.h"
13 #include "quiche/quic/platform/api/quic_logging.h"
14 
15 namespace quic {
16 
QpackDecoder(uint64_t maximum_dynamic_table_capacity,uint64_t maximum_blocked_streams,EncoderStreamErrorDelegate * encoder_stream_error_delegate)17 QpackDecoder::QpackDecoder(
18     uint64_t maximum_dynamic_table_capacity, uint64_t maximum_blocked_streams,
19     EncoderStreamErrorDelegate* encoder_stream_error_delegate)
20     : encoder_stream_error_delegate_(encoder_stream_error_delegate),
21       encoder_stream_receiver_(this),
22       maximum_blocked_streams_(maximum_blocked_streams),
23       known_received_count_(0) {
24   QUICHE_DCHECK(encoder_stream_error_delegate_);
25 
26   header_table_.SetMaximumDynamicTableCapacity(maximum_dynamic_table_capacity);
27 }
28 
~QpackDecoder()29 QpackDecoder::~QpackDecoder() {}
30 
OnStreamReset(QuicStreamId stream_id)31 void QpackDecoder::OnStreamReset(QuicStreamId stream_id) {
32   if (header_table_.maximum_dynamic_table_capacity() > 0) {
33     decoder_stream_sender_.SendStreamCancellation(stream_id);
34     if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
35       decoder_stream_sender_.Flush();
36     }
37   }
38 }
39 
OnStreamBlocked(QuicStreamId stream_id)40 bool QpackDecoder::OnStreamBlocked(QuicStreamId stream_id) {
41   auto result = blocked_streams_.insert(stream_id);
42   QUICHE_DCHECK(result.second);
43   return blocked_streams_.size() <= maximum_blocked_streams_;
44 }
45 
OnStreamUnblocked(QuicStreamId stream_id)46 void QpackDecoder::OnStreamUnblocked(QuicStreamId stream_id) {
47   size_t result = blocked_streams_.erase(stream_id);
48   QUICHE_DCHECK_EQ(1u, result);
49 }
50 
OnDecodingCompleted(QuicStreamId stream_id,uint64_t required_insert_count)51 void QpackDecoder::OnDecodingCompleted(QuicStreamId stream_id,
52                                        uint64_t required_insert_count) {
53   if (required_insert_count > 0) {
54     decoder_stream_sender_.SendHeaderAcknowledgement(stream_id);
55 
56     if (known_received_count_ < required_insert_count) {
57       known_received_count_ = required_insert_count;
58     }
59   }
60 
61   // Send an Insert Count Increment instruction if not all dynamic table entries
62   // have been acknowledged yet.  This is necessary for efficient compression in
63   // case the encoder chooses not to reference unacknowledged dynamic table
64   // entries, otherwise inserted entries would never be acknowledged.
65   if (known_received_count_ < header_table_.inserted_entry_count()) {
66     decoder_stream_sender_.SendInsertCountIncrement(
67         header_table_.inserted_entry_count() - known_received_count_);
68     known_received_count_ = header_table_.inserted_entry_count();
69   }
70 
71   if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data4)) {
72     decoder_stream_sender_.Flush();
73   }
74 }
75 
OnInsertWithNameReference(bool is_static,uint64_t name_index,absl::string_view value)76 void QpackDecoder::OnInsertWithNameReference(bool is_static,
77                                              uint64_t name_index,
78                                              absl::string_view value) {
79   if (is_static) {
80     auto entry = header_table_.LookupEntry(/* is_static = */ true, name_index);
81     if (!entry) {
82       OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INVALID_STATIC_ENTRY,
83                       "Invalid static table entry.");
84       return;
85     }
86 
87     if (!header_table_.EntryFitsDynamicTableCapacity(entry->name(), value)) {
88       OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_ERROR_INSERTING_STATIC,
89                       "Error inserting entry with name reference.");
90       return;
91     }
92     header_table_.InsertEntry(entry->name(), value);
93     return;
94   }
95 
96   uint64_t absolute_index;
97   if (!QpackEncoderStreamRelativeIndexToAbsoluteIndex(
98           name_index, header_table_.inserted_entry_count(), &absolute_index)) {
99     OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INSERTION_INVALID_RELATIVE_INDEX,
100                     "Invalid relative index.");
101     return;
102   }
103 
104   const QpackEntry* entry =
105       header_table_.LookupEntry(/* is_static = */ false, absolute_index);
106   if (!entry) {
107     OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_INSERTION_DYNAMIC_ENTRY_NOT_FOUND,
108                     "Dynamic table entry not found.");
109     return;
110   }
111   if (!header_table_.EntryFitsDynamicTableCapacity(entry->name(), value)) {
112     OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_ERROR_INSERTING_DYNAMIC,
113                     "Error inserting entry with name reference.");
114     return;
115   }
116   header_table_.InsertEntry(entry->name(), value);
117 }
118 
OnInsertWithoutNameReference(absl::string_view name,absl::string_view value)119 void QpackDecoder::OnInsertWithoutNameReference(absl::string_view name,
120                                                 absl::string_view value) {
121   if (!header_table_.EntryFitsDynamicTableCapacity(name, value)) {
122     OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_ERROR_INSERTING_LITERAL,
123                     "Error inserting literal entry.");
124     return;
125   }
126   header_table_.InsertEntry(name, value);
127 }
128 
OnDuplicate(uint64_t index)129 void QpackDecoder::OnDuplicate(uint64_t index) {
130   uint64_t absolute_index;
131   if (!QpackEncoderStreamRelativeIndexToAbsoluteIndex(
132           index, header_table_.inserted_entry_count(), &absolute_index)) {
133     OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_DUPLICATE_INVALID_RELATIVE_INDEX,
134                     "Invalid relative index.");
135     return;
136   }
137 
138   const QpackEntry* entry =
139       header_table_.LookupEntry(/* is_static = */ false, absolute_index);
140   if (!entry) {
141     OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_DUPLICATE_DYNAMIC_ENTRY_NOT_FOUND,
142                     "Dynamic table entry not found.");
143     return;
144   }
145   if (!header_table_.EntryFitsDynamicTableCapacity(entry->name(),
146                                                    entry->value())) {
147     // This is impossible since entry was retrieved from the dynamic table.
148     OnErrorDetected(QUIC_INTERNAL_ERROR, "Error inserting duplicate entry.");
149     return;
150   }
151   header_table_.InsertEntry(entry->name(), entry->value());
152 }
153 
OnSetDynamicTableCapacity(uint64_t capacity)154 void QpackDecoder::OnSetDynamicTableCapacity(uint64_t capacity) {
155   if (!header_table_.SetDynamicTableCapacity(capacity)) {
156     OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_SET_DYNAMIC_TABLE_CAPACITY,
157                     "Error updating dynamic table capacity.");
158   }
159 }
160 
OnErrorDetected(QuicErrorCode error_code,absl::string_view error_message)161 void QpackDecoder::OnErrorDetected(QuicErrorCode error_code,
162                                    absl::string_view error_message) {
163   encoder_stream_error_delegate_->OnEncoderStreamError(error_code,
164                                                        error_message);
165 }
166 
CreateProgressiveDecoder(QuicStreamId stream_id,QpackProgressiveDecoder::HeadersHandlerInterface * handler)167 std::unique_ptr<QpackProgressiveDecoder> QpackDecoder::CreateProgressiveDecoder(
168     QuicStreamId stream_id,
169     QpackProgressiveDecoder::HeadersHandlerInterface* handler) {
170   return std::make_unique<QpackProgressiveDecoder>(stream_id, this, this,
171                                                    &header_table_, handler);
172 }
173 
FlushDecoderStream()174 void QpackDecoder::FlushDecoderStream() { decoder_stream_sender_.Flush(); }
175 
176 }  // namespace quic
177