• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 QUIC_EXPORT_PRIVATE QpackEncoder
35     : public QpackDecoderStreamReceiver::Delegate {
36  public:
37   // Interface for receiving notification that an error has occurred on the
38   // decoder stream.  This MUST be treated as a connection error of type
39   // HTTP_QPACK_DECODER_STREAM_ERROR.
40   class QUIC_EXPORT_PRIVATE DecoderStreamErrorDelegate {
41    public:
~DecoderStreamErrorDelegate()42     virtual ~DecoderStreamErrorDelegate() {}
43 
44     virtual void OnDecoderStreamError(QuicErrorCode error_code,
45                                       absl::string_view error_message) = 0;
46   };
47 
48   QpackEncoder(DecoderStreamErrorDelegate* decoder_stream_error_delegate);
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   DecoderStreamErrorDelegate* const decoder_stream_error_delegate_;
150   QpackDecoderStreamReceiver decoder_stream_receiver_;
151   QpackEncoderStreamSender encoder_stream_sender_;
152   QpackEncoderHeaderTable header_table_;
153   uint64_t maximum_blocked_streams_;
154   QpackBlockingManager blocking_manager_;
155   int header_list_count_;
156 };
157 
158 // QpackEncoder::DecoderStreamErrorDelegate implementation that does nothing.
159 class QUIC_EXPORT_PRIVATE NoopDecoderStreamErrorDelegate
160     : public QpackEncoder::DecoderStreamErrorDelegate {
161  public:
162   ~NoopDecoderStreamErrorDelegate() override = default;
163 
OnDecoderStreamError(QuicErrorCode,absl::string_view)164   void OnDecoderStreamError(QuicErrorCode /*error_code*/, absl::string_view
165                             /*error_message*/) override {}
166 };
167 
168 }  // namespace quic
169 
170 #endif  // QUICHE_QUIC_CORE_QPACK_QPACK_ENCODER_H_
171