blob: 1f649456456f97682d2648c41a9138eeac39ceae [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
5#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
6
bnc463f2352019-10-10 04:49:34 -07007#include <utility>
8
bnccd5ec3c2019-08-14 13:50:46 -07009#include "net/third_party/quiche/src/quic/core/qpack/qpack_index_conversions.h"
vasilvv0fb44432019-03-13 22:47:36 -070010#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050011
12namespace quic {
13
14QpackDecoder::QpackDecoder(
bnc4c664c52019-08-04 18:14:12 -070015 uint64_t maximum_dynamic_table_capacity,
bnc57b5f622019-08-21 14:07:44 -070016 uint64_t maximum_blocked_streams,
renjietang8a2df8f2019-08-07 10:43:52 -070017 EncoderStreamErrorDelegate* encoder_stream_error_delegate)
QUICHE teama6ef0a62019-03-07 20:34:33 -050018 : encoder_stream_error_delegate_(encoder_stream_error_delegate),
bnc57b5f622019-08-21 14:07:44 -070019 encoder_stream_receiver_(this),
bnc45af7512019-10-08 06:59:58 -070020 maximum_blocked_streams_(maximum_blocked_streams),
21 known_received_count_(0) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050022 DCHECK(encoder_stream_error_delegate_);
bnc4c664c52019-08-04 18:14:12 -070023
24 header_table_.SetMaximumDynamicTableCapacity(maximum_dynamic_table_capacity);
QUICHE teama6ef0a62019-03-07 20:34:33 -050025}
26
27QpackDecoder::~QpackDecoder() {}
28
QUICHE teama6ef0a62019-03-07 20:34:33 -050029void QpackDecoder::OnStreamReset(QuicStreamId stream_id) {
renjietang8a2df8f2019-08-07 10:43:52 -070030 // TODO(bnc): SendStreamCancellation should not be called if maximum dynamic
31 // table capacity is zero.
QUICHE teama6ef0a62019-03-07 20:34:33 -050032 decoder_stream_sender_.SendStreamCancellation(stream_id);
33}
34
bnc57b5f622019-08-21 14:07:44 -070035bool QpackDecoder::OnStreamBlocked(QuicStreamId stream_id) {
36 auto result = blocked_streams_.insert(stream_id);
37 DCHECK(result.second);
38 return blocked_streams_.size() <= maximum_blocked_streams_;
39}
40
41void QpackDecoder::OnStreamUnblocked(QuicStreamId stream_id) {
42 size_t result = blocked_streams_.erase(stream_id);
43 DCHECK_EQ(1u, result);
44}
45
bnc45af7512019-10-08 06:59:58 -070046void QpackDecoder::OnDecodingCompleted(QuicStreamId stream_id,
47 uint64_t required_insert_count) {
48 if (required_insert_count > 0) {
49 decoder_stream_sender_.SendHeaderAcknowledgement(stream_id);
50
51 if (known_received_count_ < required_insert_count) {
52 known_received_count_ = required_insert_count;
53 }
54 }
55
56 // Send an Insert Count Increment instruction if not all dynamic table entries
57 // have been acknowledged yet. This is necessary for efficient compression in
58 // case the encoder chooses not to reference unacknowledged dynamic table
59 // entries, otherwise inserted entries would never be acknowledged.
60 if (known_received_count_ < header_table_.inserted_entry_count()) {
61 decoder_stream_sender_.SendInsertCountIncrement(
62 header_table_.inserted_entry_count() - known_received_count_);
63 known_received_count_ = header_table_.inserted_entry_count();
64 }
65}
66
QUICHE teama6ef0a62019-03-07 20:34:33 -050067void QpackDecoder::OnInsertWithNameReference(bool is_static,
68 uint64_t name_index,
69 QuicStringPiece value) {
70 if (is_static) {
71 auto entry = header_table_.LookupEntry(/* is_static = */ true, name_index);
72 if (!entry) {
73 encoder_stream_error_delegate_->OnEncoderStreamError(
74 "Invalid static table entry.");
75 return;
76 }
77
78 entry = header_table_.InsertEntry(entry->name(), value);
79 if (!entry) {
80 encoder_stream_error_delegate_->OnEncoderStreamError(
81 "Error inserting entry with name reference.");
82 }
83 return;
84 }
85
86 uint64_t absolute_index;
bnccd5ec3c2019-08-14 13:50:46 -070087 if (!QpackEncoderStreamRelativeIndexToAbsoluteIndex(
88 name_index, header_table_.inserted_entry_count(), &absolute_index)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050089 encoder_stream_error_delegate_->OnEncoderStreamError(
90 "Invalid relative index.");
91 return;
92 }
93
94 const QpackEntry* entry =
95 header_table_.LookupEntry(/* is_static = */ false, absolute_index);
96 if (!entry) {
97 encoder_stream_error_delegate_->OnEncoderStreamError(
98 "Dynamic table entry not found.");
99 return;
100 }
101 entry = header_table_.InsertEntry(entry->name(), value);
102 if (!entry) {
103 encoder_stream_error_delegate_->OnEncoderStreamError(
104 "Error inserting entry with name reference.");
105 }
106}
107
108void QpackDecoder::OnInsertWithoutNameReference(QuicStringPiece name,
109 QuicStringPiece value) {
110 const QpackEntry* entry = header_table_.InsertEntry(name, value);
111 if (!entry) {
112 encoder_stream_error_delegate_->OnEncoderStreamError(
113 "Error inserting literal entry.");
114 }
115}
116
117void QpackDecoder::OnDuplicate(uint64_t index) {
118 uint64_t absolute_index;
bnccd5ec3c2019-08-14 13:50:46 -0700119 if (!QpackEncoderStreamRelativeIndexToAbsoluteIndex(
120 index, header_table_.inserted_entry_count(), &absolute_index)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500121 encoder_stream_error_delegate_->OnEncoderStreamError(
122 "Invalid relative index.");
123 return;
124 }
125
126 const QpackEntry* entry =
127 header_table_.LookupEntry(/* is_static = */ false, absolute_index);
128 if (!entry) {
129 encoder_stream_error_delegate_->OnEncoderStreamError(
130 "Dynamic table entry not found.");
131 return;
132 }
133 entry = header_table_.InsertEntry(entry->name(), entry->value());
134 if (!entry) {
135 encoder_stream_error_delegate_->OnEncoderStreamError(
136 "Error inserting duplicate entry.");
137 }
138}
139
140void QpackDecoder::OnSetDynamicTableCapacity(uint64_t capacity) {
141 if (!header_table_.SetDynamicTableCapacity(capacity)) {
142 encoder_stream_error_delegate_->OnEncoderStreamError(
143 "Error updating dynamic table capacity.");
144 }
145}
146
147void QpackDecoder::OnErrorDetected(QuicStringPiece error_message) {
148 encoder_stream_error_delegate_->OnEncoderStreamError(error_message);
149}
150
bnca904b052019-06-11 11:34:38 -0700151std::unique_ptr<QpackProgressiveDecoder> QpackDecoder::CreateProgressiveDecoder(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500152 QuicStreamId stream_id,
153 QpackProgressiveDecoder::HeadersHandlerInterface* handler) {
bnc45af7512019-10-08 06:59:58 -0700154 return std::make_unique<QpackProgressiveDecoder>(stream_id, this, this,
155 &header_table_, handler);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500156}
157
158} // namespace quic