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_ENCODER_H_ 6 #define QUICHE_QUIC_CORE_QPACK_QPACK_ENCODER_H_ 7 8 #include <cstdint> 9 #include <memory> 10 #include <string> 11 #include <vector> 12 13 #include "absl/strings/string_view.h" 14 #include "quiche/quic/core/qpack/qpack_blocking_manager.h" 15 #include "quiche/quic/core/qpack/qpack_decoder_stream_receiver.h" 16 #include "quiche/quic/core/qpack/qpack_encoder_stream_sender.h" 17 #include "quiche/quic/core/qpack/qpack_header_table.h" 18 #include "quiche/quic/core/qpack/qpack_instructions.h" 19 #include "quiche/quic/core/quic_error_codes.h" 20 #include "quiche/quic/core/quic_types.h" 21 #include "quiche/quic/platform/api/quic_export.h" 22 #include "quiche/quic/platform/api/quic_exported_stats.h" 23 #include "quiche/spdy/core/http2_header_block.h" 24 25 namespace quic { 26 27 namespace test { 28 29 class QpackEncoderPeer; 30 31 } // namespace test 32 33 // QPACK encoder class. Exactly one instance should exist per QUIC connection. 34 class QUICHE_EXPORT QpackEncoder : public QpackDecoderStreamReceiver::Delegate { 35 public: 36 // Interface for receiving notification that an error has occurred on the 37 // decoder stream. This MUST be treated as a connection error of type 38 // HTTP_QPACK_DECODER_STREAM_ERROR. 39 class QUICHE_EXPORT DecoderStreamErrorDelegate { 40 public: ~DecoderStreamErrorDelegate()41 virtual ~DecoderStreamErrorDelegate() {} 42 43 virtual void OnDecoderStreamError(QuicErrorCode error_code, 44 absl::string_view error_message) = 0; 45 }; 46 47 QpackEncoder(DecoderStreamErrorDelegate* decoder_stream_error_delegate, 48 HuffmanEncoding huffman_encoding); 49 ~QpackEncoder() override; 50 51 // Encode a header list. If |encoder_stream_sent_byte_count| is not null, 52 // |*encoder_stream_sent_byte_count| will be set to the number of bytes sent 53 // on the encoder stream to insert dynamic table entries. 54 std::string EncodeHeaderList(QuicStreamId stream_id, 55 const spdy::Http2HeaderBlock& header_list, 56 QuicByteCount* encoder_stream_sent_byte_count); 57 58 // Set maximum dynamic table capacity to |maximum_dynamic_table_capacity|, 59 // measured in bytes. Called when SETTINGS_QPACK_MAX_TABLE_CAPACITY is 60 // received. Encoder needs to know this value so that it can calculate 61 // MaxEntries, used as a modulus to encode Required Insert Count. 62 // Returns true if |maximum_dynamic_table_capacity| is set for the first time 63 // or if it doesn't change current value. The setting is not changed when 64 // returning false. 65 bool SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity); 66 67 // Set dynamic table capacity to |dynamic_table_capacity|. 68 // |dynamic_table_capacity| must not exceed maximum dynamic table capacity. 69 // Also sends Set Dynamic Table Capacity instruction on encoder stream. 70 void SetDynamicTableCapacity(uint64_t dynamic_table_capacity); 71 72 // Set maximum number of blocked streams. 73 // Called when SETTINGS_QPACK_BLOCKED_STREAMS is received. 74 // Returns true if |maximum_blocked_streams| doesn't decrease current value. 75 // The setting is not changed when returning false. 76 bool SetMaximumBlockedStreams(uint64_t maximum_blocked_streams); 77 78 // QpackDecoderStreamReceiver::Delegate implementation 79 void OnInsertCountIncrement(uint64_t increment) override; 80 void OnHeaderAcknowledgement(QuicStreamId stream_id) override; 81 void OnStreamCancellation(QuicStreamId stream_id) override; 82 void OnErrorDetected(QuicErrorCode error_code, 83 absl::string_view error_message) override; 84 85 // delegate must be set if dynamic table capacity is not zero. set_qpack_stream_sender_delegate(QpackStreamSenderDelegate * delegate)86 void set_qpack_stream_sender_delegate(QpackStreamSenderDelegate* delegate) { 87 encoder_stream_sender_.set_qpack_stream_sender_delegate(delegate); 88 } 89 decoder_stream_receiver()90 QpackStreamReceiver* decoder_stream_receiver() { 91 return &decoder_stream_receiver_; 92 } 93 94 // True if any dynamic table entries have been referenced from a header block. dynamic_table_entry_referenced()95 bool dynamic_table_entry_referenced() const { 96 return header_table_.dynamic_table_entry_referenced(); 97 } 98 maximum_blocked_streams()99 uint64_t maximum_blocked_streams() const { return maximum_blocked_streams_; } 100 MaximumDynamicTableCapacity()101 uint64_t MaximumDynamicTableCapacity() const { 102 return header_table_.maximum_dynamic_table_capacity(); 103 } 104 105 private: 106 friend class test::QpackEncoderPeer; 107 108 using Representation = QpackInstructionWithValues; 109 using Representations = std::vector<Representation>; 110 111 // Generate indexed header field representation 112 // and optionally update |*referred_indices|. 113 static Representation EncodeIndexedHeaderField( 114 bool is_static, uint64_t index, 115 QpackBlockingManager::IndexSet* referred_indices); 116 117 // Generate literal header field with name reference representation 118 // and optionally update |*referred_indices|. 119 static Representation EncodeLiteralHeaderFieldWithNameReference( 120 bool is_static, uint64_t index, absl::string_view value, 121 QpackBlockingManager::IndexSet* referred_indices); 122 123 // Generate literal header field representation. 124 static Representation EncodeLiteralHeaderField(absl::string_view name, 125 absl::string_view value); 126 127 // Performs first pass of two-pass encoding: represent each header field in 128 // |*header_list| as a reference to an existing entry, the name of an existing 129 // entry with a literal value, or a literal name and value pair. Sends 130 // necessary instructions on the encoder stream coalesced in a single write. 131 // Records absolute indices of referred dynamic table entries in 132 // |*referred_indices|. If |encoder_stream_sent_byte_count| is not null, then 133 // sets |*encoder_stream_sent_byte_count| to the number of bytes sent on the 134 // encoder stream to insert dynamic table entries. Returns list of header 135 // field representations, with all dynamic table entries referred to with 136 // absolute indices. Returned representation objects may have 137 // absl::string_views pointing to strings owned by |*header_list|. 138 Representations FirstPassEncode( 139 QuicStreamId stream_id, const spdy::Http2HeaderBlock& header_list, 140 QpackBlockingManager::IndexSet* referred_indices, 141 QuicByteCount* encoder_stream_sent_byte_count); 142 143 // Performs second pass of two-pass encoding: serializes representations 144 // generated in first pass, transforming absolute indices of dynamic table 145 // entries to relative indices. 146 std::string SecondPassEncode(Representations representations, 147 uint64_t required_insert_count) const; 148 149 const HuffmanEncoding huffman_encoding_; 150 DecoderStreamErrorDelegate* const decoder_stream_error_delegate_; 151 QpackDecoderStreamReceiver decoder_stream_receiver_; 152 QpackEncoderStreamSender encoder_stream_sender_; 153 QpackEncoderHeaderTable header_table_; 154 uint64_t maximum_blocked_streams_; 155 QpackBlockingManager blocking_manager_; 156 int header_list_count_; 157 }; 158 159 // QpackEncoder::DecoderStreamErrorDelegate implementation that does nothing. 160 class QUICHE_EXPORT NoopDecoderStreamErrorDelegate 161 : public QpackEncoder::DecoderStreamErrorDelegate { 162 public: 163 ~NoopDecoderStreamErrorDelegate() override = default; 164 OnDecoderStreamError(QuicErrorCode,absl::string_view)165 void OnDecoderStreamError(QuicErrorCode /*error_code*/, absl::string_view 166 /*error_message*/) override {} 167 }; 168 169 } // namespace quic 170 171 #endif // QUICHE_QUIC_CORE_QPACK_QPACK_ENCODER_H_ 172