blob: 1e5d1124c57fa5b92d783efaafbaebcd2169b94b [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright 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
bnc3b58cfc2019-11-27 12:52:39 -08005#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05006
7#include <limits>
8
vasilvv0fb44432019-03-13 22:47:36 -07009#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE team11f55d42019-12-11 10:36:09 -080010#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050011
12namespace quic {
13
14namespace {
15
16// Validate that
17// * in each instruction, the bits of |value| that are zero in |mask| are zero;
18// * every byte matches exactly one opcode.
19void ValidateLangague(const QpackLanguage* language) {
20#ifndef NDEBUG
21 for (const auto* instruction : *language) {
22 DCHECK_EQ(0, instruction->opcode.value & ~instruction->opcode.mask);
23 }
24
25 for (uint8_t byte = 0; byte < std::numeric_limits<uint8_t>::max(); ++byte) {
26 size_t match_count = 0;
27 for (const auto* instruction : *language) {
28 if ((byte & instruction->opcode.mask) == instruction->opcode.value) {
29 ++match_count;
30 }
31 }
32 DCHECK_EQ(1u, match_count) << static_cast<int>(byte);
33 }
dschinazice59da92019-06-18 19:58:59 -070034#else
35 (void)language;
QUICHE teama6ef0a62019-03-07 20:34:33 -050036#endif
37}
38
39} // namespace
40
41bool operator==(const QpackInstructionOpcode& a,
42 const QpackInstructionOpcode& b) {
43 return std::tie(a.value, a.mask) == std::tie(b.value, b.mask);
44}
45
46const QpackInstruction* InsertWithNameReferenceInstruction() {
47 static const QpackInstructionOpcode* const opcode =
48 new QpackInstructionOpcode{0b10000000, 0b10000000};
49 static const QpackInstruction* const instruction =
50 new QpackInstruction{*opcode,
51 {{QpackInstructionFieldType::kSbit, 0b01000000},
52 {QpackInstructionFieldType::kVarint, 6},
53 {QpackInstructionFieldType::kValue, 7}}};
54 return instruction;
55}
56
57const QpackInstruction* InsertWithoutNameReferenceInstruction() {
58 static const QpackInstructionOpcode* const opcode =
59 new QpackInstructionOpcode{0b01000000, 0b11000000};
60 static const QpackInstruction* const instruction =
61 new QpackInstruction{*opcode,
62 {{QpackInstructionFieldType::kName, 5},
63 {QpackInstructionFieldType::kValue, 7}}};
64 return instruction;
65}
66
67const QpackInstruction* DuplicateInstruction() {
68 static const QpackInstructionOpcode* const opcode =
69 new QpackInstructionOpcode{0b00000000, 0b11100000};
70 static const QpackInstruction* const instruction =
71 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 5}}};
72 return instruction;
73}
74
75const QpackInstruction* SetDynamicTableCapacityInstruction() {
76 static const QpackInstructionOpcode* const opcode =
77 new QpackInstructionOpcode{0b00100000, 0b11100000};
78 static const QpackInstruction* const instruction =
79 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 5}}};
80 return instruction;
81}
82
83const QpackLanguage* QpackEncoderStreamLanguage() {
84 static const QpackLanguage* const language = new QpackLanguage{
85 InsertWithNameReferenceInstruction(),
86 InsertWithoutNameReferenceInstruction(), DuplicateInstruction(),
87 SetDynamicTableCapacityInstruction()};
88 ValidateLangague(language);
89 return language;
90}
91
92const QpackInstruction* InsertCountIncrementInstruction() {
93 static const QpackInstructionOpcode* const opcode =
94 new QpackInstructionOpcode{0b00000000, 0b11000000};
95 static const QpackInstruction* const instruction =
96 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}};
97 return instruction;
98}
99
100const QpackInstruction* HeaderAcknowledgementInstruction() {
101 static const QpackInstructionOpcode* const opcode =
102 new QpackInstructionOpcode{0b10000000, 0b10000000};
103 static const QpackInstruction* const instruction =
104 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 7}}};
105 return instruction;
106}
107
108const QpackInstruction* StreamCancellationInstruction() {
109 static const QpackInstructionOpcode* const opcode =
110 new QpackInstructionOpcode{0b01000000, 0b11000000};
111 static const QpackInstruction* const instruction =
112 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}};
113 return instruction;
114}
115
116const QpackLanguage* QpackDecoderStreamLanguage() {
117 static const QpackLanguage* const language = new QpackLanguage{
118 InsertCountIncrementInstruction(), HeaderAcknowledgementInstruction(),
119 StreamCancellationInstruction()};
120 ValidateLangague(language);
121 return language;
122}
123
124const QpackInstruction* QpackPrefixInstruction() {
125 // This opcode matches every input.
126 static const QpackInstructionOpcode* const opcode =
127 new QpackInstructionOpcode{0b00000000, 0b00000000};
128 static const QpackInstruction* const instruction =
129 new QpackInstruction{*opcode,
130 {{QpackInstructionFieldType::kVarint, 8},
131 {QpackInstructionFieldType::kSbit, 0b10000000},
132 {QpackInstructionFieldType::kVarint2, 7}}};
133 return instruction;
134}
135
136const QpackLanguage* QpackPrefixLanguage() {
137 static const QpackLanguage* const language =
138 new QpackLanguage{QpackPrefixInstruction()};
139 ValidateLangague(language);
140 return language;
141}
142
143const QpackInstruction* QpackIndexedHeaderFieldInstruction() {
144 static const QpackInstructionOpcode* const opcode =
145 new QpackInstructionOpcode{0b10000000, 0b10000000};
146 static const QpackInstruction* const instruction =
147 new QpackInstruction{*opcode,
148 {{QpackInstructionFieldType::kSbit, 0b01000000},
149 {QpackInstructionFieldType::kVarint, 6}}};
150 return instruction;
151}
152
153const QpackInstruction* QpackIndexedHeaderFieldPostBaseInstruction() {
154 static const QpackInstructionOpcode* const opcode =
155 new QpackInstructionOpcode{0b00010000, 0b11110000};
156 static const QpackInstruction* const instruction =
157 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 4}}};
158 return instruction;
159}
160
161const QpackInstruction* QpackLiteralHeaderFieldNameReferenceInstruction() {
162 static const QpackInstructionOpcode* const opcode =
163 new QpackInstructionOpcode{0b01000000, 0b11000000};
164 static const QpackInstruction* const instruction =
165 new QpackInstruction{*opcode,
166 {{QpackInstructionFieldType::kSbit, 0b00010000},
167 {QpackInstructionFieldType::kVarint, 4},
168 {QpackInstructionFieldType::kValue, 7}}};
169 return instruction;
170}
171
172const QpackInstruction* QpackLiteralHeaderFieldPostBaseInstruction() {
173 static const QpackInstructionOpcode* const opcode =
174 new QpackInstructionOpcode{0b00000000, 0b11110000};
175 static const QpackInstruction* const instruction =
176 new QpackInstruction{*opcode,
177 {{QpackInstructionFieldType::kVarint, 3},
178 {QpackInstructionFieldType::kValue, 7}}};
179 return instruction;
180}
181
182const QpackInstruction* QpackLiteralHeaderFieldInstruction() {
183 static const QpackInstructionOpcode* const opcode =
184 new QpackInstructionOpcode{0b00100000, 0b11100000};
185 static const QpackInstruction* const instruction =
186 new QpackInstruction{*opcode,
187 {{QpackInstructionFieldType::kName, 3},
188 {QpackInstructionFieldType::kValue, 7}}};
189 return instruction;
190}
191
192const QpackLanguage* QpackRequestStreamLanguage() {
193 static const QpackLanguage* const language =
194 new QpackLanguage{QpackIndexedHeaderFieldInstruction(),
195 QpackIndexedHeaderFieldPostBaseInstruction(),
196 QpackLiteralHeaderFieldNameReferenceInstruction(),
197 QpackLiteralHeaderFieldPostBaseInstruction(),
198 QpackLiteralHeaderFieldInstruction()};
199 ValidateLangague(language);
200 return language;
201}
202
bnc1c1dcab2019-10-31 05:04:08 -0700203// static
204QpackInstructionWithValues QpackInstructionWithValues::InsertWithNameReference(
205 bool is_static,
206 uint64_t name_index,
QUICHE team11f55d42019-12-11 10:36:09 -0800207 quiche::QuicheStringPiece value) {
bnc1c1dcab2019-10-31 05:04:08 -0700208 QpackInstructionWithValues instruction_with_values;
209 instruction_with_values.instruction_ = InsertWithNameReferenceInstruction();
210 instruction_with_values.s_bit_ = is_static;
211 instruction_with_values.varint_ = name_index;
212 instruction_with_values.value_ = value;
213
214 return instruction_with_values;
215}
216
217// static
218QpackInstructionWithValues
QUICHE team11f55d42019-12-11 10:36:09 -0800219QpackInstructionWithValues::InsertWithoutNameReference(
220 quiche::QuicheStringPiece name,
221 quiche::QuicheStringPiece value) {
bnc1c1dcab2019-10-31 05:04:08 -0700222 QpackInstructionWithValues instruction_with_values;
223 instruction_with_values.instruction_ =
224 InsertWithoutNameReferenceInstruction();
225 instruction_with_values.name_ = name;
226 instruction_with_values.value_ = value;
227
228 return instruction_with_values;
229}
230
231// static
232QpackInstructionWithValues QpackInstructionWithValues::Duplicate(
233 uint64_t index) {
234 QpackInstructionWithValues instruction_with_values;
235 instruction_with_values.instruction_ = DuplicateInstruction();
236 instruction_with_values.varint_ = index;
237
238 return instruction_with_values;
239}
240
241// static
242QpackInstructionWithValues QpackInstructionWithValues::SetDynamicTableCapacity(
243 uint64_t capacity) {
244 QpackInstructionWithValues instruction_with_values;
245 instruction_with_values.instruction_ = SetDynamicTableCapacityInstruction();
246 instruction_with_values.varint_ = capacity;
247
248 return instruction_with_values;
249}
250
251// static
252QpackInstructionWithValues QpackInstructionWithValues::InsertCountIncrement(
253 uint64_t increment) {
254 QpackInstructionWithValues instruction_with_values;
255 instruction_with_values.instruction_ = InsertCountIncrementInstruction();
256 instruction_with_values.varint_ = increment;
257
258 return instruction_with_values;
259}
260
261// static
262QpackInstructionWithValues QpackInstructionWithValues::HeaderAcknowledgement(
263 uint64_t stream_id) {
264 QpackInstructionWithValues instruction_with_values;
265 instruction_with_values.instruction_ = HeaderAcknowledgementInstruction();
266 instruction_with_values.varint_ = stream_id;
267
268 return instruction_with_values;
269}
270
271// static
272QpackInstructionWithValues QpackInstructionWithValues::StreamCancellation(
273 uint64_t stream_id) {
274 QpackInstructionWithValues instruction_with_values;
275 instruction_with_values.instruction_ = StreamCancellationInstruction();
276 instruction_with_values.varint_ = stream_id;
277
278 return instruction_with_values;
279}
280
281// static
282QpackInstructionWithValues QpackInstructionWithValues::Prefix(
283 uint64_t required_insert_count) {
284 QpackInstructionWithValues instruction_with_values;
285 instruction_with_values.instruction_ = QpackPrefixInstruction();
286 instruction_with_values.varint_ = required_insert_count;
287 instruction_with_values.varint2_ = 0; // Delta Base.
288 instruction_with_values.s_bit_ = false; // Delta Base sign.
289
290 return instruction_with_values;
291}
292
293// static
294QpackInstructionWithValues QpackInstructionWithValues::IndexedHeaderField(
295 bool is_static,
296 uint64_t index) {
297 QpackInstructionWithValues instruction_with_values;
298 instruction_with_values.instruction_ = QpackIndexedHeaderFieldInstruction();
299 instruction_with_values.s_bit_ = is_static;
300 instruction_with_values.varint_ = index;
301
302 return instruction_with_values;
303}
304
305// static
306QpackInstructionWithValues
307QpackInstructionWithValues::LiteralHeaderFieldNameReference(
308 bool is_static,
309 uint64_t index,
QUICHE team11f55d42019-12-11 10:36:09 -0800310 quiche::QuicheStringPiece value) {
bnc1c1dcab2019-10-31 05:04:08 -0700311 QpackInstructionWithValues instruction_with_values;
312 instruction_with_values.instruction_ =
313 QpackLiteralHeaderFieldNameReferenceInstruction();
314 instruction_with_values.s_bit_ = is_static;
315 instruction_with_values.varint_ = index;
316 instruction_with_values.value_ = value;
317
318 return instruction_with_values;
319}
320
321// static
322QpackInstructionWithValues QpackInstructionWithValues::LiteralHeaderField(
QUICHE team11f55d42019-12-11 10:36:09 -0800323 quiche::QuicheStringPiece name,
324 quiche::QuicheStringPiece value) {
bnc1c1dcab2019-10-31 05:04:08 -0700325 QpackInstructionWithValues instruction_with_values;
326 instruction_with_values.instruction_ = QpackLiteralHeaderFieldInstruction();
327 instruction_with_values.name_ = name;
328 instruction_with_values.value_ = value;
329
330 return instruction_with_values;
331}
332
QUICHE teama6ef0a62019-03-07 20:34:33 -0500333} // namespace quic