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 ~QpackEncoder() override; 49 50 // Encode a header list. If |encoder_stream_sent_byte_count| is not null, 51 // |*encoder_stream_sent_byte_count| will be set to the number of bytes sent 52 // on the encoder stream to insert dynamic table entries. 53 std::string EncodeHeaderList(QuicStreamId stream_id, 54 const spdy::Http2HeaderBlock& header_list, 55 QuicByteCount* encoder_stream_sent_byte_count); 56 57 // Set maximum dynamic table capacity to |maximum_dynamic_table_capacity|, 58 // measured in bytes. Called when SETTINGS_QPACK_MAX_TABLE_CAPACITY is 59 // received. Encoder needs to know this value so that it can calculate 60 // MaxEntries, used as a modulus to encode Required Insert Count. 61 // Returns true if |maximum_dynamic_table_capacity| is set for the first time 62 // or if it doesn't change current value. The setting is not changed when 63 // returning false. 64 bool SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity); 65 66 // Set dynamic table capacity to |dynamic_table_capacity|. 67 // |dynamic_table_capacity| must not exceed maximum dynamic table capacity. 68 // Also sends Set Dynamic Table Capacity instruction on encoder stream. 69 void SetDynamicTableCapacity(uint64_t dynamic_table_capacity); 70 71 // Set maximum number of blocked streams. 72 // Called when SETTINGS_QPACK_BLOCKED_STREAMS is received. 73 // Returns true if |maximum_blocked_streams| doesn't decrease current value. 74 // The setting is not changed when returning false. 75 bool SetMaximumBlockedStreams(uint64_t maximum_blocked_streams); 76 77 // QpackDecoderStreamReceiver::Delegate implementation 78 void OnInsertCountIncrement(uint64_t increment) override; 79 void OnHeaderAcknowledgement(QuicStreamId stream_id) override; 80 void OnStreamCancellation(QuicStreamId stream_id) override; 81 void OnErrorDetected(QuicErrorCode error_code, 82 absl::string_view error_message) override; 83 84 // delegate must be set if dynamic table capacity is not zero. set_qpack_stream_sender_delegate(QpackStreamSenderDelegate * delegate)85 void set_qpack_stream_sender_delegate(QpackStreamSenderDelegate* delegate) { 86 encoder_stream_sender_.set_qpack_stream_sender_delegate(delegate); 87 } 88 decoder_stream_receiver()89 QpackStreamReceiver* decoder_stream_receiver() { 90 return &decoder_stream_receiver_; 91 } 92 93 // True if any dynamic table entries have been referenced from a header block. dynamic_table_entry_referenced()94 bool dynamic_table_entry_referenced() const { 95 return header_table_.dynamic_table_entry_referenced(); 96 } 97 maximum_blocked_streams()98 uint64_t maximum_blocked_streams() const { return maximum_blocked_streams_; } 99 MaximumDynamicTableCapacity()100 uint64_t MaximumDynamicTableCapacity() const { 101 return header_table_.maximum_dynamic_table_capacity(); 102 } 103 104 private: 105 friend class test::QpackEncoderPeer; 106 107 using Representation = QpackInstructionWithValues; 108 using Representations = std::vector<Representation>; 109 110 // Generate indexed header field representation 111 // and optionally update |*referred_indices|. 112 static Representation EncodeIndexedHeaderField( 113 bool is_static, uint64_t index, 114 QpackBlockingManager::IndexSet* referred_indices); 115 116 // Generate literal header field with name reference representation 117 // and optionally update |*referred_indices|. 118 static Representation EncodeLiteralHeaderFieldWithNameReference( 119 bool is_static, uint64_t index, absl::string_view value, 120 QpackBlockingManager::IndexSet* referred_indices); 121 122 // Generate literal header field representation. 123 static Representation EncodeLiteralHeaderField(absl::string_view name, 124 absl::string_view value); 125 126 // Performs first pass of two-pass encoding: represent each header field in 127 // |*header_list| as a reference to an existing entry, the name of an existing 128 // entry with a literal value, or a literal name and value pair. Sends 129 // necessary instructions on the encoder stream coalesced in a single write. 130 // Records absolute indices of referred dynamic table entries in 131 // |*referred_indices|. If |encoder_stream_sent_byte_count| is not null, then 132 // sets |*encoder_stream_sent_byte_count| to the number of bytes sent on the 133 // encoder stream to insert dynamic table entries. Returns list of header 134 // field representations, with all dynamic table entries referred to with 135 // absolute indices. Returned representation objects may have 136 // absl::string_views pointing to strings owned by |*header_list|. 137 Representations FirstPassEncode( 138 QuicStreamId stream_id, const spdy::Http2HeaderBlock& header_list, 139 QpackBlockingManager::IndexSet* referred_indices, 140 QuicByteCount* encoder_stream_sent_byte_count); 141 142 // Performs second pass of two-pass encoding: serializes representations 143 // generated in first pass, transforming absolute indices of dynamic table 144 // entries to relative indices. 145 std::string SecondPassEncode(Representations representations, 146 uint64_t required_insert_count) const; 147 148 DecoderStreamErrorDelegate* const decoder_stream_error_delegate_; 149 QpackDecoderStreamReceiver decoder_stream_receiver_; 150 QpackEncoderStreamSender encoder_stream_sender_; 151 QpackEncoderHeaderTable header_table_; 152 uint64_t maximum_blocked_streams_; 153 QpackBlockingManager blocking_manager_; 154 int header_list_count_; 155 }; 156 157 // QpackEncoder::DecoderStreamErrorDelegate implementation that does nothing. 158 class QUICHE_EXPORT NoopDecoderStreamErrorDelegate 159 : public QpackEncoder::DecoderStreamErrorDelegate { 160 public: 161 ~NoopDecoderStreamErrorDelegate() override = default; 162 OnDecoderStreamError(QuicErrorCode,absl::string_view)163 void OnDecoderStreamError(QuicErrorCode /*error_code*/, absl::string_view 164 /*error_message*/) override {} 165 }; 166 167 } // namespace quic 168 169 #endif // QUICHE_QUIC_CORE_QPACK_QPACK_ENCODER_H_ 170