• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 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 Spdy.
6 
7 #ifndef NET_SPDY_SPDY_PROTOCOL_H_
8 #define NET_SPDY_SPDY_PROTOCOL_H_
9 #pragma once
10 
11 #include <limits>
12 
13 #include "base/basictypes.h"
14 #include "base/logging.h"
15 #include "net/base/sys_byteorder.h"
16 #include "net/spdy/spdy_bitmasks.h"
17 
18 //  Data Frame Format
19 //  +----------------------------------+
20 //  |0|       Stream-ID (31bits)       |
21 //  +----------------------------------+
22 //  | flags (8)  |  Length (24 bits)   |
23 //  +----------------------------------+
24 //  |               Data               |
25 //  +----------------------------------+
26 //
27 //  Control Frame Format
28 //  +----------------------------------+
29 //  |1| Version(15bits) | Type(16bits) |
30 //  +----------------------------------+
31 //  | flags (8)  |  Length (24 bits)   |
32 //  +----------------------------------+
33 //  |               Data               |
34 //  +----------------------------------+
35 //
36 //  Control Frame: SYN_STREAM
37 //  +----------------------------------+
38 //  |1|000000000000001|0000000000000001|
39 //  +----------------------------------+
40 //  | flags (8)  |  Length (24 bits)   |  >= 12
41 //  +----------------------------------+
42 //  |X|       Stream-ID(31bits)        |
43 //  +----------------------------------+
44 //  |X|Associated-To-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: RST_STREAM
61 //  +----------------------------------+
62 //  |1|000000000000001|0000000000000011|
63 //  +----------------------------------+
64 //  | flags (8)  |  Length (24 bits)   |  >= 4
65 //  +----------------------------------+
66 //  |X|       Stream-ID(31bits)        |
67 //  +----------------------------------+
68 //  |        Status code (32 bits)     |
69 //  +----------------------------------+
70 //
71 //  Control Frame: SETTINGS
72 //  +----------------------------------+
73 //  |1|000000000000001|0000000000000100|
74 //  +----------------------------------+
75 //  | flags (8)  |  Length (24 bits)   |
76 //  +----------------------------------+
77 //  |        # of entries (32)         |
78 //  +----------------------------------+
79 //
80 //  Control Frame: NOOP
81 //  +----------------------------------+
82 //  |1|000000000000001|0000000000000101|
83 //  +----------------------------------+
84 //  | flags (8)  |  Length (24 bits)   | = 0
85 //  +----------------------------------+
86 //
87 //  Control Frame: PING
88 //  +----------------------------------+
89 //  |1|000000000000001|0000000000000110|
90 //  +----------------------------------+
91 //  | flags (8)  |  Length (24 bits)   | = 4
92 //  +----------------------------------+
93 //  |        Unique id (32 bits)       |
94 //  +----------------------------------+
95 //
96 //  Control Frame: GOAWAY
97 //  +----------------------------------+
98 //  |1|000000000000001|0000000000000111|
99 //  +----------------------------------+
100 //  | flags (8)  |  Length (24 bits)   | = 4
101 //  +----------------------------------+
102 //  |X|  Last-accepted-stream-id       |
103 //  +----------------------------------+
104 //
105 //  Control Frame: HEADERS
106 //  +----------------------------------+
107 //  |1|000000000000001|0000000000001000|
108 //  +----------------------------------+
109 //  | flags (8)  |  Length (24 bits)   | >= 8
110 //  +----------------------------------+
111 //  |X|      Stream-ID (31 bits)       |
112 //  +----------------------------------+
113 //  | unused (16 bits)| Length (16bits)|
114 //  +----------------------------------+
115 //
116 //  Control Frame: WINDOW_UPDATE
117 //  +----------------------------------+
118 //  |1|000000000000001|0000000000001001|
119 //  +----------------------------------+
120 //  | flags (8)  |  Length (24 bits)   | = 8
121 //  +----------------------------------+
122 //  |X|      Stream-ID (31 bits)       |
123 //  +----------------------------------+
124 //  |   Delta-Window-Size (32 bits)    |
125 //  +----------------------------------+
126 namespace spdy {
127 
128 // This implementation of Spdy is version 2; It's like version 1, with some
129 // minor tweaks.
130 const int kSpdyProtocolVersion = 2;
131 
132 // Initial window size for a Spdy stream
133 const size_t kSpdyStreamInitialWindowSize = 64 * 1024;  // 64 KBytes
134 
135 // Maximum window size for a Spdy stream
136 const size_t kSpdyStreamMaximumWindowSize = std::numeric_limits<int32>::max();
137 
138 // HTTP-over-SPDY header constants
139 const char kMethod[] = "method";
140 const char kStatus[] = "status";
141 const char kUrl[] = "url";
142 const char kVersion[] = "version";
143 // When we server push, we will add [path: fully/qualified/url] to the server
144 // push headers so that the client will know what url the data corresponds to.
145 const char kPath[] = "path";
146 
147 // Note: all protocol data structures are on-the-wire format.  That means that
148 //       data is stored in network-normalized order.  Readers must use the
149 //       accessors provided or call ntohX() functions.
150 
151 // Types of Spdy Control Frames.
152 enum SpdyControlType {
153   SYN_STREAM = 1,
154   SYN_REPLY,
155   RST_STREAM,
156   SETTINGS,
157   NOOP,
158   PING,
159   GOAWAY,
160   HEADERS,
161   WINDOW_UPDATE,
162   NUM_CONTROL_FRAME_TYPES
163 };
164 
165 // Flags on data packets.
166 enum SpdyDataFlags {
167   DATA_FLAG_NONE = 0,
168   DATA_FLAG_FIN = 1,
169   DATA_FLAG_COMPRESSED = 2
170 };
171 
172 // Flags on control packets
173 enum SpdyControlFlags {
174   CONTROL_FLAG_NONE = 0,
175   CONTROL_FLAG_FIN = 1,
176   CONTROL_FLAG_UNIDIRECTIONAL = 2
177 };
178 
179 // Flags on the SETTINGS control frame.
180 enum SpdySettingsControlFlags {
181   SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1
182 };
183 
184 // Flags for settings within a SETTINGS frame.
185 enum SpdySettingsFlags {
186   SETTINGS_FLAG_PLEASE_PERSIST = 0x1,
187   SETTINGS_FLAG_PERSISTED = 0x2
188 };
189 
190 // List of known settings.
191 enum SpdySettingsIds {
192   SETTINGS_UPLOAD_BANDWIDTH = 0x1,
193   SETTINGS_DOWNLOAD_BANDWIDTH = 0x2,
194   // Network round trip time in milliseconds.
195   SETTINGS_ROUND_TRIP_TIME = 0x3,
196   SETTINGS_MAX_CONCURRENT_STREAMS = 0x4,
197   // TCP congestion window in packets.
198   SETTINGS_CURRENT_CWND = 0x5,
199   // Downstream byte retransmission rate in percentage.
200   SETTINGS_DOWNLOAD_RETRANS_RATE = 0x6,
201   // Initial window size in bytes
202   SETTINGS_INITIAL_WINDOW_SIZE = 0x7
203 };
204 
205 // Status codes, as used in control frames (primarily RST_STREAM).
206 enum SpdyStatusCodes {
207   INVALID = 0,
208   PROTOCOL_ERROR = 1,
209   INVALID_STREAM = 2,
210   REFUSED_STREAM = 3,
211   UNSUPPORTED_VERSION = 4,
212   CANCEL = 5,
213   INTERNAL_ERROR = 6,
214   FLOW_CONTROL_ERROR = 7,
215   INVALID_ASSOCIATED_STREAM = 8,
216   NUM_STATUS_CODES = 9
217 };
218 
219 // A SPDY stream id is a 31 bit entity.
220 typedef uint32 SpdyStreamId;
221 
222 // A SPDY priority is a number between 0 and 3 (inclusive).
223 typedef uint8 SpdyPriority;
224 
225 // SPDY Priorities. (there are only 2 bits)
226 #define SPDY_PRIORITY_LOWEST 3
227 #define SPDY_PRIORITY_HIGHEST 0
228 
229 // -------------------------------------------------------------------------
230 // These structures mirror the protocol structure definitions.
231 
232 // For the control data structures, we pack so that sizes match the
233 // protocol over-the-wire sizes.
234 #pragma pack(push)
235 #pragma pack(1)
236 
237 // A special structure for the 8 bit flags and 24 bit length fields.
238 union FlagsAndLength {
239   uint8 flags_[4];  // 8 bits
240   uint32 length_;   // 24 bits
241 };
242 
243 // The basic SPDY Frame structure.
244 struct SpdyFrameBlock {
245   union {
246     struct {
247       uint16 version_;
248       uint16 type_;
249     } control_;
250     struct {
251       SpdyStreamId stream_id_;
252     } data_;
253   };
254   FlagsAndLength flags_length_;
255 };
256 
257 // A SYN_STREAM Control Frame structure.
258 struct SpdySynStreamControlFrameBlock : SpdyFrameBlock {
259   SpdyStreamId stream_id_;
260   SpdyStreamId associated_stream_id_;
261   SpdyPriority priority_;
262   uint8 unused_;
263 };
264 
265 // A SYN_REPLY Control Frame structure.
266 struct SpdySynReplyControlFrameBlock : SpdyFrameBlock {
267   SpdyStreamId stream_id_;
268   uint16 unused_;
269 };
270 
271 // A RST_STREAM Control Frame structure.
272 struct SpdyRstStreamControlFrameBlock : SpdyFrameBlock {
273   SpdyStreamId stream_id_;
274   uint32 status_;
275 };
276 
277 // A SETTINGS Control Frame structure.
278 struct SpdySettingsControlFrameBlock : SpdyFrameBlock {
279   uint32 num_entries_;
280   // Variable data here.
281 };
282 
283 // A NOOP Control Frame structure.
284 struct SpdyNoopControlFrameBlock : SpdyFrameBlock {
285 };
286 
287 // A PING Control Frame structure.
288 struct SpdyPingControlFrameBlock : SpdyFrameBlock {
289   uint32 unique_id_;
290 };
291 
292 // A GOAWAY Control Frame structure.
293 struct SpdyGoAwayControlFrameBlock : SpdyFrameBlock {
294   SpdyStreamId last_accepted_stream_id_;
295 };
296 
297 // A HEADERS Control Frame structure.
298 struct SpdyHeadersControlFrameBlock : SpdyFrameBlock {
299   SpdyStreamId stream_id_;
300   uint16 unused_;
301 };
302 
303 // A WINDOW_UPDATE Control Frame structure
304 struct SpdyWindowUpdateControlFrameBlock : SpdyFrameBlock {
305   SpdyStreamId stream_id_;
306   uint32 delta_window_size_;
307 };
308 
309 // A structure for the 8 bit flags and 24 bit ID fields.
310 union SettingsFlagsAndId {
311   // Sets both flags and id to the value for flags-and-id as sent over the wire
SettingsFlagsAndId(uint32 val)312   SettingsFlagsAndId(uint32 val) : id_(val) {}
flags()313   uint8 flags() const { return flags_[0]; }
set_flags(uint8 flags)314   void set_flags(uint8 flags) { flags_[0] = flags; }
id()315   uint32 id() const { return (ntohl(id_) & kSettingsIdMask); }
set_id(uint32 id)316   void set_id(uint32 id) {
317     DCHECK_EQ(0u, (id & ~kSettingsIdMask));
318     id = htonl(id & kSettingsIdMask);
319     id_ = flags() | id;
320   }
321 
322   uint8 flags_[4];  // 8 bits
323   uint32 id_;       // 24 bits
324 };
325 
326 #pragma pack(pop)
327 
328 // -------------------------------------------------------------------------
329 // Wrapper classes for various SPDY frames.
330 
331 // All Spdy Frame types derive from this SpdyFrame class.
332 class SpdyFrame {
333  public:
334   // Create a SpdyFrame for a given sized buffer.
SpdyFrame(size_t size)335   explicit SpdyFrame(size_t size) : frame_(NULL), owns_buffer_(true) {
336     DCHECK_GE(size, sizeof(struct SpdyFrameBlock));
337     char* buffer = new char[size];
338     memset(buffer, 0, size);
339     frame_ = reinterpret_cast<struct SpdyFrameBlock*>(buffer);
340   }
341 
342   // Create a SpdyFrame using a pre-created buffer.
343   // If |owns_buffer| is true, this class takes ownership of the buffer
344   // and will delete it on cleanup.  The buffer must have been created using
345   // new char[].
346   // If |owns_buffer| is false, the caller retains ownership of the buffer and
347   // is responsible for making sure the buffer outlives this frame.  In other
348   // words, this class does NOT create a copy of the buffer.
SpdyFrame(char * data,bool owns_buffer)349   SpdyFrame(char* data, bool owns_buffer)
350       : frame_(reinterpret_cast<struct SpdyFrameBlock*>(data)),
351         owns_buffer_(owns_buffer) {
352     DCHECK(frame_);
353   }
354 
~SpdyFrame()355   ~SpdyFrame() {
356     if (owns_buffer_) {
357       char* buffer = reinterpret_cast<char*>(frame_);
358       delete [] buffer;
359     }
360     frame_ = NULL;
361   }
362 
363   // Provides access to the frame bytes, which is a buffer containing
364   // the frame packed as expected for sending over the wire.
data()365   char* data() const { return reinterpret_cast<char*>(frame_); }
366 
flags()367   uint8 flags() const { return frame_->flags_length_.flags_[0]; }
set_flags(uint8 flags)368   void set_flags(uint8 flags) { frame_->flags_length_.flags_[0] = flags; }
369 
length()370   uint32 length() const {
371     return ntohl(frame_->flags_length_.length_) & kLengthMask;
372   }
373 
set_length(uint32 length)374   void set_length(uint32 length) {
375     DCHECK_EQ(0u, (length & ~kLengthMask));
376     length = htonl(length & kLengthMask);
377     frame_->flags_length_.length_ = flags() | length;
378   }
379 
is_control_frame()380   bool is_control_frame() const {
381     return (ntohs(frame_->control_.version_) & kControlFlagMask) ==
382         kControlFlagMask;
383   }
384 
385   // Returns the size of the SpdyFrameBlock structure.
386   // Every SpdyFrame* class has a static size() method for accessing
387   // the size of the data structure which will be sent over the wire.
388   // Note:  this is not the same as sizeof(SpdyFrame).
size()389   static size_t size() { return sizeof(struct SpdyFrameBlock); }
390 
391  protected:
392   SpdyFrameBlock* frame_;
393 
394  private:
395   bool owns_buffer_;
396   DISALLOW_COPY_AND_ASSIGN(SpdyFrame);
397 };
398 
399 // A Data Frame.
400 class SpdyDataFrame : public SpdyFrame {
401  public:
SpdyDataFrame()402   SpdyDataFrame() : SpdyFrame(size()) {}
SpdyDataFrame(char * data,bool owns_buffer)403   SpdyDataFrame(char* data, bool owns_buffer)
404       : SpdyFrame(data, owns_buffer) {}
405 
stream_id()406   SpdyStreamId stream_id() const {
407     return ntohl(frame_->data_.stream_id_) & kStreamIdMask;
408   }
409 
410   // Note that setting the stream id sets the control bit to false.
411   // As stream id should always be set, this means the control bit
412   // should always be set correctly.
set_stream_id(SpdyStreamId id)413   void set_stream_id(SpdyStreamId id) {
414     DCHECK_EQ(0u, (id & ~kStreamIdMask));
415     frame_->data_.stream_id_ = htonl(id & kStreamIdMask);
416   }
417 
418   // Returns the size of the SpdyFrameBlock structure.
419   // Note: this is not the size of the SpdyDataFrame class.
size()420   static size_t size() { return SpdyFrame::size(); }
421 
payload()422   const char* payload() const {
423     return reinterpret_cast<const char*>(frame_) + size();
424   }
425 
426  private:
427   DISALLOW_COPY_AND_ASSIGN(SpdyDataFrame);
428 };
429 
430 // A Control Frame.
431 class SpdyControlFrame : public SpdyFrame {
432  public:
SpdyControlFrame(size_t size)433   explicit SpdyControlFrame(size_t size) : SpdyFrame(size) {}
SpdyControlFrame(char * data,bool owns_buffer)434   SpdyControlFrame(char* data, bool owns_buffer)
435       : SpdyFrame(data, owns_buffer) {}
436 
437   // Callers can use this method to check if the frame appears to be a valid
438   // frame.  Does not guarantee that there are no errors.
AppearsToBeAValidControlFrame()439   bool AppearsToBeAValidControlFrame() const {
440     // Right now we only check if the frame has an out-of-bounds type.
441     uint16 type = ntohs(block()->control_.type_);
442     return (type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES);
443   }
444 
version()445   uint16 version() const {
446     const int kVersionMask = 0x7fff;
447     return ntohs(block()->control_.version_) & kVersionMask;
448   }
449 
set_version(uint16 version)450   void set_version(uint16 version) {
451     DCHECK_EQ(0u, version & kControlFlagMask);
452     mutable_block()->control_.version_ = htons(kControlFlagMask | version);
453   }
454 
type()455   SpdyControlType type() const {
456     uint16 type = ntohs(block()->control_.type_);
457     DCHECK(type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES);
458     return static_cast<SpdyControlType>(type);
459   }
460 
set_type(SpdyControlType type)461   void set_type(SpdyControlType type) {
462     DCHECK(type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES);
463     mutable_block()->control_.type_ = htons(type);
464   }
465 
466   // Returns true if this control frame is of a type that has a header block,
467   // otherwise it returns false.
has_header_block()468   bool has_header_block() const {
469     return type() == SYN_STREAM || type() == SYN_REPLY || type() == HEADERS;
470   }
471 
472   // Returns the size of the SpdyFrameBlock structure.
473   // Note: this is not the size of the SpdyControlFrame class.
size()474   static size_t size() { return sizeof(SpdyFrameBlock); }
475 
476   // The size of the 'Number of Name/Value pairs' field in a Name/Value block.
477   static const size_t kNumNameValuePairsSize = 2;
478 
479   // The size of the 'Length of a name' field in a Name/Value block.
480   static const size_t kLengthOfNameSize = 2;
481 
482   // The size of the 'Length of a value' field in a Name/Value block.
483   static const size_t kLengthOfValueSize = 2;
484 
485  private:
block()486   const struct SpdyFrameBlock* block() const {
487     return frame_;
488   }
mutable_block()489   struct SpdyFrameBlock* mutable_block() {
490     return frame_;
491   }
492   DISALLOW_COPY_AND_ASSIGN(SpdyControlFrame);
493 };
494 
495 // A SYN_STREAM frame.
496 class SpdySynStreamControlFrame : public SpdyControlFrame {
497  public:
SpdySynStreamControlFrame()498   SpdySynStreamControlFrame() : SpdyControlFrame(size()) {}
SpdySynStreamControlFrame(char * data,bool owns_buffer)499   SpdySynStreamControlFrame(char* data, bool owns_buffer)
500       : SpdyControlFrame(data, owns_buffer) {}
501 
stream_id()502   SpdyStreamId stream_id() const {
503     return ntohl(block()->stream_id_) & kStreamIdMask;
504   }
505 
set_stream_id(SpdyStreamId id)506   void set_stream_id(SpdyStreamId id) {
507     mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
508   }
509 
associated_stream_id()510   SpdyStreamId associated_stream_id() const {
511     return ntohl(block()->associated_stream_id_) & kStreamIdMask;
512   }
513 
set_associated_stream_id(SpdyStreamId id)514   void set_associated_stream_id(SpdyStreamId id) {
515     mutable_block()->associated_stream_id_ = htonl(id & kStreamIdMask);
516   }
517 
priority()518   SpdyPriority priority() const {
519     return (block()->priority_ & kPriorityMask) >> 6;
520   }
521 
522   // The number of bytes in the header block beyond the frame header length.
header_block_len()523   int header_block_len() const {
524     return length() - (size() - SpdyFrame::size());
525   }
526 
header_block()527   const char* header_block() const {
528     return reinterpret_cast<const char*>(block()) + size();
529   }
530 
531   // Returns the size of the SpdySynStreamControlFrameBlock structure.
532   // Note: this is not the size of the SpdySynStreamControlFrame class.
size()533   static size_t size() { return sizeof(SpdySynStreamControlFrameBlock); }
534 
535  private:
block()536   const struct SpdySynStreamControlFrameBlock* block() const {
537     return static_cast<SpdySynStreamControlFrameBlock*>(frame_);
538   }
mutable_block()539   struct SpdySynStreamControlFrameBlock* mutable_block() {
540     return static_cast<SpdySynStreamControlFrameBlock*>(frame_);
541   }
542   DISALLOW_COPY_AND_ASSIGN(SpdySynStreamControlFrame);
543 };
544 
545 // A SYN_REPLY frame.
546 class SpdySynReplyControlFrame : public SpdyControlFrame {
547  public:
SpdySynReplyControlFrame()548   SpdySynReplyControlFrame() : SpdyControlFrame(size()) {}
SpdySynReplyControlFrame(char * data,bool owns_buffer)549   SpdySynReplyControlFrame(char* data, bool owns_buffer)
550       : SpdyControlFrame(data, owns_buffer) {}
551 
stream_id()552   SpdyStreamId stream_id() const {
553     return ntohl(block()->stream_id_) & kStreamIdMask;
554   }
555 
set_stream_id(SpdyStreamId id)556   void set_stream_id(SpdyStreamId id) {
557     mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
558   }
559 
header_block_len()560   int header_block_len() const {
561     return length() - (size() - SpdyFrame::size());
562   }
563 
header_block()564   const char* header_block() const {
565     return reinterpret_cast<const char*>(block()) + size();
566   }
567 
568   // Returns the size of the SpdySynReplyControlFrameBlock structure.
569   // Note: this is not the size of the SpdySynReplyControlFrame class.
size()570   static size_t size() { return sizeof(SpdySynReplyControlFrameBlock); }
571 
572  private:
block()573   const struct SpdySynReplyControlFrameBlock* block() const {
574     return static_cast<SpdySynReplyControlFrameBlock*>(frame_);
575   }
mutable_block()576   struct SpdySynReplyControlFrameBlock* mutable_block() {
577     return static_cast<SpdySynReplyControlFrameBlock*>(frame_);
578   }
579   DISALLOW_COPY_AND_ASSIGN(SpdySynReplyControlFrame);
580 };
581 
582 // A RST_STREAM frame.
583 class SpdyRstStreamControlFrame : public SpdyControlFrame {
584  public:
SpdyRstStreamControlFrame()585   SpdyRstStreamControlFrame() : SpdyControlFrame(size()) {}
SpdyRstStreamControlFrame(char * data,bool owns_buffer)586   SpdyRstStreamControlFrame(char* data, bool owns_buffer)
587       : SpdyControlFrame(data, owns_buffer) {}
588 
stream_id()589   SpdyStreamId stream_id() const {
590     return ntohl(block()->stream_id_) & kStreamIdMask;
591   }
592 
set_stream_id(SpdyStreamId id)593   void set_stream_id(SpdyStreamId id) {
594     mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
595   }
596 
status()597   SpdyStatusCodes status() const {
598     SpdyStatusCodes status =
599         static_cast<SpdyStatusCodes>(ntohl(block()->status_));
600     if (status < INVALID || status >= NUM_STATUS_CODES) {
601       status = INVALID;
602     }
603     return status;
604   }
set_status(SpdyStatusCodes status)605   void set_status(SpdyStatusCodes status) {
606     mutable_block()->status_ = htonl(static_cast<uint32>(status));
607   }
608 
609   // Returns the size of the SpdyRstStreamControlFrameBlock structure.
610   // Note: this is not the size of the SpdyRstStreamControlFrame class.
size()611   static size_t size() { return sizeof(SpdyRstStreamControlFrameBlock); }
612 
613  private:
block()614   const struct SpdyRstStreamControlFrameBlock* block() const {
615     return static_cast<SpdyRstStreamControlFrameBlock*>(frame_);
616   }
mutable_block()617   struct SpdyRstStreamControlFrameBlock* mutable_block() {
618     return static_cast<SpdyRstStreamControlFrameBlock*>(frame_);
619   }
620   DISALLOW_COPY_AND_ASSIGN(SpdyRstStreamControlFrame);
621 };
622 
623 class SpdySettingsControlFrame : public SpdyControlFrame {
624  public:
SpdySettingsControlFrame()625   SpdySettingsControlFrame() : SpdyControlFrame(size()) {}
SpdySettingsControlFrame(char * data,bool owns_buffer)626   SpdySettingsControlFrame(char* data, bool owns_buffer)
627       : SpdyControlFrame(data, owns_buffer) {}
628 
num_entries()629   uint32 num_entries() const {
630     return ntohl(block()->num_entries_);
631   }
632 
set_num_entries(int val)633   void set_num_entries(int val) {
634     mutable_block()->num_entries_ = htonl(val);
635   }
636 
header_block_len()637   int header_block_len() const {
638     return length() - (size() - SpdyFrame::size());
639   }
640 
header_block()641   const char* header_block() const {
642     return reinterpret_cast<const char*>(block()) + size();
643   }
644 
645   // Returns the size of the SpdySettingsControlFrameBlock structure.
646   // Note: this is not the size of the SpdySettingsControlFrameBlock class.
size()647   static size_t size() { return sizeof(SpdySettingsControlFrameBlock); }
648 
649  private:
block()650   const struct SpdySettingsControlFrameBlock* block() const {
651     return static_cast<SpdySettingsControlFrameBlock*>(frame_);
652   }
mutable_block()653   struct SpdySettingsControlFrameBlock* mutable_block() {
654     return static_cast<SpdySettingsControlFrameBlock*>(frame_);
655   }
656   DISALLOW_COPY_AND_ASSIGN(SpdySettingsControlFrame);
657 };
658 
659 class SpdyNoOpControlFrame : public SpdyControlFrame {
660  public:
SpdyNoOpControlFrame()661   SpdyNoOpControlFrame() : SpdyControlFrame(size()) {}
SpdyNoOpControlFrame(char * data,bool owns_buffer)662   SpdyNoOpControlFrame(char* data, bool owns_buffer)
663       : SpdyControlFrame(data, owns_buffer) {}
664 
size()665   static size_t size() { return sizeof(SpdyNoopControlFrameBlock); }
666 };
667 
668 class SpdyPingControlFrame : public SpdyControlFrame {
669  public:
SpdyPingControlFrame()670   SpdyPingControlFrame() : SpdyControlFrame(size()) {}
SpdyPingControlFrame(char * data,bool owns_buffer)671   SpdyPingControlFrame(char* data, bool owns_buffer)
672       : SpdyControlFrame(data, owns_buffer) {}
673 
unique_id()674   uint32 unique_id() const {
675     return ntohl(block()->unique_id_);
676   }
677 
set_unique_id(uint32 unique_id)678   void set_unique_id(uint32 unique_id) {
679     mutable_block()->unique_id_ = htonl(unique_id);
680   }
681 
size()682   static size_t size() { return sizeof(SpdyPingControlFrameBlock); }
683 
684  private:
block()685   const struct SpdyPingControlFrameBlock* block() const {
686     return static_cast<SpdyPingControlFrameBlock*>(frame_);
687   }
mutable_block()688   struct SpdyPingControlFrameBlock* mutable_block() {
689     return static_cast<SpdyPingControlFrameBlock*>(frame_);
690   }
691 };
692 
693 class SpdyGoAwayControlFrame : public SpdyControlFrame {
694  public:
SpdyGoAwayControlFrame()695   SpdyGoAwayControlFrame() : SpdyControlFrame(size()) {}
SpdyGoAwayControlFrame(char * data,bool owns_buffer)696   SpdyGoAwayControlFrame(char* data, bool owns_buffer)
697       : SpdyControlFrame(data, owns_buffer) {}
698 
last_accepted_stream_id()699   SpdyStreamId last_accepted_stream_id() const {
700     return ntohl(block()->last_accepted_stream_id_) & kStreamIdMask;
701   }
702 
set_last_accepted_stream_id(SpdyStreamId id)703   void set_last_accepted_stream_id(SpdyStreamId id) {
704     mutable_block()->last_accepted_stream_id_ = htonl(id & kStreamIdMask);
705   }
706 
size()707   static size_t size() { return sizeof(SpdyGoAwayControlFrameBlock); }
708 
709  private:
block()710   const struct SpdyGoAwayControlFrameBlock* block() const {
711     return static_cast<SpdyGoAwayControlFrameBlock*>(frame_);
712   }
mutable_block()713   struct SpdyGoAwayControlFrameBlock* mutable_block() {
714     return static_cast<SpdyGoAwayControlFrameBlock*>(frame_);
715   }
716   DISALLOW_COPY_AND_ASSIGN(SpdyGoAwayControlFrame);
717 };
718 
719 // A HEADERS frame.
720 class SpdyHeadersControlFrame : public SpdyControlFrame {
721  public:
SpdyHeadersControlFrame()722   SpdyHeadersControlFrame() : SpdyControlFrame(size()) {}
SpdyHeadersControlFrame(char * data,bool owns_buffer)723   SpdyHeadersControlFrame(char* data, bool owns_buffer)
724       : SpdyControlFrame(data, owns_buffer) {}
725 
stream_id()726   SpdyStreamId stream_id() const {
727     return ntohl(block()->stream_id_) & kStreamIdMask;
728   }
729 
set_stream_id(SpdyStreamId id)730   void set_stream_id(SpdyStreamId id) {
731     mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
732   }
733 
734   // The number of bytes in the header block beyond the frame header length.
header_block_len()735   int header_block_len() const {
736     return length() - (size() - SpdyFrame::size());
737   }
738 
header_block()739   const char* header_block() const {
740     return reinterpret_cast<const char*>(block()) + size();
741   }
742 
743   // Returns the size of the SpdyHeadersControlFrameBlock structure.
744   // Note: this is not the size of the SpdyHeadersControlFrame class.
size()745   static size_t size() { return sizeof(SpdyHeadersControlFrameBlock); }
746 
747  private:
block()748   const struct SpdyHeadersControlFrameBlock* block() const {
749     return static_cast<SpdyHeadersControlFrameBlock*>(frame_);
750   }
mutable_block()751   struct SpdyHeadersControlFrameBlock* mutable_block() {
752     return static_cast<SpdyHeadersControlFrameBlock*>(frame_);
753   }
754   DISALLOW_COPY_AND_ASSIGN(SpdyHeadersControlFrame);
755 };
756 
757 // A WINDOW_UPDATE frame.
758 class SpdyWindowUpdateControlFrame : public SpdyControlFrame {
759  public:
SpdyWindowUpdateControlFrame()760   SpdyWindowUpdateControlFrame() : SpdyControlFrame(size()) {}
SpdyWindowUpdateControlFrame(char * data,bool owns_buffer)761   SpdyWindowUpdateControlFrame(char* data, bool owns_buffer)
762       : SpdyControlFrame(data, owns_buffer) {}
763 
stream_id()764   SpdyStreamId stream_id() const {
765     return ntohl(block()->stream_id_) & kStreamIdMask;
766   }
767 
set_stream_id(SpdyStreamId id)768   void set_stream_id(SpdyStreamId id) {
769     mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
770   }
771 
delta_window_size()772   uint32 delta_window_size() const {
773     return ntohl(block()->delta_window_size_);
774   }
775 
set_delta_window_size(uint32 delta_window_size)776   void set_delta_window_size(uint32 delta_window_size) {
777     mutable_block()->delta_window_size_ = htonl(delta_window_size);
778   }
779 
780   // Returns the size of the SpdyWindowUpdateControlFrameBlock structure.
781   // Note: this is not the size of the SpdyWindowUpdateControlFrame class.
size()782   static size_t size() { return sizeof(SpdyWindowUpdateControlFrameBlock); }
783 
784  private:
block()785   const struct SpdyWindowUpdateControlFrameBlock* block() const {
786     return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_);
787   }
mutable_block()788   struct SpdyWindowUpdateControlFrameBlock* mutable_block() {
789     return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_);
790   }
791 
792   DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateControlFrame);
793 };
794 
795 }  // namespace spdy
796 
797 #endif  // NET_SPDY_SPDY_PROTOCOL_H_
798