xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_progressive_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_PROGRESSIVE_DECODER_H_
6 #define QUICHE_QUIC_CORE_QPACK_QPACK_PROGRESSIVE_DECODER_H_
7 
8 #include <cstdint>
9 #include <memory>
10 #include <string>
11 
12 #include "absl/strings/string_view.h"
13 #include "quiche/quic/core/qpack/qpack_encoder_stream_receiver.h"
14 #include "quiche/quic/core/qpack/qpack_header_table.h"
15 #include "quiche/quic/core/qpack/qpack_instruction_decoder.h"
16 #include "quiche/quic/core/quic_error_codes.h"
17 #include "quiche/quic/core/quic_types.h"
18 #include "quiche/quic/platform/api/quic_export.h"
19 
20 namespace quic {
21 
22 class QpackDecoderHeaderTable;
23 
24 // Class to decode a single header block.
25 class QUICHE_EXPORT QpackProgressiveDecoder
26     : public QpackInstructionDecoder::Delegate,
27       public QpackDecoderHeaderTable::Observer {
28  public:
29   // Interface for receiving decoded header block from the decoder.
30   class QUICHE_EXPORT HeadersHandlerInterface {
31    public:
~HeadersHandlerInterface()32     virtual ~HeadersHandlerInterface() {}
33 
34     // Called when a new header name-value pair is decoded.  Multiple values for
35     // a given name will be emitted as multiple calls to OnHeader.
36     virtual void OnHeaderDecoded(absl::string_view name,
37                                  absl::string_view value) = 0;
38 
39     // Called when the header block is completely decoded.
40     // Indicates the total number of bytes in this block.
41     // The decoder will not access the handler after this call.
42     // Note that this method might not be called synchronously when the header
43     // block is received on the wire, in case decoding is blocked on receiving
44     // entries on the encoder stream.
45     virtual void OnDecodingCompleted() = 0;
46 
47     // Called when a decoding error has occurred.  No other methods will be
48     // called afterwards.  Implementations are allowed to destroy
49     // the QpackProgressiveDecoder instance synchronously.
50     virtual void OnDecodingErrorDetected(QuicErrorCode error_code,
51                                          absl::string_view error_message) = 0;
52   };
53 
54   // Interface for keeping track of blocked streams for the purpose of enforcing
55   // the limit communicated to peer via QPACK_BLOCKED_STREAMS settings.
56   class QUICHE_EXPORT BlockedStreamLimitEnforcer {
57    public:
~BlockedStreamLimitEnforcer()58     virtual ~BlockedStreamLimitEnforcer() {}
59 
60     // Called when the stream becomes blocked.  Returns true if allowed. Returns
61     // false if limit is violated, in which case QpackProgressiveDecoder signals
62     // an error.
63     // Stream must not be already blocked.
64     virtual bool OnStreamBlocked(QuicStreamId stream_id) = 0;
65 
66     // Called when the stream becomes unblocked.
67     // Stream must be blocked.
68     virtual void OnStreamUnblocked(QuicStreamId stream_id) = 0;
69   };
70 
71   // Visitor to be notified when decoding is completed.
72   class QUICHE_EXPORT DecodingCompletedVisitor {
73    public:
74     virtual ~DecodingCompletedVisitor() = default;
75 
76     // Called when decoding is completed, with Required Insert Count of the
77     // decoded header block.  Required Insert Count is defined at
78     // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#blocked-streams.
79     virtual void OnDecodingCompleted(QuicStreamId stream_id,
80                                      uint64_t required_insert_count) = 0;
81   };
82 
83   QpackProgressiveDecoder() = delete;
84   QpackProgressiveDecoder(QuicStreamId stream_id,
85                           BlockedStreamLimitEnforcer* enforcer,
86                           DecodingCompletedVisitor* visitor,
87                           QpackDecoderHeaderTable* header_table,
88                           HeadersHandlerInterface* handler);
89   QpackProgressiveDecoder(const QpackProgressiveDecoder&) = delete;
90   QpackProgressiveDecoder& operator=(const QpackProgressiveDecoder&) = delete;
91   ~QpackProgressiveDecoder() override;
92 
93   // Provide a data fragment to decode.
94   void Decode(absl::string_view data);
95 
96   // Signal that the entire header block has been received and passed in
97   // through Decode().  No methods must be called afterwards.
98   void EndHeaderBlock();
99 
100   // QpackInstructionDecoder::Delegate implementation.
101   bool OnInstructionDecoded(const QpackInstruction* instruction) override;
102   void OnInstructionDecodingError(QpackInstructionDecoder::ErrorCode error_code,
103                                   absl::string_view error_message) override;
104 
105   // QpackDecoderHeaderTable::Observer implementation.
106   void OnInsertCountReachedThreshold() override;
107   void Cancel() override;
108 
109  private:
110   bool DoIndexedHeaderFieldInstruction();
111   bool DoIndexedHeaderFieldPostBaseInstruction();
112   bool DoLiteralHeaderFieldNameReferenceInstruction();
113   bool DoLiteralHeaderFieldPostBaseInstruction();
114   bool DoLiteralHeaderFieldInstruction();
115   bool DoPrefixInstruction();
116 
117   // Called when an entry is decoded.  Performs validation and calls
118   // HeadersHandlerInterface::OnHeaderDecoded() or OnError() as needed.  Returns
119   // true if header value is valid, false otherwise.  Skips validation if
120   // |value_from_static_table| is true, because static table entries are always
121   // valid.
122   bool OnHeaderDecoded(bool value_from_static_table, absl::string_view name,
123                        absl::string_view value);
124 
125   // Called as soon as EndHeaderBlock() is called and decoding is not blocked.
126   void FinishDecoding();
127 
128   // Called on error.
129   void OnError(QuicErrorCode error_code, absl::string_view error_message);
130 
131   // Calculates Base from |required_insert_count_|, which must be set before
132   // calling this method, and sign bit and Delta Base in the Header Data Prefix,
133   // which are passed in as arguments.  Returns true on success, false on
134   // failure due to overflow/underflow.
135   bool DeltaBaseToBase(bool sign, uint64_t delta_base, uint64_t* base);
136 
137   const QuicStreamId stream_id_;
138 
139   // |prefix_decoder_| only decodes a handful of bytes then it can be
140   // destroyed to conserve memory.  |instruction_decoder_|, on the other hand,
141   // is used until the entire header block is decoded.
142   std::unique_ptr<QpackInstructionDecoder> prefix_decoder_;
143   QpackInstructionDecoder instruction_decoder_;
144 
145   BlockedStreamLimitEnforcer* const enforcer_;
146   DecodingCompletedVisitor* const visitor_;
147   QpackDecoderHeaderTable* const header_table_;
148   HeadersHandlerInterface* const handler_;
149 
150   // Required Insert Count and Base are decoded from the Header Data Prefix.
151   uint64_t required_insert_count_;
152   uint64_t base_;
153 
154   // Required Insert Count is one larger than the largest absolute index of all
155   // referenced dynamic table entries, or zero if no dynamic table entries are
156   // referenced.  |required_insert_count_so_far_| starts out as zero and keeps
157   // track of the Required Insert Count based on entries decoded so far.
158   // After decoding is completed, it is compared to |required_insert_count_|.
159   uint64_t required_insert_count_so_far_;
160 
161   // False until prefix is fully read and decoded.
162   bool prefix_decoded_;
163 
164   // True if waiting for dynamic table entries to arrive.
165   bool blocked_;
166 
167   // Buffer the entire header block after the prefix while decoding is blocked.
168   std::string buffer_;
169 
170   // True until EndHeaderBlock() is called.
171   bool decoding_;
172 
173   // True if a decoding error has been detected.
174   bool error_detected_;
175 
176   // True if QpackDecoderHeaderTable has been destroyed
177   // while decoding is still blocked.
178   bool cancelled_;
179 };
180 
181 }  // namespace quic
182 
183 #endif  // QUICHE_QUIC_CORE_QPACK_QPACK_PROGRESSIVE_DECODER_H_
184