- add sources.
[platform/framework/web/crosswalk.git] / src / net / spdy / spdy_framer.h
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                              bool compressed,
384                              const SpdyHeaderBlock* headers);
385   SpdySerializedFrame* SerializeSynStream(const SpdySynStreamIR& syn_stream);
386
387   // Create a SYN_REPLY SpdyFrame.
388   // |stream_id| is the stream for this frame.
389   // |flags| is the flags to use with the data.
390   //    To mark this frame as the last frame, enable CONTROL_FLAG_FIN.
391   // |compressed| specifies whether the frame should be compressed.
392   // |headers| is the header block to include in the frame.
393   SpdyFrame* CreateSynReply(SpdyStreamId stream_id,
394                             SpdyControlFlags flags,
395                             bool compressed,
396                             const SpdyHeaderBlock* headers);
397   SpdySerializedFrame* SerializeSynReply(const SpdySynReplyIR& syn_reply);
398
399   SpdyFrame* CreateRstStream(SpdyStreamId stream_id,
400                              SpdyRstStreamStatus status) const;
401   SpdySerializedFrame* SerializeRstStream(
402       const SpdyRstStreamIR& rst_stream) const;
403
404   // Creates and serializes a SETTINGS frame. The SETTINGS frame is
405   // used to communicate name/value pairs relevant to the communication channel.
406   SpdyFrame* CreateSettings(const SettingsMap& values) const;
407   SpdySerializedFrame* SerializeSettings(const SpdySettingsIR& settings) const;
408
409   // Creates and serializes a PING frame. The unique_id is used to
410   // identify the ping request/response.
411   SpdyFrame* CreatePingFrame(uint32 unique_id) const;
412   SpdySerializedFrame* SerializePing(const SpdyPingIR& ping) const;
413
414   // Creates and serializes a GOAWAY frame. The GOAWAY frame is used
415   // prior to the shutting down of the TCP connection, and includes the
416   // stream_id of the last stream the sender of the frame is willing to process
417   // to completion.
418   SpdyFrame* CreateGoAway(SpdyStreamId last_accepted_stream_id,
419                           SpdyGoAwayStatus status) const;
420   SpdySerializedFrame* SerializeGoAway(const SpdyGoAwayIR& goaway) const;
421
422   // Creates and serializes a HEADERS frame. The HEADERS frame is used
423   // for sending additional headers outside of a SYN_STREAM/SYN_REPLY. The
424   // arguments are the same as for CreateSynReply.
425   SpdyFrame* CreateHeaders(SpdyStreamId stream_id,
426                            SpdyControlFlags flags,
427                            bool compressed,
428                            const SpdyHeaderBlock* headers);
429   SpdySerializedFrame* SerializeHeaders(const SpdyHeadersIR& headers);
430
431   // Creates and serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE
432   // frame is used to implement per stream flow control in SPDY.
433   SpdyFrame* CreateWindowUpdate(
434       SpdyStreamId stream_id,
435       uint32 delta_window_size) const;
436   SpdySerializedFrame* SerializeWindowUpdate(
437       const SpdyWindowUpdateIR& window_update) const;
438
439   // Creates and serializes a CREDENTIAL frame.  The CREDENTIAL
440   // frame is used to send a client certificate to the server when
441   // request more than one origin are sent over the same SPDY session.
442   SpdyFrame* CreateCredentialFrame(const SpdyCredential& credential) const;
443   SpdySerializedFrame* SerializeCredential(
444       const SpdyCredentialIR& credential) const;
445
446   // Serializes a BLOCKED frame. The BLOCKED frame is used to indicate to the
447   // remote endpoint that this endpoint believes itself to be flow-control
448   // blocked but otherwise ready to send data. The BLOCKED frame is purely
449   // advisory and optional.
450   SpdySerializedFrame* SerializeBlocked(const SpdyBlockedIR& blocked) const;
451
452   // Creates and serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used
453   // to inform the client that it will be receiving an additional stream
454   // in response to the original request. The frame includes synthesized
455   // headers to explain the upcoming data.
456   SpdyFrame* CreatePushPromise(SpdyStreamId stream_id,
457                                SpdyStreamId promised_stream_id,
458                                const SpdyHeaderBlock* headers);
459   SpdySerializedFrame* SerializePushPromise(
460       const SpdyPushPromiseIR& push_promise);
461
462   // Given a CREDENTIAL frame's payload, extract the credential.
463   // Returns true on successful parse, false otherwise.
464   // TODO(hkhalil): Implement CREDENTIAL frame parsing in SpdyFramer
465   // and eliminate this method.
466   static bool ParseCredentialData(const char* data, size_t len,
467                                   SpdyCredential* credential);
468
469   // Serialize a frame of unknown type.
470   SpdySerializedFrame* SerializeFrame(const SpdyFrameIR& frame);
471
472   // NOTES about frame compression.
473   // We want spdy to compress headers across the entire session.  As long as
474   // the session is over TCP, frames are sent serially.  The client & server
475   // can each compress frames in the same order and then compress them in that
476   // order, and the remote can do the reverse.  However, we ultimately want
477   // the creation of frames to be less sensitive to order so that they can be
478   // placed over a UDP based protocol and yet still benefit from some
479   // compression.  We don't know of any good compression protocol which does
480   // not build its state in a serial (stream based) manner....  For now, we're
481   // using zlib anyway.
482
483   // Compresses a SpdyFrame.
484   // On success, returns a new SpdyFrame with the payload compressed.
485   // Compression state is maintained as part of the SpdyFramer.
486   // Returned frame must be freed with "delete".
487   // On failure, returns NULL.
488   SpdyFrame* CompressFrame(const SpdyFrame& frame);
489
490   // For ease of testing and experimentation we can tweak compression on/off.
491   void set_enable_compression(bool value) {
492     enable_compression_ = value;
493   }
494
495   // Used only in log messages.
496   void set_display_protocol(const std::string& protocol) {
497     display_protocol_ = protocol;
498   }
499
500   // Returns the (minimum) size of frames (sans variable-length portions).
501   size_t GetDataFrameMinimumSize() const;
502   size_t GetControlFrameHeaderSize() const;
503   size_t GetSynStreamMinimumSize() const;
504   size_t GetSynReplyMinimumSize() const;
505   size_t GetRstStreamSize() const;
506   size_t GetSettingsMinimumSize() const;
507   size_t GetPingSize() const;
508   size_t GetGoAwaySize() const;
509   size_t GetHeadersMinimumSize() const;
510   size_t GetWindowUpdateSize() const;
511   size_t GetCredentialMinimumSize() const;
512   size_t GetBlockedSize() const;
513   size_t GetPushPromiseMinimumSize() const;
514
515   // Returns the minimum size a frame can be (data or control).
516   size_t GetFrameMinimumSize() const;
517
518   // Returns the maximum size a frame can be (data or control).
519   size_t GetFrameMaximumSize() const;
520
521   // Returns the maximum payload size of a DATA frame.
522   size_t GetDataFrameMaximumPayload() const;
523
524   // For debugging.
525   static const char* StateToString(int state);
526   static const char* ErrorCodeToString(int error_code);
527   static const char* StatusCodeToString(int status_code);
528   static const char* FrameTypeToString(SpdyFrameType type);
529
530   SpdyMajorVersion protocol_version() const { return spdy_version_; }
531
532   bool probable_http_response() const { return probable_http_response_; }
533
534   SpdyPriority GetLowestPriority() const { return spdy_version_ < 3 ? 3 : 7; }
535   SpdyPriority GetHighestPriority() const { return 0; }
536
537   // Deliver the given control frame's compressed headers block to the visitor
538   // in decompressed form, in chunks. Returns true if the visitor has
539   // accepted all of the chunks.
540   bool IncrementallyDecompressControlFrameHeaderData(
541       SpdyStreamId stream_id,
542       const char* data,
543       size_t len);
544
545  protected:
546   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, BasicCompression);
547   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameSizesAreValidated);
548   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HeaderCompression);
549   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, DecompressUncompressedFrame);
550   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ExpandBuffer_HeapSmash);
551   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HugeHeaderBlock);
552   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, UnclosedStreamDataCompressors);
553   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
554                            UnclosedStreamDataCompressorsOneByteAtATime);
555   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
556                            UncompressLargerThanFrameBufferInitialSize);
557   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ReadLargeSettingsFrame);
558   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
559                            ReadLargeSettingsFrameInSmallChunks);
560   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameAtMaxSizeLimit);
561   FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameTooLarge);
562   friend class net::HttpNetworkLayer;  // This is temporary for the server.
563   friend class net::HttpNetworkTransactionTest;
564   friend class net::HttpProxyClientSocketPoolTest;
565   friend class net::SpdyHttpStreamTest;
566   friend class net::SpdyNetworkTransactionTest;
567   friend class net::SpdyProxyClientSocketTest;
568   friend class net::SpdySessionTest;
569   friend class net::SpdyStreamTest;
570   friend class net::SpdyWebSocketStreamTest;
571   friend class net::WebSocketJobTest;
572   friend class test::TestSpdyVisitor;
573
574  private:
575   // Internal breakouts from ProcessInput. Each returns the number of bytes
576   // consumed from the data.
577   size_t ProcessCommonHeader(const char* data, size_t len);
578   size_t ProcessControlFramePayload(const char* data, size_t len);
579   size_t ProcessCredentialFramePayload(const char* data, size_t len);
580   size_t ProcessControlFrameBeforeHeaderBlock(const char* data, size_t len);
581   size_t ProcessControlFrameHeaderBlock(const char* data, size_t len);
582   size_t ProcessSettingsFramePayload(const char* data, size_t len);
583   size_t ProcessDataFramePayload(const char* data, size_t len);
584
585   // Helpers for above internal breakouts from ProcessInput.
586   void ProcessControlFrameHeader(uint16 control_frame_type_field);
587   bool ProcessSetting(const char* data);  // Always passed exactly 8 bytes.
588
589   // Retrieve serialized length of SpdyHeaderBlock. If compression is enabled, a
590   // maximum estimate is returned.
591   size_t GetSerializedLength(const SpdyHeaderBlock& headers);
592
593   // Get (and lazily initialize) the ZLib state.
594   z_stream* GetHeaderCompressor();
595   z_stream* GetHeaderDecompressor();
596
597  private:
598   // Deliver the given control frame's uncompressed headers block to the
599   // visitor in chunks. Returns true if the visitor has accepted all of the
600   // chunks.
601   bool IncrementallyDeliverControlFrameHeaderData(SpdyStreamId stream_id,
602                                                   const char* data,
603                                                   size_t len);
604
605   // Utility to copy the given data block to the current frame buffer, up
606   // to the given maximum number of bytes, and update the buffer
607   // data (pointer and length). Returns the number of bytes
608   // read, and:
609   //   *data is advanced the number of bytes read.
610   //   *len is reduced by the number of bytes read.
611   size_t UpdateCurrentFrameBuffer(const char** data, size_t* len,
612                                   size_t max_bytes);
613
614   void WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
615                            z_stream* out) const;
616
617   void SerializeNameValueBlockWithoutCompression(
618       SpdyFrameBuilder* builder,
619       const SpdyNameValueBlock& name_value_block) const;
620
621   // Compresses automatically according to enable_compression_.
622   void SerializeNameValueBlock(
623       SpdyFrameBuilder* builder,
624       const SpdyFrameWithNameValueBlockIR& frame);
625
626   // Set the error code and moves the framer into the error state.
627   void set_error(SpdyError error);
628
629   // The maximum size of the control frames that we support.
630   // This limit is arbitrary. We can enforce it here or at the application
631   // layer. We chose the framing layer, but this can be changed (or removed)
632   // if necessary later down the line.
633   size_t GetControlFrameBufferMaxSize() const {
634     // The theoretical maximum for SPDY3 and earlier is (2^24 - 1) +
635     // 8, since the length field does not count the size of the
636     // header.
637     if (spdy_version_ == SPDY2) {
638       return 64 * 1024;
639     }
640     if (spdy_version_ == SPDY3) {
641       return 16 * 1024 * 1024;
642     }
643     // The theoretical maximum for SPDY4 is 2^16 - 1, as the length
644     // field does count the size of the header.
645     return 16 * 1024;
646   }
647
648   // The size of the control frame buffer.
649   // Since this is only used for control frame headers, the maximum control
650   // frame header size (SYN_STREAM) is sufficient; all remaining control
651   // frame data is streamed to the visitor.
652   static const size_t kControlFrameBufferSize;
653
654   SpdyState state_;
655   SpdyState previous_state_;
656   SpdyError error_code_;
657   size_t remaining_data_length_;
658
659   // The number of bytes remaining to read from the current control frame's
660   // headers. Note that header data blocks (for control types that have them)
661   // are part of the frame's payload, and not the frame's headers.
662   size_t remaining_control_header_;
663
664   scoped_ptr<char[]> current_frame_buffer_;
665   // Number of bytes read into the current_frame_buffer_.
666   size_t current_frame_buffer_length_;
667
668   // The type of the frame currently being read.
669   SpdyFrameType current_frame_type_;
670
671   // The flags field of the frame currently being read.
672   uint8 current_frame_flags_;
673
674   // The total length of the frame currently being read, including frame header.
675   uint32 current_frame_length_;
676
677   // The stream ID field of the frame currently being read, if applicable.
678   SpdyStreamId current_frame_stream_id_;
679
680   // Scratch space for handling SETTINGS frames.
681   // TODO(hkhalil): Unify memory for this scratch space with
682   // current_frame_buffer_.
683   SpdySettingsScratch settings_scratch_;
684
685   bool enable_compression_;  // Controls all compression
686   // SPDY header compressors.
687   scoped_ptr<z_stream> header_compressor_;
688   scoped_ptr<z_stream> header_decompressor_;
689
690   SpdyFramerVisitorInterface* visitor_;
691   SpdyFramerDebugVisitorInterface* debug_visitor_;
692
693   std::string display_protocol_;
694
695   // The major SPDY version to be spoken/understood by this framer.
696   const SpdyMajorVersion spdy_version_;
697
698   // Tracks if we've ever gotten far enough in framing to see a control frame of
699   // type SYN_STREAM or SYN_REPLY.
700   //
701   // If we ever get something which looks like a data frame before we've had a
702   // SYN, we explicitly check to see if it looks like we got an HTTP response to
703   // a SPDY request.  This boolean lets us do that.
704   bool syn_frame_processed_;
705
706   // If we ever get a data frame before a SYN frame, we check to see if it
707   // starts with HTTP.  If it does, we likely have an HTTP response.   This
708   // isn't guaranteed though: we could have gotten a settings frame and then
709   // corrupt data that just looks like HTTP, but deterministic checking requires
710   // a lot more state.
711   bool probable_http_response_;
712 };
713
714 }  // namespace net
715
716 #endif  // NET_SPDY_SPDY_FRAMER_H_