• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
FlipFrame(size_t size)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.
FlipFrame(char * data,bool owns_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 
~FlipFrame()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.
data()207   char* data() const { return reinterpret_cast<char*>(frame_); }
208 
flags()209   uint8 flags() const { return frame_->flags_length_.flags_[0]; }
set_flags(uint8 flags)210   void set_flags(uint8 flags) { frame_->flags_length_.flags_[0] = flags; }
211 
length()212   uint32 length() const {
213     return ntohl(frame_->flags_length_.length_) & kLengthMask;
214   }
215 
set_length(uint32 length)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 
is_control_frame()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).
size()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:
FlipDataFrame()245   FlipDataFrame() : FlipFrame(size()) {}
FlipDataFrame(char * data,bool owns_buffer)246   FlipDataFrame(char* data, bool owns_buffer)
247       : FlipFrame(data, owns_buffer) {}
~FlipDataFrame()248   virtual ~FlipDataFrame() {}
249 
stream_id()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.
set_stream_id(FlipStreamId id)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.
size()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:
FlipControlFrame(size_t size)273   explicit FlipControlFrame(size_t size) : FlipFrame(size) {}
FlipControlFrame(char * data,bool owns_buffer)274   FlipControlFrame(char* data, bool owns_buffer)
275       : FlipFrame(data, owns_buffer) {}
~FlipControlFrame()276   virtual ~FlipControlFrame() {}
277 
version()278   uint16 version() const {
279     const int kVersionMask = 0x7fff;
280     return ntohs(block()->control_.version_) & kVersionMask;
281   }
type()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   }
stream_id()287   FlipStreamId stream_id() const {
288     return ntohl(block()->stream_id_) & kStreamIdMask;
289   }
290 
set_stream_id(FlipStreamId id)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.
size()297   static size_t size() { return sizeof(FlipControlFrameBlock); }
298 
299  private:
block()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:
FlipSynStreamControlFrame()309   FlipSynStreamControlFrame() : FlipControlFrame(size()) {}
FlipSynStreamControlFrame(char * data,bool owns_buffer)310   FlipSynStreamControlFrame(char* data, bool owns_buffer)
311       : FlipControlFrame(data, owns_buffer) {}
~FlipSynStreamControlFrame()312   virtual ~FlipSynStreamControlFrame() {}
313 
priority()314   uint8 priority() const { return (block()->priority_ & kPriorityMask) >> 6; }
315 
316   // The number of bytes in the header block beyond the frame header length.
header_block_len()317   int header_block_len() const {
318     return length() - (size() - FlipFrame::size());
319   }
320 
header_block()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.
size()327   static size_t size() { return sizeof(FlipSynStreamControlFrameBlock); }
328 
329  private:
block()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:
FlipSynReplyControlFrame()339   FlipSynReplyControlFrame() : FlipControlFrame(size()) {}
FlipSynReplyControlFrame(char * data,bool owns_buffer)340   FlipSynReplyControlFrame(char* data, bool owns_buffer)
341       : FlipControlFrame(data, owns_buffer) {}
~FlipSynReplyControlFrame()342   virtual ~FlipSynReplyControlFrame() {}
343 
header_block_len()344   int header_block_len() const {
345     return length() - (size() - FlipFrame::size());
346   }
347 
header_block()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.
size()354   static size_t size() { return sizeof(FlipSynReplyControlFrameBlock); }
355 
356  private:
block()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:
FlipFinStreamControlFrame()366   FlipFinStreamControlFrame() : FlipControlFrame(size()) {}
FlipFinStreamControlFrame(char * data,bool owns_buffer)367   FlipFinStreamControlFrame(char* data, bool owns_buffer)
368       : FlipControlFrame(data, owns_buffer) {}
~FlipFinStreamControlFrame()369   virtual ~FlipFinStreamControlFrame() {}
370 
status()371   uint32 status() const { return ntohl(block()->status_); }
set_status(uint32 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.
size()376   static size_t size() { return sizeof(FlipFinStreamControlFrameBlock); }
377 
378  private:
block()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