blob: 6d2e992c22431ec16d155fcb9916b496e560afad [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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>
vasilvv872e7a32019-03-12 16:42:44 -070010#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050011
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"
bnc098ff612019-07-09 03:24:37 -070014#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050015#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 teama6ef0a62019-03-07 20:34:33 -050018#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
19
20namespace quic {
21
22class QpackHeaderTable;
23
24// Class to decode a single header block.
25class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
bnc098ff612019-07-09 03:24:37 -070026 : public QpackInstructionDecoder::Delegate,
27 public QpackHeaderTable::Observer {
QUICHE teama6ef0a62019-03-07 20:34:33 -050028 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
bnc098ff612019-07-09 03:24:37 -070044 // entries on the encoder stream.
QUICHE teama6ef0a62019-03-07 20:34:33 -050045 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 teama6ef0a62019-03-07 20:34:33 -050061 // 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
bnc098ff612019-07-09 03:24:37 -070072 // QpackHeaderTable::Observer implementation.
73 void OnInsertCountReachedThreshold() override;
74
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 private:
76 bool DoIndexedHeaderFieldInstruction();
77 bool DoIndexedHeaderFieldPostBaseInstruction();
78 bool DoLiteralHeaderFieldNameReferenceInstruction();
79 bool DoLiteralHeaderFieldPostBaseInstruction();
80 bool DoLiteralHeaderFieldInstruction();
81 bool DoPrefixInstruction();
82
bnc098ff612019-07-09 03:24:37 -070083 // Called as soon as EndHeaderBlock() is called and decoding is not blocked.
84 void FinishDecoding();
85
QUICHE teama6ef0a62019-03-07 20:34:33 -050086 // 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 teama6ef0a62019-03-07 20:34:33 -050092 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
bnc098ff612019-07-09 03:24:37 -0700100 QpackHeaderTable* const header_table_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500101 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
bnc098ff612019-07-09 03:24:37 -0700118 // 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 teama6ef0a62019-03-07 20:34:33 -0500124 // 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_