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.
5 #ifndef NET_SPDY_SPDY_FRAMER_H_
6 #define NET_SPDY_SPDY_FRAMER_H_
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"
22 // TODO(akalin): Remove support for CREDENTIAL frames.
24 typedef struct z_stream_s z_stream
; // Forward declaration for zlib.
28 class HttpProxyClientSocketPoolTest
;
29 class HttpNetworkLayer
;
30 class HttpNetworkTransactionTest
;
31 class SpdyHttpStreamTest
;
32 class SpdyNetworkTransactionTest
;
33 class SpdyProxyClientSocketTest
;
34 class SpdySessionTest
;
36 class SpdyWebSocketStreamTest
;
37 class WebSocketJobTest
;
40 class SpdyFrameBuilder
;
45 class TestSpdyVisitor
;
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
;
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
{
57 static SettingsFlagsAndId
FromWireFormat(int version
, uint32 wire
);
59 SettingsFlagsAndId() : flags_(0), id_(0) {}
61 // TODO(hkhalil): restrict to enums instead of free-form ints.
62 SettingsFlagsAndId(uint8 flags
, uint32 id
);
64 uint32
GetWireFormat(int version
) const;
66 uint32
id() const { return id_
; }
67 uint8
flags() const { return flags_
; }
70 static void ConvertFlagsAndIdForSpdy2(uint32
* val
);
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
;
80 // Scratch space necessary for processing SETTINGS frames.
81 struct NET_EXPORT_PRIVATE SpdySettingsScratch
{
82 SpdySettingsScratch() { Reset(); }
89 // Buffer contains up to one complete key/value pair.
92 // The amount of the buffer that is filled with valid data.
93 size_t setting_buf_len
;
95 // The ID of the last setting that was processed in the current SETTINGS
96 // frame. Used for detecting out-of-order or duplicate keys within a settings
97 // frame. Set to 0 before first key/value pair is processed.
98 uint32 last_setting_id
;
101 // SpdyFramerVisitorInterface is a set of callbacks for the SpdyFramer.
102 // Implement this interface to receive event callbacks as frames are
103 // decoded from the framer.
105 // Control frames that contain SPDY header blocks (SYN_STREAM, SYN_REPLY,
106 // HEADER, and PUSH_PROMISE) are processed in fashion that allows the
107 // decompressed header block to be delivered in chunks to the visitor.
108 // The following steps are followed:
109 // 1. OnSynStream, OnSynReply, OnHeaders, or OnPushPromise is called.
110 // 2. Repeated: OnControlFrameHeaderData is called with chunks of the
111 // decompressed header block. In each call the len parameter is greater
113 // 3. OnControlFrameHeaderData is called with len set to zero, indicating
114 // that the full header block has been delivered for the control frame.
115 // During step 2 the visitor may return false, indicating that the chunk of
116 // header data could not be handled by the visitor (typically this indicates
117 // resource exhaustion). If this occurs the framer will discontinue
118 // delivering chunks to the visitor, set a SPDY_CONTROL_PAYLOAD_TOO_LARGE
119 // error, and clean up appropriately. Note that this will cause the header
120 // decompressor to lose synchronization with the sender's header compressor,
121 // making the SPDY session unusable for future work. The visitor's OnError
122 // function should deal with this condition by closing the SPDY connection.
123 class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface
{
125 virtual ~SpdyFramerVisitorInterface() {}
127 // Called if an error is detected in the SpdyFrame protocol.
128 virtual void OnError(SpdyFramer
* framer
) = 0;
130 // Called when a data frame header is received. The frame's data
131 // payload will be provided via subsequent calls to
132 // OnStreamFrameData().
133 virtual void OnDataFrameHeader(SpdyStreamId stream_id
,
137 // Called when data is received.
138 // |stream_id| The stream receiving data.
139 // |data| A buffer containing the data received.
140 // |len| The length of the data buffer.
141 // When the other side has finished sending data on this stream,
142 // this method will be called with a zero-length buffer.
143 virtual void OnStreamFrameData(SpdyStreamId stream_id
,
148 // Called when a chunk of header data is available. This is called
149 // after OnSynStream, OnSynReply, OnHeaders(), or OnPushPromise.
150 // |stream_id| The stream receiving the header data.
151 // |header_data| A buffer containing the header data chunk received.
152 // |len| The length of the header data buffer. A length of zero indicates
153 // that the header data block has been completely sent.
154 // When this function returns true the visitor indicates that it accepted
155 // all of the data. Returning false indicates that that an unrecoverable
156 // error has occurred, such as bad header data or resource exhaustion.
157 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id
,
158 const char* header_data
,
161 // Called when a SYN_STREAM frame is received.
162 // Note that header block data is not included. See
163 // OnControlFrameHeaderData().
164 virtual void OnSynStream(SpdyStreamId stream_id
,
165 SpdyStreamId associated_stream_id
,
166 SpdyPriority priority
,
168 bool unidirectional
) = 0;
170 // Called when a SYN_REPLY frame is received.
171 // Note that header block data is not included. See
172 // OnControlFrameHeaderData().
173 virtual void OnSynReply(SpdyStreamId stream_id
, bool fin
) = 0;
175 // Called when a RST_STREAM frame has been parsed.
176 virtual void OnRstStream(SpdyStreamId stream_id
,
177 SpdyRstStreamStatus status
) = 0;
179 // Called when a SETTINGS frame is received.
180 // |clear_persisted| True if the respective flag is set on the SETTINGS frame.
181 virtual void OnSettings(bool clear_persisted
) {}
183 // Called when a complete setting within a SETTINGS frame has been parsed and
185 virtual void OnSetting(SpdySettingsIds id
, uint8 flags
, uint32 value
) = 0;
187 // Called when a PING frame has been parsed.
188 virtual void OnPing(SpdyPingId unique_id
, bool is_ack
) = 0;
190 // Called when a GOAWAY frame has been parsed.
191 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id
,
192 SpdyGoAwayStatus status
) = 0;
194 // Called when a HEADERS frame is received.
195 // Note that header block data is not included. See
196 // OnControlFrameHeaderData().
197 virtual void OnHeaders(SpdyStreamId stream_id
, bool fin
) = 0;
199 // Called when a WINDOW_UPDATE frame has been parsed.
200 virtual void OnWindowUpdate(SpdyStreamId stream_id
,
201 uint32 delta_window_size
) = 0;
203 // Called when a goaway frame opaque data is available.
204 // |goaway_data| A buffer containing the opaque GOAWAY data chunk received.
205 // |len| The length of the header data buffer. A length of zero indicates
206 // that the header data block has been completely sent.
207 // When this function returns true the visitor indicates that it accepted
208 // all of the data. Returning false indicates that that an error has
209 // occurred while processing the data. Default implementation returns true.
210 virtual bool OnGoAwayFrameData(const char* goaway_data
, size_t len
);
212 // Called when rst_stream frame opaque data is available.
213 // |rst_stream_data| A buffer containing the opaque RST_STREAM
214 // data chunk received.
215 // |len| The length of the header data buffer. A length of zero indicates
216 // that the opaque data has been completely sent.
217 // When this function returns true the visitor indicates that it accepted
218 // all of the data. Returning false indicates that that an error has
219 // occurred while processing the data. Default implementation returns true.
220 virtual bool OnRstStreamFrameData(const char* rst_stream_data
, size_t len
);
222 // Called when a BLOCKED frame has been parsed.
223 virtual void OnBlocked(SpdyStreamId stream_id
) {}
225 // Called when a PUSH_PROMISE frame is received.
226 // Note that header block data is not included. See
227 // OnControlFrameHeaderData().
228 virtual void OnPushPromise(SpdyStreamId stream_id
,
229 SpdyStreamId promised_stream_id
) = 0;
232 // Optionally, and in addition to SpdyFramerVisitorInterface, a class supporting
233 // SpdyFramerDebugVisitorInterface may be used in conjunction with SpdyFramer in
234 // order to extract debug/internal information about the SpdyFramer as it
237 // Most SPDY implementations need not bother with this interface at all.
238 class NET_EXPORT_PRIVATE SpdyFramerDebugVisitorInterface
{
240 virtual ~SpdyFramerDebugVisitorInterface() {}
242 // Called after compressing a frame with a payload of
243 // a list of name-value pairs.
244 // |payload_len| is the uncompressed payload size.
245 // |frame_len| is the compressed frame size.
246 virtual void OnSendCompressedFrame(SpdyStreamId stream_id
,
251 // Called when a frame containing a compressed payload of
252 // name-value pairs is received.
253 // |frame_len| is the compressed frame size.
254 virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id
,
259 class NET_EXPORT_PRIVATE SpdyFramer
{
262 // TODO(mbelshe): Can we move these into the implementation
263 // and avoid exposing through the header. (Needed for test)
268 SPDY_READING_COMMON_HEADER
,
269 SPDY_CONTROL_FRAME_PAYLOAD
,
270 SPDY_IGNORE_REMAINING_PAYLOAD
,
271 SPDY_FORWARD_STREAM_FRAME
,
272 SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
,
273 SPDY_CONTROL_FRAME_HEADER_BLOCK
,
274 SPDY_GOAWAY_FRAME_PAYLOAD
,
275 SPDY_RST_STREAM_FRAME_PAYLOAD
,
276 SPDY_SETTINGS_FRAME_PAYLOAD
,
282 SPDY_INVALID_CONTROL_FRAME
, // Control frame is mal-formatted.
283 SPDY_CONTROL_PAYLOAD_TOO_LARGE
, // Control frame payload was too large.
284 SPDY_ZLIB_INIT_FAILURE
, // The Zlib library could not initialize.
285 SPDY_UNSUPPORTED_VERSION
, // Control frame has unsupported version.
286 SPDY_DECOMPRESS_FAILURE
, // There was an error decompressing.
287 SPDY_COMPRESS_FAILURE
, // There was an error compressing.
288 SPDY_GOAWAY_FRAME_CORRUPT
, // GOAWAY frame could not be parsed.
289 SPDY_RST_STREAM_FRAME_CORRUPT
, // RST_STREAM frame could not be parsed.
290 SPDY_INVALID_DATA_FRAME_FLAGS
, // Data frame has invalid flags.
291 SPDY_INVALID_CONTROL_FRAME_FLAGS
, // Control frame has invalid flags.
293 LAST_ERROR
, // Must be the last entry in the enum.
296 // Constant for invalid (or unknown) stream IDs.
297 static const SpdyStreamId kInvalidStream
;
299 // The maximum size of header data chunks delivered to the framer visitor
300 // through OnControlFrameHeaderData. (It is exposed here for unit test
302 static const size_t kHeaderDataChunkMaxSize
;
304 // Serializes a SpdyHeaderBlock.
305 static void WriteHeaderBlock(SpdyFrameBuilder
* frame
,
306 const int spdy_version
,
307 const SpdyHeaderBlock
* headers
);
309 // Retrieve serialized length of SpdyHeaderBlock.
310 // TODO(hkhalil): Remove, or move to quic code.
311 static size_t GetSerializedLength(const int spdy_version
,
312 const SpdyHeaderBlock
* headers
);
314 // Create a new Framer, provided a SPDY version.
315 explicit SpdyFramer(SpdyMajorVersion version
);
316 virtual ~SpdyFramer();
318 // Set callbacks to be called from the framer. A visitor must be set, or
319 // else the framer will likely crash. It is acceptable for the visitor
320 // to do nothing. If this is called multiple times, only the last visitor
322 void set_visitor(SpdyFramerVisitorInterface
* visitor
) {
326 // Set debug callbacks to be called from the framer. The debug visitor is
327 // completely optional and need not be set in order for normal operation.
328 // If this is called multiple times, only the last visitor will be used.
329 void set_debug_visitor(SpdyFramerDebugVisitorInterface
* debug_visitor
) {
330 debug_visitor_
= debug_visitor
;
333 // Pass data into the framer for parsing.
334 // Returns the number of bytes consumed. It is safe to pass more bytes in
335 // than may be consumed.
336 size_t ProcessInput(const char* data
, size_t len
);
338 // Resets the framer state after a frame has been successfully decoded.
339 // TODO(mbelshe): can we make this private?
342 // Check the state of the framer.
343 SpdyError
error_code() const { return error_code_
; }
344 SpdyState
state() const { return state_
; }
345 bool HasError() const { return state_
== SPDY_ERROR
; }
347 // Given a buffer containing a decompressed header block in SPDY
348 // serialized format, parse out a SpdyHeaderBlock, putting the results
349 // in the given header block.
350 // Returns number of bytes consumed if successfully parsed, 0 otherwise.
351 size_t ParseHeaderBlockInBuffer(const char* header_data
,
352 size_t header_length
,
353 SpdyHeaderBlock
* block
) const;
355 // Serialize a data frame.
356 SpdySerializedFrame
* SerializeData(const SpdyDataIR
& data
) const;
357 // Serializes just the data frame header, excluding actual data payload.
358 SpdySerializedFrame
* SerializeDataFrameHeader(const SpdyDataIR
& data
) const;
360 // Serializes a SYN_STREAM frame.
361 SpdySerializedFrame
* SerializeSynStream(const SpdySynStreamIR
& syn_stream
);
363 // Serialize a SYN_REPLY SpdyFrame.
364 SpdySerializedFrame
* SerializeSynReply(const SpdySynReplyIR
& syn_reply
);
366 SpdySerializedFrame
* SerializeRstStream(
367 const SpdyRstStreamIR
& rst_stream
) const;
369 // Serializes a SETTINGS frame. The SETTINGS frame is
370 // used to communicate name/value pairs relevant to the communication channel.
371 SpdySerializedFrame
* SerializeSettings(const SpdySettingsIR
& settings
) const;
373 // Serializes a PING frame. The unique_id is used to
374 // identify the ping request/response.
375 SpdySerializedFrame
* SerializePing(const SpdyPingIR
& ping
) const;
377 // Serializes a GOAWAY frame. The GOAWAY frame is used
378 // prior to the shutting down of the TCP connection, and includes the
379 // stream_id of the last stream the sender of the frame is willing to process
381 SpdySerializedFrame
* SerializeGoAway(const SpdyGoAwayIR
& goaway
) const;
383 // Serializes a HEADERS frame. The HEADERS frame is used
384 // for sending additional headers outside of a SYN_STREAM/SYN_REPLY.
385 SpdySerializedFrame
* SerializeHeaders(const SpdyHeadersIR
& headers
);
387 // Serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE
388 // frame is used to implement per stream flow control in SPDY.
389 SpdySerializedFrame
* SerializeWindowUpdate(
390 const SpdyWindowUpdateIR
& window_update
) const;
392 // Serializes a BLOCKED frame. The BLOCKED frame is used to
393 // indicate to the remote endpoint that this endpoint believes itself to be
394 // flow-control blocked but otherwise ready to send data. The BLOCKED frame
395 // is purely advisory and optional.
396 SpdySerializedFrame
* SerializeBlocked(const SpdyBlockedIR
& blocked
) const;
398 // Serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used
399 // to inform the client that it will be receiving an additional stream
400 // in response to the original request. The frame includes synthesized
401 // headers to explain the upcoming data.
402 SpdySerializedFrame
* SerializePushPromise(
403 const SpdyPushPromiseIR
& push_promise
);
405 // Serialize a frame of unknown type.
406 SpdySerializedFrame
* SerializeFrame(const SpdyFrameIR
& frame
);
408 // NOTES about frame compression.
409 // We want spdy to compress headers across the entire session. As long as
410 // the session is over TCP, frames are sent serially. The client & server
411 // can each compress frames in the same order and then compress them in that
412 // order, and the remote can do the reverse. However, we ultimately want
413 // the creation of frames to be less sensitive to order so that they can be
414 // placed over a UDP based protocol and yet still benefit from some
415 // compression. We don't know of any good compression protocol which does
416 // not build its state in a serial (stream based) manner.... For now, we're
417 // using zlib anyway.
419 // Compresses a SpdyFrame.
420 // On success, returns a new SpdyFrame with the payload compressed.
421 // Compression state is maintained as part of the SpdyFramer.
422 // Returned frame must be freed with "delete".
423 // On failure, returns NULL.
424 SpdyFrame
* CompressFrame(const SpdyFrame
& frame
);
426 // For ease of testing and experimentation we can tweak compression on/off.
427 void set_enable_compression(bool value
) {
428 enable_compression_
= value
;
431 // Used only in log messages.
432 void set_display_protocol(const std::string
& protocol
) {
433 display_protocol_
= protocol
;
436 // Returns the (minimum) size of frames (sans variable-length portions).
437 size_t GetDataFrameMinimumSize() const;
438 size_t GetControlFrameHeaderSize() const;
439 size_t GetSynStreamMinimumSize() const;
440 size_t GetSynReplyMinimumSize() const;
441 size_t GetRstStreamMinimumSize() const;
442 size_t GetSettingsMinimumSize() const;
443 size_t GetPingSize() const;
444 size_t GetGoAwayMinimumSize() const;
445 size_t GetHeadersMinimumSize() const;
446 size_t GetWindowUpdateSize() const;
447 size_t GetBlockedSize() const;
448 size_t GetPushPromiseMinimumSize() const;
450 // Returns the minimum size a frame can be (data or control).
451 size_t GetFrameMinimumSize() const;
453 // Returns the maximum size a frame can be (data or control).
454 size_t GetFrameMaximumSize() const;
456 // Returns the maximum payload size of a DATA frame.
457 size_t GetDataFrameMaximumPayload() const;
460 static const char* StateToString(int state
);
461 static const char* ErrorCodeToString(int error_code
);
462 static const char* StatusCodeToString(int status_code
);
463 static const char* FrameTypeToString(SpdyFrameType type
);
465 SpdyMajorVersion
protocol_version() const { return spdy_version_
; }
467 bool probable_http_response() const { return probable_http_response_
; }
469 SpdyPriority
GetLowestPriority() const { return spdy_version_
< 3 ? 3 : 7; }
470 SpdyPriority
GetHighestPriority() const { return 0; }
472 // Deliver the given control frame's compressed headers block to the visitor
473 // in decompressed form, in chunks. Returns true if the visitor has
474 // accepted all of the chunks.
475 bool IncrementallyDecompressControlFrameHeaderData(
476 SpdyStreamId stream_id
,
481 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
, BasicCompression
);
482 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
, ControlFrameSizesAreValidated
);
483 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
, HeaderCompression
);
484 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
, DecompressUncompressedFrame
);
485 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
, ExpandBuffer_HeapSmash
);
486 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
, HugeHeaderBlock
);
487 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
, UnclosedStreamDataCompressors
);
488 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
,
489 UnclosedStreamDataCompressorsOneByteAtATime
);
490 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
,
491 UncompressLargerThanFrameBufferInitialSize
);
492 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
, ReadLargeSettingsFrame
);
493 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
,
494 ReadLargeSettingsFrameInSmallChunks
);
495 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
, ControlFrameAtMaxSizeLimit
);
496 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest
, ControlFrameTooLarge
);
497 friend class net::HttpNetworkLayer
; // This is temporary for the server.
498 friend class net::HttpNetworkTransactionTest
;
499 friend class net::HttpProxyClientSocketPoolTest
;
500 friend class net::SpdyHttpStreamTest
;
501 friend class net::SpdyNetworkTransactionTest
;
502 friend class net::SpdyProxyClientSocketTest
;
503 friend class net::SpdySessionTest
;
504 friend class net::SpdyStreamTest
;
505 friend class net::SpdyWebSocketStreamTest
;
506 friend class net::WebSocketJobTest
;
507 friend class test::TestSpdyVisitor
;
510 // Internal breakouts from ProcessInput. Each returns the number of bytes
511 // consumed from the data.
512 size_t ProcessCommonHeader(const char* data
, size_t len
);
513 size_t ProcessControlFramePayload(const char* data
, size_t len
);
514 size_t ProcessControlFrameBeforeHeaderBlock(const char* data
, size_t len
);
515 size_t ProcessControlFrameHeaderBlock(const char* data
, size_t len
);
516 size_t ProcessDataFramePayload(const char* data
, size_t len
);
517 size_t ProcessGoAwayFramePayload(const char* data
, size_t len
);
518 size_t ProcessRstStreamFramePayload(const char* data
, size_t len
);
519 size_t ProcessSettingsFramePayload(const char* data
, size_t len
);
522 // Helpers for above internal breakouts from ProcessInput.
523 void ProcessControlFrameHeader(uint16 control_frame_type_field
);
524 bool ProcessSetting(const char* data
); // Always passed exactly 8 bytes.
526 // Retrieve serialized length of SpdyHeaderBlock. If compression is enabled, a
527 // maximum estimate is returned.
528 size_t GetSerializedLength(const SpdyHeaderBlock
& headers
);
530 // Get (and lazily initialize) the ZLib state.
531 z_stream
* GetHeaderCompressor();
532 z_stream
* GetHeaderDecompressor();
535 // Deliver the given control frame's uncompressed headers block to the
536 // visitor in chunks. Returns true if the visitor has accepted all of the
538 bool IncrementallyDeliverControlFrameHeaderData(SpdyStreamId stream_id
,
542 // Utility to copy the given data block to the current frame buffer, up
543 // to the given maximum number of bytes, and update the buffer
544 // data (pointer and length). Returns the number of bytes
546 // *data is advanced the number of bytes read.
547 // *len is reduced by the number of bytes read.
548 size_t UpdateCurrentFrameBuffer(const char** data
, size_t* len
,
551 void WriteHeaderBlockToZ(const SpdyHeaderBlock
* headers
,
552 z_stream
* out
) const;
554 void SerializeNameValueBlockWithoutCompression(
555 SpdyFrameBuilder
* builder
,
556 const SpdyNameValueBlock
& name_value_block
) const;
558 // Compresses automatically according to enable_compression_.
559 void SerializeNameValueBlock(
560 SpdyFrameBuilder
* builder
,
561 const SpdyFrameWithNameValueBlockIR
& frame
);
563 // Set the error code and moves the framer into the error state.
564 void set_error(SpdyError error
);
566 // The maximum size of the control frames that we support.
567 // This limit is arbitrary. We can enforce it here or at the application
568 // layer. We chose the framing layer, but this can be changed (or removed)
569 // if necessary later down the line.
570 size_t GetControlFrameBufferMaxSize() const {
571 // The theoretical maximum for SPDY3 and earlier is (2^24 - 1) +
572 // 8, since the length field does not count the size of the
574 if (spdy_version_
== SPDY2
) {
577 if (spdy_version_
== SPDY3
) {
578 return 16 * 1024 * 1024;
580 // The theoretical maximum for SPDY4 is 2^16 - 1, as the length
581 // field does count the size of the header.
585 // The size of the control frame buffer.
586 // Since this is only used for control frame headers, the maximum control
587 // frame header size (SYN_STREAM) is sufficient; all remaining control
588 // frame data is streamed to the visitor.
589 static const size_t kControlFrameBufferSize
;
592 SpdyState previous_state_
;
593 SpdyError error_code_
;
594 size_t remaining_data_length_
;
596 // The number of bytes remaining to read from the current control frame's
597 // headers. Note that header data blocks (for control types that have them)
598 // are part of the frame's payload, and not the frame's headers.
599 size_t remaining_control_header_
;
601 scoped_ptr
<char[]> current_frame_buffer_
;
602 // Number of bytes read into the current_frame_buffer_.
603 size_t current_frame_buffer_length_
;
605 // The type of the frame currently being read.
606 SpdyFrameType current_frame_type_
;
608 // The flags field of the frame currently being read.
609 uint8 current_frame_flags_
;
611 // The total length of the frame currently being read, including frame header.
612 uint32 current_frame_length_
;
614 // The stream ID field of the frame currently being read, if applicable.
615 SpdyStreamId current_frame_stream_id_
;
617 // Scratch space for handling SETTINGS frames.
618 // TODO(hkhalil): Unify memory for this scratch space with
619 // current_frame_buffer_.
620 SpdySettingsScratch settings_scratch_
;
622 bool enable_compression_
; // Controls all compression
623 // SPDY header compressors.
624 scoped_ptr
<z_stream
> header_compressor_
;
625 scoped_ptr
<z_stream
> header_decompressor_
;
627 SpdyFramerVisitorInterface
* visitor_
;
628 SpdyFramerDebugVisitorInterface
* debug_visitor_
;
630 std::string display_protocol_
;
632 // The major SPDY version to be spoken/understood by this framer.
633 const SpdyMajorVersion spdy_version_
;
635 // Tracks if we've ever gotten far enough in framing to see a control frame of
636 // type SYN_STREAM or SYN_REPLY.
638 // If we ever get something which looks like a data frame before we've had a
639 // SYN, we explicitly check to see if it looks like we got an HTTP response
640 // to a SPDY request. This boolean lets us do that.
641 bool syn_frame_processed_
;
643 // If we ever get a data frame before a SYN frame, we check to see if it
644 // starts with HTTP. If it does, we likely have an HTTP response. This
645 // isn't guaranteed though: we could have gotten a settings frame and then
646 // corrupt data that just looks like HTTP, but deterministic checking requires
648 bool probable_http_response_
;
653 #endif // NET_SPDY_SPDY_FRAMER_H_