1 // 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 #ifndef QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTIONS_H_ 6 #define QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTIONS_H_ 7 8 #include <cstdint> 9 #include <string> 10 #include <tuple> 11 #include <vector> 12 13 #include "absl/strings/string_view.h" 14 #include "quiche/quic/platform/api/quic_export.h" 15 16 namespace quic { 17 18 namespace test { 19 class QpackInstructionWithValuesPeer; 20 } // namespace test 21 22 // Each instruction is identified with an opcode in the first byte. 23 // |mask| determines which bits are part of the opcode. 24 // |value| is the value of these bits. (Other bits in value must be zero.) 25 struct QUICHE_EXPORT QpackInstructionOpcode { 26 uint8_t value; 27 uint8_t mask; 28 }; 29 30 bool operator==(const QpackInstructionOpcode& a, 31 const QpackInstructionOpcode& b); 32 33 // Possible types of an instruction field. Decoding a static bit does not 34 // consume the current byte. Decoding an integer or a length-prefixed string 35 // literal consumes all bytes containing the field value. 36 enum class QpackInstructionFieldType { 37 // A single bit indicating whether the index refers to the static table, or 38 // indicating the sign of Delta Base. Called "S" bit because both "static" 39 // and "sign" start with the letter "S". 40 kSbit, 41 // An integer encoded with variable length encoding. This could be an index, 42 // stream ID, maximum size, or Encoded Required Insert Count. 43 kVarint, 44 // A second integer encoded with variable length encoding. This could be 45 // Delta Base. 46 kVarint2, 47 // A header name or header value encoded as: 48 // a bit indicating whether it is Huffman encoded; 49 // the encoded length of the string; 50 // the header name or value optionally Huffman encoded. 51 kName, 52 kValue 53 }; 54 55 // Each instruction field has a type and a parameter. 56 // The meaning of the parameter depends on the field type. 57 struct QUICHE_EXPORT QpackInstructionField { 58 QpackInstructionFieldType type; 59 // For a kSbit field, |param| is a mask with exactly one bit set. 60 // For kVarint fields, |param| is the prefix length of the integer encoding. 61 // For kName and kValue fields, |param| is the prefix length of the length of 62 // the string, and the bit immediately preceding the prefix is interpreted as 63 // the Huffman bit. 64 uint8_t param; 65 }; 66 67 using QpackInstructionFields = std::vector<QpackInstructionField>; 68 69 // A QPACK instruction consists of an opcode identifying the instruction, 70 // followed by a non-empty list of fields. The last field must be integer or 71 // string literal type to guarantee that all bytes of the instruction are 72 // consumed. 73 struct QUICHE_EXPORT QpackInstruction { QpackInstructionQpackInstruction74 QpackInstruction(QpackInstructionOpcode opcode, QpackInstructionFields fields) 75 : opcode(std::move(opcode)), fields(std::move(fields)) {} 76 77 QpackInstruction(const QpackInstruction&) = delete; 78 const QpackInstruction& operator=(const QpackInstruction&) = delete; 79 80 QpackInstructionOpcode opcode; 81 QpackInstructionFields fields; 82 }; 83 84 // A language is a collection of instructions. The order does not matter. 85 // Every possible input must match exactly one instruction. 86 using QpackLanguage = std::vector<const QpackInstruction*>; 87 88 // Wire format defined in 89 // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5 90 91 // 5.2 Encoder stream instructions 92 93 // 5.2.1 Insert With Name Reference 94 const QpackInstruction* InsertWithNameReferenceInstruction(); 95 96 // 5.2.2 Insert Without Name Reference 97 const QpackInstruction* InsertWithoutNameReferenceInstruction(); 98 99 // 5.2.3 Duplicate 100 const QpackInstruction* DuplicateInstruction(); 101 102 // 5.2.4 Dynamic Table Size Update 103 const QpackInstruction* SetDynamicTableCapacityInstruction(); 104 105 // Encoder stream language. 106 const QpackLanguage* QpackEncoderStreamLanguage(); 107 108 // 5.3 Decoder stream instructions 109 110 // 5.3.1 Insert Count Increment 111 const QpackInstruction* InsertCountIncrementInstruction(); 112 113 // 5.3.2 Header Acknowledgement 114 const QpackInstruction* HeaderAcknowledgementInstruction(); 115 116 // 5.3.3 Stream Cancellation 117 const QpackInstruction* StreamCancellationInstruction(); 118 119 // Decoder stream language. 120 const QpackLanguage* QpackDecoderStreamLanguage(); 121 122 // 5.4.1. Header data prefix instructions 123 124 const QpackInstruction* QpackPrefixInstruction(); 125 126 const QpackLanguage* QpackPrefixLanguage(); 127 128 // 5.4.2. Request and push stream instructions 129 130 // 5.4.2.1. Indexed Header Field 131 const QpackInstruction* QpackIndexedHeaderFieldInstruction(); 132 133 // 5.4.2.2. Indexed Header Field With Post-Base Index 134 const QpackInstruction* QpackIndexedHeaderFieldPostBaseInstruction(); 135 136 // 5.4.2.3. Literal Header Field With Name Reference 137 const QpackInstruction* QpackLiteralHeaderFieldNameReferenceInstruction(); 138 139 // 5.4.2.4. Literal Header Field With Post-Base Name Reference 140 const QpackInstruction* QpackLiteralHeaderFieldPostBaseInstruction(); 141 142 // 5.4.2.5. Literal Header Field Without Name Reference 143 const QpackInstruction* QpackLiteralHeaderFieldInstruction(); 144 145 // Request and push stream language. 146 const QpackLanguage* QpackRequestStreamLanguage(); 147 148 // Storage for instruction and field values to be encoded. 149 // This class can only be instantiated using factory methods that take exactly 150 // the arguments that the corresponding instruction needs. 151 class QUICHE_EXPORT QpackInstructionWithValues { 152 public: 153 // 5.2 Encoder stream instructions 154 static QpackInstructionWithValues InsertWithNameReference( 155 bool is_static, uint64_t name_index, absl::string_view value); 156 static QpackInstructionWithValues InsertWithoutNameReference( 157 absl::string_view name, absl::string_view value); 158 static QpackInstructionWithValues Duplicate(uint64_t index); 159 static QpackInstructionWithValues SetDynamicTableCapacity(uint64_t capacity); 160 161 // 5.3 Decoder stream instructions 162 static QpackInstructionWithValues InsertCountIncrement(uint64_t increment); 163 static QpackInstructionWithValues HeaderAcknowledgement(uint64_t stream_id); 164 static QpackInstructionWithValues StreamCancellation(uint64_t stream_id); 165 166 // 5.4.1. Header data prefix. Delta Base is hardcoded to be zero. 167 static QpackInstructionWithValues Prefix(uint64_t required_insert_count); 168 169 // 5.4.2. Request and push stream instructions 170 static QpackInstructionWithValues IndexedHeaderField(bool is_static, 171 uint64_t index); 172 static QpackInstructionWithValues LiteralHeaderFieldNameReference( 173 bool is_static, uint64_t index, absl::string_view value); 174 static QpackInstructionWithValues LiteralHeaderField(absl::string_view name, 175 absl::string_view value); 176 instruction()177 const QpackInstruction* instruction() const { return instruction_; } s_bit()178 bool s_bit() const { return s_bit_; } varint()179 uint64_t varint() const { return varint_; } varint2()180 uint64_t varint2() const { return varint2_; } name()181 absl::string_view name() const { return name_; } value()182 absl::string_view value() const { return value_; } 183 184 // Used by QpackEncoder, because in the first pass it stores absolute indices, 185 // which are converted into relative indices in the second pass after base is 186 // determined. set_varint(uint64_t varint)187 void set_varint(uint64_t varint) { varint_ = varint; } 188 189 private: 190 friend test::QpackInstructionWithValuesPeer; 191 192 QpackInstructionWithValues() = default; 193 194 // |*instruction| is not owned. 195 const QpackInstruction* instruction_ = nullptr; 196 bool s_bit_ = false; 197 uint64_t varint_ = 0; 198 uint64_t varint2_ = 0; 199 absl::string_view name_; 200 absl::string_view value_; 201 }; 202 203 } // namespace quic 204 205 #endif // QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTIONS_H_ 206