blob: 17790defd5fdaa4d621e43f440bcb950ead88ab9 [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 team11f55d42019-12-11 10:36:09 -080011#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012
13namespace quic {
14
15QpackDecoder::QpackDecoder(
bnc4c664c52019-08-04 18:14:12 -070016 uint64_t maximum_dynamic_table_capacity,
bnc57b5f622019-08-21 14:07:44 -070017 uint64_t maximum_blocked_streams,
renjietang8a2df8f2019-08-07 10:43:52 -070018 EncoderStreamErrorDelegate* encoder_stream_error_delegate)
QUICHE teama6ef0a62019-03-07 20:34:33 -050019 : encoder_stream_error_delegate_(encoder_stream_error_delegate),
bnc57b5f622019-08-21 14:07:44 -070020 encoder_stream_receiver_(this),
bnc45af7512019-10-08 06:59:58 -070021 maximum_blocked_streams_(maximum_blocked_streams),
22 known_received_count_(0) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050023 DCHECK(encoder_stream_error_delegate_);
bnc4c664c52019-08-04 18:14:12 -070024
25 header_table_.SetMaximumDynamicTableCapacity(maximum_dynamic_table_capacity);
QUICHE teama6ef0a62019-03-07 20:34:33 -050026}
27
28QpackDecoder::~QpackDecoder() {}
29
QUICHE teama6ef0a62019-03-07 20:34:33 -050030void QpackDecoder::OnStreamReset(QuicStreamId stream_id) {
bnc6f18a822019-11-27 17:50:38 -080031 if (header_table_.maximum_dynamic_table_capacity() > 0) {
32 decoder_stream_sender_.SendStreamCancellation(stream_id);
33 decoder_stream_sender_.Flush();
34 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050035}
36
bnc57b5f622019-08-21 14:07:44 -070037bool QpackDecoder::OnStreamBlocked(QuicStreamId stream_id) {
38 auto result = blocked_streams_.insert(stream_id);
39 DCHECK(result.second);
40 return blocked_streams_.size() <= maximum_blocked_streams_;
41}
42
43void QpackDecoder::OnStreamUnblocked(QuicStreamId stream_id) {
44 size_t result = blocked_streams_.erase(stream_id);
45 DCHECK_EQ(1u, result);
46}
47
bnc45af7512019-10-08 06:59:58 -070048void QpackDecoder::OnDecodingCompleted(QuicStreamId stream_id,
49 uint64_t required_insert_count) {
50 if (required_insert_count > 0) {
51 decoder_stream_sender_.SendHeaderAcknowledgement(stream_id);
52
53 if (known_received_count_ < required_insert_count) {
54 known_received_count_ = required_insert_count;
55 }
56 }
57
58 // Send an Insert Count Increment instruction if not all dynamic table entries
59 // have been acknowledged yet. This is necessary for efficient compression in
60 // case the encoder chooses not to reference unacknowledged dynamic table
61 // entries, otherwise inserted entries would never be acknowledged.
62 if (known_received_count_ < header_table_.inserted_entry_count()) {
63 decoder_stream_sender_.SendInsertCountIncrement(
64 header_table_.inserted_entry_count() - known_received_count_);
65 known_received_count_ = header_table_.inserted_entry_count();
66 }
bnc6b1fc8a2019-10-11 17:17:14 -070067
68 decoder_stream_sender_.Flush();
bnc45af7512019-10-08 06:59:58 -070069}
70
QUICHE teama6ef0a62019-03-07 20:34:33 -050071void QpackDecoder::OnInsertWithNameReference(bool is_static,
72 uint64_t name_index,
QUICHE team11f55d42019-12-11 10:36:09 -080073 quiche::QuicheStringPiece value) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050074 if (is_static) {
75 auto entry = header_table_.LookupEntry(/* is_static = */ true, name_index);
76 if (!entry) {
77 encoder_stream_error_delegate_->OnEncoderStreamError(
78 "Invalid static table entry.");
79 return;
80 }
81
82 entry = header_table_.InsertEntry(entry->name(), value);
83 if (!entry) {
84 encoder_stream_error_delegate_->OnEncoderStreamError(
85 "Error inserting entry with name reference.");
86 }
87 return;
88 }
89
90 uint64_t absolute_index;
bnccd5ec3c2019-08-14 13:50:46 -070091 if (!QpackEncoderStreamRelativeIndexToAbsoluteIndex(
92 name_index, header_table_.inserted_entry_count(), &absolute_index)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050093 encoder_stream_error_delegate_->OnEncoderStreamError(
94 "Invalid relative index.");
95 return;
96 }
97
98 const QpackEntry* entry =
99 header_table_.LookupEntry(/* is_static = */ false, absolute_index);
100 if (!entry) {
101 encoder_stream_error_delegate_->OnEncoderStreamError(
102 "Dynamic table entry not found.");
103 return;
104 }
105 entry = header_table_.InsertEntry(entry->name(), value);
106 if (!entry) {
107 encoder_stream_error_delegate_->OnEncoderStreamError(
108 "Error inserting entry with name reference.");
109 }
110}
111
QUICHE team11f55d42019-12-11 10:36:09 -0800112void QpackDecoder::OnInsertWithoutNameReference(
113 quiche::QuicheStringPiece name,
114 quiche::QuicheStringPiece value) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500115 const QpackEntry* entry = header_table_.InsertEntry(name, value);
116 if (!entry) {
117 encoder_stream_error_delegate_->OnEncoderStreamError(
118 "Error inserting literal entry.");
119 }
120}
121
122void QpackDecoder::OnDuplicate(uint64_t index) {
123 uint64_t absolute_index;
bnccd5ec3c2019-08-14 13:50:46 -0700124 if (!QpackEncoderStreamRelativeIndexToAbsoluteIndex(
125 index, header_table_.inserted_entry_count(), &absolute_index)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500126 encoder_stream_error_delegate_->OnEncoderStreamError(
127 "Invalid relative index.");
128 return;
129 }
130
131 const QpackEntry* entry =
132 header_table_.LookupEntry(/* is_static = */ false, absolute_index);
133 if (!entry) {
134 encoder_stream_error_delegate_->OnEncoderStreamError(
135 "Dynamic table entry not found.");
136 return;
137 }
138 entry = header_table_.InsertEntry(entry->name(), entry->value());
139 if (!entry) {
140 encoder_stream_error_delegate_->OnEncoderStreamError(
141 "Error inserting duplicate entry.");
142 }
143}
144
145void QpackDecoder::OnSetDynamicTableCapacity(uint64_t capacity) {
146 if (!header_table_.SetDynamicTableCapacity(capacity)) {
147 encoder_stream_error_delegate_->OnEncoderStreamError(
148 "Error updating dynamic table capacity.");
149 }
150}
151
QUICHE team11f55d42019-12-11 10:36:09 -0800152void QpackDecoder::OnErrorDetected(quiche::QuicheStringPiece error_message) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500153 encoder_stream_error_delegate_->OnEncoderStreamError(error_message);
154}
155
bnca904b052019-06-11 11:34:38 -0700156std::unique_ptr<QpackProgressiveDecoder> QpackDecoder::CreateProgressiveDecoder(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157 QuicStreamId stream_id,
158 QpackProgressiveDecoder::HeadersHandlerInterface* handler) {
bnc45af7512019-10-08 06:59:58 -0700159 return std::make_unique<QpackProgressiveDecoder>(stream_id, this, this,
160 &header_table_, handler);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500161}
162
163} // namespace quic