| Index: net/spdy/spdy_framer.h
|
| ===================================================================
|
| --- net/spdy/spdy_framer.h (revision 102678)
|
| +++ net/spdy/spdy_framer.h (working copy)
|
| @@ -61,9 +61,28 @@
|
| // Called if an error is detected in the SpdyFrame protocol.
|
| virtual void OnError(SpdyFramer* framer) = 0;
|
|
|
| - // Called when a Control Frame is received.
|
| + // Called when a control frame is received.
|
| virtual void OnControl(const SpdyControlFrame* frame) = 0;
|
|
|
| + // Called when a chunk of header data is available. This is called
|
| + // after OnControl() is called with the control frame associated with the
|
| + // header data being delivered here.
|
| + // |stream_id| The stream receiving the header data.
|
| + // |header_data| A buffer containing the header data chunk received.
|
| + // |len| The length of the header data buffer. A length of zero indicates
|
| + // that the header data block has been completely sent.
|
| + // When this function returns true the visitor indicates that it accepted
|
| + // all of the data. Returning false indicates that that an unrecoverable
|
| + // error has occurred, such as bad header data or resource exhaustion.
|
| + virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
|
| + const char* header_data,
|
| + size_t len) = 0;
|
| +
|
| + // Called when a data frame header is received. The frame's data
|
| + // payload will be provided via subsequent calls to
|
| + // OnStreamFrameData().
|
| + virtual void OnDataFrameHeader(const SpdyDataFrame* frame) = 0;
|
| +
|
| // Called when data is received.
|
| // |stream_id| The stream receiving data.
|
| // |data| A buffer containing the data received.
|
| @@ -89,7 +108,9 @@
|
| SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER,
|
| SPDY_CONTROL_FRAME_PAYLOAD,
|
| SPDY_IGNORE_REMAINING_PAYLOAD,
|
| - SPDY_FORWARD_STREAM_FRAME
|
| + SPDY_FORWARD_STREAM_FRAME,
|
| + SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK,
|
| + SPDY_CONTROL_FRAME_HEADER_BLOCK,
|
| };
|
|
|
| // SPDY error codes.
|
| @@ -105,6 +126,14 @@
|
| LAST_ERROR, // Must be the last entry in the enum.
|
| };
|
|
|
| + // Constant for invalid (or unknown) stream IDs.
|
| + static const SpdyStreamId kInvalidStream;
|
| +
|
| + // The maximum size of header data chunks delivered to the framer visitor
|
| + // through OnControlFrameHeaderData. (It is exposed here for unit test
|
| + // purposes.)
|
| + static const size_t kHeaderDataChunkMaxSize;
|
| +
|
| // Create a new Framer.
|
| SpdyFramer();
|
| virtual ~SpdyFramer();
|
| @@ -141,6 +170,14 @@
|
| // Returns true if successfully parsed, false otherwise.
|
| bool ParseHeaderBlock(const SpdyFrame* frame, SpdyHeaderBlock* block);
|
|
|
| + // Given a buffer containing a decompressed header block in SPDY
|
| + // serialized format, parse out a SpdyHeaderBlock, putting the results
|
| + // in the given header block.
|
| + // Returns true if successfully parsed, false otherwise.
|
| + static bool ParseHeaderBlockInBuffer(const char* header_data,
|
| + size_t header_length,
|
| + SpdyHeaderBlock* block);
|
| +
|
| // Create a SpdySynStreamControlFrame.
|
| // |stream_id| is the id for this stream.
|
| // |associated_stream_id| is the associated stream id for this stream.
|
| @@ -154,7 +191,7 @@
|
| int priority,
|
| SpdyControlFlags flags,
|
| bool compressed,
|
| - SpdyHeaderBlock* headers);
|
| + const SpdyHeaderBlock* headers);
|
|
|
| // Create a SpdySynReplyControlFrame.
|
| // |stream_id| is the stream for this frame.
|
| @@ -165,7 +202,7 @@
|
| SpdySynReplyControlFrame* CreateSynReply(SpdyStreamId stream_id,
|
| SpdyControlFlags flags,
|
| bool compressed,
|
| - SpdyHeaderBlock* headers);
|
| + const SpdyHeaderBlock* headers);
|
|
|
| static SpdyRstStreamControlFrame* CreateRstStream(SpdyStreamId stream_id,
|
| SpdyStatusCodes status);
|
| @@ -175,8 +212,12 @@
|
| // TODO(mbelshe): add the name/value pairs!!
|
| static SpdySettingsControlFrame* CreateSettings(const SpdySettings& values);
|
|
|
| - static SpdyControlFrame* CreateNopFrame();
|
| + static SpdyNoOpControlFrame* CreateNopFrame();
|
|
|
| + // Creates an instance of SpdyPingControlFrame. The unique_id is used to
|
| + // identify the ping request/response.
|
| + static SpdyPingControlFrame* CreatePingFrame(uint32 unique_id);
|
| +
|
| // Creates an instance of SpdyGoAwayControlFrame. The GOAWAY frame is used
|
| // prior to the shutting down of the TCP connection, and includes the
|
| // stream_id of the last stream the sender of the frame is willing to process
|
| @@ -190,7 +231,7 @@
|
| SpdyHeadersControlFrame* CreateHeaders(SpdyStreamId stream_id,
|
| SpdyControlFlags flags,
|
| bool compressed,
|
| - SpdyHeaderBlock* headers);
|
| + const SpdyHeaderBlock* headers);
|
|
|
| // Creates an instance of SpdyWindowUpdateControlFrame. The WINDOW_UPDATE
|
| // frame is used to implement per stream flow control in SPDY.
|
| @@ -245,9 +286,29 @@
|
| // Returns true if a frame could be compressed.
|
| bool IsCompressible(const SpdyFrame& frame) const;
|
|
|
| + // Get the minimum size of the control frame for the given control frame
|
| + // type. This is useful for validating frame blocks.
|
| + static size_t GetMinimumControlFrameSize(SpdyControlType type);
|
| +
|
| + // Get the stream ID for the given control frame (SYN_STREAM, SYN_REPLY, and
|
| + // HEADERS). If the control frame is NULL or of another type, this
|
| + // function returns kInvalidStream.
|
| + static SpdyStreamId GetControlFrameStreamId(
|
| + const SpdyControlFrame* control_frame);
|
| +
|
| + // For ease of testing and experimentation we can tweak compression on/off.
|
| + void set_enable_compression(bool value);
|
| +
|
| + // SPDY will by default validate the length of incoming control
|
| + // frames. Set validation to false if you do not want this behavior.
|
| + void set_validate_control_frame_sizes(bool value);
|
| + static void set_enable_compression_default(bool value);
|
| +
|
| // For debugging.
|
| static const char* StateToString(int state);
|
| static const char* ErrorCodeToString(int error_code);
|
| + static const char* StatusCodeToString(int status_code);
|
| + static const char* ControlTypeToString(SpdyControlType type);
|
| static void set_protocol_version(int version) { spdy_version_= version; }
|
| static int protocol_version() { return spdy_version_; }
|
|
|
| @@ -276,14 +337,11 @@
|
| friend void test::FramerSetEnableCompressionHelper(SpdyFramer* framer,
|
| bool compress);
|
|
|
| - // For ease of testing we can tweak compression on/off.
|
| - void set_enable_compression(bool value);
|
| - static void set_enable_compression_default(bool value);
|
| -
|
| -
|
| // The initial size of the control frame buffer; this is used internally
|
| // as we parse through control frames. (It is exposed here for unit test
|
| // purposes.)
|
| + // This is only used when compression is enabled; otherwise,
|
| + // kUncompressedControlFrameBufferInitialSize is used.
|
| static size_t kControlFrameBufferInitialSize;
|
|
|
| // The maximum size of the control frame buffer that we support.
|
| @@ -298,6 +356,11 @@
|
| size_t ProcessCommonHeader(const char* data, size_t len);
|
| void ProcessControlFrameHeader();
|
| size_t ProcessControlFramePayload(const char* data, size_t len);
|
| + size_t ProcessControlFrameBeforeHeaderBlock(const char* data, size_t len);
|
| + // TODO(hkhalil): Rename to ProcessControlFrameHeaderBlock once said flag is
|
| + // removed, replacing the old method.
|
| + size_t NewProcessControlFrameHeaderBlock(const char* data, size_t len);
|
| + size_t ProcessControlFrameHeaderBlock(const char* data, size_t len);
|
| size_t ProcessDataFramePayload(const char* data, size_t len);
|
|
|
| // Get (and lazily initialize) the ZLib state.
|
| @@ -322,6 +385,36 @@
|
| // Not used (yet)
|
| size_t BytesSafeToRead() const;
|
|
|
| + // Deliver the given control frame's compressed headers block to the visitor
|
| + // in decompressed form, in chunks. Returns true if the visitor has
|
| + // accepted all of the chunks.
|
| + bool IncrementallyDecompressControlFrameHeaderData(
|
| + const SpdyControlFrame* frame);
|
| +
|
| + // Deliver the given control frame's compressed headers block to the visitor
|
| + // in decompressed form, in chunks. Returns true if the visitor has
|
| + // accepted all of the chunks.
|
| + bool IncrementallyDecompressControlFrameHeaderData(
|
| + const SpdyControlFrame* frame,
|
| + const char* data,
|
| + size_t len);
|
| +
|
| + // Deliver the given control frame's uncompressed headers block to the
|
| + // visitor in chunks. Returns true if the visitor has accepted all of the
|
| + // chunks.
|
| + bool IncrementallyDeliverControlFrameHeaderData(const SpdyControlFrame* frame,
|
| + const char* data,
|
| + size_t len);
|
| +
|
| + // Utility to copy the given data block to the current frame buffer, up
|
| + // to the given maximum number of bytes, and update the buffer
|
| + // data (pointer and length). Returns the number of bytes
|
| + // read, and:
|
| + // *data is advanced the number of bytes read.
|
| + // *len is reduced by the number of bytes read.
|
| + size_t UpdateCurrentFrameBuffer(const char** data, size_t* len,
|
| + size_t max_bytes);
|
| +
|
| // Set the error code and moves the framer into the error state.
|
| void set_error(SpdyError error);
|
|
|
| @@ -336,15 +429,38 @@
|
| int num_stream_compressors() const { return stream_compressors_.size(); }
|
| int num_stream_decompressors() const { return stream_decompressors_.size(); }
|
|
|
| + // The initial size of the control frame buffer when compression is disabled.
|
| + // This exists because we don't do stream (de)compressed control frame data to
|
| + // our visitor; we instead buffer the entirety of the control frame and then
|
| + // decompress in one fell swoop.
|
| + // Since this is only used for control frame headers, the maximum control
|
| + // frame header size (18B) is sufficient; all remaining control frame data is
|
| + // streamed to the visitor.
|
| + // In addition to the maximum control frame header size, we account for any
|
| + // LOAS checksumming (16B) that may occur in the VTL case.
|
| + static const size_t kUncompressedControlFrameBufferInitialSize = 18 + 16;
|
| +
|
| + // The size of the buffer into which compressed frames are inflated.
|
| + static const size_t kDecompressionBufferSize = 8 * 1024;
|
| +
|
| SpdyState state_;
|
| SpdyError error_code_;
|
| - size_t remaining_payload_;
|
| + size_t remaining_data_;
|
| +
|
| + // The number of bytes remaining to read from the current control frame's
|
| + // payload.
|
| size_t remaining_control_payload_;
|
|
|
| + // The number of bytes remaining to read from the current control frame's
|
| + // headers. Note that header data blocks (for control types that have them)
|
| + // are part of the frame's payload, and not the frame's headers.
|
| + size_t remaining_control_header_;
|
| +
|
| char* current_frame_buffer_;
|
| size_t current_frame_len_; // Number of bytes read into the current_frame_.
|
| size_t current_frame_capacity_;
|
|
|
| + bool validate_control_frame_sizes_;
|
| bool enable_compression_; // Controls all compression
|
| // SPDY header compressors.
|
| scoped_ptr<z_stream> header_compressor_;
|
|
|