Home | History | Annotate | Download | only in flip
      1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // This file contains some protocol structures for use with Flip.
      6 
      7 #ifndef NET_FLIP_FLIP_PROTOCOL_H_
      8 #define NET_FLIP_FLIP_PROTOCOL_H_
      9 
     10 #ifdef WIN32
     11 #include <winsock2.h>
     12 #else
     13 #include <arpa/inet.h>
     14 #endif
     15 
     16 #include "base/basictypes.h"
     17 #include "base/logging.h"
     18 #include "flip_bitmasks.h"  // cross-google3 directory naming.
     19 
     20 //  Data Frame Format
     21 //  +----------------------------------+
     22 //  |0|       Stream-ID (31bits)       |
     23 //  +----------------------------------+
     24 //  | flags (8)  |  Length (24 bits)   |
     25 //  +----------------------------------+
     26 //  |               Data               |
     27 //  +----------------------------------+
     28 //
     29 //  Control Frame Format
     30 //  +----------------------------------+
     31 //  |1| Version(15bits) | Type(16bits) |
     32 //  +----------------------------------+
     33 //  | flags (8)  |  Length (24 bits)   |
     34 //  +----------------------------------+
     35 //  |               Data               |
     36 //  +----------------------------------+
     37 //
     38 //  Control Frame: SYN_STREAM
     39 //  +----------------------------------+
     40 //  |1|000000000000001|0000000000000001|
     41 //  +----------------------------------+
     42 //  | flags (8)  |  Length (24 bits)   |  >= 8
     43 //  +----------------------------------+
     44 //  |X|       Stream-ID(31bits)        |
     45 //  +----------------------------------+
     46 //  |Pri| unused      | Length (16bits)|
     47 //  +----------------------------------+
     48 //
     49 //  Control Frame: SYN_REPLY
     50 //  +----------------------------------+
     51 //  |1|000000000000001|0000000000000010|
     52 //  +----------------------------------+
     53 //  | flags (8)  |  Length (24 bits)   |  >= 8
     54 //  +----------------------------------+
     55 //  |X|       Stream-ID(31bits)        |
     56 //  +----------------------------------+
     57 //  | unused (16 bits)| Length (16bits)|
     58 //  +----------------------------------+
     59 //
     60 //  Control Frame: FIN_STREAM
     61 //  +----------------------------------+
     62 //  |1|000000000000001|0000000000000011|
     63 //  +----------------------------------+
     64 //  | flags (8)  |  Length (24 bits)   |  >= 4
     65 //  +----------------------------------+
     66 //  |X|       Stream-ID(31bits)        |
     67 //  +----------------------------------+
     68 //  |             Status (32 bits)     |
     69 //  +----------------------------------+
     70 //
     71 //  Control Frame: SetMaxStreams
     72 //  +----------------------------------+
     73 //  |1|000000000000001|0000000000000100|
     74 //  +----------------------------------+
     75 //  | flags (8)  |  Length (24 bits)   |  >= 4
     76 //  +----------------------------------+
     77 //  |X|       Stream-ID(31bits)        |
     78 //  +----------------------------------+
     79 
     80 // TODO(fenix): add ChangePriority support.
     81 
     82 namespace flip {
     83 
     84 // This implementation of Flip is version 1.
     85 const int kFlipProtocolVersion = 1;
     86 
     87 // Note: all protocol data structures are on-the-wire format.  That means that
     88 //       data is stored in network-normalized order.  Readers must use the
     89 //       accessors provided or call ntohX() functions.
     90 
     91 // Types of Flip Control Frames.
     92 enum FlipControlType {
     93   SYN_STREAM = 1,
     94   SYN_REPLY,
     95   FIN_STREAM,
     96   NOOP
     97 };
     98 
     99 // Flags on data packets
    100 enum FlipDataFlags {
    101   DATA_FLAG_NONE = 0,
    102   DATA_FLAG_FIN = 1,
    103   DATA_FLAG_COMPRESSED = 2  // TODO(mbelshe): remove me.
    104 };
    105 
    106 // Flags on control packets
    107 enum FlipControlFlags {
    108   CONTROL_FLAG_NONE = 0,
    109   CONTROL_FLAG_FIN = 1
    110 };
    111 
    112 // A FLIP stream id is a 31 bit entity.
    113 typedef uint32 FlipStreamId;
    114 
    115 // FLIP Priorities. (there are only 2 bits)
    116 #define FLIP_PRIORITY_LOWEST 3
    117 #define FLIP_PRIORITY_HIGHEST 0
    118 
    119 // -------------------------------------------------------------------------
    120 // These structures mirror the protocol structure definitions.
    121 
    122 // For the control data structures, we pack so that sizes match the
    123 // protocol over-the-wire sizes.
    124 #pragma pack(push)
    125 #pragma pack(1)
    126 
    127 // A special structure for the 8 bit flags and 24 bit length fields.
    128 union FlagsAndLength {
    129   uint8 flags_[4];  // 8 bits
    130   uint32 length_;   // 24 bits
    131 };
    132 
    133 // The basic FLIP Frame structure.
    134 struct FlipFrameBlock {
    135   union {
    136     struct {
    137       uint16 version_;
    138       uint16 type_;
    139     } control_;
    140     struct {
    141       FlipStreamId stream_id_;
    142     } data_;
    143   };
    144   FlagsAndLength flags_length_;
    145 };
    146 
    147 // A Control Frame structure.
    148 struct FlipControlFrameBlock : FlipFrameBlock {
    149   FlipStreamId stream_id_;
    150 };
    151 
    152 // A SYN_STREAM Control Frame structure.
    153 struct FlipSynStreamControlFrameBlock : FlipControlFrameBlock {
    154   uint8 priority_;
    155   uint8 unused_;
    156 };
    157 
    158 // A SYN_REPLY Control Frame structure.
    159 struct FlipSynReplyControlFrameBlock : FlipControlFrameBlock {
    160   uint16 unused_;
    161 };
    162 
    163 // A FNI_STREAM Control Frame structure.
    164 struct FlipFinStreamControlFrameBlock : FlipControlFrameBlock {
    165   uint32 status_;
    166 };
    167 
    168 #pragma pack(pop)
    169 
    170 // -------------------------------------------------------------------------
    171 // Wrapper classes for various FLIP frames.
    172 
    173 // All Flip Frame types derive from this FlipFrame class.
    174 class FlipFrame {
    175  public:
    176   // Create a FlipFrame for a given sized buffer.
    177   explicit FlipFrame(size_t size) : frame_(NULL), owns_buffer_(true) {
    178     DCHECK_GE(size, sizeof(struct FlipFrameBlock));
    179     char* buffer = new char[size];
    180     memset(buffer, 0, size);
    181     frame_ = reinterpret_cast<struct FlipFrameBlock*>(buffer);
    182   }
    183 
    184   // Create a FlipFrame using a pre-created buffer.
    185   // If |owns_buffer| is true, this class takes ownership of the buffer
    186   // and will delete it on cleanup.  The buffer must have been created using
    187   // new char[].
    188   // If |owns_buffer| is false, the caller retains ownership of the buffer and
    189   // is responsible for making sure the buffer outlives this frame.  In other
    190   // words, this class does NOT create a copy of the buffer.
    191   FlipFrame(char* data, bool owns_buffer)
    192       : frame_(reinterpret_cast<struct FlipFrameBlock*>(data)),
    193         owns_buffer_(owns_buffer) {
    194     DCHECK(frame_);
    195   }
    196 
    197   virtual ~FlipFrame() {
    198     if (owns_buffer_) {
    199       char* buffer = reinterpret_cast<char*>(frame_);
    200       delete [] buffer;
    201     }
    202     frame_ = NULL;
    203   }
    204 
    205   // Provides access to the frame bytes, which is a buffer containing
    206   // the frame packed as expected for sending over the wire.
    207   char* data() const { return reinterpret_cast<char*>(frame_); }
    208 
    209   uint8 flags() const { return frame_->flags_length_.flags_[0]; }
    210   void set_flags(uint8 flags) { frame_->flags_length_.flags_[0] = flags; }
    211 
    212   uint32 length() const {
    213     return ntohl(frame_->flags_length_.length_) & kLengthMask;
    214   }
    215 
    216   void set_length(uint32 length) {
    217     DCHECK_EQ(0u, (length & ~kLengthMask));
    218     length = htonl(length & kLengthMask);
    219     frame_->flags_length_.length_ = flags() | length;
    220   }
    221 
    222   bool is_control_frame() const {
    223     return (ntohs(frame_->control_.version_) & kControlFlagMask) ==
    224         kControlFlagMask;
    225   }
    226 
    227   // Returns the size of the FlipFrameBlock structure.
    228   // Note: this is not the size of the FlipFrame class.
    229   // Every FlipFrame* class has a static size() method for accessing
    230   // the size of the data structure which will be sent over the wire.
    231   // Note:  this is not the same as sizeof(FlipFrame).
    232   static size_t size() { return sizeof(struct FlipFrameBlock); }
    233 
    234  protected:
    235   FlipFrameBlock* frame_;
    236 
    237  private:
    238   bool owns_buffer_;
    239   DISALLOW_COPY_AND_ASSIGN(FlipFrame);
    240 };
    241 
    242 // A Data Frame.
    243 class FlipDataFrame : public FlipFrame {
    244  public:
    245   FlipDataFrame() : FlipFrame(size()) {}
    246   FlipDataFrame(char* data, bool owns_buffer)
    247       : FlipFrame(data, owns_buffer) {}
    248   virtual ~FlipDataFrame() {}
    249 
    250   FlipStreamId stream_id() const {
    251     return ntohl(frame_->data_.stream_id_) & kStreamIdMask;
    252   }
    253 
    254   // Note that setting the stream id sets the control bit to false.
    255   // As stream id should always be set, this means the control bit
    256   // should always be set correctly.
    257   void set_stream_id(FlipStreamId id) {
    258     DCHECK_EQ(0u, (id & ~kStreamIdMask));
    259     frame_->data_.stream_id_ = htonl(id & kStreamIdMask);
    260   }
    261 
    262   // Returns the size of the FlipFrameBlock structure.
    263   // Note: this is not the size of the FlipDataFrame class.
    264   static size_t size() { return FlipFrame::size(); }
    265 
    266  private:
    267   DISALLOW_COPY_AND_ASSIGN(FlipDataFrame);
    268 };
    269 
    270 // A Control Frame.
    271 class FlipControlFrame : public FlipFrame {
    272  public:
    273   explicit FlipControlFrame(size_t size) : FlipFrame(size) {}
    274   FlipControlFrame(char* data, bool owns_buffer)
    275       : FlipFrame(data, owns_buffer) {}
    276   virtual ~FlipControlFrame() {}
    277 
    278   uint16 version() const {
    279     const int kVersionMask = 0x7fff;
    280     return ntohs(block()->control_.version_) & kVersionMask;
    281   }
    282   FlipControlType type() const {
    283     uint16 type = ntohs(block()->control_.type_);
    284     DCHECK(type >= SYN_STREAM && type <= NOOP);
    285     return static_cast<FlipControlType>(type);
    286   }
    287   FlipStreamId stream_id() const {
    288     return ntohl(block()->stream_id_) & kStreamIdMask;
    289   }
    290 
    291   void set_stream_id(FlipStreamId id) {
    292     block()->stream_id_ = htonl(id & kStreamIdMask);
    293   }
    294 
    295   // Returns the size of the FlipControlFrameBlock structure.
    296   // Note: this is not the size of the FlipControlFrame class.
    297   static size_t size() { return sizeof(FlipControlFrameBlock); }
    298 
    299  private:
    300   struct FlipControlFrameBlock* block() const {
    301     return static_cast<FlipControlFrameBlock*>(frame_);
    302   }
    303   DISALLOW_COPY_AND_ASSIGN(FlipControlFrame);
    304 };
    305 
    306 // A SYN_STREAM frame.
    307 class FlipSynStreamControlFrame : public FlipControlFrame {
    308  public:
    309   FlipSynStreamControlFrame() : FlipControlFrame(size()) {}
    310   FlipSynStreamControlFrame(char* data, bool owns_buffer)
    311       : FlipControlFrame(data, owns_buffer) {}
    312   virtual ~FlipSynStreamControlFrame() {}
    313 
    314   uint8 priority() const { return (block()->priority_ & kPriorityMask) >> 6; }
    315 
    316   // The number of bytes in the header block beyond the frame header length.
    317   int header_block_len() const {
    318     return length() - (size() - FlipFrame::size());
    319   }
    320 
    321   const char* header_block() const {
    322     return reinterpret_cast<const char*>(block()) + size();
    323   }
    324 
    325   // Returns the size of the FlipSynStreamControlFrameBlock structure.
    326   // Note: this is not the size of the FlipSynStreamControlFrame class.
    327   static size_t size() { return sizeof(FlipSynStreamControlFrameBlock); }
    328 
    329  private:
    330   struct FlipSynStreamControlFrameBlock* block() const {
    331     return static_cast<FlipSynStreamControlFrameBlock*>(frame_);
    332   }
    333   DISALLOW_COPY_AND_ASSIGN(FlipSynStreamControlFrame);
    334 };
    335 
    336 // A SYN_REPLY frame.
    337 class FlipSynReplyControlFrame : public FlipControlFrame {
    338  public:
    339   FlipSynReplyControlFrame() : FlipControlFrame(size()) {}
    340   FlipSynReplyControlFrame(char* data, bool owns_buffer)
    341       : FlipControlFrame(data, owns_buffer) {}
    342   virtual ~FlipSynReplyControlFrame() {}
    343 
    344   int header_block_len() const {
    345     return length() - (size() - FlipFrame::size());
    346   }
    347 
    348   const char* header_block() const {
    349     return reinterpret_cast<const char*>(block()) + size();
    350   }
    351 
    352   // Returns the size of the FlipSynReplyControlFrameBlock structure.
    353   // Note: this is not the size of the FlipSynReplyControlFrame class.
    354   static size_t size() { return sizeof(FlipSynReplyControlFrameBlock); }
    355 
    356  private:
    357   struct FlipSynReplyControlFrameBlock* block() const {
    358     return static_cast<FlipSynReplyControlFrameBlock*>(frame_);
    359   }
    360   DISALLOW_COPY_AND_ASSIGN(FlipSynReplyControlFrame);
    361 };
    362 
    363 // A FIN_STREAM frame.
    364 class FlipFinStreamControlFrame : public FlipControlFrame {
    365  public:
    366   FlipFinStreamControlFrame() : FlipControlFrame(size()) {}
    367   FlipFinStreamControlFrame(char* data, bool owns_buffer)
    368       : FlipControlFrame(data, owns_buffer) {}
    369   virtual ~FlipFinStreamControlFrame() {}
    370 
    371   uint32 status() const { return ntohl(block()->status_); }
    372   void set_status(uint32 status) { block()->status_ = htonl(status); }
    373 
    374   // Returns the size of the FlipFinStreamControlFrameBlock structure.
    375   // Note: this is not the size of the FlipFinStreamControlFrame class.
    376   static size_t size() { return sizeof(FlipFinStreamControlFrameBlock); }
    377 
    378  private:
    379   struct FlipFinStreamControlFrameBlock* block() const {
    380     return static_cast<FlipFinStreamControlFrameBlock*>(frame_);
    381   }
    382   DISALLOW_COPY_AND_ASSIGN(FlipFinStreamControlFrame);
    383 };
    384 
    385 }  // namespace flip
    386 
    387 #endif  // NET_FLIP_FLIP_PROTOCOL_H_
    388