xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder.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_DECODER_H_
6 #define QUICHE_QUIC_CORE_QPACK_QPACK_DECODER_H_
7 
8 #include <cstdint>
9 #include <memory>
10 #include <set>
11 
12 #include "absl/strings/string_view.h"
13 #include "quiche/quic/core/qpack/qpack_decoder_stream_sender.h"
14 #include "quiche/quic/core/qpack/qpack_encoder_stream_receiver.h"
15 #include "quiche/quic/core/qpack/qpack_header_table.h"
16 #include "quiche/quic/core/qpack/qpack_progressive_decoder.h"
17 #include "quiche/quic/core/quic_error_codes.h"
18 #include "quiche/quic/core/quic_types.h"
19 #include "quiche/quic/platform/api/quic_export.h"
20 
21 namespace quic {
22 
23 // QPACK decoder class.  Exactly one instance should exist per QUIC connection.
24 // This class vends a new QpackProgressiveDecoder instance for each new header
25 // list to be encoded.
26 // QpackProgressiveDecoder detects and signals errors with header blocks, which
27 // are stream errors.
28 // The only input of QpackDecoder is the encoder stream.  Any error QpackDecoder
29 // signals is an encoder stream error, which is fatal to the connection.
30 class QUICHE_EXPORT QpackDecoder
31     : public QpackEncoderStreamReceiver::Delegate,
32       public QpackProgressiveDecoder::BlockedStreamLimitEnforcer,
33       public QpackProgressiveDecoder::DecodingCompletedVisitor {
34  public:
35   // Interface for receiving notification that an error has occurred on the
36   // encoder stream.  This MUST be treated as a connection error of type
37   // HTTP_QPACK_ENCODER_STREAM_ERROR.
38   class QUICHE_EXPORT EncoderStreamErrorDelegate {
39    public:
~EncoderStreamErrorDelegate()40     virtual ~EncoderStreamErrorDelegate() {}
41 
42     virtual void OnEncoderStreamError(QuicErrorCode error_code,
43                                       absl::string_view error_message) = 0;
44   };
45 
46   QpackDecoder(uint64_t maximum_dynamic_table_capacity,
47                uint64_t maximum_blocked_streams,
48                EncoderStreamErrorDelegate* encoder_stream_error_delegate);
49   ~QpackDecoder() override;
50 
51   // Signal to the peer's encoder that a stream is reset.  This lets the peer's
52   // encoder know that no more header blocks will be processed on this stream,
53   // therefore references to dynamic table entries shall not prevent their
54   // eviction.
55   // This method should be called regardless of whether a header block is being
56   // decoded on that stream, because a header block might be in flight from the
57   // peer.
58   // This method should be called every time a request or push stream is reset
59   // for any reason: for example, client cancels request, or a decoding error
60   // occurs and HeadersHandlerInterface::OnDecodingErrorDetected() is called.
61   // This method should also be called if the stream is reset by the peer,
62   // because the peer's encoder can only evict entries referenced by header
63   // blocks once it receives acknowledgement from this endpoint that the stream
64   // is reset.
65   // However, this method should not be called if the stream is closed normally
66   // using the FIN bit.
67   void OnStreamReset(QuicStreamId stream_id);
68 
69   // QpackProgressiveDecoder::BlockedStreamLimitEnforcer implementation.
70   bool OnStreamBlocked(QuicStreamId stream_id) override;
71   void OnStreamUnblocked(QuicStreamId stream_id) override;
72 
73   // QpackProgressiveDecoder::DecodingCompletedVisitor implementation.
74   void OnDecodingCompleted(QuicStreamId stream_id,
75                            uint64_t required_insert_count) override;
76 
77   // Factory method to create a QpackProgressiveDecoder for decoding a header
78   // block.  |handler| must remain valid until the returned
79   // QpackProgressiveDecoder instance is destroyed or the decoder calls
80   // |handler->OnHeaderBlockEnd()|.
81   std::unique_ptr<QpackProgressiveDecoder> CreateProgressiveDecoder(
82       QuicStreamId stream_id,
83       QpackProgressiveDecoder::HeadersHandlerInterface* handler);
84 
85   // QpackEncoderStreamReceiver::Delegate implementation
86   void OnInsertWithNameReference(bool is_static, uint64_t name_index,
87                                  absl::string_view value) override;
88   void OnInsertWithoutNameReference(absl::string_view name,
89                                     absl::string_view value) override;
90   void OnDuplicate(uint64_t index) override;
91   void OnSetDynamicTableCapacity(uint64_t capacity) override;
92   void OnErrorDetected(QuicErrorCode error_code,
93                        absl::string_view error_message) override;
94 
95   // delegate must be set if dynamic table capacity is not zero.
set_qpack_stream_sender_delegate(QpackStreamSenderDelegate * delegate)96   void set_qpack_stream_sender_delegate(QpackStreamSenderDelegate* delegate) {
97     decoder_stream_sender_.set_qpack_stream_sender_delegate(delegate);
98   }
99 
encoder_stream_receiver()100   QpackStreamReceiver* encoder_stream_receiver() {
101     return &encoder_stream_receiver_;
102   }
103 
104   // True if any dynamic table entries have been referenced from a header block.
dynamic_table_entry_referenced()105   bool dynamic_table_entry_referenced() const {
106     return header_table_.dynamic_table_entry_referenced();
107   }
108 
109   // Flush buffered data on the decoder stream.
110   void FlushDecoderStream();
111 
112  private:
113   EncoderStreamErrorDelegate* const encoder_stream_error_delegate_;
114   QpackEncoderStreamReceiver encoder_stream_receiver_;
115   QpackDecoderStreamSender decoder_stream_sender_;
116   QpackDecoderHeaderTable header_table_;
117   std::set<QuicStreamId> blocked_streams_;
118   const uint64_t maximum_blocked_streams_;
119 
120   // Known Received Count is the number of insertions the encoder has received
121   // acknowledgement for (through Header Acknowledgement and Insert Count
122   // Increment instructions).  The encoder must keep track of it in order to be
123   // able to send Insert Count Increment instructions.  See
124   // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#known-received-count.
125   uint64_t known_received_count_;
126 };
127 
128 // QpackDecoder::EncoderStreamErrorDelegate implementation that does nothing.
129 class QUICHE_EXPORT NoopEncoderStreamErrorDelegate
130     : public QpackDecoder::EncoderStreamErrorDelegate {
131  public:
132   ~NoopEncoderStreamErrorDelegate() override = default;
133 
OnEncoderStreamError(QuicErrorCode,absl::string_view)134   void OnEncoderStreamError(QuicErrorCode /*error_code*/,
135                             absl::string_view /*error_message*/) override {}
136 };
137 
138 }  // namespace quic
139 
140 #endif  // QUICHE_QUIC_CORE_QPACK_QPACK_DECODER_H_
141