blob: dd4487d70609010758b4958502071cb6cd44cffd [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 }
33#endif
34}
35
36} // namespace
37
38bool operator==(const QpackInstructionOpcode& a,
39 const QpackInstructionOpcode& b) {
40 return std::tie(a.value, a.mask) == std::tie(b.value, b.mask);
41}
42
43const QpackInstruction* InsertWithNameReferenceInstruction() {
44 static const QpackInstructionOpcode* const opcode =
45 new QpackInstructionOpcode{0b10000000, 0b10000000};
46 static const QpackInstruction* const instruction =
47 new QpackInstruction{*opcode,
48 {{QpackInstructionFieldType::kSbit, 0b01000000},
49 {QpackInstructionFieldType::kVarint, 6},
50 {QpackInstructionFieldType::kValue, 7}}};
51 return instruction;
52}
53
54const QpackInstruction* InsertWithoutNameReferenceInstruction() {
55 static const QpackInstructionOpcode* const opcode =
56 new QpackInstructionOpcode{0b01000000, 0b11000000};
57 static const QpackInstruction* const instruction =
58 new QpackInstruction{*opcode,
59 {{QpackInstructionFieldType::kName, 5},
60 {QpackInstructionFieldType::kValue, 7}}};
61 return instruction;
62}
63
64const QpackInstruction* DuplicateInstruction() {
65 static const QpackInstructionOpcode* const opcode =
66 new QpackInstructionOpcode{0b00000000, 0b11100000};
67 static const QpackInstruction* const instruction =
68 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 5}}};
69 return instruction;
70}
71
72const QpackInstruction* SetDynamicTableCapacityInstruction() {
73 static const QpackInstructionOpcode* const opcode =
74 new QpackInstructionOpcode{0b00100000, 0b11100000};
75 static const QpackInstruction* const instruction =
76 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 5}}};
77 return instruction;
78}
79
80const QpackLanguage* QpackEncoderStreamLanguage() {
81 static const QpackLanguage* const language = new QpackLanguage{
82 InsertWithNameReferenceInstruction(),
83 InsertWithoutNameReferenceInstruction(), DuplicateInstruction(),
84 SetDynamicTableCapacityInstruction()};
85 ValidateLangague(language);
86 return language;
87}
88
89const QpackInstruction* InsertCountIncrementInstruction() {
90 static const QpackInstructionOpcode* const opcode =
91 new QpackInstructionOpcode{0b00000000, 0b11000000};
92 static const QpackInstruction* const instruction =
93 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}};
94 return instruction;
95}
96
97const QpackInstruction* HeaderAcknowledgementInstruction() {
98 static const QpackInstructionOpcode* const opcode =
99 new QpackInstructionOpcode{0b10000000, 0b10000000};
100 static const QpackInstruction* const instruction =
101 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 7}}};
102 return instruction;
103}
104
105const QpackInstruction* StreamCancellationInstruction() {
106 static const QpackInstructionOpcode* const opcode =
107 new QpackInstructionOpcode{0b01000000, 0b11000000};
108 static const QpackInstruction* const instruction =
109 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}};
110 return instruction;
111}
112
113const QpackLanguage* QpackDecoderStreamLanguage() {
114 static const QpackLanguage* const language = new QpackLanguage{
115 InsertCountIncrementInstruction(), HeaderAcknowledgementInstruction(),
116 StreamCancellationInstruction()};
117 ValidateLangague(language);
118 return language;
119}
120
121const QpackInstruction* QpackPrefixInstruction() {
122 // This opcode matches every input.
123 static const QpackInstructionOpcode* const opcode =
124 new QpackInstructionOpcode{0b00000000, 0b00000000};
125 static const QpackInstruction* const instruction =
126 new QpackInstruction{*opcode,
127 {{QpackInstructionFieldType::kVarint, 8},
128 {QpackInstructionFieldType::kSbit, 0b10000000},
129 {QpackInstructionFieldType::kVarint2, 7}}};
130 return instruction;
131}
132
133const QpackLanguage* QpackPrefixLanguage() {
134 static const QpackLanguage* const language =
135 new QpackLanguage{QpackPrefixInstruction()};
136 ValidateLangague(language);
137 return language;
138}
139
140const QpackInstruction* QpackIndexedHeaderFieldInstruction() {
141 static const QpackInstructionOpcode* const opcode =
142 new QpackInstructionOpcode{0b10000000, 0b10000000};
143 static const QpackInstruction* const instruction =
144 new QpackInstruction{*opcode,
145 {{QpackInstructionFieldType::kSbit, 0b01000000},
146 {QpackInstructionFieldType::kVarint, 6}}};
147 return instruction;
148}
149
150const QpackInstruction* QpackIndexedHeaderFieldPostBaseInstruction() {
151 static const QpackInstructionOpcode* const opcode =
152 new QpackInstructionOpcode{0b00010000, 0b11110000};
153 static const QpackInstruction* const instruction =
154 new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 4}}};
155 return instruction;
156}
157
158const QpackInstruction* QpackLiteralHeaderFieldNameReferenceInstruction() {
159 static const QpackInstructionOpcode* const opcode =
160 new QpackInstructionOpcode{0b01000000, 0b11000000};
161 static const QpackInstruction* const instruction =
162 new QpackInstruction{*opcode,
163 {{QpackInstructionFieldType::kSbit, 0b00010000},
164 {QpackInstructionFieldType::kVarint, 4},
165 {QpackInstructionFieldType::kValue, 7}}};
166 return instruction;
167}
168
169const QpackInstruction* QpackLiteralHeaderFieldPostBaseInstruction() {
170 static const QpackInstructionOpcode* const opcode =
171 new QpackInstructionOpcode{0b00000000, 0b11110000};
172 static const QpackInstruction* const instruction =
173 new QpackInstruction{*opcode,
174 {{QpackInstructionFieldType::kVarint, 3},
175 {QpackInstructionFieldType::kValue, 7}}};
176 return instruction;
177}
178
179const QpackInstruction* QpackLiteralHeaderFieldInstruction() {
180 static const QpackInstructionOpcode* const opcode =
181 new QpackInstructionOpcode{0b00100000, 0b11100000};
182 static const QpackInstruction* const instruction =
183 new QpackInstruction{*opcode,
184 {{QpackInstructionFieldType::kName, 3},
185 {QpackInstructionFieldType::kValue, 7}}};
186 return instruction;
187}
188
189const QpackLanguage* QpackRequestStreamLanguage() {
190 static const QpackLanguage* const language =
191 new QpackLanguage{QpackIndexedHeaderFieldInstruction(),
192 QpackIndexedHeaderFieldPostBaseInstruction(),
193 QpackLiteralHeaderFieldNameReferenceInstruction(),
194 QpackLiteralHeaderFieldPostBaseInstruction(),
195 QpackLiteralHeaderFieldInstruction()};
196 ValidateLangague(language);
197 return language;
198}
199
200} // namespace quic