1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef NET_SPDY_SPDY_FRAMER_H_ 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define NET_SPDY_SPDY_FRAMER_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <list> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <map> 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <utility> 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h" 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/gtest_prod_util.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/sys_byteorder.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_protocol.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef struct z_stream_s z_stream; // Forward declaration for zlib. 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net { 23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickclass HttpProxyClientSocketPoolTest; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass HttpNetworkLayer; 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass HttpNetworkTransactionTest; 26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickclass SpdyHttpStreamTest; 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdyNetworkTransactionTest; 28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickclass SpdyProxyClientSocketTest; 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdySessionTest; 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdyStreamTest; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace spdy { 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdyFramer; 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdyFramerTest; 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace test { 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass TestSpdyVisitor; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FramerSetEnableCompressionHelper(SpdyFramer* framer, bool compress); 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace test 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A datastructure for holding a set of headers from either a 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SYN_STREAM or SYN_REPLY frame. 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef std::map<std::string, std::string> SpdyHeaderBlock; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A datastructure for holding a set of ID/value pairs for a SETTINGS frame. 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef std::pair<spdy::SettingsFlagsAndId, uint32> SpdySetting; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef std::list<SpdySetting> SpdySettings; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SpdyFramerVisitorInterface is a set of callbacks for the SpdyFramer. 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Implement this interface to receive event callbacks as frames are 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// decoded from the framer. 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdyFramerVisitorInterface { 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~SpdyFramerVisitorInterface() {} 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called if an error is detected in the SpdyFrame protocol. 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnError(SpdyFramer* framer) = 0; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 612c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Called when a control frame is received. 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnControl(const SpdyControlFrame* frame) = 0; 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 642c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Called when a chunk of header data is available. This is called 652c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // after OnControl() is called with the control frame associated with the 662c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // header data being delivered here. 672c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // |stream_id| The stream receiving the header data. 682c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // |header_data| A buffer containing the header data chunk received. 692c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // |len| The length of the header data buffer. A length of zero indicates 702c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // that the header data block has been completely sent. 712c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // When this function returns true the visitor indicates that it accepted 722c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // all of the data. Returning false indicates that that an unrecoverable 732c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // error has occurred, such as bad header data or resource exhaustion. 742c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id, 752c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const char* header_data, 762c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t len) = 0; 772c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 782c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Called when a data frame header is received. The frame's data 792c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // payload will be provided via subsequent calls to 802c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // OnStreamFrameData(). 812c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun virtual void OnDataFrameHeader(const SpdyDataFrame* frame) = 0; 822c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called when data is received. 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |stream_id| The stream receiving data. 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |data| A buffer containing the data received. 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |len| The length of the data buffer. 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When the other side has finished sending data on this stream, 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this method will be called with a zero-length buffer. 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnStreamFrameData(SpdyStreamId stream_id, 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* data, 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t len) = 0; 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdyFramer { 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SPDY states. 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(mbelshe): Can we move these into the implementation 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and avoid exposing through the header. (Needed for test) 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum SpdyState { 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_ERROR, 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_DONE, 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_RESET, 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_AUTO_RESET, 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_READING_COMMON_HEADER, 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER, 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_CONTROL_FRAME_PAYLOAD, 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_IGNORE_REMAINING_PAYLOAD, 1082c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SPDY_FORWARD_STREAM_FRAME, 1092c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, 1102c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SPDY_CONTROL_FRAME_HEADER_BLOCK, 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SPDY error codes. 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum SpdyError { 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_NO_ERROR, 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_INVALID_CONTROL_FRAME, // Control frame is mal-formatted. 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_CONTROL_PAYLOAD_TOO_LARGE, // Control frame payload was too large. 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_ZLIB_INIT_FAILURE, // The Zlib library could not initialize. 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_UNSUPPORTED_VERSION, // Control frame has unsupported version. 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_DECOMPRESS_FAILURE, // There was an error decompressing. 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_COMPRESS_FAILURE, // There was an error compressing. 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LAST_ERROR, // Must be the last entry in the enum. 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1262c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Constant for invalid (or unknown) stream IDs. 1272c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static const SpdyStreamId kInvalidStream; 1282c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 1292c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // The maximum size of header data chunks delivered to the framer visitor 1302c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // through OnControlFrameHeaderData. (It is exposed here for unit test 1312c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // purposes.) 1322c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static const size_t kHeaderDataChunkMaxSize; 1332c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a new Framer. 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer(); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~SpdyFramer(); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set callbacks to be called from the framer. A visitor must be set, or 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // else the framer will likely crash. It is acceptable for the visitor 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to do nothing. If this is called multiple times, only the last visitor 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will be used. 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void set_visitor(SpdyFramerVisitorInterface* visitor) { 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visitor_ = visitor; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Pass data into the framer for parsing. 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns the number of bytes consumed. It is safe to pass more bytes in 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // than may be consumed. 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t ProcessInput(const char* data, size_t len); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Resets the framer state after a frame has been successfully decoded. 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(mbelshe): can we make this private? 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Reset(); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check the state of the framer. 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyError error_code() const { return error_code_; } 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyState state() const { return state_; } 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool MessageFullyRead() { 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return state_ == SPDY_DONE || state_ == SPDY_AUTO_RESET; 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool HasError() { return state_ == SPDY_ERROR; } 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Further parsing utilities. 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Given a control frame, parse out a SpdyHeaderBlock. Only 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // valid for SYN_STREAM and SYN_REPLY frames. 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns true if successfully parsed, false otherwise. 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool ParseHeaderBlock(const SpdyFrame* frame, SpdyHeaderBlock* block); 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1702c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Given a buffer containing a decompressed header block in SPDY 1712c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // serialized format, parse out a SpdyHeaderBlock, putting the results 1722c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // in the given header block. 1732c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Returns true if successfully parsed, false otherwise. 1742c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static bool ParseHeaderBlockInBuffer(const char* header_data, 1752c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t header_length, 1762c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyHeaderBlock* block); 1772c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a SpdySynStreamControlFrame. 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |stream_id| is the id for this stream. 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |associated_stream_id| is the associated stream id for this stream. 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |priority| is the priority (0-3) for this stream. 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |flags| is the flags to use with the data. 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // To mark this frame as the last frame, enable CONTROL_FLAG_FIN. 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |compressed| specifies whether the frame should be compressed. 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |headers| is the header block to include in the frame. 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdySynStreamControlFrame* CreateSynStream(SpdyStreamId stream_id, 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyStreamId associated_stream_id, 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int priority, 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyControlFlags flags, 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool compressed, 1912c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyHeaderBlock* headers); 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 193201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Create a SpdySynReplyControlFrame. 194201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // |stream_id| is the stream for this frame. 195201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // |flags| is the flags to use with the data. 196201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // To mark this frame as the last frame, enable CONTROL_FLAG_FIN. 197201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // |compressed| specifies whether the frame should be compressed. 198201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // |headers| is the header block to include in the frame. 199201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdySynReplyControlFrame* CreateSynReply(SpdyStreamId stream_id, 200201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyControlFlags flags, 201201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch bool compressed, 2022c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyHeaderBlock* headers); 203201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static SpdyRstStreamControlFrame* CreateRstStream(SpdyStreamId stream_id, 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyStatusCodes status); 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Creates an instance of SpdySettingsControlFrame. The SETTINGS frame is 208201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // used to communicate name/value pairs relevant to the communication channel. 209201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // TODO(mbelshe): add the name/value pairs!! 210201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch static SpdySettingsControlFrame* CreateSettings(const SpdySettings& values); 211201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 2122c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static SpdyNoOpControlFrame* CreateNopFrame(); 2132c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 2142c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Creates an instance of SpdyPingControlFrame. The unique_id is used to 2152c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // identify the ping request/response. 2162c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static SpdyPingControlFrame* CreatePingFrame(uint32 unique_id); 217201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Creates an instance of SpdyGoAwayControlFrame. The GOAWAY frame is used 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // prior to the shutting down of the TCP connection, and includes the 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // stream_id of the last stream the sender of the frame is willing to process 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to completion. 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static SpdyGoAwayControlFrame* CreateGoAway( 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyStreamId last_accepted_stream_id); 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 225201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Creates an instance of SpdyHeadersControlFrame. The HEADERS frame is used 226201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // for sending additional headers outside of a SYN_STREAM/SYN_REPLY. The 227201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // arguments are the same as for CreateSynReply. 228201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyHeadersControlFrame* CreateHeaders(SpdyStreamId stream_id, 229201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyControlFlags flags, 230201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch bool compressed, 2312c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyHeaderBlock* headers); 232201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Creates an instance of SpdyWindowUpdateControlFrame. The WINDOW_UPDATE 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // frame is used to implement per stream flow control in SPDY. 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static SpdyWindowUpdateControlFrame* CreateWindowUpdate( 236201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyStreamId stream_id, 237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch uint32 delta_window_size); 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Given a SpdySettingsControlFrame, extract the settings. 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns true on successful parse, false otherwise. 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static bool ParseSettings(const SpdySettingsControlFrame* frame, 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdySettings* settings); 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a data frame. 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |stream_id| is the stream for this frame 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |data| is the data to be included in the frame. 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |len| is the length of the data 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |flags| is the flags to use with the data. 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // To create a compressed frame, enable DATA_FLAG_COMPRESSED. 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // To mark this frame as the last data frame, enable DATA_FLAG_FIN. 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyDataFrame* CreateDataFrame(SpdyStreamId stream_id, const char* data, 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint32 len, SpdyDataFlags flags); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTES about frame compression. 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We want spdy to compress headers across the entire session. As long as 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the session is over TCP, frames are sent serially. The client & server 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // can each compress frames in the same order and then compress them in that 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // order, and the remote can do the reverse. However, we ultimately want 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the creation of frames to be less sensitive to order so that they can be 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // placed over a UDP based protocol and yet still benefit from some 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // compression. We don't know of any good compression protocol which does 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // not build its state in a serial (stream based) manner.... For now, we're 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // using zlib anyway. 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Compresses a SpdyFrame. 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // On success, returns a new SpdyFrame with the payload compressed. 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Compression state is maintained as part of the SpdyFramer. 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returned frame must be freed with "delete". 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // On failure, returns NULL. 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrame* CompressFrame(const SpdyFrame& frame); 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Decompresses a SpdyFrame. 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // On success, returns a new SpdyFrame with the payload decompressed. 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Compression state is maintained as part of the SpdyFramer. 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returned frame must be freed with "delete". 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // On failure, returns NULL. 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrame* DecompressFrame(const SpdyFrame& frame); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a copy of a frame. 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returned frame must be freed with "delete". 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrame* DuplicateFrame(const SpdyFrame& frame); 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns true if a frame could be compressed. 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool IsCompressible(const SpdyFrame& frame) const; 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2862c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Get the minimum size of the control frame for the given control frame 2872c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // type. This is useful for validating frame blocks. 2882c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static size_t GetMinimumControlFrameSize(SpdyControlType type); 2892c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 2902c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Get the stream ID for the given control frame (SYN_STREAM, SYN_REPLY, and 2912c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // HEADERS). If the control frame is NULL or of another type, this 2922c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // function returns kInvalidStream. 2932c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static SpdyStreamId GetControlFrameStreamId( 2942c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyControlFrame* control_frame); 2952c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 2962c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // For ease of testing and experimentation we can tweak compression on/off. 2972c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun void set_enable_compression(bool value); 2982c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 2992c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // SPDY will by default validate the length of incoming control 3002c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // frames. Set validation to false if you do not want this behavior. 3012c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun void set_validate_control_frame_sizes(bool value); 3022c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static void set_enable_compression_default(bool value); 3032c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For debugging. 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const char* StateToString(int state); 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const char* ErrorCodeToString(int error_code); 3072c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static const char* StatusCodeToString(int status_code); 3082c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static const char* ControlTypeToString(SpdyControlType type); 3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static void set_protocol_version(int version) { spdy_version_= version; } 3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static int protocol_version() { return spdy_version_; } 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Export the compression dictionary 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const char kDictionary[]; 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const int kDictionarySize; 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 3173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, DataCompression); 318201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ExpandBuffer_HeapSmash); 319201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HugeHeaderBlock); 3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, UnclosedStreamDataCompressors); 321201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, 322201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch UncompressLargerThanFrameBufferInitialSize); 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class net::HttpNetworkLayer; // This is temporary for the server. 324731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick friend class net::HttpNetworkTransactionTest; 325731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick friend class net::HttpProxyClientSocketPoolTest; 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class net::SpdyHttpStreamTest; 327731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick friend class net::SpdyNetworkTransactionTest; 328731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick friend class net::SpdyProxyClientSocketTest; 329731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick friend class net::SpdySessionTest; 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class net::SpdyStreamTest; 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class test::TestSpdyVisitor; 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend void test::FramerSetEnableCompressionHelper(SpdyFramer* framer, 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool compress); 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 335201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // The initial size of the control frame buffer; this is used internally 336201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // as we parse through control frames. (It is exposed here for unit test 337201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // purposes.) 3382c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // This is only used when compression is enabled; otherwise, 3392c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // kUncompressedControlFrameBufferInitialSize is used. 340201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch static size_t kControlFrameBufferInitialSize; 341201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 342201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // The maximum size of the control frame buffer that we support. 343201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // TODO(mbelshe): We should make this stream-based so there are no limits. 344201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch static size_t kControlFrameBufferMaxSize; 345201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef std::map<SpdyStreamId, z_stream*> CompressorMap; 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Internal breakout from ProcessInput. Returns the number of bytes 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // consumed from the data. 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t ProcessCommonHeader(const char* data, size_t len); 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ProcessControlFrameHeader(); 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t ProcessControlFramePayload(const char* data, size_t len); 3542c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t ProcessControlFrameBeforeHeaderBlock(const char* data, size_t len); 3552c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // TODO(hkhalil): Rename to ProcessControlFrameHeaderBlock once said flag is 3562c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // removed, replacing the old method. 3572c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t NewProcessControlFrameHeaderBlock(const char* data, size_t len); 3582c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t ProcessControlFrameHeaderBlock(const char* data, size_t len); 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t ProcessDataFramePayload(const char* data, size_t len); 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get (and lazily initialize) the ZLib state. 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* GetHeaderCompressor(); 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* GetHeaderDecompressor(); 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* GetStreamCompressor(SpdyStreamId id); 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* GetStreamDecompressor(SpdyStreamId id); 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Compression helpers 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyControlFrame* CompressControlFrame(const SpdyControlFrame& frame); 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyDataFrame* CompressDataFrame(const SpdyDataFrame& frame); 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyControlFrame* DecompressControlFrame(const SpdyControlFrame& frame); 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyDataFrame* DecompressDataFrame(const SpdyDataFrame& frame); 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrame* CompressFrameWithZStream(const SpdyFrame& frame, 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* compressor); 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrame* DecompressFrameWithZStream(const SpdyFrame& frame, 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* decompressor); 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CleanupCompressorForStream(SpdyStreamId id); 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CleanupDecompressorForStream(SpdyStreamId id); 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CleanupStreamCompressorsAndDecompressors(); 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Not used (yet) 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t BytesSafeToRead() const; 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3832c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Deliver the given control frame's compressed headers block to the visitor 3842c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // in decompressed form, in chunks. Returns true if the visitor has 3852c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // accepted all of the chunks. 3862c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool IncrementallyDecompressControlFrameHeaderData( 3872c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyControlFrame* frame); 3882c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 3892c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Deliver the given control frame's compressed headers block to the visitor 3902c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // in decompressed form, in chunks. Returns true if the visitor has 3912c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // accepted all of the chunks. 3922c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool IncrementallyDecompressControlFrameHeaderData( 3932c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyControlFrame* frame, 3942c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const char* data, 3952c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t len); 3962c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 3972c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Deliver the given control frame's uncompressed headers block to the 3982c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // visitor in chunks. Returns true if the visitor has accepted all of the 3992c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // chunks. 4002c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool IncrementallyDeliverControlFrameHeaderData(const SpdyControlFrame* frame, 4012c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const char* data, 4022c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t len); 4032c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4042c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Utility to copy the given data block to the current frame buffer, up 4052c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // to the given maximum number of bytes, and update the buffer 4062c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // data (pointer and length). Returns the number of bytes 4072c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // read, and: 4082c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // *data is advanced the number of bytes read. 4092c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // *len is reduced by the number of bytes read. 4102c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t UpdateCurrentFrameBuffer(const char** data, size_t* len, 4112c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t max_bytes); 4122c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set the error code and moves the framer into the error state. 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void set_error(SpdyError error); 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Expands the control frame buffer to accomodate a particular payload size. 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ExpandControlFrameBuffer(size_t size); 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Given a frame, breakdown the variable payload length, the static header 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // header length, and variable payload pointer. 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool GetFrameBoundaries(const SpdyFrame& frame, int* payload_length, 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* header_length, const char** payload) const; 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int num_stream_compressors() const { return stream_compressors_.size(); } 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int num_stream_decompressors() const { return stream_decompressors_.size(); } 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4272c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // The initial size of the control frame buffer when compression is disabled. 4282c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // This exists because we don't do stream (de)compressed control frame data to 4292c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // our visitor; we instead buffer the entirety of the control frame and then 4302c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // decompress in one fell swoop. 4312c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Since this is only used for control frame headers, the maximum control 4322c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // frame header size (18B) is sufficient; all remaining control frame data is 4332c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // streamed to the visitor. 4342c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // In addition to the maximum control frame header size, we account for any 4352c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // LOAS checksumming (16B) that may occur in the VTL case. 4362c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static const size_t kUncompressedControlFrameBufferInitialSize = 18 + 16; 4372c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4382c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // The size of the buffer into which compressed frames are inflated. 4392c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun static const size_t kDecompressionBufferSize = 8 * 1024; 4402c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyState state_; 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyError error_code_; 4432c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t remaining_data_; 4442c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4452c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // The number of bytes remaining to read from the current control frame's 4462c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // payload. 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t remaining_control_payload_; 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4492c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // The number of bytes remaining to read from the current control frame's 4502c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // headers. Note that header data blocks (for control types that have them) 4512c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // are part of the frame's payload, and not the frame's headers. 4522c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t remaining_control_header_; 4532c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char* current_frame_buffer_; 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t current_frame_len_; // Number of bytes read into the current_frame_. 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t current_frame_capacity_; 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4582c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool validate_control_frame_sizes_; 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool enable_compression_; // Controls all compression 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SPDY header compressors. 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<z_stream> header_compressor_; 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<z_stream> header_decompressor_; 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Per-stream data compressors. 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompressorMap stream_compressors_; 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompressorMap stream_decompressors_; 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramerVisitorInterface* visitor_; 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static bool compression_default_; 4713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static int spdy_version_; 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace spdy 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // NET_SPDY_SPDY_FRAMER_H_ 477