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