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 <string> 14 15 #include "absl/strings/string_view.h" 16 #include "quiche/http2/hpack/decoder/hpack_decoder.h" 17 #include "quiche/http2/hpack/decoder/hpack_decoder_listener.h" 18 #include "quiche/http2/hpack/decoder/hpack_decoding_error.h" 19 #include "quiche/common/platform/api/quiche_export.h" 20 #include "quiche/spdy/core/http2_header_block.h" 21 #include "quiche/spdy/core/no_op_headers_handler.h" 22 #include "quiche/spdy/core/spdy_headers_handler_interface.h" 23 24 namespace spdy { 25 namespace test { 26 class HpackDecoderAdapterPeer; 27 } // namespace test 28 29 class QUICHE_EXPORT HpackDecoderAdapter { 30 public: 31 friend test::HpackDecoderAdapterPeer; 32 HpackDecoderAdapter(); 33 HpackDecoderAdapter(const HpackDecoderAdapter&) = delete; 34 HpackDecoderAdapter& operator=(const HpackDecoderAdapter&) = delete; 35 ~HpackDecoderAdapter(); 36 37 // Called upon acknowledgement of SETTINGS_HEADER_TABLE_SIZE. 38 void ApplyHeaderTableSizeSetting(size_t size_setting); 39 40 // Returns the most recently applied value of SETTINGS_HEADER_TABLE_SIZE. 41 size_t GetCurrentHeaderTableSizeSetting() const; 42 43 // The decoder will emit headers to the provided SpdyHeadersHandlerInterface. 44 // Does not take ownership of the handler, but does use the pointer until 45 // the current HPACK block is completely decoded. 46 // `handler` must not be nullptr. 47 void HandleControlFrameHeadersStart(SpdyHeadersHandlerInterface* handler); 48 49 // Called as HPACK block fragments arrive. Returns false if an error occurred 50 // while decoding the block. Does not take ownership of headers_data. 51 bool HandleControlFrameHeadersData(const char* headers_data, 52 size_t headers_data_length); 53 54 // Called after a HPACK block has been completely delivered via 55 // HandleControlFrameHeadersData(). Returns false if an error occurred. 56 // |compressed_len| if non-null will be set to the size of the encoded 57 // buffered block that was accumulated in HandleControlFrameHeadersData(), 58 // to support subsequent calculation of compression percentage. 59 // Discards the handler supplied at the start of decoding the block. 60 bool HandleControlFrameHeadersComplete(); 61 62 // Returns the current dynamic table size, including the 32 bytes per entry 63 // overhead mentioned in RFC 7541 section 4.1. GetDynamicTableSize()64 size_t GetDynamicTableSize() const { 65 return hpack_decoder_.GetDynamicTableSize(); 66 } 67 68 // Set how much encoded data this decoder is willing to buffer. 69 // TODO(jamessynge): Resolve definition of this value, as it is currently 70 // too tied to a single implementation. We probably want to limit one or more 71 // of these: individual name or value strings, header entries, the entire 72 // header list, or the HPACK block; we probably shouldn't care about the size 73 // of individual transport buffers. 74 void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes); 75 76 // Specifies the maximum size of an on-the-wire header block that will be 77 // accepted. 78 void set_max_header_block_bytes(size_t max_header_block_bytes); 79 80 // Error code if an error has occurred, Error::kOk otherwise. error()81 http2::HpackDecodingError error() const { return error_; } 82 83 private: 84 class QUICHE_EXPORT ListenerAdapter : public http2::HpackDecoderListener { 85 public: 86 ListenerAdapter(); 87 ~ListenerAdapter() override; 88 89 // Sets the SpdyHeadersHandlerInterface to which headers are emitted. 90 // Does not take ownership of the handler, but does use the pointer until 91 // the current HPACK block is completely decoded. 92 // `handler` must not be nullptr. 93 void set_handler(SpdyHeadersHandlerInterface* handler); 94 95 // From HpackDecoderListener 96 void OnHeaderListStart() override; 97 void OnHeader(absl::string_view name, absl::string_view value) override; 98 void OnHeaderListEnd() override; 99 void OnHeaderErrorDetected(absl::string_view error_message) override; 100 AddToTotalHpackBytes(size_t delta)101 void AddToTotalHpackBytes(size_t delta) { total_hpack_bytes_ += delta; } total_hpack_bytes()102 size_t total_hpack_bytes() const { return total_hpack_bytes_; } 103 104 private: 105 NoOpHeadersHandler no_op_handler_; 106 107 // Handles decoded headers. 108 SpdyHeadersHandlerInterface* handler_; 109 110 // Total bytes that have been received as input (i.e. HPACK encoded) 111 // in the current HPACK block. 112 size_t total_hpack_bytes_; 113 114 // Total bytes of the name and value strings in the current HPACK block. 115 size_t total_uncompressed_bytes_; 116 }; 117 118 // Converts calls to HpackDecoderListener into calls to 119 // SpdyHeadersHandlerInterface. 120 ListenerAdapter listener_adapter_; 121 122 // The actual decoder. 123 http2::HpackDecoder hpack_decoder_; 124 125 // How much encoded data this decoder is willing to buffer. 126 size_t max_decode_buffer_size_bytes_; 127 128 // How much encoded data this decoder is willing to process. 129 size_t max_header_block_bytes_; 130 131 // Flag to keep track of having seen the header block start. Needed at the 132 // moment because HandleControlFrameHeadersStart won't be called if a handler 133 // is not being provided by the caller. 134 bool header_block_started_; 135 136 // Error code if an error has occurred, Error::kOk otherwise. 137 http2::HpackDecodingError error_; 138 }; 139 140 } // namespace spdy 141 142 #endif // QUICHE_SPDY_CORE_HPACK_HPACK_DECODER_ADAPTER_H_ 143