blob: 6644918b34a15117426cc1f0bb58264804aa3bab [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
5#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.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
11namespace quic {
12
13namespace {
14
15// Validate that
16// * in each instruction, the bits of |value| that are zero in |mask| are zero;
17// * every byte matches exactly one opcode.
18void ValidateLangague(const QpackLanguage* language) {
19#ifndef NDEBUG
20 for (const auto* instruction : *language) {
21 DCHECK_EQ(0, instruction->opcode.value & ~instruction->opcode.mask);
22 }
23
24 for (uint8_t byte = 0; byte < std::numeric_limits<uint8_t>::max(); ++byte) {
25 size_t match_count = 0;
26 for (const auto* instruction : *language) {
27 if ((byte & instruction->opcode.mask) == instruction->opcode.value) {
28 ++match_count;
29 }
30 }
31 DCHECK_EQ(1u, match_count) << static_cast<int>(byte);
32 }
dschinazice59da92019-06-18 19:58:59 -070033#else
34 (void)language;
QUICHE teama6ef0a62019-03-07 20:34:33 -050035#endif
36}
37
38} // namespace
39
40bool operator==(const QpackInstructionOpcode& a,
41 const QpackInstructionOpcode& b) {
42 return std::tie(a.value, a.mask) == std::tie(b.value, b.mask);
43}
44
45const QpackInstruction* InsertWithNameReferenceInstruction() {
46 static const QpackInstructionOpcode* const opcode =
47 new QpackInstructionOpcode{0b10000000, 0b10000000};
48 static const QpackInstruction* const instruction =
49 new QpackInstruction{*opcode,
50 {{QpackInstructionFieldType::kSbit, 0b01000000},
51 {QpackInstructionFieldType::kVarint, 6},
52 {QpackInstructionFieldType::kValue, 7}}};
53 return instruction;
54}
55
56const QpackInstruction* InsertWithoutNameReferenceInstruction() {
57 static const QpackInstructionOpcode* const opcode =
58 new QpackInstructionOpcode{0b01000000, 0b11000000};
59 static const QpackInstruction* const instruction =
60 new QpackInstruction{*opcode,
61 {{QpackInstructionFieldType::kName, 5},
62 {QpackInstructionFieldType::kValue, 7}}};
63 return instruction;
64}
65
66const QpackInstruction* DuplicateInstruction() {
67 static const QpackInstructionOpcode* const opcode =
68 new QpackInstructionOpcode{0b00000000, 0b11100000};
69 static const QpackInstruction* const instruction =
70 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 5}}};
71 return instruction;
72}
73
74const QpackInstruction* SetDynamicTableCapacityInstruction() {
75 static const QpackInstructionOpcode* const opcode =
76 new QpackInstructionOpcode{0b00100000, 0b11100000};
77 static const QpackInstruction* const instruction =
78 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 5}}};
79 return instruction;
80}
81
82const QpackLanguage* QpackEncoderStreamLanguage() {
83 static const QpackLanguage* const language = new QpackLanguage{
84 InsertWithNameReferenceInstruction(),
85 InsertWithoutNameReferenceInstruction(), DuplicateInstruction(),
86 SetDynamicTableCapacityInstruction()};
87 ValidateLangague(language);
88 return language;
89}
90
91const QpackInstruction* InsertCountIncrementInstruction() {
92 static const QpackInstructionOpcode* const opcode =
93 new QpackInstructionOpcode{0b00000000, 0b11000000};
94 static const QpackInstruction* const instruction =
95 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}};
96 return instruction;
97}
98
99const QpackInstruction* HeaderAcknowledgementInstruction() {
100 static const QpackInstructionOpcode* const opcode =
101 new QpackInstructionOpcode{0b10000000, 0b10000000};
102 static const QpackInstruction* const instruction =
103 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 7}}};
104 return instruction;
105}
106
107const QpackInstruction* StreamCancellationInstruction() {
108 static const QpackInstructionOpcode* const opcode =
109 new QpackInstructionOpcode{0b01000000, 0b11000000};
110 static const QpackInstruction* const instruction =
111 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}};
112 return instruction;
113}
114
115const QpackLanguage* QpackDecoderStreamLanguage() {
116 static const QpackLanguage* const language = new QpackLanguage{
117 InsertCountIncrementInstruction(), HeaderAcknowledgementInstruction(),
118 StreamCancellationInstruction()};
119 ValidateLangague(language);
120 return language;
121}
122
123const QpackInstruction* QpackPrefixInstruction() {
124 // This opcode matches every input.
125 static const QpackInstructionOpcode* const opcode =
126 new QpackInstructionOpcode{0b00000000, 0b00000000};
127 static const QpackInstruction* const instruction =
128 new QpackInstruction{*opcode,
129 {{QpackInstructionFieldType::kVarint, 8},
130 {QpackInstructionFieldType::kSbit, 0b10000000},
131 {QpackInstructionFieldType::kVarint2, 7}}};
132 return instruction;
133}
134
135const QpackLanguage* QpackPrefixLanguage() {
136 static const QpackLanguage* const language =
137 new QpackLanguage{QpackPrefixInstruction()};
138 ValidateLangague(language);
139 return language;
140}
141
142const QpackInstruction* QpackIndexedHeaderFieldInstruction() {
143 static const QpackInstructionOpcode* const opcode =
144 new QpackInstructionOpcode{0b10000000, 0b10000000};
145 static const QpackInstruction* const instruction =
146 new QpackInstruction{*opcode,
147 {{QpackInstructionFieldType::kSbit, 0b01000000},
148 {QpackInstructionFieldType::kVarint, 6}}};
149 return instruction;
150}
151
152const QpackInstruction* QpackIndexedHeaderFieldPostBaseInstruction() {
153 static const QpackInstructionOpcode* const opcode =
154 new QpackInstructionOpcode{0b00010000, 0b11110000};
155 static const QpackInstruction* const instruction =
156 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 4}}};
157 return instruction;
158}
159
160const QpackInstruction* QpackLiteralHeaderFieldNameReferenceInstruction() {
161 static const QpackInstructionOpcode* const opcode =
162 new QpackInstructionOpcode{0b01000000, 0b11000000};
163 static const QpackInstruction* const instruction =
164 new QpackInstruction{*opcode,
165 {{QpackInstructionFieldType::kSbit, 0b00010000},
166 {QpackInstructionFieldType::kVarint, 4},
167 {QpackInstructionFieldType::kValue, 7}}};
168 return instruction;
169}
170
171const QpackInstruction* QpackLiteralHeaderFieldPostBaseInstruction() {
172 static const QpackInstructionOpcode* const opcode =
173 new QpackInstructionOpcode{0b00000000, 0b11110000};
174 static const QpackInstruction* const instruction =
175 new QpackInstruction{*opcode,
176 {{QpackInstructionFieldType::kVarint, 3},
177 {QpackInstructionFieldType::kValue, 7}}};
178 return instruction;
179}
180
181const QpackInstruction* QpackLiteralHeaderFieldInstruction() {
182 static const QpackInstructionOpcode* const opcode =
183 new QpackInstructionOpcode{0b00100000, 0b11100000};
184 static const QpackInstruction* const instruction =
185 new QpackInstruction{*opcode,
186 {{QpackInstructionFieldType::kName, 3},
187 {QpackInstructionFieldType::kValue, 7}}};
188 return instruction;
189}
190
191const QpackLanguage* QpackRequestStreamLanguage() {
192 static const QpackLanguage* const language =
193 new QpackLanguage{QpackIndexedHeaderFieldInstruction(),
194 QpackIndexedHeaderFieldPostBaseInstruction(),
195 QpackLiteralHeaderFieldNameReferenceInstruction(),
196 QpackLiteralHeaderFieldPostBaseInstruction(),
197 QpackLiteralHeaderFieldInstruction()};
198 ValidateLangague(language);
199 return language;
200}
201
202} // namespace quic