• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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_SPDY_CORE_HPACK_HPACK_DECODER_ADAPTER_H_
6 #define QUICHE_SPDY_CORE_HPACK_HPACK_DECODER_ADAPTER_H_
7 
8 // HpackDecoderAdapter uses http2::HpackDecoder to decode HPACK blocks into
9 // HTTP/2 header lists as outlined in http://tools.ietf.org/html/rfc7541.
10 
11 #include <stddef.h>
12 
13 #include <cstdint>
14 #include <memory>
15 
16 #include "absl/strings/string_view.h"
17 #include "quiche/http2/hpack/decoder/hpack_decoder.h"
18 #include "quiche/http2/hpack/decoder/hpack_decoder_listener.h"
19 #include "quiche/http2/hpack/decoder/hpack_decoder_tables.h"
20 #include "quiche/http2/hpack/http2_hpack_constants.h"
21 #include "quiche/common/platform/api/quiche_export.h"
22 #include "quiche/spdy/core/hpack/hpack_header_table.h"
23 #include "quiche/spdy/core/http2_header_block.h"
24 #include "quiche/spdy/core/spdy_headers_handler_interface.h"
25 
26 namespace spdy {
27 namespace test {
28 class HpackDecoderAdapterPeer;
29 }  // namespace test
30 
31 class QUICHE_EXPORT HpackDecoderAdapter {
32  public:
33   friend test::HpackDecoderAdapterPeer;
34   HpackDecoderAdapter();
35   HpackDecoderAdapter(const HpackDecoderAdapter&) = delete;
36   HpackDecoderAdapter& operator=(const HpackDecoderAdapter&) = delete;
37   ~HpackDecoderAdapter();
38 
39   // Called upon acknowledgement of SETTINGS_HEADER_TABLE_SIZE.
40   void ApplyHeaderTableSizeSetting(size_t size_setting);
41 
42   // Returns the most recently applied value of SETTINGS_HEADER_TABLE_SIZE.
43   size_t GetCurrentHeaderTableSizeSetting() const;
44 
45   // If a SpdyHeadersHandlerInterface is provided, the decoder will emit
46   // headers to it rather than accumulating them in a Http2HeaderBlock.
47   // Does not take ownership of the handler, but does use the pointer until
48   // the current HPACK block is completely decoded.
49   void HandleControlFrameHeadersStart(SpdyHeadersHandlerInterface* handler);
50 
51   // Called as HPACK block fragments arrive. Returns false if an error occurred
52   // while decoding the block. Does not take ownership of headers_data.
53   bool HandleControlFrameHeadersData(const char* headers_data,
54                                      size_t headers_data_length);
55 
56   // Called after a HPACK block has been completely delivered via
57   // HandleControlFrameHeadersData(). Returns false if an error occurred.
58   // |compressed_len| if non-null will be set to the size of the encoded
59   // buffered block that was accumulated in HandleControlFrameHeadersData(),
60   // to support subsequent calculation of compression percentage.
61   // Discards the handler supplied at the start of decoding the block.
62   bool HandleControlFrameHeadersComplete();
63 
64   // Accessor for the most recently decoded headers block. Valid until the next
65   // call to HandleControlFrameHeadersData().
66   // TODO(birenroy): Remove this method when all users of HpackDecoder specify
67   // a SpdyHeadersHandlerInterface.
68   const Http2HeaderBlock& decoded_block() const;
69 
70   // Returns the current dynamic table size, including the 32 bytes per entry
71   // overhead mentioned in RFC 7541 section 4.1.
GetDynamicTableSize()72   size_t GetDynamicTableSize() const {
73     return hpack_decoder_.GetDynamicTableSize();
74   }
75 
76   // Set how much encoded data this decoder is willing to buffer.
77   // TODO(jamessynge): Resolve definition of this value, as it is currently
78   // too tied to a single implementation. We probably want to limit one or more
79   // of these: individual name or value strings, header entries, the entire
80   // header list, or the HPACK block; we probably shouldn't care about the size
81   // of individual transport buffers.
82   void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes);
83 
84   // Specifies the maximum size of an on-the-wire header block that will be
85   // accepted.
86   void set_max_header_block_bytes(size_t max_header_block_bytes);
87 
88   // Error code if an error has occurred, Error::kOk otherwise.
error()89   http2::HpackDecodingError error() const { return error_; }
90 
detailed_error()91   std::string detailed_error() const { return detailed_error_; }
92 
93  private:
94   class QUICHE_EXPORT ListenerAdapter : public http2::HpackDecoderListener {
95    public:
96     ListenerAdapter();
97     ~ListenerAdapter() override;
98 
99     // If a SpdyHeadersHandlerInterface is provided, the decoder will emit
100     // headers to it rather than accumulating them in a Http2HeaderBlock.
101     // Does not take ownership of the handler, but does use the pointer until
102     // the current HPACK block is completely decoded.
103     void set_handler(SpdyHeadersHandlerInterface* handler);
decoded_block()104     const Http2HeaderBlock& decoded_block() const { return decoded_block_; }
105 
106     // Override the HpackDecoderListener methods:
107     void OnHeaderListStart() override;
108     void OnHeader(const std::string& name, const std::string& value) override;
109     void OnHeaderListEnd() override;
110     void OnHeaderErrorDetected(absl::string_view error_message) override;
111 
AddToTotalHpackBytes(size_t delta)112     void AddToTotalHpackBytes(size_t delta) { total_hpack_bytes_ += delta; }
total_hpack_bytes()113     size_t total_hpack_bytes() const { return total_hpack_bytes_; }
114 
115    private:
116     // If the caller doesn't provide a handler, the header list is stored in
117     // this Http2HeaderBlock.
118     Http2HeaderBlock decoded_block_;
119 
120     // If non-NULL, handles decoded headers. Not owned.
121     SpdyHeadersHandlerInterface* handler_;
122 
123     // Total bytes that have been received as input (i.e. HPACK encoded)
124     // in the current HPACK block.
125     size_t total_hpack_bytes_;
126 
127     // Total bytes of the name and value strings in the current HPACK block.
128     size_t total_uncompressed_bytes_;
129   };
130 
131   // Converts calls to HpackDecoderListener into calls to
132   // SpdyHeadersHandlerInterface.
133   ListenerAdapter listener_adapter_;
134 
135   // The actual decoder.
136   http2::HpackDecoder hpack_decoder_;
137 
138   // How much encoded data this decoder is willing to buffer.
139   size_t max_decode_buffer_size_bytes_;
140 
141   // How much encoded data this decoder is willing to process.
142   size_t max_header_block_bytes_;
143 
144   // Flag to keep track of having seen the header block start. Needed at the
145   // moment because HandleControlFrameHeadersStart won't be called if a handler
146   // is not being provided by the caller.
147   bool header_block_started_;
148 
149   // Error code if an error has occurred, Error::kOk otherwise.
150   http2::HpackDecodingError error_;
151   std::string detailed_error_;
152 };
153 
154 }  // namespace spdy
155 
156 #endif  // QUICHE_SPDY_CORE_HPACK_HPACK_DECODER_ADAPTER_H_
157