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
82namespace flip {
83
84// This implementation of Flip is version 1.
85const 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.
92enum FlipControlType {
93  SYN_STREAM = 1,
94  SYN_REPLY,
95  FIN_STREAM,
96  NOOP
97};
98
99// Flags on data packets
100enum 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
107enum FlipControlFlags {
108  CONTROL_FLAG_NONE = 0,
109  CONTROL_FLAG_FIN = 1
110};
111
112// A FLIP stream id is a 31 bit entity.
113typedef 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.
128union FlagsAndLength {
129  uint8 flags_[4];  // 8 bits
130  uint32 length_;   // 24 bits
131};
132
133// The basic FLIP Frame structure.
134struct 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.
148struct FlipControlFrameBlock : FlipFrameBlock {
149  FlipStreamId stream_id_;
150};
151
152// A SYN_STREAM Control Frame structure.
153struct FlipSynStreamControlFrameBlock : FlipControlFrameBlock {
154  uint8 priority_;
155  uint8 unused_;
156};
157
158// A SYN_REPLY Control Frame structure.
159struct FlipSynReplyControlFrameBlock : FlipControlFrameBlock {
160  uint16 unused_;
161};
162
163// A FNI_STREAM Control Frame structure.
164struct 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.
174class 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.
243class 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.
271class 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.
307class 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.
337class 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.
364class 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