• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 // HpackDecoderState maintains the HPACK decompressor state; i.e. updates the
6 // HPACK dynamic table according to RFC 7541 as the entries in an HPACK block
7 // are decoded, and reads from the static and dynamic tables in order to build
8 // complete header entries. Calls an HpackDecoderListener with the completely
9 // decoded headers (i.e. after resolving table indices into names or values),
10 // thus translating the decoded HPACK entries into HTTP/2 headers.
11 
12 #ifndef QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_
13 #define QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_
14 
15 #include <stddef.h>
16 
17 #include <cstdint>
18 
19 #include "absl/strings/string_view.h"
20 #include "quiche/http2/hpack/decoder/hpack_decoder_listener.h"
21 #include "quiche/http2/hpack/decoder/hpack_decoder_string_buffer.h"
22 #include "quiche/http2/hpack/decoder/hpack_decoder_tables.h"
23 #include "quiche/http2/hpack/decoder/hpack_decoding_error.h"
24 #include "quiche/http2/hpack/decoder/hpack_whole_entry_listener.h"
25 #include "quiche/http2/hpack/http2_hpack_constants.h"
26 #include "quiche/common/platform/api/quiche_export.h"
27 
28 namespace http2 {
29 namespace test {
30 class HpackDecoderStatePeer;
31 }  // namespace test
32 
33 class QUICHE_EXPORT HpackDecoderState : public HpackWholeEntryListener {
34  public:
35   explicit HpackDecoderState(HpackDecoderListener* listener);
36   ~HpackDecoderState() override;
37 
38   HpackDecoderState(const HpackDecoderState&) = delete;
39   HpackDecoderState& operator=(const HpackDecoderState&) = delete;
40 
41   // Set the listener to be notified when a whole entry has been decoded,
42   // including resolving name or name and value references.
43   // The listener may be changed at any time.
listener()44   HpackDecoderListener* listener() const { return listener_; }
45 
46   // ApplyHeaderTableSizeSetting notifies this object that this endpoint has
47   // received a SETTINGS ACK frame acknowledging an earlier SETTINGS frame from
48   // this endpoint specifying a new value for SETTINGS_HEADER_TABLE_SIZE (the
49   // maximum size of the dynamic table that this endpoint will use to decode
50   // HPACK blocks).
51   // Because a SETTINGS frame can contain SETTINGS_HEADER_TABLE_SIZE values,
52   // the caller must keep track of those multiple changes, and make
53   // corresponding calls to this method. In particular, a call must be made
54   // with the lowest value acknowledged by the peer, and a call must be made
55   // with the final value acknowledged, in that order; additional calls may
56   // be made if additional values were sent. These calls must be made between
57   // decoding the SETTINGS ACK, and before the next HPACK block is decoded.
58   void ApplyHeaderTableSizeSetting(uint32_t max_header_table_size);
59 
60   // Returns the most recently applied value of SETTINGS_HEADER_TABLE_SIZE.
GetCurrentHeaderTableSizeSetting()61   size_t GetCurrentHeaderTableSizeSetting() const {
62     return final_header_table_size_;
63   }
64 
65   // OnHeaderBlockStart notifies this object that we're starting to decode the
66   // HPACK payload of a HEADERS or PUSH_PROMISE frame.
67   void OnHeaderBlockStart();
68 
69   // Implement the HpackWholeEntryListener methods, each of which notifies this
70   // object when an entire entry has been decoded.
71   void OnIndexedHeader(size_t index) override;
72   void OnNameIndexAndLiteralValue(
73       HpackEntryType entry_type, size_t name_index,
74       HpackDecoderStringBuffer* value_buffer) override;
75   void OnLiteralNameAndValue(HpackEntryType entry_type,
76                              HpackDecoderStringBuffer* name_buffer,
77                              HpackDecoderStringBuffer* value_buffer) override;
78   void OnDynamicTableSizeUpdate(size_t size) override;
79   void OnHpackDecodeError(HpackDecodingError error,
80                           std::string detailed_error) override;
81 
82   // OnHeaderBlockEnd notifies this object that an entire HPACK block has been
83   // decoded, which might have extended into CONTINUATION blocks.
84   void OnHeaderBlockEnd();
85 
86   // Returns error code after an error has been detected and reported.
87   // No further callbacks will be made to the listener.
error()88   HpackDecodingError error() const { return error_; }
89 
GetDynamicTableSize()90   size_t GetDynamicTableSize() const {
91     return decoder_tables_.current_header_table_size();
92   }
93 
decoder_tables_for_test()94   const HpackDecoderTables& decoder_tables_for_test() const {
95     return decoder_tables_;
96   }
97 
detailed_error()98   std::string detailed_error() const { return detailed_error_; }
99 
100  private:
101   friend class test::HpackDecoderStatePeer;
102 
103   // Reports an error to the listener IF this is the first error detected.
104   void ReportError(HpackDecodingError error, std::string detailed_error);
105 
106   // The static and dynamic HPACK tables.
107   HpackDecoderTables decoder_tables_;
108 
109   // The listener to be notified of headers, the start and end of header
110   // lists, and of errors.
111   HpackDecoderListener* listener_;
112 
113   // The most recent HEADER_TABLE_SIZE setting acknowledged by the peer.
114   uint32_t final_header_table_size_;
115 
116   // The lowest HEADER_TABLE_SIZE setting acknowledged by the peer; valid until
117   // the next HPACK block is decoded.
118   // TODO(jamessynge): Test raising the HEADER_TABLE_SIZE.
119   uint32_t lowest_header_table_size_;
120 
121   // Must the next (first) HPACK entry be a dynamic table size update?
122   bool require_dynamic_table_size_update_;
123 
124   // May the next (first or second) HPACK entry be a dynamic table size update?
125   bool allow_dynamic_table_size_update_;
126 
127   // Have we already seen a dynamic table size update in this HPACK block?
128   bool saw_dynamic_table_size_update_;
129 
130   // Has an error already been detected and reported to the listener?
131   HpackDecodingError error_;
132   std::string detailed_error_;
133 };
134 
135 }  // namespace http2
136 
137 #endif  // QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_
138