summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_protocol.h
diff options
context:
space:
mode:
Diffstat (limited to 'net/spdy/spdy_protocol.h')
-rw-r--r--net/spdy/spdy_protocol.h387
1 files changed, 387 insertions, 0 deletions
diff --git a/net/spdy/spdy_protocol.h b/net/spdy/spdy_protocol.h
new file mode 100644
index 0000000..455e5aa
--- /dev/null
+++ b/net/spdy/spdy_protocol.h
@@ -0,0 +1,387 @@
+// Copyright (c) 2009 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 Flip.
+
+#ifndef NET_SPDY_SPDY_PROTOCOL_H_
+#define NET_SPDY_SPDY_PROTOCOL_H_
+
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <arpa/inet.h>
+#endif
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "spdy_bitmasks.h" // cross-google3 directory naming.
+
+// 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) | >= 8
+// +----------------------------------+
+// |X| 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: FIN_STREAM
+// +----------------------------------+
+// |1|000000000000001|0000000000000011|
+// +----------------------------------+
+// | flags (8) | Length (24 bits) | >= 4
+// +----------------------------------+
+// |X| Stream-ID(31bits) |
+// +----------------------------------+
+// | Status (32 bits) |
+// +----------------------------------+
+//
+// Control Frame: SetMaxStreams
+// +----------------------------------+
+// |1|000000000000001|0000000000000100|
+// +----------------------------------+
+// | flags (8) | Length (24 bits) | >= 4
+// +----------------------------------+
+// |X| Stream-ID(31bits) |
+// +----------------------------------+
+
+// TODO(fenix): add ChangePriority support.
+
+namespace flip {
+
+// This implementation of Flip is version 1.
+const int kFlipProtocolVersion = 1;
+
+// 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 Flip Control Frames.
+enum FlipControlType {
+ SYN_STREAM = 1,
+ SYN_REPLY,
+ FIN_STREAM,
+ NOOP
+};
+
+// Flags on data packets
+enum FlipDataFlags {
+ DATA_FLAG_NONE = 0,
+ DATA_FLAG_FIN = 1,
+ DATA_FLAG_COMPRESSED = 2 // TODO(mbelshe): remove me.
+};
+
+// Flags on control packets
+enum FlipControlFlags {
+ CONTROL_FLAG_NONE = 0,
+ CONTROL_FLAG_FIN = 1
+};
+
+// A FLIP stream id is a 31 bit entity.
+typedef uint32 FlipStreamId;
+
+// FLIP Priorities. (there are only 2 bits)
+#define FLIP_PRIORITY_LOWEST 3
+#define FLIP_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 FLIP Frame structure.
+struct FlipFrameBlock {
+ union {
+ struct {
+ uint16 version_;
+ uint16 type_;
+ } control_;
+ struct {
+ FlipStreamId stream_id_;
+ } data_;
+ };
+ FlagsAndLength flags_length_;
+};
+
+// A Control Frame structure.
+struct FlipControlFrameBlock : FlipFrameBlock {
+ FlipStreamId stream_id_;
+};
+
+// A SYN_STREAM Control Frame structure.
+struct FlipSynStreamControlFrameBlock : FlipControlFrameBlock {
+ uint8 priority_;
+ uint8 unused_;
+};
+
+// A SYN_REPLY Control Frame structure.
+struct FlipSynReplyControlFrameBlock : FlipControlFrameBlock {
+ uint16 unused_;
+};
+
+// A FNI_STREAM Control Frame structure.
+struct FlipFinStreamControlFrameBlock : FlipControlFrameBlock {
+ uint32 status_;
+};
+
+#pragma pack(pop)
+
+// -------------------------------------------------------------------------
+// Wrapper classes for various FLIP frames.
+
+// All Flip Frame types derive from this FlipFrame class.
+class FlipFrame {
+ public:
+ // Create a FlipFrame for a given sized buffer.
+ explicit FlipFrame(size_t size) : frame_(NULL), owns_buffer_(true) {
+ DCHECK_GE(size, sizeof(struct FlipFrameBlock));
+ char* buffer = new char[size];
+ memset(buffer, 0, size);
+ frame_ = reinterpret_cast<struct FlipFrameBlock*>(buffer);
+ }
+
+ // Create a FlipFrame 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.
+ FlipFrame(char* data, bool owns_buffer)
+ : frame_(reinterpret_cast<struct FlipFrameBlock*>(data)),
+ owns_buffer_(owns_buffer) {
+ DCHECK(frame_);
+ }
+
+ virtual ~FlipFrame() {
+ 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 FlipFrameBlock structure.
+ // Note: this is not the size of the FlipFrame class.
+ // Every FlipFrame* 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(FlipFrame).
+ static size_t size() { return sizeof(struct FlipFrameBlock); }
+
+ protected:
+ FlipFrameBlock* frame_;
+
+ private:
+ bool owns_buffer_;
+ DISALLOW_COPY_AND_ASSIGN(FlipFrame);
+};
+
+// A Data Frame.
+class FlipDataFrame : public FlipFrame {
+ public:
+ FlipDataFrame() : FlipFrame(size()) {}
+ FlipDataFrame(char* data, bool owns_buffer)
+ : FlipFrame(data, owns_buffer) {}
+ virtual ~FlipDataFrame() {}
+
+ FlipStreamId 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(FlipStreamId id) {
+ DCHECK_EQ(0u, (id & ~kStreamIdMask));
+ frame_->data_.stream_id_ = htonl(id & kStreamIdMask);
+ }
+
+ // Returns the size of the FlipFrameBlock structure.
+ // Note: this is not the size of the FlipDataFrame class.
+ static size_t size() { return FlipFrame::size(); }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FlipDataFrame);
+};
+
+// A Control Frame.
+class FlipControlFrame : public FlipFrame {
+ public:
+ explicit FlipControlFrame(size_t size) : FlipFrame(size) {}
+ FlipControlFrame(char* data, bool owns_buffer)
+ : FlipFrame(data, owns_buffer) {}
+ virtual ~FlipControlFrame() {}
+
+ uint16 version() const {
+ const int kVersionMask = 0x7fff;
+ return ntohs(block()->control_.version_) & kVersionMask;
+ }
+ FlipControlType type() const {
+ uint16 type = ntohs(block()->control_.type_);
+ DCHECK(type >= SYN_STREAM && type <= NOOP);
+ return static_cast<FlipControlType>(type);
+ }
+ FlipStreamId stream_id() const {
+ return ntohl(block()->stream_id_) & kStreamIdMask;
+ }
+
+ void set_stream_id(FlipStreamId id) {
+ block()->stream_id_ = htonl(id & kStreamIdMask);
+ }
+
+ // Returns the size of the FlipControlFrameBlock structure.
+ // Note: this is not the size of the FlipControlFrame class.
+ static size_t size() { return sizeof(FlipControlFrameBlock); }
+
+ private:
+ struct FlipControlFrameBlock* block() const {
+ return static_cast<FlipControlFrameBlock*>(frame_);
+ }
+ DISALLOW_COPY_AND_ASSIGN(FlipControlFrame);
+};
+
+// A SYN_STREAM frame.
+class FlipSynStreamControlFrame : public FlipControlFrame {
+ public:
+ FlipSynStreamControlFrame() : FlipControlFrame(size()) {}
+ FlipSynStreamControlFrame(char* data, bool owns_buffer)
+ : FlipControlFrame(data, owns_buffer) {}
+ virtual ~FlipSynStreamControlFrame() {}
+
+ uint8 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() - FlipFrame::size());
+ }
+
+ const char* header_block() const {
+ return reinterpret_cast<const char*>(block()) + size();
+ }
+
+ // Returns the size of the FlipSynStreamControlFrameBlock structure.
+ // Note: this is not the size of the FlipSynStreamControlFrame class.
+ static size_t size() { return sizeof(FlipSynStreamControlFrameBlock); }
+
+ private:
+ struct FlipSynStreamControlFrameBlock* block() const {
+ return static_cast<FlipSynStreamControlFrameBlock*>(frame_);
+ }
+ DISALLOW_COPY_AND_ASSIGN(FlipSynStreamControlFrame);
+};
+
+// A SYN_REPLY frame.
+class FlipSynReplyControlFrame : public FlipControlFrame {
+ public:
+ FlipSynReplyControlFrame() : FlipControlFrame(size()) {}
+ FlipSynReplyControlFrame(char* data, bool owns_buffer)
+ : FlipControlFrame(data, owns_buffer) {}
+ virtual ~FlipSynReplyControlFrame() {}
+
+ int header_block_len() const {
+ return length() - (size() - FlipFrame::size());
+ }
+
+ const char* header_block() const {
+ return reinterpret_cast<const char*>(block()) + size();
+ }
+
+ // Returns the size of the FlipSynReplyControlFrameBlock structure.
+ // Note: this is not the size of the FlipSynReplyControlFrame class.
+ static size_t size() { return sizeof(FlipSynReplyControlFrameBlock); }
+
+ private:
+ struct FlipSynReplyControlFrameBlock* block() const {
+ return static_cast<FlipSynReplyControlFrameBlock*>(frame_);
+ }
+ DISALLOW_COPY_AND_ASSIGN(FlipSynReplyControlFrame);
+};
+
+// A FIN_STREAM frame.
+class FlipFinStreamControlFrame : public FlipControlFrame {
+ public:
+ FlipFinStreamControlFrame() : FlipControlFrame(size()) {}
+ FlipFinStreamControlFrame(char* data, bool owns_buffer)
+ : FlipControlFrame(data, owns_buffer) {}
+ virtual ~FlipFinStreamControlFrame() {}
+
+ uint32 status() const { return ntohl(block()->status_); }
+ void set_status(uint32 status) { block()->status_ = htonl(status); }
+
+ // Returns the size of the FlipFinStreamControlFrameBlock structure.
+ // Note: this is not the size of the FlipFinStreamControlFrame class.
+ static size_t size() { return sizeof(FlipFinStreamControlFrameBlock); }
+
+ private:
+ struct FlipFinStreamControlFrameBlock* block() const {
+ return static_cast<FlipFinStreamControlFrameBlock*>(frame_);
+ }
+ DISALLOW_COPY_AND_ASSIGN(FlipFinStreamControlFrame);
+};
+
+} // namespace flip
+
+#endif // NET_SPDY_SPDY_PROTOCOL_H_