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 #ifndef QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTION_ENCODER_H_ 6 #define QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTION_ENCODER_H_ 7 8 #include <cstdint> 9 #include <string> 10 11 #include "absl/strings/string_view.h" 12 #include "quiche/quic/core/qpack/qpack_instructions.h" 13 #include "quiche/quic/platform/api/quic_export.h" 14 15 namespace quic { 16 17 // Enum which specifies if Huffman encoding should be used when sending 18 // QPACK headers. 19 enum class HuffmanEncoding { 20 kEnabled, 21 kDisabled, 22 }; 23 24 // Generic instruction encoder class. Takes a QpackLanguage that describes a 25 // language, that is, a set of instruction opcodes together with a list of 26 // fields that follow each instruction. 27 class QUICHE_EXPORT QpackInstructionEncoder { 28 public: 29 explicit QpackInstructionEncoder(HuffmanEncoding huffman_encoding); 30 QpackInstructionEncoder(const QpackInstructionEncoder&) = delete; 31 QpackInstructionEncoder& operator=(const QpackInstructionEncoder&) = delete; 32 33 // Append encoded instruction to |output|. 34 void Encode(const QpackInstructionWithValues& instruction_with_values, 35 std::string* output); 36 37 private: 38 enum class State { 39 // Write instruction opcode to |byte_|. 40 kOpcode, 41 // Select state based on type of current field. 42 kStartField, 43 // Write static bit to |byte_|. 44 kSbit, 45 // Encode an integer (|varint_| or |varint2_| or string length) with a 46 // prefix, using |byte_| for the high bits. 47 kVarintEncode, 48 // Determine if Huffman encoding should be used for the header name or 49 // value, set |use_huffman_| and |string_length_| appropriately, write the 50 // Huffman bit to |byte_|. 51 kStartString, 52 // Write header name or value, performing Huffman encoding if |use_huffman_| 53 // is true. 54 kWriteString 55 }; 56 57 // One method for each state. Some append encoded bytes to |output|. 58 // Some only change internal state. 59 void DoOpcode(); 60 void DoStartField(); 61 void DoSBit(bool s_bit); 62 void DoVarintEncode(uint64_t varint, uint64_t varint2, std::string* output); 63 void DoStartString(absl::string_view name, absl::string_view value); 64 void DoWriteString(absl::string_view name, absl::string_view value, 65 std::string* output); 66 67 // If true then Huffman encoding will not be used, regardless of the 68 // string size. 69 const HuffmanEncoding huffman_encoding_; 70 71 // True if name or value should be Huffman encoded. 72 bool use_huffman_; 73 74 // Length of name or value string to be written. 75 // If |use_huffman_| is true, length is after Huffman encoding. 76 size_t string_length_; 77 78 // Storage for a single byte that contains multiple fields, that is, multiple 79 // states are writing it. 80 uint8_t byte_; 81 82 // Encoding state. 83 State state_; 84 85 // Instruction currently being decoded. 86 const QpackInstruction* instruction_; 87 88 // Field currently being decoded. 89 QpackInstructionFields::const_iterator field_; 90 }; 91 92 } // namespace quic 93 94 #endif // QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTION_ENCODER_H_ 95