1 // Copyright (c) 2019 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_DECODED_HEADERS_ACCUMULATOR_H_
6 #define QUICHE_QUIC_CORE_QPACK_QPACK_DECODED_HEADERS_ACCUMULATOR_H_
7 
8 #include <cstddef>
9 #include <string>
10 
11 #include "absl/strings/string_view.h"
12 #include "quiche/quic/core/http/quic_header_list.h"
13 #include "quiche/quic/core/qpack/qpack_progressive_decoder.h"
14 #include "quiche/quic/core/quic_error_codes.h"
15 #include "quiche/quic/core/quic_types.h"
16 #include "quiche/quic/platform/api/quic_export.h"
17 
18 namespace quic {
19 
20 class QpackDecoder;
21 
22 // A class that creates and owns a QpackProgressiveDecoder instance, accumulates
23 // decoded headers in a QuicHeaderList, and keeps track of uncompressed and
24 // compressed size so that it can be passed to
25 // QuicHeaderList::OnHeaderBlockEnd().
26 class QUICHE_EXPORT QpackDecodedHeadersAccumulator
27     : public QpackProgressiveDecoder::HeadersHandlerInterface {
28  public:
29   // Visitor interface to signal success or error.
30   // Exactly one method will be called.
31   // Methods may be called synchronously from Decode() and EndHeaderBlock(),
32   // or asynchronously.
33   // Method implementations are allowed to destroy |this|.
34   class QUICHE_EXPORT Visitor {
35    public:
36     virtual ~Visitor() = default;
37 
38     // Called when headers are successfully decoded.  If the uncompressed header
39     // list size including an overhead for each header field exceeds the limit
40     // specified via |max_header_list_size| in QpackDecodedHeadersAccumulator
41     // constructor, then |header_list_size_limit_exceeded| will be true, and
42     // |headers| will be empty but will still have the correct compressed and
43     // uncompressed size
44     // information.
45     virtual void OnHeadersDecoded(QuicHeaderList headers,
46                                   bool header_list_size_limit_exceeded) = 0;
47 
48     // Called when an error has occurred.
49     virtual void OnHeaderDecodingError(QuicErrorCode error_code,
50                                        absl::string_view error_message) = 0;
51   };
52 
53   QpackDecodedHeadersAccumulator(QuicStreamId id, QpackDecoder* qpack_decoder,
54                                  Visitor* visitor, size_t max_header_list_size);
55   virtual ~QpackDecodedHeadersAccumulator() = default;
56 
57   // QpackProgressiveDecoder::HeadersHandlerInterface implementation.
58   // These methods should only be called by |decoder_|.
59   void OnHeaderDecoded(absl::string_view name,
60                        absl::string_view value) override;
61   void OnDecodingCompleted() override;
62   void OnDecodingErrorDetected(QuicErrorCode error_code,
63                                absl::string_view error_message) override;
64 
65   // Decode payload data.
66   // Must not be called if an error has been detected.
67   // Must not be called after EndHeaderBlock().
68   void Decode(absl::string_view data);
69 
70   // Signal end of HEADERS frame.
71   // Must not be called if an error has been detected.
72   // Must not be called more that once.
73   void EndHeaderBlock();
74 
75  private:
76   std::unique_ptr<QpackProgressiveDecoder> decoder_;
77   Visitor* visitor_;
78   // Maximum header list size including overhead.
79   size_t max_header_list_size_;
80   // Uncompressed header list size including overhead, for enforcing the limit.
81   size_t uncompressed_header_bytes_including_overhead_;
82   QuicHeaderList quic_header_list_;
83   // Uncompressed header list size with overhead,
84   // for passing in to QuicHeaderList::OnHeaderBlockEnd().
85   size_t uncompressed_header_bytes_without_overhead_;
86   // Compressed header list size
87   // for passing in to QuicHeaderList::OnHeaderBlockEnd().
88   size_t compressed_header_bytes_;
89 
90   // True if the header size limit has been exceeded.
91   // Input data is still fed to QpackProgressiveDecoder.
92   bool header_list_size_limit_exceeded_;
93 
94   // The following two members are only used for QUICHE_DCHECKs.
95 
96   // True if headers have been completedly and successfully decoded.
97   bool headers_decoded_;
98   // True if an error has been detected during decoding.
99   bool error_detected_;
100 };
101 
102 }  // namespace quic
103 
104 #endif  // QUICHE_QUIC_CORE_QPACK_QPACK_DECODED_HEADERS_ACCUMULATOR_H_
105