rAc - revert invalid suggestions to edit mode
[chromium-blink-merge.git] / net / spdy / spdy_framer.h
blob6cd889a5c5df0714a5a8951938440bba64d6de51
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_
8 #include <list>
9 #include <map>
10 #include <string>
11 #include <utility>
12 #include <vector>
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.
26 namespace net {
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;
39 class SpdyFramer;
40 class SpdyFrameBuilder;
41 class SpdyFramerTest;
43 namespace test {
45 class TestSpdyVisitor;
47 } // namespace test
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 {
56 public:
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_; }
69 private:
70 static void ConvertFlagsAndIdForSpdy2(uint32* val);
72 uint8 flags_;
73 uint32 id_;
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(); }
84 void Reset() {
85 setting_buf_len = 0;
86 last_setting_id = 0;
89 // Buffer contains up to one complete key/value pair.
90 char setting_buf[8];
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
112 // than zero.
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 {
124 public:
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,
134 size_t length,
135 bool fin) = 0;
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,
144 const char* data,
145 size_t len,
146 bool fin) = 0;
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,
159 size_t len) = 0;
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,
167 bool fin,
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
184 // validated.
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
235 // operates.
237 // Most SPDY implementations need not bother with this interface at all.
238 class NET_EXPORT_PRIVATE SpdyFramerDebugVisitorInterface {
239 public:
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,
247 SpdyFrameType type,
248 size_t payload_len,
249 size_t frame_len) {}
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,
255 SpdyFrameType type,
256 size_t frame_len) {}
259 class NET_EXPORT_PRIVATE SpdyFramer {
260 public:
261 // SPDY states.
262 // TODO(mbelshe): Can we move these into the implementation
263 // and avoid exposing through the header. (Needed for test)
264 enum SpdyState {
265 SPDY_ERROR,
266 SPDY_RESET,
267 SPDY_AUTO_RESET,
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,
279 // SPDY error codes.
280 enum SpdyError {
281 SPDY_NO_ERROR,
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
301 // purposes.)
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
321 // will be used.
322 void set_visitor(SpdyFramerVisitorInterface* visitor) {
323 visitor_ = 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?
340 void Reset();
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
380 // to completion.
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;
459 // For debugging.
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,
477 const char* data,
478 size_t len);
480 protected:
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;
509 private:
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();
534 private:
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
537 // chunks.
538 bool IncrementallyDeliverControlFrameHeaderData(SpdyStreamId stream_id,
539 const char* data,
540 size_t len);
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
545 // read, and:
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,
549 size_t max_bytes);
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
573 // header.
574 if (spdy_version_ == SPDY2) {
575 return 64 * 1024;
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.
582 return 16 * 1024;
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;
591 SpdyState state_;
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
647 // a lot more state.
648 bool probable_http_response_;
651 } // namespace net
653 #endif // NET_SPDY_SPDY_FRAMER_H_