| // Copyright (c) 2010 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. |
| |
| // This file contains some protocol structures for use with Spdy. |
| |
| #ifndef NET_SPDY_SPDY_PROTOCOL_H_ |
| #define NET_SPDY_SPDY_PROTOCOL_H_ |
| #pragma once |
| |
| #include <limits> |
| |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| #include "net/base/sys_byteorder.h" |
| #include "net/spdy/spdy_bitmasks.h" |
| |
| // Data Frame Format |
| // +----------------------------------+ |
| // |0| Stream-ID (31bits) | |
| // +----------------------------------+ |
| // | flags (8) | Length (24 bits) | |
| // +----------------------------------+ |
| // | Data | |
| // +----------------------------------+ |
| // |
| // Control Frame Format |
| // +----------------------------------+ |
| // |1| Version(15bits) | Type(16bits) | |
| // +----------------------------------+ |
| // | flags (8) | Length (24 bits) | |
| // +----------------------------------+ |
| // | Data | |
| // +----------------------------------+ |
| // |
| // Control Frame: SYN_STREAM |
| // +----------------------------------+ |
| // |1|000000000000001|0000000000000001| |
| // +----------------------------------+ |
| // | flags (8) | Length (24 bits) | >= 12 |
| // +----------------------------------+ |
| // |X| Stream-ID(31bits) | |
| // +----------------------------------+ |
| // |X|Associated-To-Stream-ID (31bits)| |
| // +----------------------------------+ |
| // |Pri| unused | Length (16bits)| |
| // +----------------------------------+ |
| // |
| // Control Frame: SYN_REPLY |
| // +----------------------------------+ |
| // |1|000000000000001|0000000000000010| |
| // +----------------------------------+ |
| // | flags (8) | Length (24 bits) | >= 8 |
| // +----------------------------------+ |
| // |X| Stream-ID(31bits) | |
| // +----------------------------------+ |
| // | unused (16 bits)| Length (16bits)| |
| // +----------------------------------+ |
| // |
| // Control Frame: RST_STREAM |
| // +----------------------------------+ |
| // |1|000000000000001|0000000000000011| |
| // +----------------------------------+ |
| // | flags (8) | Length (24 bits) | >= 4 |
| // +----------------------------------+ |
| // |X| Stream-ID(31bits) | |
| // +----------------------------------+ |
| // | Status code (32 bits) | |
| // +----------------------------------+ |
| // |
| // Control Frame: SETTINGS |
| // +----------------------------------+ |
| // |1|000000000000001|0000000000000100| |
| // +----------------------------------+ |
| // | flags (8) | Length (24 bits) | |
| // +----------------------------------+ |
| // | # of entries (32) | |
| // +----------------------------------+ |
| // |
| // Control Frame: NOOP |
| // +----------------------------------+ |
| // |1|000000000000001|0000000000000101| |
| // +----------------------------------+ |
| // | flags (8) | Length (24 bits) | = 0 |
| // +----------------------------------+ |
| // |
| // Control Frame: PING |
| // +----------------------------------+ |
| // |1|000000000000001|0000000000000110| |
| // +----------------------------------+ |
| // | flags (8) | Length (24 bits) | = 4 |
| // +----------------------------------+ |
| // | Unique id (32 bits) | |
| // +----------------------------------+ |
| // |
| // Control Frame: GOAWAY |
| // +----------------------------------+ |
| // |1|000000000000001|0000000000000111| |
| // +----------------------------------+ |
| // | flags (8) | Length (24 bits) | = 4 |
| // +----------------------------------+ |
| // |X| Last-accepted-stream-id | |
| // +----------------------------------+ |
| // |
| // Control Frame: HEADERS |
| // +----------------------------------+ |
| // |1|000000000000001|0000000000001000| |
| // +----------------------------------+ |
| // | flags (8) | Length (24 bits) | >= 8 |
| // +----------------------------------+ |
| // |X| Stream-ID (31 bits) | |
| // +----------------------------------+ |
| // | unused (16 bits)| Length (16bits)| |
| // +----------------------------------+ |
| // |
| // Control Frame: WINDOW_UPDATE |
| // +----------------------------------+ |
| // |1|000000000000001|0000000000001001| |
| // +----------------------------------+ |
| // | flags (8) | Length (24 bits) | = 8 |
| // +----------------------------------+ |
| // |X| Stream-ID (31 bits) | |
| // +----------------------------------+ |
| // | Delta-Window-Size (32 bits) | |
| // +----------------------------------+ |
| namespace spdy { |
| |
| // This implementation of Spdy is version 2; It's like version 1, with some |
| // minor tweaks. |
| const int kSpdyProtocolVersion = 2; |
| |
| // Initial window size for a Spdy stream |
| const size_t kSpdyStreamInitialWindowSize = 64 * 1024; // 64 KBytes |
| |
| // Maximum window size for a Spdy stream |
| const size_t kSpdyStreamMaximumWindowSize = std::numeric_limits<int32>::max(); |
| |
| // HTTP-over-SPDY header constants |
| const char kMethod[] = "method"; |
| const char kStatus[] = "status"; |
| const char kUrl[] = "url"; |
| const char kVersion[] = "version"; |
| // When we server push, we will add [path: fully/qualified/url] to the server |
| // push headers so that the client will know what url the data corresponds to. |
| const char kPath[] = "path"; |
| |
| // Note: all protocol data structures are on-the-wire format. That means that |
| // data is stored in network-normalized order. Readers must use the |
| // accessors provided or call ntohX() functions. |
| |
| // Types of Spdy Control Frames. |
| enum SpdyControlType { |
| SYN_STREAM = 1, |
| SYN_REPLY, |
| RST_STREAM, |
| SETTINGS, |
| NOOP, |
| PING, |
| GOAWAY, |
| HEADERS, |
| WINDOW_UPDATE, |
| NUM_CONTROL_FRAME_TYPES |
| }; |
| |
| // Flags on data packets. |
| enum SpdyDataFlags { |
| DATA_FLAG_NONE = 0, |
| DATA_FLAG_FIN = 1, |
| DATA_FLAG_COMPRESSED = 2 |
| }; |
| |
| // Flags on control packets |
| enum SpdyControlFlags { |
| CONTROL_FLAG_NONE = 0, |
| CONTROL_FLAG_FIN = 1, |
| CONTROL_FLAG_UNIDIRECTIONAL = 2 |
| }; |
| |
| // Flags on the SETTINGS control frame. |
| enum SpdySettingsControlFlags { |
| SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1 |
| }; |
| |
| // Flags for settings within a SETTINGS frame. |
| enum SpdySettingsFlags { |
| SETTINGS_FLAG_PLEASE_PERSIST = 0x1, |
| SETTINGS_FLAG_PERSISTED = 0x2 |
| }; |
| |
| // List of known settings. |
| enum SpdySettingsIds { |
| SETTINGS_UPLOAD_BANDWIDTH = 0x1, |
| SETTINGS_DOWNLOAD_BANDWIDTH = 0x2, |
| // Network round trip time in milliseconds. |
| SETTINGS_ROUND_TRIP_TIME = 0x3, |
| SETTINGS_MAX_CONCURRENT_STREAMS = 0x4, |
| // TCP congestion window in packets. |
| SETTINGS_CURRENT_CWND = 0x5, |
| // Downstream byte retransmission rate in percentage. |
| SETTINGS_DOWNLOAD_RETRANS_RATE = 0x6, |
| // Initial window size in bytes |
| SETTINGS_INITIAL_WINDOW_SIZE = 0x7 |
| }; |
| |
| // Status codes, as used in control frames (primarily RST_STREAM). |
| enum SpdyStatusCodes { |
| INVALID = 0, |
| PROTOCOL_ERROR = 1, |
| INVALID_STREAM = 2, |
| REFUSED_STREAM = 3, |
| UNSUPPORTED_VERSION = 4, |
| CANCEL = 5, |
| INTERNAL_ERROR = 6, |
| FLOW_CONTROL_ERROR = 7, |
| INVALID_ASSOCIATED_STREAM = 8, |
| NUM_STATUS_CODES = 9 |
| }; |
| |
| // A SPDY stream id is a 31 bit entity. |
| typedef uint32 SpdyStreamId; |
| |
| // A SPDY priority is a number between 0 and 3 (inclusive). |
| typedef uint8 SpdyPriority; |
| |
| // SPDY Priorities. (there are only 2 bits) |
| #define SPDY_PRIORITY_LOWEST 3 |
| #define SPDY_PRIORITY_HIGHEST 0 |
| |
| // ------------------------------------------------------------------------- |
| // These structures mirror the protocol structure definitions. |
| |
| // For the control data structures, we pack so that sizes match the |
| // protocol over-the-wire sizes. |
| #pragma pack(push) |
| #pragma pack(1) |
| |
| // A special structure for the 8 bit flags and 24 bit length fields. |
| union FlagsAndLength { |
| uint8 flags_[4]; // 8 bits |
| uint32 length_; // 24 bits |
| }; |
| |
| // The basic SPDY Frame structure. |
| struct SpdyFrameBlock { |
| union { |
| struct { |
| uint16 version_; |
| uint16 type_; |
| } control_; |
| struct { |
| SpdyStreamId stream_id_; |
| } data_; |
| }; |
| FlagsAndLength flags_length_; |
| }; |
| |
| // A SYN_STREAM Control Frame structure. |
| struct SpdySynStreamControlFrameBlock : SpdyFrameBlock { |
| SpdyStreamId stream_id_; |
| SpdyStreamId associated_stream_id_; |
| SpdyPriority priority_; |
| uint8 unused_; |
| }; |
| |
| // A SYN_REPLY Control Frame structure. |
| struct SpdySynReplyControlFrameBlock : SpdyFrameBlock { |
| SpdyStreamId stream_id_; |
| uint16 unused_; |
| }; |
| |
| // A RST_STREAM Control Frame structure. |
| struct SpdyRstStreamControlFrameBlock : SpdyFrameBlock { |
| SpdyStreamId stream_id_; |
| uint32 status_; |
| }; |
| |
| // A SETTINGS Control Frame structure. |
| struct SpdySettingsControlFrameBlock : SpdyFrameBlock { |
| uint32 num_entries_; |
| // Variable data here. |
| }; |
| |
| // A NOOP Control Frame structure. |
| struct SpdyNoopControlFrameBlock : SpdyFrameBlock { |
| }; |
| |
| // A PING Control Frame structure. |
| struct SpdyPingControlFrameBlock : SpdyFrameBlock { |
| uint32 unique_id_; |
| }; |
| |
| // A GOAWAY Control Frame structure. |
| struct SpdyGoAwayControlFrameBlock : SpdyFrameBlock { |
| SpdyStreamId last_accepted_stream_id_; |
| }; |
| |
| // A HEADERS Control Frame structure. |
| struct SpdyHeadersControlFrameBlock : SpdyFrameBlock { |
| SpdyStreamId stream_id_; |
| uint16 unused_; |
| }; |
| |
| // A WINDOW_UPDATE Control Frame structure |
| struct SpdyWindowUpdateControlFrameBlock : SpdyFrameBlock { |
| SpdyStreamId stream_id_; |
| uint32 delta_window_size_; |
| }; |
| |
| // A structure for the 8 bit flags and 24 bit ID fields. |
| union SettingsFlagsAndId { |
| // Sets both flags and id to the value for flags-and-id as sent over the wire |
| SettingsFlagsAndId(uint32 val) : id_(val) {} |
| uint8 flags() const { return flags_[0]; } |
| void set_flags(uint8 flags) { flags_[0] = flags; } |
| uint32 id() const { return (ntohl(id_) & kSettingsIdMask); } |
| void set_id(uint32 id) { |
| DCHECK_EQ(0u, (id & ~kSettingsIdMask)); |
| id = htonl(id & kSettingsIdMask); |
| id_ = flags() | id; |
| } |
| |
| uint8 flags_[4]; // 8 bits |
| uint32 id_; // 24 bits |
| }; |
| |
| #pragma pack(pop) |
| |
| // ------------------------------------------------------------------------- |
| // Wrapper classes for various SPDY frames. |
| |
| // All Spdy Frame types derive from this SpdyFrame class. |
| class SpdyFrame { |
| public: |
| // Create a SpdyFrame for a given sized buffer. |
| explicit SpdyFrame(size_t size) : frame_(NULL), owns_buffer_(true) { |
| DCHECK_GE(size, sizeof(struct SpdyFrameBlock)); |
| char* buffer = new char[size]; |
| memset(buffer, 0, size); |
| frame_ = reinterpret_cast<struct SpdyFrameBlock*>(buffer); |
| } |
| |
| // Create a SpdyFrame using a pre-created buffer. |
| // If |owns_buffer| is true, this class takes ownership of the buffer |
| // and will delete it on cleanup. The buffer must have been created using |
| // new char[]. |
| // If |owns_buffer| is false, the caller retains ownership of the buffer and |
| // is responsible for making sure the buffer outlives this frame. In other |
| // words, this class does NOT create a copy of the buffer. |
| SpdyFrame(char* data, bool owns_buffer) |
| : frame_(reinterpret_cast<struct SpdyFrameBlock*>(data)), |
| owns_buffer_(owns_buffer) { |
| DCHECK(frame_); |
| } |
| |
| ~SpdyFrame() { |
| if (owns_buffer_) { |
| char* buffer = reinterpret_cast<char*>(frame_); |
| delete [] buffer; |
| } |
| frame_ = NULL; |
| } |
| |
| // Provides access to the frame bytes, which is a buffer containing |
| // the frame packed as expected for sending over the wire. |
| char* data() const { return reinterpret_cast<char*>(frame_); } |
| |
| uint8 flags() const { return frame_->flags_length_.flags_[0]; } |
| void set_flags(uint8 flags) { frame_->flags_length_.flags_[0] = flags; } |
| |
| uint32 length() const { |
| return ntohl(frame_->flags_length_.length_) & kLengthMask; |
| } |
| |
| void set_length(uint32 length) { |
| DCHECK_EQ(0u, (length & ~kLengthMask)); |
| length = htonl(length & kLengthMask); |
| frame_->flags_length_.length_ = flags() | length; |
| } |
| |
| bool is_control_frame() const { |
| return (ntohs(frame_->control_.version_) & kControlFlagMask) == |
| kControlFlagMask; |
| } |
| |
| // Returns the size of the SpdyFrameBlock structure. |
| // Every SpdyFrame* class has a static size() method for accessing |
| // the size of the data structure which will be sent over the wire. |
| // Note: this is not the same as sizeof(SpdyFrame). |
| static size_t size() { return sizeof(struct SpdyFrameBlock); } |
| |
| protected: |
| SpdyFrameBlock* frame_; |
| |
| private: |
| bool owns_buffer_; |
| DISALLOW_COPY_AND_ASSIGN(SpdyFrame); |
| }; |
| |
| // A Data Frame. |
| class SpdyDataFrame : public SpdyFrame { |
| public: |
| SpdyDataFrame() : SpdyFrame(size()) {} |
| SpdyDataFrame(char* data, bool owns_buffer) |
| : SpdyFrame(data, owns_buffer) {} |
| |
| SpdyStreamId stream_id() const { |
| return ntohl(frame_->data_.stream_id_) & kStreamIdMask; |
| } |
| |
| // Note that setting the stream id sets the control bit to false. |
| // As stream id should always be set, this means the control bit |
| // should always be set correctly. |
| void set_stream_id(SpdyStreamId id) { |
| DCHECK_EQ(0u, (id & ~kStreamIdMask)); |
| frame_->data_.stream_id_ = htonl(id & kStreamIdMask); |
| } |
| |
| // Returns the size of the SpdyFrameBlock structure. |
| // Note: this is not the size of the SpdyDataFrame class. |
| static size_t size() { return SpdyFrame::size(); } |
| |
| const char* payload() const { |
| return reinterpret_cast<const char*>(frame_) + size(); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SpdyDataFrame); |
| }; |
| |
| // A Control Frame. |
| class SpdyControlFrame : public SpdyFrame { |
| public: |
| explicit SpdyControlFrame(size_t size) : SpdyFrame(size) {} |
| SpdyControlFrame(char* data, bool owns_buffer) |
| : SpdyFrame(data, owns_buffer) {} |
| |
| // Callers can use this method to check if the frame appears to be a valid |
| // frame. Does not guarantee that there are no errors. |
| bool AppearsToBeAValidControlFrame() const { |
| // Right now we only check if the frame has an out-of-bounds type. |
| uint16 type = ntohs(block()->control_.type_); |
| return (type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES); |
| } |
| |
| uint16 version() const { |
| const int kVersionMask = 0x7fff; |
| return ntohs(block()->control_.version_) & kVersionMask; |
| } |
| |
| void set_version(uint16 version) { |
| DCHECK_EQ(0u, version & kControlFlagMask); |
| mutable_block()->control_.version_ = htons(kControlFlagMask | version); |
| } |
| |
| SpdyControlType type() const { |
| uint16 type = ntohs(block()->control_.type_); |
| DCHECK(type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES); |
| return static_cast<SpdyControlType>(type); |
| } |
| |
| void set_type(SpdyControlType type) { |
| DCHECK(type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES); |
| mutable_block()->control_.type_ = htons(type); |
| } |
| |
| // Returns true if this control frame is of a type that has a header block, |
| // otherwise it returns false. |
| bool has_header_block() const { |
| return type() == SYN_STREAM || type() == SYN_REPLY || type() == HEADERS; |
| } |
| |
| // Returns the size of the SpdyFrameBlock structure. |
| // Note: this is not the size of the SpdyControlFrame class. |
| static size_t size() { return sizeof(SpdyFrameBlock); } |
| |
| // The size of the 'Number of Name/Value pairs' field in a Name/Value block. |
| static const size_t kNumNameValuePairsSize = 2; |
| |
| // The size of the 'Length of a name' field in a Name/Value block. |
| static const size_t kLengthOfNameSize = 2; |
| |
| // The size of the 'Length of a value' field in a Name/Value block. |
| static const size_t kLengthOfValueSize = 2; |
| |
| private: |
| const struct SpdyFrameBlock* block() const { |
| return frame_; |
| } |
| struct SpdyFrameBlock* mutable_block() { |
| return frame_; |
| } |
| DISALLOW_COPY_AND_ASSIGN(SpdyControlFrame); |
| }; |
| |
| // A SYN_STREAM frame. |
| class SpdySynStreamControlFrame : public SpdyControlFrame { |
| public: |
| SpdySynStreamControlFrame() : SpdyControlFrame(size()) {} |
| SpdySynStreamControlFrame(char* data, bool owns_buffer) |
| : SpdyControlFrame(data, owns_buffer) {} |
| |
| SpdyStreamId stream_id() const { |
| return ntohl(block()->stream_id_) & kStreamIdMask; |
| } |
| |
| void set_stream_id(SpdyStreamId id) { |
| mutable_block()->stream_id_ = htonl(id & kStreamIdMask); |
| } |
| |
| SpdyStreamId associated_stream_id() const { |
| return ntohl(block()->associated_stream_id_) & kStreamIdMask; |
| } |
| |
| void set_associated_stream_id(SpdyStreamId id) { |
| mutable_block()->associated_stream_id_ = htonl(id & kStreamIdMask); |
| } |
| |
| SpdyPriority priority() const { |
| return (block()->priority_ & kPriorityMask) >> 6; |
| } |
| |
| // The number of bytes in the header block beyond the frame header length. |
| int header_block_len() const { |
| return length() - (size() - SpdyFrame::size()); |
| } |
| |
| const char* header_block() const { |
| return reinterpret_cast<const char*>(block()) + size(); |
| } |
| |
| // Returns the size of the SpdySynStreamControlFrameBlock structure. |
| // Note: this is not the size of the SpdySynStreamControlFrame class. |
| static size_t size() { return sizeof(SpdySynStreamControlFrameBlock); } |
| |
| private: |
| const struct SpdySynStreamControlFrameBlock* block() const { |
| return static_cast<SpdySynStreamControlFrameBlock*>(frame_); |
| } |
| struct SpdySynStreamControlFrameBlock* mutable_block() { |
| return static_cast<SpdySynStreamControlFrameBlock*>(frame_); |
| } |
| DISALLOW_COPY_AND_ASSIGN(SpdySynStreamControlFrame); |
| }; |
| |
| // A SYN_REPLY frame. |
| class SpdySynReplyControlFrame : public SpdyControlFrame { |
| public: |
| SpdySynReplyControlFrame() : SpdyControlFrame(size()) {} |
| SpdySynReplyControlFrame(char* data, bool owns_buffer) |
| : SpdyControlFrame(data, owns_buffer) {} |
| |
| SpdyStreamId stream_id() const { |
| return ntohl(block()->stream_id_) & kStreamIdMask; |
| } |
| |
| void set_stream_id(SpdyStreamId id) { |
| mutable_block()->stream_id_ = htonl(id & kStreamIdMask); |
| } |
| |
| int header_block_len() const { |
| return length() - (size() - SpdyFrame::size()); |
| } |
| |
| const char* header_block() const { |
| return reinterpret_cast<const char*>(block()) + size(); |
| } |
| |
| // Returns the size of the SpdySynReplyControlFrameBlock structure. |
| // Note: this is not the size of the SpdySynReplyControlFrame class. |
| static size_t size() { return sizeof(SpdySynReplyControlFrameBlock); } |
| |
| private: |
| const struct SpdySynReplyControlFrameBlock* block() const { |
| return static_cast<SpdySynReplyControlFrameBlock*>(frame_); |
| } |
| struct SpdySynReplyControlFrameBlock* mutable_block() { |
| return static_cast<SpdySynReplyControlFrameBlock*>(frame_); |
| } |
| DISALLOW_COPY_AND_ASSIGN(SpdySynReplyControlFrame); |
| }; |
| |
| // A RST_STREAM frame. |
| class SpdyRstStreamControlFrame : public SpdyControlFrame { |
| public: |
| SpdyRstStreamControlFrame() : SpdyControlFrame(size()) {} |
| SpdyRstStreamControlFrame(char* data, bool owns_buffer) |
| : SpdyControlFrame(data, owns_buffer) {} |
| |
| SpdyStreamId stream_id() const { |
| return ntohl(block()->stream_id_) & kStreamIdMask; |
| } |
| |
| void set_stream_id(SpdyStreamId id) { |
| mutable_block()->stream_id_ = htonl(id & kStreamIdMask); |
| } |
| |
| SpdyStatusCodes status() const { |
| SpdyStatusCodes status = |
| static_cast<SpdyStatusCodes>(ntohl(block()->status_)); |
| if (status < INVALID || status >= NUM_STATUS_CODES) { |
| status = INVALID; |
| } |
| return status; |
| } |
| void set_status(SpdyStatusCodes status) { |
| mutable_block()->status_ = htonl(static_cast<uint32>(status)); |
| } |
| |
| // Returns the size of the SpdyRstStreamControlFrameBlock structure. |
| // Note: this is not the size of the SpdyRstStreamControlFrame class. |
| static size_t size() { return sizeof(SpdyRstStreamControlFrameBlock); } |
| |
| private: |
| const struct SpdyRstStreamControlFrameBlock* block() const { |
| return static_cast<SpdyRstStreamControlFrameBlock*>(frame_); |
| } |
| struct SpdyRstStreamControlFrameBlock* mutable_block() { |
| return static_cast<SpdyRstStreamControlFrameBlock*>(frame_); |
| } |
| DISALLOW_COPY_AND_ASSIGN(SpdyRstStreamControlFrame); |
| }; |
| |
| class SpdySettingsControlFrame : public SpdyControlFrame { |
| public: |
| SpdySettingsControlFrame() : SpdyControlFrame(size()) {} |
| SpdySettingsControlFrame(char* data, bool owns_buffer) |
| : SpdyControlFrame(data, owns_buffer) {} |
| |
| uint32 num_entries() const { |
| return ntohl(block()->num_entries_); |
| } |
| |
| void set_num_entries(int val) { |
| mutable_block()->num_entries_ = htonl(val); |
| } |
| |
| int header_block_len() const { |
| return length() - (size() - SpdyFrame::size()); |
| } |
| |
| const char* header_block() const { |
| return reinterpret_cast<const char*>(block()) + size(); |
| } |
| |
| // Returns the size of the SpdySettingsControlFrameBlock structure. |
| // Note: this is not the size of the SpdySettingsControlFrameBlock class. |
| static size_t size() { return sizeof(SpdySettingsControlFrameBlock); } |
| |
| private: |
| const struct SpdySettingsControlFrameBlock* block() const { |
| return static_cast<SpdySettingsControlFrameBlock*>(frame_); |
| } |
| struct SpdySettingsControlFrameBlock* mutable_block() { |
| return static_cast<SpdySettingsControlFrameBlock*>(frame_); |
| } |
| DISALLOW_COPY_AND_ASSIGN(SpdySettingsControlFrame); |
| }; |
| |
| class SpdyNoOpControlFrame : public SpdyControlFrame { |
| public: |
| SpdyNoOpControlFrame() : SpdyControlFrame(size()) {} |
| SpdyNoOpControlFrame(char* data, bool owns_buffer) |
| : SpdyControlFrame(data, owns_buffer) {} |
| |
| static size_t size() { return sizeof(SpdyNoopControlFrameBlock); } |
| }; |
| |
| class SpdyPingControlFrame : public SpdyControlFrame { |
| public: |
| SpdyPingControlFrame() : SpdyControlFrame(size()) {} |
| SpdyPingControlFrame(char* data, bool owns_buffer) |
| : SpdyControlFrame(data, owns_buffer) {} |
| |
| uint32 unique_id() const { |
| return ntohl(block()->unique_id_); |
| } |
| |
| void set_unique_id(uint32 unique_id) { |
| mutable_block()->unique_id_ = htonl(unique_id); |
| } |
| |
| static size_t size() { return sizeof(SpdyPingControlFrameBlock); } |
| |
| private: |
| const struct SpdyPingControlFrameBlock* block() const { |
| return static_cast<SpdyPingControlFrameBlock*>(frame_); |
| } |
| struct SpdyPingControlFrameBlock* mutable_block() { |
| return static_cast<SpdyPingControlFrameBlock*>(frame_); |
| } |
| }; |
| |
| class SpdyGoAwayControlFrame : public SpdyControlFrame { |
| public: |
| SpdyGoAwayControlFrame() : SpdyControlFrame(size()) {} |
| SpdyGoAwayControlFrame(char* data, bool owns_buffer) |
| : SpdyControlFrame(data, owns_buffer) {} |
| |
| SpdyStreamId last_accepted_stream_id() const { |
| return ntohl(block()->last_accepted_stream_id_) & kStreamIdMask; |
| } |
| |
| void set_last_accepted_stream_id(SpdyStreamId id) { |
| mutable_block()->last_accepted_stream_id_ = htonl(id & kStreamIdMask); |
| } |
| |
| static size_t size() { return sizeof(SpdyGoAwayControlFrameBlock); } |
| |
| private: |
| const struct SpdyGoAwayControlFrameBlock* block() const { |
| return static_cast<SpdyGoAwayControlFrameBlock*>(frame_); |
| } |
| struct SpdyGoAwayControlFrameBlock* mutable_block() { |
| return static_cast<SpdyGoAwayControlFrameBlock*>(frame_); |
| } |
| DISALLOW_COPY_AND_ASSIGN(SpdyGoAwayControlFrame); |
| }; |
| |
| // A HEADERS frame. |
| class SpdyHeadersControlFrame : public SpdyControlFrame { |
| public: |
| SpdyHeadersControlFrame() : SpdyControlFrame(size()) {} |
| SpdyHeadersControlFrame(char* data, bool owns_buffer) |
| : SpdyControlFrame(data, owns_buffer) {} |
| |
| SpdyStreamId stream_id() const { |
| return ntohl(block()->stream_id_) & kStreamIdMask; |
| } |
| |
| void set_stream_id(SpdyStreamId id) { |
| mutable_block()->stream_id_ = htonl(id & kStreamIdMask); |
| } |
| |
| // The number of bytes in the header block beyond the frame header length. |
| int header_block_len() const { |
| return length() - (size() - SpdyFrame::size()); |
| } |
| |
| const char* header_block() const { |
| return reinterpret_cast<const char*>(block()) + size(); |
| } |
| |
| // Returns the size of the SpdyHeadersControlFrameBlock structure. |
| // Note: this is not the size of the SpdyHeadersControlFrame class. |
| static size_t size() { return sizeof(SpdyHeadersControlFrameBlock); } |
| |
| private: |
| const struct SpdyHeadersControlFrameBlock* block() const { |
| return static_cast<SpdyHeadersControlFrameBlock*>(frame_); |
| } |
| struct SpdyHeadersControlFrameBlock* mutable_block() { |
| return static_cast<SpdyHeadersControlFrameBlock*>(frame_); |
| } |
| DISALLOW_COPY_AND_ASSIGN(SpdyHeadersControlFrame); |
| }; |
| |
| // A WINDOW_UPDATE frame. |
| class SpdyWindowUpdateControlFrame : public SpdyControlFrame { |
| public: |
| SpdyWindowUpdateControlFrame() : SpdyControlFrame(size()) {} |
| SpdyWindowUpdateControlFrame(char* data, bool owns_buffer) |
| : SpdyControlFrame(data, owns_buffer) {} |
| |
| SpdyStreamId stream_id() const { |
| return ntohl(block()->stream_id_) & kStreamIdMask; |
| } |
| |
| void set_stream_id(SpdyStreamId id) { |
| mutable_block()->stream_id_ = htonl(id & kStreamIdMask); |
| } |
| |
| uint32 delta_window_size() const { |
| return ntohl(block()->delta_window_size_); |
| } |
| |
| void set_delta_window_size(uint32 delta_window_size) { |
| mutable_block()->delta_window_size_ = htonl(delta_window_size); |
| } |
| |
| // Returns the size of the SpdyWindowUpdateControlFrameBlock structure. |
| // Note: this is not the size of the SpdyWindowUpdateControlFrame class. |
| static size_t size() { return sizeof(SpdyWindowUpdateControlFrameBlock); } |
| |
| private: |
| const struct SpdyWindowUpdateControlFrameBlock* block() const { |
| return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_); |
| } |
| struct SpdyWindowUpdateControlFrameBlock* mutable_block() { |
| return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_); |
| } |
| |
| DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateControlFrame); |
| }; |
| |
| } // namespace spdy |
| |
| #endif // NET_SPDY_SPDY_PROTOCOL_H_ |