| Index: net/spdy/spdy_framer.h
|
| diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h
|
| deleted file mode 100644
|
| index 7ce2c850e50eac3e087ddf76ba182e00e7fb1372..0000000000000000000000000000000000000000
|
| --- a/net/spdy/spdy_framer.h
|
| +++ /dev/null
|
| @@ -1,810 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#ifndef NET_SPDY_SPDY_FRAMER_H_
|
| -#define NET_SPDY_SPDY_FRAMER_H_
|
| -
|
| -#include <list>
|
| -#include <map>
|
| -#include <memory>
|
| -#include <string>
|
| -#include <utility>
|
| -#include <vector>
|
| -
|
| -#include "base/basictypes.h"
|
| -#include "base/gtest_prod_util.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/strings/string_piece.h"
|
| -#include "base/sys_byteorder.h"
|
| -#include "net/base/net_export.h"
|
| -#include "net/spdy/hpack_decoder.h"
|
| -#include "net/spdy/hpack_encoder.h"
|
| -#include "net/spdy/spdy_header_block.h"
|
| -#include "net/spdy/spdy_protocol.h"
|
| -
|
| -// TODO(akalin): Remove support for CREDENTIAL frames.
|
| -
|
| -typedef struct z_stream_s z_stream; // Forward declaration for zlib.
|
| -
|
| -namespace net {
|
| -
|
| -class HttpProxyClientSocketPoolTest;
|
| -class HttpNetworkLayer;
|
| -class HttpNetworkTransactionTest;
|
| -class SpdyHttpStreamTest;
|
| -class SpdyNetworkTransactionTest;
|
| -class SpdyProxyClientSocketTest;
|
| -class SpdySessionTest;
|
| -class SpdyStreamTest;
|
| -
|
| -class SpdyFramer;
|
| -class SpdyFrameBuilder;
|
| -class SpdyFramerTest;
|
| -
|
| -namespace test {
|
| -
|
| -class TestSpdyVisitor;
|
| -
|
| -} // namespace test
|
| -
|
| -// A datastructure for holding a set of headers from a HEADERS, PUSH_PROMISE,
|
| -// SYN_STREAM, or SYN_REPLY frame.
|
| -typedef std::map<std::string, std::string> SpdyHeaderBlock;
|
| -
|
| -// A datastructure for holding the ID and flag fields for SETTINGS.
|
| -// Conveniently handles converstion to/from wire format.
|
| -class NET_EXPORT_PRIVATE SettingsFlagsAndId {
|
| - public:
|
| - static SettingsFlagsAndId FromWireFormat(SpdyMajorVersion version,
|
| - uint32 wire);
|
| -
|
| - SettingsFlagsAndId() : flags_(0), id_(0) {}
|
| -
|
| - // TODO(hkhalil): restrict to enums instead of free-form ints.
|
| - SettingsFlagsAndId(uint8 flags, uint32 id);
|
| -
|
| - uint32 GetWireFormat(SpdyMajorVersion version) const;
|
| -
|
| - uint32 id() const { return id_; }
|
| - uint8 flags() const { return flags_; }
|
| -
|
| - private:
|
| - static void ConvertFlagsAndIdForSpdy2(uint32* val);
|
| -
|
| - uint8 flags_;
|
| - uint32 id_;
|
| -};
|
| -
|
| -// SettingsMap has unique (flags, value) pair for given SpdySettingsIds ID.
|
| -typedef std::pair<SpdySettingsFlags, uint32> SettingsFlagsAndValue;
|
| -typedef std::map<SpdySettingsIds, SettingsFlagsAndValue> SettingsMap;
|
| -
|
| -// Scratch space necessary for processing SETTINGS frames.
|
| -struct NET_EXPORT_PRIVATE SpdySettingsScratch {
|
| - SpdySettingsScratch() { Reset(); }
|
| -
|
| - void Reset() {
|
| - setting_buf_len = 0;
|
| - last_setting_id = -1;
|
| - }
|
| -
|
| - // Buffer contains up to one complete key/value pair.
|
| - char setting_buf[8];
|
| -
|
| - // The amount of the buffer that is filled with valid data.
|
| - size_t setting_buf_len;
|
| -
|
| - // The ID of the last setting that was processed in the current SETTINGS
|
| - // frame. Used for detecting out-of-order or duplicate keys within a settings
|
| - // frame. Set to -1 before first key/value pair is processed.
|
| - int last_setting_id;
|
| -};
|
| -
|
| -// Scratch space necessary for processing ALTSVC frames.
|
| -struct NET_EXPORT_PRIVATE SpdyAltSvcScratch {
|
| - SpdyAltSvcScratch();
|
| - ~SpdyAltSvcScratch();
|
| -
|
| - void Reset() {
|
| - max_age = 0;
|
| - port = 0;
|
| - pid_len = 0;
|
| - host_len = 0;
|
| - origin_len = 0;
|
| - pid_buf_len = 0;
|
| - host_buf_len = 0;
|
| - origin_buf_len = 0;
|
| - protocol_id.reset();
|
| - host.reset();
|
| - origin.reset();
|
| - }
|
| -
|
| - uint32 max_age;
|
| - uint16 port;
|
| - uint8 pid_len;
|
| - uint8 host_len;
|
| - size_t origin_len;
|
| - size_t pid_buf_len;
|
| - size_t host_buf_len;
|
| - size_t origin_buf_len;
|
| - scoped_ptr<char[]> protocol_id;
|
| - scoped_ptr<char[]> host;
|
| - scoped_ptr<char[]> origin;
|
| -};
|
| -
|
| -// SpdyFramerVisitorInterface is a set of callbacks for the SpdyFramer.
|
| -// Implement this interface to receive event callbacks as frames are
|
| -// decoded from the framer.
|
| -//
|
| -// Control frames that contain SPDY header blocks (SYN_STREAM, SYN_REPLY,
|
| -// HEADER, and PUSH_PROMISE) are processed in fashion that allows the
|
| -// decompressed header block to be delivered in chunks to the visitor.
|
| -// The following steps are followed:
|
| -// 1. OnSynStream, OnSynReply, OnHeaders, or OnPushPromise is called.
|
| -// 2. Repeated: OnControlFrameHeaderData is called with chunks of the
|
| -// decompressed header block. In each call the len parameter is greater
|
| -// than zero.
|
| -// 3. OnControlFrameHeaderData is called with len set to zero, indicating
|
| -// that the full header block has been delivered for the control frame.
|
| -// During step 2 the visitor may return false, indicating that the chunk of
|
| -// header data could not be handled by the visitor (typically this indicates
|
| -// resource exhaustion). If this occurs the framer will discontinue
|
| -// delivering chunks to the visitor, set a SPDY_CONTROL_PAYLOAD_TOO_LARGE
|
| -// error, and clean up appropriately. Note that this will cause the header
|
| -// decompressor to lose synchronization with the sender's header compressor,
|
| -// making the SPDY session unusable for future work. The visitor's OnError
|
| -// function should deal with this condition by closing the SPDY connection.
|
| -class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface {
|
| - public:
|
| - virtual ~SpdyFramerVisitorInterface() {}
|
| -
|
| - // Called if an error is detected in the SpdyFrame protocol.
|
| - virtual void OnError(SpdyFramer* framer) = 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(SpdyStreamId stream_id,
|
| - size_t length,
|
| - bool fin) = 0;
|
| -
|
| - // Called when data is received.
|
| - // |stream_id| The stream receiving data.
|
| - // |data| A buffer containing the data received.
|
| - // |len| The length of the data buffer.
|
| - // When the other side has finished sending data on this stream,
|
| - // this method will be called with a zero-length buffer.
|
| - virtual void OnStreamFrameData(SpdyStreamId stream_id,
|
| - const char* data,
|
| - size_t len,
|
| - bool fin) = 0;
|
| -
|
| - // Called when a chunk of header data is available. This is called
|
| - // after OnSynStream, OnSynReply, OnHeaders(), or OnPushPromise.
|
| - // |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 SYN_STREAM frame is received.
|
| - // Note that header block data is not included. See
|
| - // OnControlFrameHeaderData().
|
| - virtual void OnSynStream(SpdyStreamId stream_id,
|
| - SpdyStreamId associated_stream_id,
|
| - SpdyPriority priority,
|
| - bool fin,
|
| - bool unidirectional) = 0;
|
| -
|
| - // Called when a SYN_REPLY frame is received.
|
| - // Note that header block data is not included. See
|
| - // OnControlFrameHeaderData().
|
| - virtual void OnSynReply(SpdyStreamId stream_id, bool fin) = 0;
|
| -
|
| - // Called when a RST_STREAM frame has been parsed.
|
| - virtual void OnRstStream(SpdyStreamId stream_id,
|
| - SpdyRstStreamStatus status) = 0;
|
| -
|
| - // Called when a SETTINGS frame is received.
|
| - // |clear_persisted| True if the respective flag is set on the SETTINGS frame.
|
| - virtual void OnSettings(bool clear_persisted) {}
|
| -
|
| - // Called when a complete setting within a SETTINGS frame has been parsed and
|
| - // validated.
|
| - virtual void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) = 0;
|
| -
|
| - // Called when a SETTINGS frame is received with the ACK flag set.
|
| - virtual void OnSettingsAck() {}
|
| -
|
| - // Called before and after parsing SETTINGS id and value tuples.
|
| - virtual void OnSettingsEnd() = 0;
|
| -
|
| - // Called when a PING frame has been parsed.
|
| - virtual void OnPing(SpdyPingId unique_id, bool is_ack) = 0;
|
| -
|
| - // Called when a GOAWAY frame has been parsed.
|
| - virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
|
| - SpdyGoAwayStatus status) = 0;
|
| -
|
| - // Called when a HEADERS frame is received.
|
| - // Note that header block data is not included. See
|
| - // OnControlFrameHeaderData().
|
| - virtual void OnHeaders(SpdyStreamId stream_id,
|
| - bool has_priority,
|
| - SpdyPriority priority,
|
| - bool fin,
|
| - bool end) = 0;
|
| -
|
| - // Called when a WINDOW_UPDATE frame has been parsed.
|
| - virtual void OnWindowUpdate(SpdyStreamId stream_id,
|
| - uint32 delta_window_size) = 0;
|
| -
|
| - // Called when a goaway frame opaque data is available.
|
| - // |goaway_data| A buffer containing the opaque GOAWAY 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 error has
|
| - // occurred while processing the data. Default implementation returns true.
|
| - virtual bool OnGoAwayFrameData(const char* goaway_data, size_t len);
|
| -
|
| - // Called when rst_stream frame opaque data is available.
|
| - // |rst_stream_data| A buffer containing the opaque RST_STREAM
|
| - // data chunk received.
|
| - // |len| The length of the header data buffer. A length of zero indicates
|
| - // that the opaque data 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 error has
|
| - // occurred while processing the data. Default implementation returns true.
|
| - virtual bool OnRstStreamFrameData(const char* rst_stream_data, size_t len);
|
| -
|
| - // Called when a BLOCKED frame has been parsed.
|
| - virtual void OnBlocked(SpdyStreamId stream_id) {}
|
| -
|
| - // Called when a PUSH_PROMISE frame is received.
|
| - // Note that header block data is not included. See
|
| - // OnControlFrameHeaderData().
|
| - virtual void OnPushPromise(SpdyStreamId stream_id,
|
| - SpdyStreamId promised_stream_id,
|
| - bool end) = 0;
|
| -
|
| - // Called when a CONTINUATION frame is received.
|
| - // Note that header block data is not included. See
|
| - // OnControlFrameHeaderData().
|
| - virtual void OnContinuation(SpdyStreamId stream_id, bool end) = 0;
|
| -
|
| - // Called when an ALTSVC frame has been parsed.
|
| - virtual void OnAltSvc(SpdyStreamId stream_id,
|
| - uint32 max_age,
|
| - uint16 port,
|
| - base::StringPiece protocol_id,
|
| - base::StringPiece host,
|
| - base::StringPiece origin) {}
|
| -
|
| - // Called when a PRIORITY frame is received.
|
| - virtual void OnPriority(SpdyStreamId stream_id,
|
| - SpdyStreamId parent_stream_id,
|
| - uint8 weight,
|
| - bool exclusive) {}
|
| -
|
| - // Called when a frame type we don't recognize is received.
|
| - // Return true if this appears to be a valid extension frame, false otherwise.
|
| - // We distinguish between extension frames and nonsense by checking
|
| - // whether the stream id is valid.
|
| - virtual bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) = 0;
|
| -};
|
| -
|
| -// Optionally, and in addition to SpdyFramerVisitorInterface, a class supporting
|
| -// SpdyFramerDebugVisitorInterface may be used in conjunction with SpdyFramer in
|
| -// order to extract debug/internal information about the SpdyFramer as it
|
| -// operates.
|
| -//
|
| -// Most SPDY implementations need not bother with this interface at all.
|
| -class NET_EXPORT_PRIVATE SpdyFramerDebugVisitorInterface {
|
| - public:
|
| - virtual ~SpdyFramerDebugVisitorInterface() {}
|
| -
|
| - // Called after compressing a frame with a payload of
|
| - // a list of name-value pairs.
|
| - // |payload_len| is the uncompressed payload size.
|
| - // |frame_len| is the compressed frame size.
|
| - virtual void OnSendCompressedFrame(SpdyStreamId stream_id,
|
| - SpdyFrameType type,
|
| - size_t payload_len,
|
| - size_t frame_len) {}
|
| -
|
| - // Called when a frame containing a compressed payload of
|
| - // name-value pairs is received.
|
| - // |frame_len| is the compressed frame size.
|
| - virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id,
|
| - SpdyFrameType type,
|
| - size_t frame_len) {}
|
| -};
|
| -
|
| -class NET_EXPORT_PRIVATE SpdyFramer {
|
| - public:
|
| - // SPDY states.
|
| - // TODO(mbelshe): Can we move these into the implementation
|
| - // and avoid exposing through the header. (Needed for test)
|
| - enum SpdyState {
|
| - SPDY_ERROR,
|
| - SPDY_RESET,
|
| - SPDY_AUTO_RESET,
|
| - SPDY_READING_COMMON_HEADER,
|
| - SPDY_CONTROL_FRAME_PAYLOAD,
|
| - SPDY_READ_DATA_FRAME_PADDING_LENGTH,
|
| - SPDY_CONSUME_PADDING,
|
| - SPDY_IGNORE_REMAINING_PAYLOAD,
|
| - SPDY_FORWARD_STREAM_FRAME,
|
| - SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK,
|
| - SPDY_CONTROL_FRAME_HEADER_BLOCK,
|
| - SPDY_GOAWAY_FRAME_PAYLOAD,
|
| - SPDY_RST_STREAM_FRAME_PAYLOAD,
|
| - SPDY_SETTINGS_FRAME_PAYLOAD,
|
| - SPDY_ALTSVC_FRAME_PAYLOAD,
|
| - };
|
| -
|
| - // SPDY error codes.
|
| - enum SpdyError {
|
| - SPDY_NO_ERROR,
|
| - SPDY_INVALID_CONTROL_FRAME, // Control frame is mal-formatted.
|
| - SPDY_CONTROL_PAYLOAD_TOO_LARGE, // Control frame payload was too large.
|
| - SPDY_ZLIB_INIT_FAILURE, // The Zlib library could not initialize.
|
| - SPDY_UNSUPPORTED_VERSION, // Control frame has unsupported version.
|
| - SPDY_DECOMPRESS_FAILURE, // There was an error decompressing.
|
| - SPDY_COMPRESS_FAILURE, // There was an error compressing.
|
| - SPDY_GOAWAY_FRAME_CORRUPT, // GOAWAY frame could not be parsed.
|
| - SPDY_RST_STREAM_FRAME_CORRUPT, // RST_STREAM frame could not be parsed.
|
| - SPDY_INVALID_DATA_FRAME_FLAGS, // Data frame has invalid flags.
|
| - SPDY_INVALID_CONTROL_FRAME_FLAGS, // Control frame has invalid flags.
|
| - SPDY_UNEXPECTED_FRAME, // Frame received out of order.
|
| -
|
| - 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;
|
| -
|
| - // Serializes a SpdyHeaderBlock.
|
| - static void WriteHeaderBlock(SpdyFrameBuilder* frame,
|
| - const SpdyMajorVersion spdy_version,
|
| - const SpdyHeaderBlock* headers);
|
| -
|
| - // Retrieve serialized length of SpdyHeaderBlock.
|
| - // TODO(hkhalil): Remove, or move to quic code.
|
| - static size_t GetSerializedLength(
|
| - const SpdyMajorVersion spdy_version,
|
| - const SpdyHeaderBlock* headers);
|
| -
|
| - // Create a new Framer, provided a SPDY version.
|
| - explicit SpdyFramer(SpdyMajorVersion version);
|
| - virtual ~SpdyFramer();
|
| -
|
| - // Set callbacks to be called from the framer. A visitor must be set, or
|
| - // else the framer will likely crash. It is acceptable for the visitor
|
| - // to do nothing. If this is called multiple times, only the last visitor
|
| - // will be used.
|
| - void set_visitor(SpdyFramerVisitorInterface* visitor) {
|
| - visitor_ = visitor;
|
| - }
|
| -
|
| - // Set debug callbacks to be called from the framer. The debug visitor is
|
| - // completely optional and need not be set in order for normal operation.
|
| - // If this is called multiple times, only the last visitor will be used.
|
| - void set_debug_visitor(SpdyFramerDebugVisitorInterface* debug_visitor) {
|
| - debug_visitor_ = debug_visitor;
|
| - }
|
| -
|
| - // Pass data into the framer for parsing.
|
| - // Returns the number of bytes consumed. It is safe to pass more bytes in
|
| - // than may be consumed.
|
| - size_t ProcessInput(const char* data, size_t len);
|
| -
|
| - // Resets the framer state after a frame has been successfully decoded.
|
| - // TODO(mbelshe): can we make this private?
|
| - void Reset();
|
| -
|
| - // Check the state of the framer.
|
| - SpdyError error_code() const { return error_code_; }
|
| - SpdyState state() const { return state_; }
|
| - bool HasError() const { return state_ == SPDY_ERROR; }
|
| -
|
| - // 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 number of bytes consumed if successfully parsed, 0 otherwise.
|
| - size_t ParseHeaderBlockInBuffer(const char* header_data,
|
| - size_t header_length,
|
| - SpdyHeaderBlock* block) const;
|
| -
|
| - // Serialize a data frame.
|
| - SpdySerializedFrame* SerializeData(const SpdyDataIR& data) const;
|
| - // Serializes the data frame header and optionally padding length fields,
|
| - // excluding actual data payload and padding.
|
| - SpdySerializedFrame* SerializeDataFrameHeaderWithPaddingLengthField(
|
| - const SpdyDataIR& data) const;
|
| -
|
| - // Serializes a SYN_STREAM frame.
|
| - SpdySerializedFrame* SerializeSynStream(const SpdySynStreamIR& syn_stream);
|
| -
|
| - // Serialize a SYN_REPLY SpdyFrame.
|
| - SpdySerializedFrame* SerializeSynReply(const SpdySynReplyIR& syn_reply);
|
| -
|
| - SpdySerializedFrame* SerializeRstStream(
|
| - const SpdyRstStreamIR& rst_stream) const;
|
| -
|
| - // Serializes a SETTINGS frame. The SETTINGS frame is
|
| - // used to communicate name/value pairs relevant to the communication channel.
|
| - SpdySerializedFrame* SerializeSettings(const SpdySettingsIR& settings) const;
|
| -
|
| - // Serializes a PING frame. The unique_id is used to
|
| - // identify the ping request/response.
|
| - SpdySerializedFrame* SerializePing(const SpdyPingIR& ping) const;
|
| -
|
| - // Serializes a GOAWAY frame. 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
|
| - // to completion.
|
| - SpdySerializedFrame* SerializeGoAway(const SpdyGoAwayIR& goaway) const;
|
| -
|
| - // Serializes a HEADERS frame. The HEADERS frame is used
|
| - // for sending additional headers outside of a SYN_STREAM/SYN_REPLY.
|
| - SpdySerializedFrame* SerializeHeaders(const SpdyHeadersIR& headers);
|
| -
|
| - // Serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE
|
| - // frame is used to implement per stream flow control in SPDY.
|
| - SpdySerializedFrame* SerializeWindowUpdate(
|
| - const SpdyWindowUpdateIR& window_update) const;
|
| -
|
| - // Serializes a BLOCKED frame. The BLOCKED frame is used to
|
| - // indicate to the remote endpoint that this endpoint believes itself to be
|
| - // flow-control blocked but otherwise ready to send data. The BLOCKED frame
|
| - // is purely advisory and optional.
|
| - SpdySerializedFrame* SerializeBlocked(const SpdyBlockedIR& blocked) const;
|
| -
|
| - // Serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used
|
| - // to inform the client that it will be receiving an additional stream
|
| - // in response to the original request. The frame includes synthesized
|
| - // headers to explain the upcoming data.
|
| - SpdySerializedFrame* SerializePushPromise(
|
| - const SpdyPushPromiseIR& push_promise);
|
| -
|
| - // Serializes a CONTINUATION frame. The CONTINUATION frame is used
|
| - // to continue a sequence of header block fragments.
|
| - // TODO(jgraettinger): This implementation is incorrect. The continuation
|
| - // frame continues a previously-begun HPACK encoding; it doesn't begin a
|
| - // new one. Figure out whether it makes sense to keep SerializeContinuation().
|
| - SpdySerializedFrame* SerializeContinuation(
|
| - const SpdyContinuationIR& continuation);
|
| -
|
| - // Serializes an ALTSVC frame. The ALTSVC frame advertises the
|
| - // availability of an alternative service to the client.
|
| - SpdySerializedFrame* SerializeAltSvc(const SpdyAltSvcIR& altsvc);
|
| -
|
| - // Serializes a PRIORITY frame. The PRIORITY frame advises a change in
|
| - // the relative priority of the given stream.
|
| - SpdySerializedFrame* SerializePriority(const SpdyPriorityIR& priority) const;
|
| -
|
| - // Serialize a frame of unknown type.
|
| - SpdySerializedFrame* SerializeFrame(const SpdyFrameIR& frame);
|
| -
|
| - // NOTES about frame compression.
|
| - // We want spdy to compress headers across the entire session. As long as
|
| - // the session is over TCP, frames are sent serially. The client & server
|
| - // can each compress frames in the same order and then compress them in that
|
| - // order, and the remote can do the reverse. However, we ultimately want
|
| - // the creation of frames to be less sensitive to order so that they can be
|
| - // placed over a UDP based protocol and yet still benefit from some
|
| - // compression. We don't know of any good compression protocol which does
|
| - // not build its state in a serial (stream based) manner.... For now, we're
|
| - // using zlib anyway.
|
| -
|
| - // Compresses a SpdyFrame.
|
| - // On success, returns a new SpdyFrame with the payload compressed.
|
| - // Compression state is maintained as part of the SpdyFramer.
|
| - // Returned frame must be freed with "delete".
|
| - // On failure, returns NULL.
|
| - SpdyFrame* CompressFrame(const SpdyFrame& frame);
|
| -
|
| - // For ease of testing and experimentation we can tweak compression on/off.
|
| - void set_enable_compression(bool value) {
|
| - enable_compression_ = value;
|
| - }
|
| -
|
| - // Used only in log messages.
|
| - void set_display_protocol(const std::string& protocol) {
|
| - display_protocol_ = protocol;
|
| - }
|
| -
|
| - // Returns the (minimum) size of frames (sans variable-length portions).
|
| - size_t GetDataFrameMinimumSize() const;
|
| - size_t GetControlFrameHeaderSize() const;
|
| - size_t GetSynStreamMinimumSize() const;
|
| - size_t GetSynReplyMinimumSize() const;
|
| - size_t GetRstStreamMinimumSize() const;
|
| - size_t GetSettingsMinimumSize() const;
|
| - size_t GetPingSize() const;
|
| - size_t GetGoAwayMinimumSize() const;
|
| - size_t GetHeadersMinimumSize() const;
|
| - size_t GetWindowUpdateSize() const;
|
| - size_t GetBlockedSize() const;
|
| - size_t GetPushPromiseMinimumSize() const;
|
| - size_t GetContinuationMinimumSize() const;
|
| - size_t GetAltSvcMinimumSize() const;
|
| - size_t GetPrioritySize() const;
|
| -
|
| - // Returns the minimum size a frame can be (data or control).
|
| - size_t GetFrameMinimumSize() const;
|
| -
|
| - // Returns the maximum size a frame can be (data or control).
|
| - size_t GetFrameMaximumSize() const;
|
| -
|
| - // Returns the maximum size that a control frame can be.
|
| - size_t GetControlFrameMaximumSize() const;
|
| -
|
| - // Returns the maximum payload size of a DATA frame.
|
| - size_t GetDataFrameMaximumPayload() const;
|
| -
|
| - // Returns the prefix length for the given frame type.
|
| - size_t GetPrefixLength(SpdyFrameType type) const;
|
| -
|
| - // 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* FrameTypeToString(SpdyFrameType type);
|
| -
|
| - SpdyMajorVersion protocol_version() const { return protocol_version_; }
|
| -
|
| - bool probable_http_response() const { return probable_http_response_; }
|
| -
|
| - SpdyStreamId expect_continuation() const { return expect_continuation_; }
|
| -
|
| - SpdyPriority GetLowestPriority() const {
|
| - return protocol_version_ < SPDY3 ? 3 : 7;
|
| - }
|
| -
|
| - SpdyPriority GetHighestPriority() const { return 0; }
|
| -
|
| - // Interpolates SpdyPriority values into SPDY4/HTTP2 priority weights,
|
| - // and vice versa.
|
| - static uint8 MapPriorityToWeight(SpdyPriority priority);
|
| - static SpdyPriority MapWeightToPriority(uint8 weight);
|
| -
|
| - // 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(
|
| - SpdyStreamId stream_id,
|
| - const char* data,
|
| - size_t len);
|
| -
|
| - protected:
|
| - // TODO(jgraettinger): Switch to test peer pattern.
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, BasicCompression);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameSizesAreValidated);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HeaderCompression);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, DecompressUncompressedFrame);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ExpandBuffer_HeapSmash);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HugeHeaderBlock);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, UnclosedStreamDataCompressors);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
|
| - UnclosedStreamDataCompressorsOneByteAtATime);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
|
| - UncompressLargerThanFrameBufferInitialSize);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
|
| - CreatePushPromiseThenContinuationUncompressed);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ReadLargeSettingsFrame);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
|
| - ReadLargeSettingsFrameInSmallChunks);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameAtMaxSizeLimit);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameTooLarge);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
|
| - TooLargeHeadersFrameUsesContinuation);
|
| - FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest,
|
| - TooLargePushPromiseFrameUsesContinuation);
|
| - friend class HttpNetworkLayer; // This is temporary for the server.
|
| - friend class HttpNetworkTransactionTest;
|
| - friend class HttpProxyClientSocketPoolTest;
|
| - friend class SpdyHttpStreamTest;
|
| - friend class SpdyNetworkTransactionTest;
|
| - friend class SpdyProxyClientSocketTest;
|
| - friend class SpdySessionTest;
|
| - friend class SpdyStreamTest;
|
| - friend class test::TestSpdyVisitor;
|
| -
|
| - private:
|
| - // Internal breakouts from ProcessInput. Each returns the number of bytes
|
| - // consumed from the data.
|
| - size_t ProcessCommonHeader(const char* data, size_t len);
|
| - size_t ProcessControlFramePayload(const char* data, size_t len);
|
| - size_t ProcessControlFrameBeforeHeaderBlock(const char* data, size_t len);
|
| - // HPACK data is re-encoded as SPDY3 and re-entrantly delivered through
|
| - // |ProcessControlFrameHeaderBlock()|. |is_hpack_header_block| controls
|
| - // whether data is treated as HPACK- vs SPDY3-encoded.
|
| - size_t ProcessControlFrameHeaderBlock(const char* data,
|
| - size_t len,
|
| - bool is_hpack_header_block);
|
| - size_t ProcessDataFramePaddingLength(const char* data, size_t len);
|
| - size_t ProcessFramePadding(const char* data, size_t len);
|
| - size_t ProcessDataFramePayload(const char* data, size_t len);
|
| - size_t ProcessGoAwayFramePayload(const char* data, size_t len);
|
| - size_t ProcessRstStreamFramePayload(const char* data, size_t len);
|
| - size_t ProcessSettingsFramePayload(const char* data, size_t len);
|
| - size_t ProcessAltSvcFramePayload(const char* data, size_t len);
|
| - size_t ProcessIgnoredControlFramePayload(/*const char* data,*/ size_t len);
|
| -
|
| - // TODO(jgraettinger): To be removed with migration to
|
| - // SpdyHeadersHandlerInterface.
|
| - // Serializes the last-processed header block of |hpack_decoder_| as
|
| - // a SPDY3 format block, and delivers it to the visitor via reentrant
|
| - // call to ProcessControlFrameHeaderBlock().
|
| - void DeliverHpackBlockAsSpdy3Block();
|
| -
|
| - // Helpers for above internal breakouts from ProcessInput.
|
| - void ProcessControlFrameHeader(int control_frame_type_field);
|
| - // Always passed exactly 1 setting's worth of data.
|
| - bool ProcessSetting(const char* data);
|
| -
|
| - // Retrieve serialized length of SpdyHeaderBlock. If compression is enabled, a
|
| - // maximum estimate is returned.
|
| - size_t GetSerializedLength(const SpdyHeaderBlock& headers);
|
| -
|
| - // Get (and lazily initialize) the ZLib state.
|
| - z_stream* GetHeaderCompressor();
|
| - z_stream* GetHeaderDecompressor();
|
| -
|
| - // Get (and lazily initialize) the HPACK state.
|
| - HpackEncoder* GetHpackEncoder();
|
| - HpackDecoder* GetHpackDecoder();
|
| -
|
| - size_t GetNumberRequiredContinuationFrames(size_t size);
|
| -
|
| - void WritePayloadWithContinuation(SpdyFrameBuilder* builder,
|
| - const std::string& hpack_encoding,
|
| - SpdyStreamId stream_id,
|
| - SpdyFrameType type,
|
| - int padding_payload_len);
|
| -
|
| - private:
|
| - // 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(SpdyStreamId stream_id,
|
| - 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);
|
| -
|
| - void WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
|
| - z_stream* out) const;
|
| -
|
| - void SerializeNameValueBlockWithoutCompression(
|
| - SpdyFrameBuilder* builder,
|
| - const SpdyNameValueBlock& name_value_block) const;
|
| -
|
| - // Compresses automatically according to enable_compression_.
|
| - void SerializeNameValueBlock(
|
| - SpdyFrameBuilder* builder,
|
| - const SpdyFrameWithNameValueBlockIR& frame);
|
| -
|
| - // Set the error code and moves the framer into the error state.
|
| - void set_error(SpdyError error);
|
| -
|
| - // The size of the control frame buffer.
|
| - // Since this is only used for control frame headers, the maximum control
|
| - // frame header size (SYN_STREAM) is sufficient; all remaining control
|
| - // frame data is streamed to the visitor.
|
| - static const size_t kControlFrameBufferSize;
|
| -
|
| - // The maximum size of the control frames that we support.
|
| - // This limit is arbitrary. We can enforce it here or at the application
|
| - // layer. We chose the framing layer, but this can be changed (or removed)
|
| - // if necessary later down the line.
|
| - static const size_t kMaxControlFrameSize;
|
| -
|
| - SpdyState state_;
|
| - SpdyState previous_state_;
|
| - SpdyError error_code_;
|
| -
|
| - // Note that for DATA frame, remaining_data_length_ is sum of lengths of
|
| - // frame header, padding length field (optional), data payload (optional) and
|
| - // padding payload (optional).
|
| - size_t remaining_data_length_;
|
| -
|
| - // The length (in bytes) of the padding payload to be processed.
|
| - size_t remaining_padding_payload_length_;
|
| -
|
| - // 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_;
|
| -
|
| - scoped_ptr<char[]> current_frame_buffer_;
|
| - // Number of bytes read into the current_frame_buffer_.
|
| - size_t current_frame_buffer_length_;
|
| -
|
| - // The type of the frame currently being read.
|
| - SpdyFrameType current_frame_type_;
|
| -
|
| - // The flags field of the frame currently being read.
|
| - uint8 current_frame_flags_;
|
| -
|
| - // The total length of the frame currently being read, including frame header.
|
| - uint32 current_frame_length_;
|
| -
|
| - // The stream ID field of the frame currently being read, if applicable.
|
| - SpdyStreamId current_frame_stream_id_;
|
| -
|
| - // Scratch space for handling SETTINGS frames.
|
| - // TODO(hkhalil): Unify memory for this scratch space with
|
| - // current_frame_buffer_.
|
| - SpdySettingsScratch settings_scratch_;
|
| -
|
| - SpdyAltSvcScratch altsvc_scratch_;
|
| -
|
| - bool enable_compression_; // Controls all compression
|
| - // SPDY header compressors.
|
| - scoped_ptr<z_stream> header_compressor_;
|
| - scoped_ptr<z_stream> header_decompressor_;
|
| -
|
| - scoped_ptr<HpackEncoder> hpack_encoder_;
|
| - scoped_ptr<HpackDecoder> hpack_decoder_;
|
| -
|
| - SpdyFramerVisitorInterface* visitor_;
|
| - SpdyFramerDebugVisitorInterface* debug_visitor_;
|
| -
|
| - std::string display_protocol_;
|
| -
|
| - // The protocol version to be spoken/understood by this framer.
|
| - const SpdyMajorVersion protocol_version_;
|
| -
|
| - // Tracks if we've ever gotten far enough in framing to see a control frame of
|
| - // type SYN_STREAM or SYN_REPLY.
|
| - //
|
| - // If we ever get something which looks like a data frame before we've had a
|
| - // SYN, we explicitly check to see if it looks like we got an HTTP response
|
| - // to a SPDY request. This boolean lets us do that.
|
| - bool syn_frame_processed_;
|
| -
|
| - // If we ever get a data frame before a SYN frame, we check to see if it
|
| - // starts with HTTP. If it does, we likely have an HTTP response. This
|
| - // isn't guaranteed though: we could have gotten a settings frame and then
|
| - // corrupt data that just looks like HTTP, but deterministic checking requires
|
| - // a lot more state.
|
| - bool probable_http_response_;
|
| -
|
| - // Set this to the current stream when we receive a HEADERS, PUSH_PROMISE, or
|
| - // CONTINUATION frame without the END_HEADERS(0x4) bit set. These frames must
|
| - // be followed by a CONTINUATION frame, or else we throw a PROTOCOL_ERROR.
|
| - // A value of 0 indicates that we are not expecting a CONTINUATION frame.
|
| - SpdyStreamId expect_continuation_;
|
| -
|
| - // If a HEADERS frame is followed by a CONTINUATION frame, the FIN/END_STREAM
|
| - // flag is still carried in the HEADERS frame. If it's set, flip this so that
|
| - // we know to terminate the stream when the entire header block has been
|
| - // processed.
|
| - bool end_stream_when_done_;
|
| -};
|
| -
|
| -} // namespace net
|
| -
|
| -#endif // NET_SPDY_SPDY_FRAMER_H_
|
|
|