QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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> |
vasilvv | 872e7a3 | 2019-03-12 16:42:44 -0700 | [diff] [blame] | 10 | #include <string> |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 11 | |
| 12 | #include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h" |
| 13 | #include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h" |
bnc | 098ff61 | 2019-07-09 03:24:37 -0700 | [diff] [blame] | 14 | #include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 15 | #include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h" |
| 16 | #include "net/third_party/quiche/src/quic/core/quic_types.h" |
| 17 | #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 18 | #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h" |
| 19 | |
| 20 | namespace quic { |
| 21 | |
| 22 | class QpackHeaderTable; |
| 23 | |
| 24 | // Class to decode a single header block. |
| 25 | class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder |
bnc | 098ff61 | 2019-07-09 03:24:37 -0700 | [diff] [blame] | 26 | : public QpackInstructionDecoder::Delegate, |
| 27 | public QpackHeaderTable::Observer { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 28 | public: |
| 29 | // Interface for receiving decoded header block from the decoder. |
| 30 | class QUIC_EXPORT_PRIVATE HeadersHandlerInterface { |
| 31 | public: |
| 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(QuicStringPiece name, |
| 37 | QuicStringPiece 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 |
bnc | 098ff61 | 2019-07-09 03:24:37 -0700 | [diff] [blame] | 44 | // entries on the encoder stream. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 45 | virtual void OnDecodingCompleted() = 0; |
| 46 | |
| 47 | // Called when a decoding error has occurred. No other methods will be |
| 48 | // called afterwards. |
| 49 | virtual void OnDecodingErrorDetected(QuicStringPiece error_message) = 0; |
| 50 | }; |
| 51 | |
| 52 | QpackProgressiveDecoder() = delete; |
| 53 | QpackProgressiveDecoder(QuicStreamId stream_id, |
| 54 | QpackHeaderTable* header_table, |
| 55 | QpackDecoderStreamSender* decoder_stream_sender, |
| 56 | HeadersHandlerInterface* handler); |
| 57 | QpackProgressiveDecoder(const QpackProgressiveDecoder&) = delete; |
| 58 | QpackProgressiveDecoder& operator=(const QpackProgressiveDecoder&) = delete; |
| 59 | ~QpackProgressiveDecoder() override = default; |
| 60 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 61 | // Provide a data fragment to decode. |
| 62 | void Decode(QuicStringPiece data); |
| 63 | |
| 64 | // Signal that the entire header block has been received and passed in |
| 65 | // through Decode(). No methods must be called afterwards. |
| 66 | void EndHeaderBlock(); |
| 67 | |
| 68 | // QpackInstructionDecoder::Delegate implementation. |
| 69 | bool OnInstructionDecoded(const QpackInstruction* instruction) override; |
| 70 | void OnError(QuicStringPiece error_message) override; |
| 71 | |
bnc | 098ff61 | 2019-07-09 03:24:37 -0700 | [diff] [blame] | 72 | // QpackHeaderTable::Observer implementation. |
| 73 | void OnInsertCountReachedThreshold() override; |
| 74 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 75 | private: |
| 76 | bool DoIndexedHeaderFieldInstruction(); |
| 77 | bool DoIndexedHeaderFieldPostBaseInstruction(); |
| 78 | bool DoLiteralHeaderFieldNameReferenceInstruction(); |
| 79 | bool DoLiteralHeaderFieldPostBaseInstruction(); |
| 80 | bool DoLiteralHeaderFieldInstruction(); |
| 81 | bool DoPrefixInstruction(); |
| 82 | |
bnc | 098ff61 | 2019-07-09 03:24:37 -0700 | [diff] [blame] | 83 | // Called as soon as EndHeaderBlock() is called and decoding is not blocked. |
| 84 | void FinishDecoding(); |
| 85 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 86 | // Calculates Base from |required_insert_count_|, which must be set before |
| 87 | // calling this method, and sign bit and Delta Base in the Header Data Prefix, |
| 88 | // which are passed in as arguments. Returns true on success, false on |
| 89 | // failure due to overflow/underflow. |
| 90 | bool DeltaBaseToBase(bool sign, uint64_t delta_base, uint64_t* base); |
| 91 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 92 | const QuicStreamId stream_id_; |
| 93 | |
| 94 | // |prefix_decoder_| only decodes a handful of bytes then it can be |
| 95 | // destroyed to conserve memory. |instruction_decoder_|, on the other hand, |
| 96 | // is used until the entire header block is decoded. |
| 97 | std::unique_ptr<QpackInstructionDecoder> prefix_decoder_; |
| 98 | QpackInstructionDecoder instruction_decoder_; |
| 99 | |
bnc | 098ff61 | 2019-07-09 03:24:37 -0700 | [diff] [blame] | 100 | QpackHeaderTable* const header_table_; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 101 | QpackDecoderStreamSender* const decoder_stream_sender_; |
| 102 | HeadersHandlerInterface* const handler_; |
| 103 | |
| 104 | // Required Insert Count and Base are decoded from the Header Data Prefix. |
| 105 | uint64_t required_insert_count_; |
| 106 | uint64_t base_; |
| 107 | |
| 108 | // Required Insert Count is one larger than the largest absolute index of all |
| 109 | // referenced dynamic table entries, or zero if no dynamic table entries are |
| 110 | // referenced. |required_insert_count_so_far_| starts out as zero and keeps |
| 111 | // track of the Required Insert Count based on entries decoded so far. |
| 112 | // After decoding is completed, it is compared to |required_insert_count_|. |
| 113 | uint64_t required_insert_count_so_far_; |
| 114 | |
| 115 | // False until prefix is fully read and decoded. |
| 116 | bool prefix_decoded_; |
| 117 | |
bnc | 098ff61 | 2019-07-09 03:24:37 -0700 | [diff] [blame] | 118 | // True if waiting for dynamic table entries to arrive. |
| 119 | bool blocked_; |
| 120 | |
| 121 | // Buffer the entire header block after the prefix while decoding is blocked. |
| 122 | std::string buffer_; |
| 123 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 124 | // True until EndHeaderBlock() is called. |
| 125 | bool decoding_; |
| 126 | |
| 127 | // True if a decoding error has been detected. |
| 128 | bool error_detected_; |
| 129 | }; |
| 130 | |
| 131 | } // namespace quic |
| 132 | |
| 133 | #endif // QUICHE_QUIC_CORE_QPACK_QPACK_PROGRESSIVE_DECODER_H_ |