xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instructions.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // 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 
5 #include "quiche/quic/core/qpack/qpack_instructions.h"
6 
7 #include <limits>
8 
9 #include "absl/strings/string_view.h"
10 #include "quiche/quic/platform/api/quic_logging.h"
11 
12 namespace quic {
13 
14 namespace {
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.
ValidateLangague(const QpackLanguage * language)19 void ValidateLangague(const QpackLanguage* language) {
20 #ifndef NDEBUG
21   for (const auto* instruction : *language) {
22     QUICHE_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     QUICHE_DCHECK_EQ(1u, match_count) << static_cast<int>(byte);
33   }
34 #else
35   (void)language;
36 #endif
37 }
38 
39 }  // namespace
40 
operator ==(const QpackInstructionOpcode & a,const QpackInstructionOpcode & b)41 bool operator==(const QpackInstructionOpcode& a,
42                 const QpackInstructionOpcode& b) {
43   return std::tie(a.value, a.mask) == std::tie(b.value, b.mask);
44 }
45 
InsertWithNameReferenceInstruction()46 const 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 
InsertWithoutNameReferenceInstruction()57 const 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 
DuplicateInstruction()67 const 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 
SetDynamicTableCapacityInstruction()75 const 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 
QpackEncoderStreamLanguage()83 const 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 
InsertCountIncrementInstruction()92 const 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 
HeaderAcknowledgementInstruction()100 const 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 
StreamCancellationInstruction()108 const 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 
QpackDecoderStreamLanguage()116 const QpackLanguage* QpackDecoderStreamLanguage() {
117   static const QpackLanguage* const language = new QpackLanguage{
118       InsertCountIncrementInstruction(), HeaderAcknowledgementInstruction(),
119       StreamCancellationInstruction()};
120   ValidateLangague(language);
121   return language;
122 }
123 
QpackPrefixInstruction()124 const 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 
QpackPrefixLanguage()136 const QpackLanguage* QpackPrefixLanguage() {
137   static const QpackLanguage* const language =
138       new QpackLanguage{QpackPrefixInstruction()};
139   ValidateLangague(language);
140   return language;
141 }
142 
QpackIndexedHeaderFieldInstruction()143 const 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 
QpackIndexedHeaderFieldPostBaseInstruction()153 const 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 
QpackLiteralHeaderFieldNameReferenceInstruction()161 const 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 
QpackLiteralHeaderFieldPostBaseInstruction()172 const 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 
QpackLiteralHeaderFieldInstruction()182 const 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 
QpackRequestStreamLanguage()192 const 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 
203 // static
InsertWithNameReference(bool is_static,uint64_t name_index,absl::string_view value)204 QpackInstructionWithValues QpackInstructionWithValues::InsertWithNameReference(
205     bool is_static, uint64_t name_index, absl::string_view value) {
206   QpackInstructionWithValues instruction_with_values;
207   instruction_with_values.instruction_ = InsertWithNameReferenceInstruction();
208   instruction_with_values.s_bit_ = is_static;
209   instruction_with_values.varint_ = name_index;
210   instruction_with_values.value_ = value;
211 
212   return instruction_with_values;
213 }
214 
215 // static
216 QpackInstructionWithValues
InsertWithoutNameReference(absl::string_view name,absl::string_view value)217 QpackInstructionWithValues::InsertWithoutNameReference(
218     absl::string_view name, absl::string_view value) {
219   QpackInstructionWithValues instruction_with_values;
220   instruction_with_values.instruction_ =
221       InsertWithoutNameReferenceInstruction();
222   instruction_with_values.name_ = name;
223   instruction_with_values.value_ = value;
224 
225   return instruction_with_values;
226 }
227 
228 // static
Duplicate(uint64_t index)229 QpackInstructionWithValues QpackInstructionWithValues::Duplicate(
230     uint64_t index) {
231   QpackInstructionWithValues instruction_with_values;
232   instruction_with_values.instruction_ = DuplicateInstruction();
233   instruction_with_values.varint_ = index;
234 
235   return instruction_with_values;
236 }
237 
238 // static
SetDynamicTableCapacity(uint64_t capacity)239 QpackInstructionWithValues QpackInstructionWithValues::SetDynamicTableCapacity(
240     uint64_t capacity) {
241   QpackInstructionWithValues instruction_with_values;
242   instruction_with_values.instruction_ = SetDynamicTableCapacityInstruction();
243   instruction_with_values.varint_ = capacity;
244 
245   return instruction_with_values;
246 }
247 
248 // static
InsertCountIncrement(uint64_t increment)249 QpackInstructionWithValues QpackInstructionWithValues::InsertCountIncrement(
250     uint64_t increment) {
251   QpackInstructionWithValues instruction_with_values;
252   instruction_with_values.instruction_ = InsertCountIncrementInstruction();
253   instruction_with_values.varint_ = increment;
254 
255   return instruction_with_values;
256 }
257 
258 // static
HeaderAcknowledgement(uint64_t stream_id)259 QpackInstructionWithValues QpackInstructionWithValues::HeaderAcknowledgement(
260     uint64_t stream_id) {
261   QpackInstructionWithValues instruction_with_values;
262   instruction_with_values.instruction_ = HeaderAcknowledgementInstruction();
263   instruction_with_values.varint_ = stream_id;
264 
265   return instruction_with_values;
266 }
267 
268 // static
StreamCancellation(uint64_t stream_id)269 QpackInstructionWithValues QpackInstructionWithValues::StreamCancellation(
270     uint64_t stream_id) {
271   QpackInstructionWithValues instruction_with_values;
272   instruction_with_values.instruction_ = StreamCancellationInstruction();
273   instruction_with_values.varint_ = stream_id;
274 
275   return instruction_with_values;
276 }
277 
278 // static
Prefix(uint64_t required_insert_count)279 QpackInstructionWithValues QpackInstructionWithValues::Prefix(
280     uint64_t required_insert_count) {
281   QpackInstructionWithValues instruction_with_values;
282   instruction_with_values.instruction_ = QpackPrefixInstruction();
283   instruction_with_values.varint_ = required_insert_count;
284   instruction_with_values.varint2_ = 0;    // Delta Base.
285   instruction_with_values.s_bit_ = false;  // Delta Base sign.
286 
287   return instruction_with_values;
288 }
289 
290 // static
IndexedHeaderField(bool is_static,uint64_t index)291 QpackInstructionWithValues QpackInstructionWithValues::IndexedHeaderField(
292     bool is_static, uint64_t index) {
293   QpackInstructionWithValues instruction_with_values;
294   instruction_with_values.instruction_ = QpackIndexedHeaderFieldInstruction();
295   instruction_with_values.s_bit_ = is_static;
296   instruction_with_values.varint_ = index;
297 
298   return instruction_with_values;
299 }
300 
301 // static
302 QpackInstructionWithValues
LiteralHeaderFieldNameReference(bool is_static,uint64_t index,absl::string_view value)303 QpackInstructionWithValues::LiteralHeaderFieldNameReference(
304     bool is_static, uint64_t index, absl::string_view value) {
305   QpackInstructionWithValues instruction_with_values;
306   instruction_with_values.instruction_ =
307       QpackLiteralHeaderFieldNameReferenceInstruction();
308   instruction_with_values.s_bit_ = is_static;
309   instruction_with_values.varint_ = index;
310   instruction_with_values.value_ = value;
311 
312   return instruction_with_values;
313 }
314 
315 // static
LiteralHeaderField(absl::string_view name,absl::string_view value)316 QpackInstructionWithValues QpackInstructionWithValues::LiteralHeaderField(
317     absl::string_view name, absl::string_view value) {
318   QpackInstructionWithValues instruction_with_values;
319   instruction_with_values.instruction_ = QpackLiteralHeaderFieldInstruction();
320   instruction_with_values.name_ = name;
321   instruction_with_values.value_ = value;
322 
323   return instruction_with_values;
324 }
325 
326 }  // namespace quic
327