Home | History | Annotate | Download | only in spdy
      1 // Copyright (c) 2012 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_SPDY_FRAMER_H_
      6 #define NET_SPDY_SPDY_FRAMER_H_
      7 
      8 #include <list>
      9 #include <map>
     10 #include <string>
     11 #include <utility>
     12 #include <vector>
     13 
     14 #include "base/basictypes.h"
     15 #include "base/gtest_prod_util.h"
     16 #include "base/memory/scoped_ptr.h"
     17 #include "base/sys_byteorder.h"
     18 #include "net/base/net_export.h"
     19 #include "net/spdy/spdy_header_block.h"
     20 #include "net/spdy/spdy_protocol.h"
     21 
     22 // TODO(akalin): Remove support for CREDENTIAL frames.
     23 
     24 typedef struct z_stream_s z_stream;  // Forward declaration for zlib.
     25 
     26 namespace net {
     27 
     28 class HttpProxyClientSocketPoolTest;
     29 class HttpNetworkLayer;
     30 class HttpNetworkTransactionTest;
     31 class SpdyHttpStreamTest;
     32 class SpdyNetworkTransactionTest;
     33 class SpdyProxyClientSocketTest;
     34 class SpdySessionTest;
     35 class SpdyStreamTest;
     36 class SpdyWebSocketStreamTest;
     37 class WebSocketJobTest;
     38 
     39 class SpdyFramer;
     40 class SpdyFrameBuilder;
     41 class SpdyFramerTest;
     42 
     43 namespace test {
     44 
     45 class TestSpdyVisitor;
     46 
     47 }  // namespace test
     48 
     49 // A datastructure for holding a set of headers from a HEADERS, PUSH_PROMISE,
     50 // SYN_STREAM, or SYN_REPLY frame.
     51 typedef std::map<std::string, std::string> SpdyHeaderBlock;
     52 
     53 // A datastructure for holding the ID and flag fields for SETTINGS.
     54 // Conveniently handles converstion to/from wire format.
     55 class NET_EXPORT_PRIVATE SettingsFlagsAndId {
     56  public:
     57   static SettingsFlagsAndId FromWireFormat(int version, uint32 wire);
     58 
     59   SettingsFlagsAndId() : flags_(0), id_(0) {}
     60 
     61   // TODO(hkhalil): restrict to enums instead of free-form ints.
     62   SettingsFlagsAndId(uint8 flags, uint32 id);
     63 
     64   uint32 GetWireFormat(int version) const;
     65 
     66   uint32 id() const { return id_; }
     67   uint8 flags() const { return flags_; }
     68 
     69  private:
     70   static void ConvertFlagsAndIdForSpdy2(uint32* val);
     71 
     72   uint8 flags_;
     73   uint32 id_;
     74 };
     75 
     76 // SettingsMap has unique (flags, value) pair for given SpdySettingsIds ID.
     77 typedef std::pair<SpdySettingsFlags, uint32> SettingsFlagsAndValue;
     78 typedef std::map<SpdySettingsIds, SettingsFlagsAndValue> SettingsMap;
     79 
     80 // A datastrcture for holding the contents of a CREDENTIAL frame.
     81 // TODO(hkhalil): Remove, use SpdyCredentialIR instead.
     82 struct NET_EXPORT_PRIVATE SpdyCredential {
     83   SpdyCredential();
     84   ~SpdyCredential();
     85 
     86   uint16 slot;
     87   std::vector<std::string> certs;
     88   std::string proof;
     89 };
     90 
     91 // Scratch space necessary for processing SETTINGS frames.
     92 struct NET_EXPORT_PRIVATE SpdySettingsScratch {
     93   SpdySettingsScratch() { Reset(); }
     94 
     95   void Reset() {
     96     setting_buf_len = 0;
     97     last_setting_id = 0;
     98   }
     99 
    100   // Buffer contains up to one complete key/value pair.
    101   char setting_buf[8];
    102 
    103   // The amount of the buffer that is filled with valid data.
    104   size_t setting_buf_len;
    105 
    106   // The ID of the last setting that was processed in the current SETTINGS
    107   // frame. Used for detecting out-of-order or duplicate keys within a settings
    108   // frame. Set to 0 before first key/value pair is processed.
    109   uint32 last_setting_id;
    110 };
    111 
    112 // SpdyFramerVisitorInterface is a set of callbacks for the SpdyFramer.
    113 // Implement this interface to receive event callbacks as frames are
    114 // decoded from the framer.
    115 //
    116 // Control frames that contain SPDY header blocks (SYN_STREAM, SYN_REPLY,
    117 // HEADER, and PUSH_PROMISE) are processed in fashion that allows the
    118 // decompressed header block to be delivered in chunks to the visitor.
    119 // The following steps are followed:
    120 //   1. OnSynStream, OnSynReply, OnHeaders, or OnPushPromise is called.
    121 //   2. Repeated: OnControlFrameHeaderData is called with chunks of the
    122 //      decompressed header block. In each call the len parameter is greater
    123 //      than zero.
    124 //   3. OnControlFrameHeaderData is called with len set to zero, indicating
    125 //      that the full header block has been delivered for the control frame.
    126 // During step 2 the visitor may return false, indicating that the chunk of
    127 // header data could not be handled by the visitor (typically this indicates
    128 // resource exhaustion). If this occurs the framer will discontinue
    129 // delivering chunks to the visitor, set a SPDY_CONTROL_PAYLOAD_TOO_LARGE
    130 // error, and clean up appropriately. Note that this will cause the header
    131 // decompressor to lose synchronization with the sender's header compressor,
    132 // making the SPDY session unusable for future work. The visitor's OnError
    133 // function should deal with this condition by closing the SPDY connection.
    134 class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface {
    135  public:
    136   virtual ~SpdyFramerVisitorInterface() {}
    137 
    138   // Called if an error is detected in the SpdyFrame protocol.
    139   virtual void OnError(SpdyFramer* framer) = 0;
    140 
    141   // Called when a data frame header is received. The frame's data
    142   // payload will be provided via subsequent calls to
    143   // OnStreamFrameData().
    144   virtual void OnDataFrameHeader(SpdyStreamId stream_id,
    145                                  size_t length,
    146                                  bool fin) = 0;
    147 
    148   // Called when data is received.
    149   // |stream_id| The stream receiving data.
    150   // |data| A buffer containing the data received.
    151   // |len| The length of the data buffer.
    152   // When the other side has finished sending data on this stream,
    153   // this method will be called with a zero-length buffer.
    154   virtual void OnStreamFrameData(SpdyStreamId stream_id,
    155                                  const char* data,
    156                                  size_t len,
    157                                  bool fin) = 0;
    158 
    159   // Called when a chunk of header data is available. This is called
    160   // after OnSynStream, OnSynReply, OnHeaders(), or OnPushPromise.
    161   // |stream_id| The stream receiving the header data.
    162   // |header_data| A buffer containing the header data chunk received.
    163   // |len| The length of the header data buffer. A length of zero indicates
    164   //       that the header data block has been completely sent.
    165   // When this function returns true the visitor indicates that it accepted
    166   // all of the data. Returning false indicates that that an unrecoverable
    167   // error has occurred, such as bad header data or resource exhaustion.
    168   virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
    169                                         const char* header_data,
    170                                         size_t len) = 0;
    171 
    172   // Called when a SYN_STREAM frame is received.
    173   // Note that header block data is not included. See
    174   // OnControlFrameHeaderData().
    175   virtual void OnSynStream(SpdyStreamId stream_id,
    176                            SpdyStreamId associated_stream_id,
    177                            SpdyPriority priority,
    178                            uint8 credential_slot,
    179                            bool fin,
    180                            bool unidirectional) = 0;
    181 
    182   // Called when a SYN_REPLY frame is received.
    183   // Note that header block data is not included. See
    184   // OnControlFrameHeaderData().
    185   virtual void OnSynReply(SpdyStreamId stream_id, bool fin) = 0;
    186 
    187   // Called when a RST_STREAM frame has been parsed.
    188   virtual void OnRstStream(SpdyStreamId stream_id,
    189                            SpdyRstStreamStatus status) = 0;
    190 
    191   // Called when a SETTINGS frame is received.
    192   // |clear_persisted| True if the respective flag is set on the SETTINGS frame.
    193   virtual void OnSettings(bool clear_persisted) {}
    194 
    195   // Called when a complete setting within a SETTINGS frame has been parsed and
    196   // validated.
    197   virtual void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) = 0;
    198 
    199   // Called when a PING frame has been parsed.
    200   virtual void OnPing(uint32 unique_id) = 0;
    201 
    202   // Called when a GOAWAY frame has been parsed.
    203   virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
    204                         SpdyGoAwayStatus status) = 0;
    205 
    206   // Called when a HEADERS frame is received.
    207   // Note that header block data is not included. See
    208   // OnControlFrameHeaderData().
    209   virtual void OnHeaders(SpdyStreamId stream_id, bool fin) = 0;
    210 
    211   // Called when a WINDOW_UPDATE frame has been parsed.
    212   virtual void OnWindowUpdate(SpdyStreamId stream_id,
    213                               uint32 delta_window_size) = 0;
    214 
    215   // Called when a chunk of payload data for a credential frame is available.
    216   // |header_data| A buffer containing the header data chunk received.
    217   // |len| The length of the header data buffer. A length of zero indicates
    218   //       that the header data block has been completely sent.
    219   // When this function returns true the visitor indicates that it accepted
    220   // all of the data. Returning false indicates that that an unrecoverable
    221   // error has occurred, such as bad header data or resource exhaustion.
    222   virtual bool OnCredentialFrameData(const char* credential_data,
    223                                      size_t len) = 0;
    224 
    225   // Called when a BLOCKED frame has been parsed.
    226   virtual void OnBlocked(SpdyStreamId stream_id) {}
    227 
    228   // Called when a PUSH_PROMISE frame is received.
    229   // Note that header block data is not included. See
    230   // OnControlFrameHeaderData().
    231   virtual void OnPushPromise(SpdyStreamId stream_id,
    232                              SpdyStreamId promised_stream_id) = 0;
    233 };
    234 
    235 // Optionally, and in addition to SpdyFramerVisitorInterface, a class supporting
    236 // SpdyFramerDebugVisitorInterface may be used in conjunction with SpdyFramer in
    237 // order to extract debug/internal information about the SpdyFramer as it
    238 // operates.
    239 //
    240 // Most SPDY implementations need not bother with this interface at all.
    241 class NET_EXPORT_PRIVATE SpdyFramerDebugVisitorInterface {
    242  public:
    243   virtual ~SpdyFramerDebugVisitorInterface() {}
    244 
    245   // Called after compressing a frame with a payload of
    246   // a list of name-value pairs.
    247   // |payload_len| is the uncompressed payload size.
    248   // |frame_len| is the compressed frame size.
    249   virtual void OnSendCompressedFrame(SpdyStreamId stream_id,
    250                                      SpdyFrameType type,
    251                                      size_t payload_len,
    252                                      size_t frame_len) {}
    253 
    254   // Called when a frame containing a compressed payload of
    255   // name-value pairs is received.
    256   // |frame_len| is the compressed frame size.
    257   virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id,
    258                                         SpdyFrameType type,
    259                                         size_t frame_len) {}
    260 };
    261 
    262 class NET_EXPORT_PRIVATE SpdyFramer {
    263  public:
    264   // SPDY states.
    265   // TODO(mbelshe): Can we move these into the implementation
    266   //                and avoid exposing through the header.  (Needed for test)
    267   enum SpdyState {
    268     SPDY_ERROR,
    269     SPDY_RESET,
    270     SPDY_AUTO_RESET,
    271     SPDY_READING_COMMON_HEADER,
    272     SPDY_CONTROL_FRAME_PAYLOAD,
    273     SPDY_IGNORE_REMAINING_PAYLOAD,
    274     SPDY_FORWARD_STREAM_FRAME,
    275     SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK,
    276     SPDY_CONTROL_FRAME_HEADER_BLOCK,
    277     SPDY_CREDENTIAL_FRAME_PAYLOAD,
    278     SPDY_SETTINGS_FRAME_PAYLOAD,
    279   };
    280 
    281   // SPDY error codes.
    282   enum SpdyError {
    283     SPDY_NO_ERROR,
    284     SPDY_INVALID_CONTROL_FRAME,        // Control frame is mal-formatted.
    285     SPDY_CONTROL_PAYLOAD_TOO_LARGE,    // Control frame payload was too large.
    286     SPDY_ZLIB_INIT_FAILURE,            // The Zlib library could not initialize.
    287     SPDY_UNSUPPORTED_VERSION,          // Control frame has unsupported version.
    288     SPDY_DECOMPRESS_FAILURE,           // There was an error decompressing.
    289     SPDY_COMPRESS_FAILURE,             // There was an error compressing.
    290     SPDY_CREDENTIAL_FRAME_CORRUPT,     // CREDENTIAL frame could not be parsed.
    291     SPDY_INVALID_DATA_FRAME_FLAGS,     // Data frame has invalid flags.
    292     SPDY_INVALID_CONTROL_FRAME_FLAGS,  // Control frame has invalid flags.
    293 
    294     LAST_ERROR,  // Must be the last entry in the enum.
    295   };
    296 
    297   // Constant for invalid (or unknown) stream IDs.
    298   static const SpdyStreamId kInvalidStream;
    299 
    300   // The maximum size of header data chunks delivered to the framer visitor
    301   // through OnControlFrameHeaderData. (It is exposed here for unit test
    302   // purposes.)
    303   static const size_t kHeaderDataChunkMaxSize;
    304 
    305   // Serializes a SpdyHeaderBlock.
    306   static void WriteHeaderBlock(SpdyFrameBuilder* frame,
    307                                const int spdy_version,
    308                                const SpdyHeaderBlock* headers);
    309 
    310   // Retrieve serialized length of SpdyHeaderBlock.
    311   // TODO(hkhalil): Remove, or move to quic code.
    312   static size_t GetSerializedLength(const int spdy_version,
    313                                     const SpdyHeaderBlock* headers);
    314 
    315   // Create a new Framer, provided a SPDY version.
    316   explicit SpdyFramer(SpdyMajorVersion version);
    317   virtual ~SpdyFramer();
    318 
    319   // Set callbacks to be called from the framer.  A visitor must be set, or
    320   // else the framer will likely crash.  It is acceptable for the visitor
    321   // to do nothing.  If this is called multiple times, only the last visitor
    322   // will be used.
    323   void set_visitor(SpdyFramerVisitorInterface* visitor) {
    324     visitor_ = visitor;
    325   }
    326 
    327   // Set debug callbacks to be called from the framer. The debug visitor is
    328   // completely optional and need not be set in order for normal operation.
    329   // If this is called multiple times, only the last visitor will be used.
    330   void set_debug_visitor(SpdyFramerDebugVisitorInterface* debug_visitor) {
    331     debug_visitor_ = debug_visitor;
    332   }
    333 
    334   // Pass data into the framer for parsing.
    335   // Returns the number of bytes consumed. It is safe to pass more bytes in
    336   // than may be consumed.
    337   size_t ProcessInput(const char* data, size_t len);
    338 
    339   // Resets the framer state after a frame has been successfully decoded.
    340   // TODO(mbelshe): can we make this private?
    341   void Reset();
    342 
    343   // Check the state of the framer.
    344   SpdyError error_code() const { return error_code_; }
    345   SpdyState state() const { return state_; }
    346   bool HasError() const { return state_ == SPDY_ERROR; }
    347 
    348   // Given a buffer containing a decompressed header block in SPDY
    349   // serialized format, parse out a SpdyHeaderBlock, putting the results
    350   // in the given header block.
    351   // Returns number of bytes consumed if successfully parsed, 0 otherwise.
    352   size_t ParseHeaderBlockInBuffer(const char* header_data,
    353                                 size_t header_length,
    354                                 SpdyHeaderBlock* block) const;
    355 
    356   // Create a data frame.
    357   // |stream_id| is the stream  for this frame
    358   // |data| is the data to be included in the frame.
    359   // |len| is the length of the data
    360   // |flags| is the flags to use with the data.
    361   //    To mark this frame as the last data frame, enable DATA_FLAG_FIN.
    362   SpdyFrame* CreateDataFrame(SpdyStreamId stream_id, const char* data,
    363                              uint32 len, SpdyDataFlags flags) const;
    364   SpdySerializedFrame* SerializeData(const SpdyDataIR& data) const;
    365   // Serializes just the data frame header, excluding actual data payload.
    366   SpdySerializedFrame* SerializeDataFrameHeader(const SpdyDataIR& data) const;
    367 
    368   // Creates and serializes a SYN_STREAM frame.
    369   // |stream_id| is the id for this stream.
    370   // |associated_stream_id| is the associated stream id for this stream.
    371   // |priority| is the priority (GetHighestPriority()-GetLowestPriority) for
    372   //    this stream.
    373   // |credential_slot| is the CREDENTIAL slot to be used for this request.
    374   // |flags| is the flags to use with the data.
    375   //    To mark this frame as the last frame, enable CONTROL_FLAG_FIN.
    376   // |compressed| specifies whether the frame should be compressed.
    377   // |headers| is the header block to include in the frame.
    378   SpdyFrame* CreateSynStream(SpdyStreamId stream_id,
    379                              SpdyStreamId associated_stream_id,
    380                              SpdyPriority priority,
    381                              uint8 credential_slot,
    382                              SpdyControlFlags flags,
    383                              const SpdyHeaderBlock* headers);
    384   SpdySerializedFrame* SerializeSynStream(const SpdySynStreamIR& syn_stream);
    385 
    386   // Create a SYN_REPLY SpdyFrame.
    387   // |stream_id| is the stream for this frame.
    388   // |flags| is the flags to use with the data.
    389   //    To mark this frame as the last frame, enable CONTROL_FLAG_FIN.
    390   // |compressed| specifies whether the frame should be compressed.
    391   // |headers| is the header block to include in the frame.
    392   SpdyFrame* CreateSynReply(SpdyStreamId stream_id,
    393                             SpdyControlFlags flags,
    394                             const SpdyHeaderBlock* headers);
    395   SpdySerializedFrame* SerializeSynReply(const SpdySynReplyIR& syn_reply);
    396 
    397   SpdyFrame* CreateRstStream(SpdyStreamId stream_id,
    398                              SpdyRstStreamStatus status) const;
    399   SpdySerializedFrame* SerializeRstStream(
    400       const SpdyRstStreamIR& rst_stream) const;
    401 
    402   // Creates and serializes a SETTINGS frame. The SETTINGS frame is
    403   // used to communicate name/value pairs relevant to the communication channel.
    404   SpdyFrame* CreateSettings(const SettingsMap& values) const;
    405   SpdySerializedFrame* SerializeSettings(const SpdySettingsIR& settings) const;
    406 
    407   // Creates and serializes a PING frame. The unique_id is used to
    408   // identify the ping request/response.
    409   SpdyFrame* CreatePingFrame(uint32 unique_id) const;
    410   SpdySerializedFrame* SerializePing(const SpdyPingIR& ping) const;
    411 
    412   // Creates and serializes a GOAWAY frame. The GOAWAY frame is used
    413   // prior to the shutting down of the TCP connection, and includes the
    414   // stream_id of the last stream the sender of the frame is willing to process
    415   // to completion.
    416   SpdyFrame* CreateGoAway(SpdyStreamId last_accepted_stream_id,
    417                           SpdyGoAwayStatus status) const;
    418   SpdySerializedFrame* SerializeGoAway(const SpdyGoAwayIR& goaway) const;
    419 
    420   // Creates and serializes a HEADERS frame. The HEADERS frame is used
    421   // for sending additional headers outside of a SYN_STREAM/SYN_REPLY. The
    422   // arguments are the same as for CreateSynReply.
    423   SpdyFrame* CreateHeaders(SpdyStreamId stream_id,
    424                            SpdyControlFlags flags,
    425                            const SpdyHeaderBlock* headers);
    426   SpdySerializedFrame* SerializeHeaders(const SpdyHeadersIR& headers);
    427 
    428   // Creates and serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE
    429   // frame is used to implement per stream flow control in SPDY.
    430   SpdyFrame* CreateWindowUpdate(
    431       SpdyStreamId stream_id,
    432       uint32 delta_window_size) const;
    433   SpdySerializedFrame* SerializeWindowUpdate(
    434       const SpdyWindowUpdateIR& window_update) const;
    435 
    436   // Creates and serializes a CREDENTIAL frame.  The CREDENTIAL
    437   // frame is used to send a client certificate to the server when
    438   // request more than one origin are sent over the same SPDY session.
    439   SpdyFrame* CreateCredentialFrame(const SpdyCredential& credential) const;
    440   SpdySerializedFrame* SerializeCredential(
    441       const SpdyCredentialIR& credential) const;
    442 
    443   // Serializes a BLOCKED frame. The BLOCKED frame is used to indicate to the
    444   // remote endpoint that this endpoint believes itself to be flow-control
    445   // blocked but otherwise ready to send data. The BLOCKED frame is purely
    446   // advisory and optional.
    447   SpdySerializedFrame* SerializeBlocked(const SpdyBlockedIR& blocked) const;
    448 
    449   // Creates and serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used
    450   // to inform the client that it will be receiving an additional stream
    451   // in response to the original request. The frame includes synthesized
    452   // headers to explain the upcoming data.
    453   SpdyFrame* CreatePushPromise(SpdyStreamId stream_id,
    454                                SpdyStreamId promised_stream_id,
    455                                const SpdyHeaderBlock* headers);
    456   SpdySerializedFrame* SerializePushPromise(
    457       const SpdyPushPromiseIR& push_promise);
    458 
    459   // Given a CREDENTIAL frame's payload, extract the credential.
    460   // Returns true on successful parse, false otherwise.
    461   // TODO(hkhalil): Implement CREDENTIAL frame parsing in SpdyFramer
    462   // and eliminate this method.
    463   static bool ParseCredentialData(const char* data, size_t len,
    464                                   SpdyCredential* credential);
    465 
    466   // Serialize a frame of unknown type.
    467   SpdySerializedFrame* SerializeFrame(const SpdyFrameIR& frame);
    468 
    469   // NOTES about frame compression.
    470   // We want spdy to compress headers across the entire session.  As long as
    471   // the session is over TCP, frames are sent serially.  The client & server
    472   // can each compress frames in the same order and then compress them in that
    473   // order, and the remote can do the reverse.  However, we ultimately want
    474   // the creation of frames to be less sensitive to order so that they can be
    475   // placed over a UDP based protocol and yet still benefit from some
    476   // compression.  We don't know of any good compression protocol which does
    477   // not build its state in a serial (stream based) manner....  For now, we're
    478   // using zlib anyway.
    479 
    480   // Compresses a SpdyFrame.
    481   // On success, returns a new SpdyFrame with the payload compressed.
    482   // Compression state is maintained as part of the SpdyFramer.
    483   // Returned frame must be freed with "delete".
    484   // On failure, returns NULL.
    485   SpdyFrame* CompressFrame(const SpdyFrame& frame);
    486 
    487   // For ease of testing and experimentation we can tweak compression on/off.
    488   void set_enable_compression(bool value) {
    489     enable_compression_ = value;
    490   }
    491 
    492   // Used only in log messages.
    493   void set_display_protocol(const std::string& protocol) {
    494     display_protocol_ = protocol;
    495   }
    496 
    497   // Returns the (minimum) size of frames (sans variable-length portions).
    498   size_t GetDataFrameMinimumSize() const;
    499   size_t GetControlFrameHeaderSize() const;
    500   size_t GetSynStreamMinimumSize() const;
    501   size_t GetSynReplyMinimumSize() const;
    502   size_t GetRstStreamSize() const;
    503   size_t GetSettingsMinimumSize() const;
    504   size_t GetPingSize() const;
    505   size_t GetGoAwaySize() const;
    506   size_t GetHeadersMinimumSize() const;
    507   size_t GetWindowUpdateSize() const;
    508   size_t GetCredentialMinimumSize() const;
    509   size_t GetBlockedSize() const;
    510   size_t GetPushPromiseMinimumSize() const;
    511 
    512   // Returns the minimum size a frame can be (data or control).
    513   size_t GetFrameMinimumSize() const;
    514 
    515   // Returns the maximum size a frame can be (data or control).
    516   size_t GetFrameMaximumSize() const;
    517 
    518   // Returns the maximum payload size of a DATA frame.
    519   size_t GetDataFrameMaximumPayload() const;
    520 
    521   // For debugging.
    522   static const char* StateToString(int state);
    523   static const char* ErrorCodeToString(int error_code);
    524   static const char* StatusCodeToString(int status_code);
    525   static const char* FrameTypeToString(SpdyFrameType type);
    526 
    527   SpdyMajorVersion protocol_version() const { return spdy_version_; }
    528 
    529   bool probable_http_response() const { return probable_http_response_; }
    530 
    531   SpdyPriority GetLowestPriority() const { return spdy_version_ < 3 ? 3 : 7; }
    532   SpdyPriority GetHighestPriority() const { return 0; }
    533 
    534   // Deliver the given control frame's compressed headers block to the visitor
    535   // in decompressed form, in chunks. Returns true if the visitor has
    536   // accepted all of the chunks.
    537   bool IncrementallyDecompressControlFrameHeaderData(
    538       SpdyStreamId stream_id,
    539       const char* data,
    540       size_t len);
    541 
    542  protected:
    543   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, BasicCompression);
    544   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameSizesAreValidated);
    545   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HeaderCompression);
    546   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, DecompressUncompressedFrame);
    547   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ExpandBuffer_HeapSmash);
    548   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HugeHeaderBlock);
    549   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, UnclosedStreamDataCompressors);
    550   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
    551                            UnclosedStreamDataCompressorsOneByteAtATime);
    552   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
    553                            UncompressLargerThanFrameBufferInitialSize);
    554   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ReadLargeSettingsFrame);
    555   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
    556                            ReadLargeSettingsFrameInSmallChunks);
    557   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameAtMaxSizeLimit);
    558   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameTooLarge);
    559   friend class net::HttpNetworkLayer;  // This is temporary for the server.
    560   friend class net::HttpNetworkTransactionTest;
    561   friend class net::HttpProxyClientSocketPoolTest;
    562   friend class net::SpdyHttpStreamTest;
    563   friend class net::SpdyNetworkTransactionTest;
    564   friend class net::SpdyProxyClientSocketTest;
    565   friend class net::SpdySessionTest;
    566   friend class net::SpdyStreamTest;
    567   friend class net::SpdyWebSocketStreamTest;
    568   friend class net::WebSocketJobTest;
    569   friend class test::TestSpdyVisitor;
    570 
    571  private:
    572   // Internal breakouts from ProcessInput. Each returns the number of bytes
    573   // consumed from the data.
    574   size_t ProcessCommonHeader(const char* data, size_t len);
    575   size_t ProcessControlFramePayload(const char* data, size_t len);
    576   size_t ProcessCredentialFramePayload(const char* data, size_t len);
    577   size_t ProcessControlFrameBeforeHeaderBlock(const char* data, size_t len);
    578   size_t ProcessControlFrameHeaderBlock(const char* data, size_t len);
    579   size_t ProcessSettingsFramePayload(const char* data, size_t len);
    580   size_t ProcessDataFramePayload(const char* data, size_t len);
    581 
    582   // Helpers for above internal breakouts from ProcessInput.
    583   void ProcessControlFrameHeader(uint16 control_frame_type_field);
    584   bool ProcessSetting(const char* data);  // Always passed exactly 8 bytes.
    585 
    586   // Retrieve serialized length of SpdyHeaderBlock. If compression is enabled, a
    587   // maximum estimate is returned.
    588   size_t GetSerializedLength(const SpdyHeaderBlock& headers);
    589 
    590   // Get (and lazily initialize) the ZLib state.
    591   z_stream* GetHeaderCompressor();
    592   z_stream* GetHeaderDecompressor();
    593 
    594  private:
    595   // Deliver the given control frame's uncompressed headers block to the
    596   // visitor in chunks. Returns true if the visitor has accepted all of the
    597   // chunks.
    598   bool IncrementallyDeliverControlFrameHeaderData(SpdyStreamId stream_id,
    599                                                   const char* data,
    600                                                   size_t len);
    601 
    602   // Utility to copy the given data block to the current frame buffer, up
    603   // to the given maximum number of bytes, and update the buffer
    604   // data (pointer and length). Returns the number of bytes
    605   // read, and:
    606   //   *data is advanced the number of bytes read.
    607   //   *len is reduced by the number of bytes read.
    608   size_t UpdateCurrentFrameBuffer(const char** data, size_t* len,
    609                                   size_t max_bytes);
    610 
    611   void WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
    612                            z_stream* out) const;
    613 
    614   void SerializeNameValueBlockWithoutCompression(
    615       SpdyFrameBuilder* builder,
    616       const SpdyNameValueBlock& name_value_block) const;
    617 
    618   // Compresses automatically according to enable_compression_.
    619   void SerializeNameValueBlock(
    620       SpdyFrameBuilder* builder,
    621       const SpdyFrameWithNameValueBlockIR& frame);
    622 
    623   // Set the error code and moves the framer into the error state.
    624   void set_error(SpdyError error);
    625 
    626   // The maximum size of the control frames that we support.
    627   // This limit is arbitrary. We can enforce it here or at the application
    628   // layer. We chose the framing layer, but this can be changed (or removed)
    629   // if necessary later down the line.
    630   size_t GetControlFrameBufferMaxSize() const {
    631     // The theoretical maximum for SPDY3 and earlier is (2^24 - 1) +
    632     // 8, since the length field does not count the size of the
    633     // header.
    634     if (spdy_version_ == SPDY2) {
    635       return 64 * 1024;
    636     }
    637     if (spdy_version_ == SPDY3) {
    638       return 16 * 1024 * 1024;
    639     }
    640     // The theoretical maximum for SPDY4 is 2^16 - 1, as the length
    641     // field does count the size of the header.
    642     return 16 * 1024;
    643   }
    644 
    645   // The size of the control frame buffer.
    646   // Since this is only used for control frame headers, the maximum control
    647   // frame header size (SYN_STREAM) is sufficient; all remaining control
    648   // frame data is streamed to the visitor.
    649   static const size_t kControlFrameBufferSize;
    650 
    651   SpdyState state_;
    652   SpdyState previous_state_;
    653   SpdyError error_code_;
    654   size_t remaining_data_length_;
    655 
    656   // The number of bytes remaining to read from the current control frame's
    657   // headers. Note that header data blocks (for control types that have them)
    658   // are part of the frame's payload, and not the frame's headers.
    659   size_t remaining_control_header_;
    660 
    661   scoped_ptr<char[]> current_frame_buffer_;
    662   // Number of bytes read into the current_frame_buffer_.
    663   size_t current_frame_buffer_length_;
    664 
    665   // The type of the frame currently being read.
    666   SpdyFrameType current_frame_type_;
    667 
    668   // The flags field of the frame currently being read.
    669   uint8 current_frame_flags_;
    670 
    671   // The total length of the frame currently being read, including frame header.
    672   uint32 current_frame_length_;
    673 
    674   // The stream ID field of the frame currently being read, if applicable.
    675   SpdyStreamId current_frame_stream_id_;
    676 
    677   // Scratch space for handling SETTINGS frames.
    678   // TODO(hkhalil): Unify memory for this scratch space with
    679   // current_frame_buffer_.
    680   SpdySettingsScratch settings_scratch_;
    681 
    682   bool enable_compression_;  // Controls all compression
    683   // SPDY header compressors.
    684   scoped_ptr<z_stream> header_compressor_;
    685   scoped_ptr<z_stream> header_decompressor_;
    686 
    687   SpdyFramerVisitorInterface* visitor_;
    688   SpdyFramerDebugVisitorInterface* debug_visitor_;
    689 
    690   std::string display_protocol_;
    691 
    692   // The major SPDY version to be spoken/understood by this framer.
    693   const SpdyMajorVersion spdy_version_;
    694 
    695   // Tracks if we've ever gotten far enough in framing to see a control frame of
    696   // type SYN_STREAM or SYN_REPLY.
    697   //
    698   // If we ever get something which looks like a data frame before we've had a
    699   // SYN, we explicitly check to see if it looks like we got an HTTP response to
    700   // a SPDY request.  This boolean lets us do that.
    701   bool syn_frame_processed_;
    702 
    703   // If we ever get a data frame before a SYN frame, we check to see if it
    704   // starts with HTTP.  If it does, we likely have an HTTP response.   This
    705   // isn't guaranteed though: we could have gotten a settings frame and then
    706   // corrupt data that just looks like HTTP, but deterministic checking requires
    707   // a lot more state.
    708   bool probable_http_response_;
    709 };
    710 
    711 }  // namespace net
    712 
    713 #endif  // NET_SPDY_SPDY_FRAMER_H_
    714