blob: 9efccb6c02954a776855bc8d865383d42c346bf2 [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
7#include <limits>
8
vasilvv0fb44432019-03-13 22:47:36 -07009#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
11
12namespace quic {
13
14QpackDecoder::QpackDecoder(
15 EncoderStreamErrorDelegate* encoder_stream_error_delegate,
16 QpackDecoderStreamSender::Delegate* decoder_stream_sender_delegate)
17 : encoder_stream_error_delegate_(encoder_stream_error_delegate),
18 encoder_stream_receiver_(this),
19 decoder_stream_sender_(decoder_stream_sender_delegate) {
20 DCHECK(encoder_stream_error_delegate_);
21 DCHECK(decoder_stream_sender_delegate);
22}
23
24QpackDecoder::~QpackDecoder() {}
25
26void QpackDecoder::SetMaximumDynamicTableCapacity(
27 uint64_t maximum_dynamic_table_capacity) {
28 header_table_.SetMaximumDynamicTableCapacity(maximum_dynamic_table_capacity);
29}
30
31void QpackDecoder::OnStreamReset(QuicStreamId stream_id) {
32 decoder_stream_sender_.SendStreamCancellation(stream_id);
33}
34
35void QpackDecoder::DecodeEncoderStreamData(QuicStringPiece data) {
36 encoder_stream_receiver_.Decode(data);
37}
38
39void QpackDecoder::OnInsertWithNameReference(bool is_static,
40 uint64_t name_index,
41 QuicStringPiece value) {
42 if (is_static) {
43 auto entry = header_table_.LookupEntry(/* is_static = */ true, name_index);
44 if (!entry) {
45 encoder_stream_error_delegate_->OnEncoderStreamError(
46 "Invalid static table entry.");
47 return;
48 }
49
50 entry = header_table_.InsertEntry(entry->name(), value);
51 if (!entry) {
52 encoder_stream_error_delegate_->OnEncoderStreamError(
53 "Error inserting entry with name reference.");
54 }
55 return;
56 }
57
58 uint64_t absolute_index;
59 if (!EncoderStreamRelativeIndexToAbsoluteIndex(name_index, &absolute_index)) {
60 encoder_stream_error_delegate_->OnEncoderStreamError(
61 "Invalid relative index.");
62 return;
63 }
64
65 const QpackEntry* entry =
66 header_table_.LookupEntry(/* is_static = */ false, absolute_index);
67 if (!entry) {
68 encoder_stream_error_delegate_->OnEncoderStreamError(
69 "Dynamic table entry not found.");
70 return;
71 }
72 entry = header_table_.InsertEntry(entry->name(), value);
73 if (!entry) {
74 encoder_stream_error_delegate_->OnEncoderStreamError(
75 "Error inserting entry with name reference.");
76 }
77}
78
79void QpackDecoder::OnInsertWithoutNameReference(QuicStringPiece name,
80 QuicStringPiece value) {
81 const QpackEntry* entry = header_table_.InsertEntry(name, value);
82 if (!entry) {
83 encoder_stream_error_delegate_->OnEncoderStreamError(
84 "Error inserting literal entry.");
85 }
86}
87
88void QpackDecoder::OnDuplicate(uint64_t index) {
89 uint64_t absolute_index;
90 if (!EncoderStreamRelativeIndexToAbsoluteIndex(index, &absolute_index)) {
91 encoder_stream_error_delegate_->OnEncoderStreamError(
92 "Invalid relative index.");
93 return;
94 }
95
96 const QpackEntry* entry =
97 header_table_.LookupEntry(/* is_static = */ false, absolute_index);
98 if (!entry) {
99 encoder_stream_error_delegate_->OnEncoderStreamError(
100 "Dynamic table entry not found.");
101 return;
102 }
103 entry = header_table_.InsertEntry(entry->name(), entry->value());
104 if (!entry) {
105 encoder_stream_error_delegate_->OnEncoderStreamError(
106 "Error inserting duplicate entry.");
107 }
108}
109
110void QpackDecoder::OnSetDynamicTableCapacity(uint64_t capacity) {
111 if (!header_table_.SetDynamicTableCapacity(capacity)) {
112 encoder_stream_error_delegate_->OnEncoderStreamError(
113 "Error updating dynamic table capacity.");
114 }
115}
116
117void QpackDecoder::OnErrorDetected(QuicStringPiece error_message) {
118 encoder_stream_error_delegate_->OnEncoderStreamError(error_message);
119}
120
121bool QpackDecoder::EncoderStreamRelativeIndexToAbsoluteIndex(
122 uint64_t relative_index,
123 uint64_t* absolute_index) const {
124 if (relative_index == std::numeric_limits<uint64_t>::max() ||
125 relative_index + 1 > std::numeric_limits<uint64_t>::max() -
126 header_table_.inserted_entry_count()) {
127 return false;
128 }
129
130 *absolute_index = header_table_.inserted_entry_count() - relative_index - 1;
131 return true;
132}
133
134std::unique_ptr<QpackProgressiveDecoder> QpackDecoder::DecodeHeaderBlock(
135 QuicStreamId stream_id,
136 QpackProgressiveDecoder::HeadersHandlerInterface* handler) {
137 return QuicMakeUnique<QpackProgressiveDecoder>(
138 stream_id, &header_table_, &decoder_stream_sender_, handler);
139}
140
141} // namespace quic