1 // Copyright 2014 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 NET_SPDY_HPACK_DECODER_H_ 6 #define NET_SPDY_HPACK_DECODER_H_ 7 8 #include <map> 9 #include <string> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/macros.h" 14 #include "base/strings/string_piece.h" 15 #include "net/base/net_export.h" 16 #include "net/spdy/hpack_header_table.h" 17 #include "net/spdy/hpack_input_stream.h" 18 #include "net/spdy/spdy_protocol.h" 19 20 // An HpackDecoder decodes header sets as outlined in 21 // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08 22 23 namespace net { 24 25 class HpackHuffmanTable; 26 27 namespace test { 28 class HpackDecoderPeer; 29 } // namespace test 30 31 class NET_EXPORT_PRIVATE HpackDecoder { 32 public: 33 friend class test::HpackDecoderPeer; 34 35 // |table| is an initialized HPACK Huffman table, having an 36 // externally-managed lifetime which spans beyond HpackDecoder. 37 explicit HpackDecoder(const HpackHuffmanTable& table); 38 ~HpackDecoder(); 39 40 // Called upon acknowledgement of SETTINGS_HEADER_TABLE_SIZE. ApplyHeaderTableSizeSetting(size_t size_setting)41 void ApplyHeaderTableSizeSetting(size_t size_setting) { 42 header_table_.SetSettingsHeaderTableSize(size_setting); 43 } 44 45 // Called as headers data arrives. Returns false if an error occurred. 46 // TODO(jgraettinger): A future version of this method will incrementally 47 // parse and deliver headers via SpdyHeadersHandlerInterface. For now, 48 // header data is buffered until HandleControlFrameHeadersComplete(). 49 bool HandleControlFrameHeadersData(SpdyStreamId stream_id, 50 const char* headers_data, 51 size_t headers_data_length); 52 53 // Called after a headers block has been completely delivered via 54 // HandleControlFrameHeadersData(). Returns false if an error occurred. 55 // TODO(jgraettinger): A future version of this method will simply deliver 56 // the Cookie header (which has been incrementally reconstructed) and notify 57 // the visitor that the block is finished. For now, this method decodes the 58 // complete buffered block, and stores results to |decoded_block_|. 59 bool HandleControlFrameHeadersComplete(SpdyStreamId stream_id); 60 61 // Accessor for the most recently decoded headers block. Valid until the next 62 // call to HandleControlFrameHeadersData(). 63 // TODO(jgraettinger): This was added to facilitate re-encoding the block in 64 // SPDY3 format for delivery to the SpdyFramer visitor, and will be removed 65 // with the migration to SpdyHeadersHandlerInterface. decoded_block()66 const std::map<std::string, std::string>& decoded_block() { 67 return decoded_block_; 68 } 69 70 private: 71 // Adds the header representation to |decoded_block_|, applying the 72 // following rules, as per sections 8.1.3.3 & 8.1.3.4 of the HTTP2 draft 73 // specification: 74 // - Multiple values of the Cookie header are joined, delmited by '; '. 75 // This reconstruction is required to properly handle Cookie crumbling. 76 // - Multiple values of other headers are joined and delimited by '\0'. 77 // Note that this may be too accomodating, as the sender's HTTP2 layer 78 // should have already joined and delimited these values. 79 // 80 // Returns false if a pseudo-header field follows a regular header one, which 81 // MUST be treated as malformed, as per sections 8.1.2.1. of the HTTP2 draft 82 // specification. 83 // 84 // TODO(jgraettinger): This method will eventually emit to the 85 // SpdyHeadersHandlerInterface visitor. 86 bool HandleHeaderRepresentation(base::StringPiece name, 87 base::StringPiece value); 88 89 const uint32 max_string_literal_size_; 90 HpackHeaderTable header_table_; 91 92 // Incrementally reconstructed cookie value. 93 std::string cookie_value_; 94 95 // TODO(jgraettinger): Buffer for headers data, and storage for the last- 96 // processed headers block. Both will be removed with the switch to 97 // SpdyHeadersHandlerInterface. 98 std::string headers_block_buffer_; 99 std::map<std::string, std::string> decoded_block_; 100 101 // Flag to keep track of having seen a regular header field. 102 bool regular_header_seen_; 103 104 // Huffman table to be applied to decoded Huffman literals, 105 // and scratch space for storing those decoded literals. 106 const HpackHuffmanTable& huffman_table_; 107 std::string key_buffer_, value_buffer_; 108 109 // Handlers for decoding HPACK opcodes and header representations 110 // (or parts thereof). These methods return true on success and 111 // false on error. 112 bool DecodeNextOpcode(HpackInputStream* input_stream); 113 bool DecodeNextHeaderTableSizeUpdate(HpackInputStream* input_stream); 114 bool DecodeNextIndexedHeader(HpackInputStream* input_stream); 115 bool DecodeNextLiteralHeader(HpackInputStream* input_stream, 116 bool should_index); 117 bool DecodeNextName(HpackInputStream* input_stream, 118 base::StringPiece* next_name); 119 bool DecodeNextStringLiteral(HpackInputStream* input_stream, 120 bool is_header_key, // As distinct from a value. 121 base::StringPiece* output); 122 123 DISALLOW_COPY_AND_ASSIGN(HpackDecoder); 124 }; 125 126 } // namespace net 127 128 #endif // NET_SPDY_HPACK_DECODER_H_ 129