15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef NET_SPDY_SPDY_HEADERS_BLOCK_PARSER_H_ 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define NET_SPDY_SPDY_HEADERS_BLOCK_PARSER_H_ 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_piece.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/net_export.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/spdy/spdy_prefixed_buffer_reader.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/spdy/spdy_protocol.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace net { 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A handler class for SPDY headers. 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class SpdyHeadersHandlerInterface { 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~SpdyHeadersHandlerInterface() {} 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // A callback method which notifies when the parser starts handling a new 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // SPDY headers block, this method also notifies on the number of headers in 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the block. 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnHeaderBlock(SpdyStreamId stream_id, 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint32_t num_of_headers) = 0; 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // A callback method which notifies on a SPDY header key value pair. 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnHeader(SpdyStreamId stream_id, 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::StringPiece key, 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::StringPiece value) = 0; 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // A callback method which notifies when the parser finishes handling a SPDY 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // headers block. Also notifies on the total number of bytes in this block. 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void OnHeaderBlockEnd(SpdyStreamId stream_id, 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t header_bytes_parsed) = 0; 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace test { 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class SpdyHeadersBlockParserPeer; 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace test 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This class handles SPDY headers block bytes and parses out key-value pairs 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// as they arrive. This class is not thread-safe, and assumes that all headers 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// block bytes are processed in a single thread. 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class NET_EXPORT_PRIVATE SpdyHeadersBlockParser { 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Bound on acceptable header name or value length. 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static const size_t kMaximumFieldLength; // = 16 * 1024 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Constructor. The handler's OnHeader will be called for every key 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // value pair that we parsed from the headers block. 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SpdyHeadersBlockParser(SpdyMajorVersion spdy_version, 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SpdyHeadersHandlerInterface* handler); 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~SpdyHeadersBlockParser(); 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Handles headers block data as it arrives. Returns false if an error has 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // been set, which can include the recoverable error NEED_MORE_DATA. Returns 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // true if the invocation completes the parse of the entire headers block, 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // in which case the parser is ready for a new headers block. 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool HandleControlFrameHeadersData(SpdyStreamId stream_id, 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const char* headers_data, 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t len); 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) enum ParserError { 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OK, 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Set when parsing failed due to insufficient data. 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // This error is recoverable, by passing in new data. 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NEED_MORE_DATA, 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Set when a complete block has been read, but unprocessed data remains. 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TOO_MUCH_DATA, 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Set when a block exceeds |MaxNumberOfHeadersForVersion| headers. 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HEADER_BLOCK_TOO_LARGE, 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Set when a header key or value exceeds |kMaximumFieldLength|. 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HEADER_FIELD_TOO_LARGE, 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }; 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ParserError get_error() const { return error_; } 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Resets the state of the parser to prepare it for a headers block of a 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // new frame. 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void Reset(); 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Returns the size in bytes of a length field in a SPDY header. 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static size_t LengthFieldSizeForVersion(SpdyMajorVersion spdy_version); 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Returns the maximal number of headers in a SPDY headers block. 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static size_t MaxNumberOfHeadersForVersion(SpdyMajorVersion spdy_version); 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typedef SpdyPrefixedBufferReader Reader; 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Parses and sanity-checks header block length. 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void ParseBlockLength(Reader* reader); 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Parses and sanity-checks header field length. 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void ParseFieldLength(Reader* reader); 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Parses and decodes network-order lengths into |parsed_length|. 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void ParseLength(Reader* reader, uint32_t* parsed_length); 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The state of the parser. 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enum ParserState { 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) READING_HEADER_BLOCK_LEN, 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) READING_KEY_LEN, 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) READING_KEY, 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) READING_VALUE_LEN, 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) READING_VALUE, 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FINISHED_HEADER 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ParserState state_; 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Size in bytes of a length field in the spdy header. 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const size_t length_field_size_; 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The maximal number of headers in a SPDY headers block. 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const size_t max_headers_in_block_; 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // A running total of the bytes parsed since the last call to Reset(). 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t total_bytes_received_; 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Number of key-value pairs until we complete handling the current 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // headers block. 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32_t remaining_key_value_pairs_for_frame_; 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The length of the next header field to be read (either key or value). 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint32_t next_field_length_; 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Handles key-value pairs as we parse them. 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SpdyHeadersHandlerInterface* handler_; 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Holds unprocessed buffer remainders between calls to 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // |HandleControlFrameHeadersData|. 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SpdyPinnableBufferPiece headers_block_prefix_; 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Holds the key of a partially processed header between calls to 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // |HandleControlFrameHeadersData|. 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SpdyPinnableBufferPiece key_; 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The current header block stream identifier. 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SpdyStreamId stream_id_; 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ParserError error_; 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace net 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // NET_SPDY_SPDY_HEADERS_BLOCK_PARSER_H_ 150