summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_framer.h
diff options
context:
space:
mode:
Diffstat (limited to 'net/spdy/spdy_framer.h')
-rw-r--r--net/spdy/spdy_framer.h140
1 files changed, 128 insertions, 12 deletions
diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h
index 332a47f..b861a3f 100644
--- a/net/spdy/spdy_framer.h
+++ b/net/spdy/spdy_framer.h
@@ -58,9 +58,28 @@ class SpdyFramerVisitorInterface {
// 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.
@@ -86,7 +105,9 @@ class SpdyFramer {
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.
@@ -102,6 +123,14 @@ class SpdyFramer {
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();
@@ -138,6 +167,14 @@ class SpdyFramer {
// 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.
@@ -151,7 +188,7 @@ class SpdyFramer {
int priority,
SpdyControlFlags flags,
bool compressed,
- SpdyHeaderBlock* headers);
+ const SpdyHeaderBlock* headers);
// Create a SpdySynReplyControlFrame.
// |stream_id| is the stream for this frame.
@@ -162,7 +199,7 @@ class SpdyFramer {
SpdySynReplyControlFrame* CreateSynReply(SpdyStreamId stream_id,
SpdyControlFlags flags,
bool compressed,
- SpdyHeaderBlock* headers);
+ const SpdyHeaderBlock* headers);
static SpdyRstStreamControlFrame* CreateRstStream(SpdyStreamId stream_id,
SpdyStatusCodes status);
@@ -172,7 +209,11 @@ class SpdyFramer {
// 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
@@ -187,7 +228,7 @@ class SpdyFramer {
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.
@@ -242,9 +283,29 @@ class SpdyFramer {
// 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_; }
@@ -271,14 +332,11 @@ class SpdyFramer {
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.
@@ -293,6 +351,11 @@ class SpdyFramer {
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.
@@ -317,6 +380,36 @@ class SpdyFramer {
// 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);
@@ -331,15 +424,38 @@ class SpdyFramer {
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_;