xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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