|  | // Copyright (c) 2018 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTIONS_H_ | 
|  | #define QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTIONS_H_ | 
|  |  | 
|  | #include <cstdint> | 
|  | #include <string> | 
|  | #include <tuple> | 
|  | #include <vector> | 
|  |  | 
|  | #include "absl/strings/string_view.h" | 
|  | #include "quic/platform/api/quic_export.h" | 
|  |  | 
|  | namespace quic { | 
|  |  | 
|  | namespace test { | 
|  | class QpackInstructionWithValuesPeer; | 
|  | }  // namespace test | 
|  |  | 
|  | // Each instruction is identified with an opcode in the first byte. | 
|  | // |mask| determines which bits are part of the opcode. | 
|  | // |value| is the value of these bits.  (Other bits in value must be zero.) | 
|  | struct QUIC_EXPORT_PRIVATE QpackInstructionOpcode { | 
|  | uint8_t value; | 
|  | uint8_t mask; | 
|  | }; | 
|  |  | 
|  | bool operator==(const QpackInstructionOpcode& a, | 
|  | const QpackInstructionOpcode& b); | 
|  |  | 
|  | // Possible types of an instruction field.  Decoding a static bit does not | 
|  | // consume the current byte.  Decoding an integer or a length-prefixed string | 
|  | // literal consumes all bytes containing the field value. | 
|  | enum class QpackInstructionFieldType { | 
|  | // A single bit indicating whether the index refers to the static table, or | 
|  | // indicating the sign of Delta Base.  Called "S" bit because both "static" | 
|  | // and "sign" start with the letter "S". | 
|  | kSbit, | 
|  | // An integer encoded with variable length encoding.  This could be an index, | 
|  | // stream ID, maximum size, or Encoded Required Insert Count. | 
|  | kVarint, | 
|  | // A second integer encoded with variable length encoding.  This could be | 
|  | // Delta Base. | 
|  | kVarint2, | 
|  | // A header name or header value encoded as: | 
|  | //   a bit indicating whether it is Huffman encoded; | 
|  | //   the encoded length of the string; | 
|  | //   the header name or value optionally Huffman encoded. | 
|  | kName, | 
|  | kValue | 
|  | }; | 
|  |  | 
|  | // Each instruction field has a type and a parameter. | 
|  | // The meaning of the parameter depends on the field type. | 
|  | struct QUIC_EXPORT_PRIVATE QpackInstructionField { | 
|  | QpackInstructionFieldType type; | 
|  | // For a kSbit field, |param| is a mask with exactly one bit set. | 
|  | // For kVarint fields, |param| is the prefix length of the integer encoding. | 
|  | // For kName and kValue fields, |param| is the prefix length of the length of | 
|  | // the string, and the bit immediately preceding the prefix is interpreted as | 
|  | // the Huffman bit. | 
|  | uint8_t param; | 
|  | }; | 
|  |  | 
|  | using QpackInstructionFields = std::vector<QpackInstructionField>; | 
|  |  | 
|  | // A QPACK instruction consists of an opcode identifying the instruction, | 
|  | // followed by a non-empty list of fields.  The last field must be integer or | 
|  | // string literal type to guarantee that all bytes of the instruction are | 
|  | // consumed. | 
|  | struct QUIC_EXPORT_PRIVATE QpackInstruction { | 
|  | QpackInstruction(const QpackInstruction&) = delete; | 
|  | const QpackInstruction& operator=(const QpackInstruction&) = delete; | 
|  |  | 
|  | QpackInstructionOpcode opcode; | 
|  | QpackInstructionFields fields; | 
|  | }; | 
|  |  | 
|  | // A language is a collection of instructions.  The order does not matter. | 
|  | // Every possible input must match exactly one instruction. | 
|  | using QpackLanguage = std::vector<const QpackInstruction*>; | 
|  |  | 
|  | // Wire format defined in | 
|  | // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5 | 
|  |  | 
|  | // 5.2 Encoder stream instructions | 
|  |  | 
|  | // 5.2.1 Insert With Name Reference | 
|  | const QpackInstruction* InsertWithNameReferenceInstruction(); | 
|  |  | 
|  | // 5.2.2 Insert Without Name Reference | 
|  | const QpackInstruction* InsertWithoutNameReferenceInstruction(); | 
|  |  | 
|  | // 5.2.3 Duplicate | 
|  | const QpackInstruction* DuplicateInstruction(); | 
|  |  | 
|  | // 5.2.4 Dynamic Table Size Update | 
|  | const QpackInstruction* SetDynamicTableCapacityInstruction(); | 
|  |  | 
|  | // Encoder stream language. | 
|  | const QpackLanguage* QpackEncoderStreamLanguage(); | 
|  |  | 
|  | // 5.3 Decoder stream instructions | 
|  |  | 
|  | // 5.3.1 Insert Count Increment | 
|  | const QpackInstruction* InsertCountIncrementInstruction(); | 
|  |  | 
|  | // 5.3.2 Header Acknowledgement | 
|  | const QpackInstruction* HeaderAcknowledgementInstruction(); | 
|  |  | 
|  | // 5.3.3 Stream Cancellation | 
|  | const QpackInstruction* StreamCancellationInstruction(); | 
|  |  | 
|  | // Decoder stream language. | 
|  | const QpackLanguage* QpackDecoderStreamLanguage(); | 
|  |  | 
|  | // 5.4.1. Header data prefix instructions | 
|  |  | 
|  | const QpackInstruction* QpackPrefixInstruction(); | 
|  |  | 
|  | const QpackLanguage* QpackPrefixLanguage(); | 
|  |  | 
|  | // 5.4.2. Request and push stream instructions | 
|  |  | 
|  | // 5.4.2.1. Indexed Header Field | 
|  | const QpackInstruction* QpackIndexedHeaderFieldInstruction(); | 
|  |  | 
|  | // 5.4.2.2. Indexed Header Field With Post-Base Index | 
|  | const QpackInstruction* QpackIndexedHeaderFieldPostBaseInstruction(); | 
|  |  | 
|  | // 5.4.2.3. Literal Header Field With Name Reference | 
|  | const QpackInstruction* QpackLiteralHeaderFieldNameReferenceInstruction(); | 
|  |  | 
|  | // 5.4.2.4. Literal Header Field With Post-Base Name Reference | 
|  | const QpackInstruction* QpackLiteralHeaderFieldPostBaseInstruction(); | 
|  |  | 
|  | // 5.4.2.5. Literal Header Field Without Name Reference | 
|  | const QpackInstruction* QpackLiteralHeaderFieldInstruction(); | 
|  |  | 
|  | // Request and push stream language. | 
|  | const QpackLanguage* QpackRequestStreamLanguage(); | 
|  |  | 
|  | // Storage for instruction and field values to be encoded. | 
|  | // This class can only be instantiated using factory methods that take exactly | 
|  | // the arguments that the corresponding instruction needs. | 
|  | class QUIC_EXPORT_PRIVATE QpackInstructionWithValues { | 
|  | public: | 
|  | // 5.2 Encoder stream instructions | 
|  | static QpackInstructionWithValues InsertWithNameReference( | 
|  | bool is_static, | 
|  | uint64_t name_index, | 
|  | absl::string_view value); | 
|  | static QpackInstructionWithValues InsertWithoutNameReference( | 
|  | absl::string_view name, | 
|  | absl::string_view value); | 
|  | static QpackInstructionWithValues Duplicate(uint64_t index); | 
|  | static QpackInstructionWithValues SetDynamicTableCapacity(uint64_t capacity); | 
|  |  | 
|  | // 5.3 Decoder stream instructions | 
|  | static QpackInstructionWithValues InsertCountIncrement(uint64_t increment); | 
|  | static QpackInstructionWithValues HeaderAcknowledgement(uint64_t stream_id); | 
|  | static QpackInstructionWithValues StreamCancellation(uint64_t stream_id); | 
|  |  | 
|  | // 5.4.1. Header data prefix.  Delta Base is hardcoded to be zero. | 
|  | static QpackInstructionWithValues Prefix(uint64_t required_insert_count); | 
|  |  | 
|  | // 5.4.2. Request and push stream instructions | 
|  | static QpackInstructionWithValues IndexedHeaderField(bool is_static, | 
|  | uint64_t index); | 
|  | static QpackInstructionWithValues LiteralHeaderFieldNameReference( | 
|  | bool is_static, | 
|  | uint64_t index, | 
|  | absl::string_view value); | 
|  | static QpackInstructionWithValues LiteralHeaderField(absl::string_view name, | 
|  | absl::string_view value); | 
|  |  | 
|  | const QpackInstruction* instruction() const { return instruction_; } | 
|  | bool s_bit() const { return s_bit_; } | 
|  | uint64_t varint() const { return varint_; } | 
|  | uint64_t varint2() const { return varint2_; } | 
|  | absl::string_view name() const { return name_; } | 
|  | absl::string_view value() const { return value_; } | 
|  |  | 
|  | // Used by QpackEncoder, because in the first pass it stores absolute indices, | 
|  | // which are converted into relative indices in the second pass after base is | 
|  | // determined. | 
|  | void set_varint(uint64_t varint) { varint_ = varint; } | 
|  |  | 
|  | private: | 
|  | friend test::QpackInstructionWithValuesPeer; | 
|  |  | 
|  | QpackInstructionWithValues() = default; | 
|  |  | 
|  | // |*instruction| is not owned. | 
|  | const QpackInstruction* instruction_ = nullptr; | 
|  | bool s_bit_ = false; | 
|  | uint64_t varint_ = 0; | 
|  | uint64_t varint2_ = 0; | 
|  | absl::string_view name_; | 
|  | absl::string_view value_; | 
|  | }; | 
|  |  | 
|  | }  // namespace quic | 
|  |  | 
|  | #endif  // QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTIONS_H_ |