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