• 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   SETTINGS_ROUND_TRIP_TIME = 0x3,
195   SETTINGS_MAX_CONCURRENT_STREAMS = 0x4,
196   SETTINGS_CURRENT_CWND = 0x5,
197   // Downstream byte retransmission rate in percentage.
198   SETTINGS_DOWNLOAD_RETRANS_RATE = 0x6,
199   // Initial window size in bytes
200   SETTINGS_INITIAL_WINDOW_SIZE = 0x7
201 };
202 
203 // Status codes, as used in control frames (primarily RST_STREAM).
204 enum SpdyStatusCodes {
205   INVALID = 0,
206   PROTOCOL_ERROR = 1,
207   INVALID_STREAM = 2,
208   REFUSED_STREAM = 3,
209   UNSUPPORTED_VERSION = 4,
210   CANCEL = 5,
211   INTERNAL_ERROR = 6,
212   FLOW_CONTROL_ERROR = 7,
213   INVALID_ASSOCIATED_STREAM = 8,
214   NUM_STATUS_CODES = 9
215 };
216 
217 // A SPDY stream id is a 31 bit entity.
218 typedef uint32 SpdyStreamId;
219 
220 // A SPDY priority is a number between 0 and 3 (inclusive).
221 typedef uint8 SpdyPriority;
222 
223 // SPDY Priorities. (there are only 2 bits)
224 #define SPDY_PRIORITY_LOWEST 3
225 #define SPDY_PRIORITY_HIGHEST 0
226 
227 // -------------------------------------------------------------------------
228 // These structures mirror the protocol structure definitions.
229 
230 // For the control data structures, we pack so that sizes match the
231 // protocol over-the-wire sizes.
232 #pragma pack(push)
233 #pragma pack(1)
234 
235 // A special structure for the 8 bit flags and 24 bit length fields.
236 union FlagsAndLength {
237   uint8 flags_[4];  // 8 bits
238   uint32 length_;   // 24 bits
239 };
240 
241 // The basic SPDY Frame structure.
242 struct SpdyFrameBlock {
243   union {
244     struct {
245       uint16 version_;
246       uint16 type_;
247     } control_;
248     struct {
249       SpdyStreamId stream_id_;
250     } data_;
251   };
252   FlagsAndLength flags_length_;
253 };
254 
255 // A SYN_STREAM Control Frame structure.
256 struct SpdySynStreamControlFrameBlock : SpdyFrameBlock {
257   SpdyStreamId stream_id_;
258   SpdyStreamId associated_stream_id_;
259   SpdyPriority priority_;
260   uint8 unused_;
261 };
262 
263 // A SYN_REPLY Control Frame structure.
264 struct SpdySynReplyControlFrameBlock : SpdyFrameBlock {
265   SpdyStreamId stream_id_;
266   uint16 unused_;
267 };
268 
269 // A RST_STREAM Control Frame structure.
270 struct SpdyRstStreamControlFrameBlock : SpdyFrameBlock {
271   SpdyStreamId stream_id_;
272   uint32 status_;
273 };
274 
275 // A SETTINGS Control Frame structure.
276 struct SpdySettingsControlFrameBlock : SpdyFrameBlock {
277   uint32 num_entries_;
278   // Variable data here.
279 };
280 
281 // A GOAWAY Control Frame structure.
282 struct SpdyGoAwayControlFrameBlock : SpdyFrameBlock {
283   SpdyStreamId last_accepted_stream_id_;
284 };
285 
286 // A HEADERS Control Frame structure.
287 struct SpdyHeadersControlFrameBlock : SpdyFrameBlock {
288   SpdyStreamId stream_id_;
289   uint16 unused_;
290 };
291 
292 // A WINDOW_UPDATE Control Frame structure
293 struct SpdyWindowUpdateControlFrameBlock : SpdyFrameBlock {
294   SpdyStreamId stream_id_;
295   uint32 delta_window_size_;
296 };
297 
298 // A structure for the 8 bit flags and 24 bit ID fields.
299 union SettingsFlagsAndId {
SettingsFlagsAndId(uint32 val)300   SettingsFlagsAndId(uint32 val) : id_(val) {}
flags()301   uint8 flags() const { return flags_[0]; }
set_flags(uint8 flags)302   void set_flags(uint8 flags) { flags_[0] = flags; }
id()303   uint32 id() const { return (ntohl(id_) & kSettingsIdMask); }
set_id(uint32 id)304   void set_id(uint32 id) {
305     DCHECK_EQ(0u, (id & ~kSettingsIdMask));
306     id = htonl(id & kSettingsIdMask);
307     id_ = flags() | id;
308   }
309 
310   uint8 flags_[4];  // 8 bits
311   uint32 id_;       // 24 bits
312 };
313 
314 #pragma pack(pop)
315 
316 // -------------------------------------------------------------------------
317 // Wrapper classes for various SPDY frames.
318 
319 // All Spdy Frame types derive from this SpdyFrame class.
320 class SpdyFrame {
321  public:
322   // Create a SpdyFrame for a given sized buffer.
SpdyFrame(size_t size)323   explicit SpdyFrame(size_t size) : frame_(NULL), owns_buffer_(true) {
324     DCHECK_GE(size, sizeof(struct SpdyFrameBlock));
325     char* buffer = new char[size];
326     memset(buffer, 0, size);
327     frame_ = reinterpret_cast<struct SpdyFrameBlock*>(buffer);
328   }
329 
330   // Create a SpdyFrame using a pre-created buffer.
331   // If |owns_buffer| is true, this class takes ownership of the buffer
332   // and will delete it on cleanup.  The buffer must have been created using
333   // new char[].
334   // If |owns_buffer| is false, the caller retains ownership of the buffer and
335   // is responsible for making sure the buffer outlives this frame.  In other
336   // words, this class does NOT create a copy of the buffer.
SpdyFrame(char * data,bool owns_buffer)337   SpdyFrame(char* data, bool owns_buffer)
338       : frame_(reinterpret_cast<struct SpdyFrameBlock*>(data)),
339         owns_buffer_(owns_buffer) {
340     DCHECK(frame_);
341   }
342 
~SpdyFrame()343   ~SpdyFrame() {
344     if (owns_buffer_) {
345       char* buffer = reinterpret_cast<char*>(frame_);
346       delete [] buffer;
347     }
348     frame_ = NULL;
349   }
350 
351   // Provides access to the frame bytes, which is a buffer containing
352   // the frame packed as expected for sending over the wire.
data()353   char* data() const { return reinterpret_cast<char*>(frame_); }
354 
flags()355   uint8 flags() const { return frame_->flags_length_.flags_[0]; }
set_flags(uint8 flags)356   void set_flags(uint8 flags) { frame_->flags_length_.flags_[0] = flags; }
357 
length()358   uint32 length() const {
359     return ntohl(frame_->flags_length_.length_) & kLengthMask;
360   }
361 
set_length(uint32 length)362   void set_length(uint32 length) {
363     DCHECK_EQ(0u, (length & ~kLengthMask));
364     length = htonl(length & kLengthMask);
365     frame_->flags_length_.length_ = flags() | length;
366   }
367 
is_control_frame()368   bool is_control_frame() const {
369     return (ntohs(frame_->control_.version_) & kControlFlagMask) ==
370         kControlFlagMask;
371   }
372 
373   // Returns the size of the SpdyFrameBlock structure.
374   // Every SpdyFrame* class has a static size() method for accessing
375   // the size of the data structure which will be sent over the wire.
376   // Note:  this is not the same as sizeof(SpdyFrame).
size()377   static size_t size() { return sizeof(struct SpdyFrameBlock); }
378 
379  protected:
380   SpdyFrameBlock* frame_;
381 
382  private:
383   bool owns_buffer_;
384   DISALLOW_COPY_AND_ASSIGN(SpdyFrame);
385 };
386 
387 // A Data Frame.
388 class SpdyDataFrame : public SpdyFrame {
389  public:
SpdyDataFrame()390   SpdyDataFrame() : SpdyFrame(size()) {}
SpdyDataFrame(char * data,bool owns_buffer)391   SpdyDataFrame(char* data, bool owns_buffer)
392       : SpdyFrame(data, owns_buffer) {}
393 
stream_id()394   SpdyStreamId stream_id() const {
395     return ntohl(frame_->data_.stream_id_) & kStreamIdMask;
396   }
397 
398   // Note that setting the stream id sets the control bit to false.
399   // As stream id should always be set, this means the control bit
400   // should always be set correctly.
set_stream_id(SpdyStreamId id)401   void set_stream_id(SpdyStreamId id) {
402     DCHECK_EQ(0u, (id & ~kStreamIdMask));
403     frame_->data_.stream_id_ = htonl(id & kStreamIdMask);
404   }
405 
406   // Returns the size of the SpdyFrameBlock structure.
407   // Note: this is not the size of the SpdyDataFrame class.
size()408   static size_t size() { return SpdyFrame::size(); }
409 
payload()410   const char* payload() const {
411     return reinterpret_cast<const char*>(frame_) + size();
412   }
413 
414  private:
415   DISALLOW_COPY_AND_ASSIGN(SpdyDataFrame);
416 };
417 
418 // A Control Frame.
419 class SpdyControlFrame : public SpdyFrame {
420  public:
SpdyControlFrame(size_t size)421   explicit SpdyControlFrame(size_t size) : SpdyFrame(size) {}
SpdyControlFrame(char * data,bool owns_buffer)422   SpdyControlFrame(char* data, bool owns_buffer)
423       : SpdyFrame(data, owns_buffer) {}
424 
425   // Callers can use this method to check if the frame appears to be a valid
426   // frame.  Does not guarantee that there are no errors.
AppearsToBeAValidControlFrame()427   bool AppearsToBeAValidControlFrame() const {
428     // Right now we only check if the frame has an out-of-bounds type.
429     uint16 type = ntohs(block()->control_.type_);
430     return (type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES);
431   }
432 
version()433   uint16 version() const {
434     const int kVersionMask = 0x7fff;
435     return ntohs(block()->control_.version_) & kVersionMask;
436   }
437 
set_version(uint16 version)438   void set_version(uint16 version) {
439     DCHECK_EQ(0u, version & kControlFlagMask);
440     mutable_block()->control_.version_ = htons(kControlFlagMask | version);
441   }
442 
type()443   SpdyControlType type() const {
444     uint16 type = ntohs(block()->control_.type_);
445     DCHECK(type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES);
446     return static_cast<SpdyControlType>(type);
447   }
448 
set_type(SpdyControlType type)449   void set_type(SpdyControlType type) {
450     DCHECK(type >= SYN_STREAM && type < NUM_CONTROL_FRAME_TYPES);
451     mutable_block()->control_.type_ = htons(type);
452   }
453 
454   // Returns the size of the SpdyFrameBlock structure.
455   // Note: this is not the size of the SpdyControlFrame class.
size()456   static size_t size() { return sizeof(SpdyFrameBlock); }
457 
458  private:
block()459   const struct SpdyFrameBlock* block() const {
460     return frame_;
461   }
mutable_block()462   struct SpdyFrameBlock* mutable_block() {
463     return frame_;
464   }
465   DISALLOW_COPY_AND_ASSIGN(SpdyControlFrame);
466 };
467 
468 // A SYN_STREAM frame.
469 class SpdySynStreamControlFrame : public SpdyControlFrame {
470  public:
SpdySynStreamControlFrame()471   SpdySynStreamControlFrame() : SpdyControlFrame(size()) {}
SpdySynStreamControlFrame(char * data,bool owns_buffer)472   SpdySynStreamControlFrame(char* data, bool owns_buffer)
473       : SpdyControlFrame(data, owns_buffer) {}
474 
stream_id()475   SpdyStreamId stream_id() const {
476     return ntohl(block()->stream_id_) & kStreamIdMask;
477   }
478 
set_stream_id(SpdyStreamId id)479   void set_stream_id(SpdyStreamId id) {
480     mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
481   }
482 
associated_stream_id()483   SpdyStreamId associated_stream_id() const {
484     return ntohl(block()->associated_stream_id_) & kStreamIdMask;
485   }
486 
set_associated_stream_id(SpdyStreamId id)487   void set_associated_stream_id(SpdyStreamId id) {
488     mutable_block()->associated_stream_id_ = htonl(id & kStreamIdMask);
489   }
490 
priority()491   SpdyPriority priority() const {
492     return (block()->priority_ & kPriorityMask) >> 6;
493   }
494 
495   // The number of bytes in the header block beyond the frame header length.
header_block_len()496   int header_block_len() const {
497     return length() - (size() - SpdyFrame::size());
498   }
499 
header_block()500   const char* header_block() const {
501     return reinterpret_cast<const char*>(block()) + size();
502   }
503 
504   // Returns the size of the SpdySynStreamControlFrameBlock structure.
505   // Note: this is not the size of the SpdySynStreamControlFrame class.
size()506   static size_t size() { return sizeof(SpdySynStreamControlFrameBlock); }
507 
508  private:
block()509   const struct SpdySynStreamControlFrameBlock* block() const {
510     return static_cast<SpdySynStreamControlFrameBlock*>(frame_);
511   }
mutable_block()512   struct SpdySynStreamControlFrameBlock* mutable_block() {
513     return static_cast<SpdySynStreamControlFrameBlock*>(frame_);
514   }
515   DISALLOW_COPY_AND_ASSIGN(SpdySynStreamControlFrame);
516 };
517 
518 // A SYN_REPLY frame.
519 class SpdySynReplyControlFrame : public SpdyControlFrame {
520  public:
SpdySynReplyControlFrame()521   SpdySynReplyControlFrame() : SpdyControlFrame(size()) {}
SpdySynReplyControlFrame(char * data,bool owns_buffer)522   SpdySynReplyControlFrame(char* data, bool owns_buffer)
523       : SpdyControlFrame(data, owns_buffer) {}
524 
stream_id()525   SpdyStreamId stream_id() const {
526     return ntohl(block()->stream_id_) & kStreamIdMask;
527   }
528 
set_stream_id(SpdyStreamId id)529   void set_stream_id(SpdyStreamId id) {
530     mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
531   }
532 
header_block_len()533   int header_block_len() const {
534     return length() - (size() - SpdyFrame::size());
535   }
536 
header_block()537   const char* header_block() const {
538     return reinterpret_cast<const char*>(block()) + size();
539   }
540 
541   // Returns the size of the SpdySynReplyControlFrameBlock structure.
542   // Note: this is not the size of the SpdySynReplyControlFrame class.
size()543   static size_t size() { return sizeof(SpdySynReplyControlFrameBlock); }
544 
545  private:
block()546   const struct SpdySynReplyControlFrameBlock* block() const {
547     return static_cast<SpdySynReplyControlFrameBlock*>(frame_);
548   }
mutable_block()549   struct SpdySynReplyControlFrameBlock* mutable_block() {
550     return static_cast<SpdySynReplyControlFrameBlock*>(frame_);
551   }
552   DISALLOW_COPY_AND_ASSIGN(SpdySynReplyControlFrame);
553 };
554 
555 // A RST_STREAM frame.
556 class SpdyRstStreamControlFrame : public SpdyControlFrame {
557  public:
SpdyRstStreamControlFrame()558   SpdyRstStreamControlFrame() : SpdyControlFrame(size()) {}
SpdyRstStreamControlFrame(char * data,bool owns_buffer)559   SpdyRstStreamControlFrame(char* data, bool owns_buffer)
560       : SpdyControlFrame(data, owns_buffer) {}
561 
stream_id()562   SpdyStreamId stream_id() const {
563     return ntohl(block()->stream_id_) & kStreamIdMask;
564   }
565 
set_stream_id(SpdyStreamId id)566   void set_stream_id(SpdyStreamId id) {
567     mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
568   }
569 
status()570   SpdyStatusCodes status() const {
571     return static_cast<SpdyStatusCodes>(ntohl(block()->status_));
572   }
set_status(SpdyStatusCodes status)573   void set_status(SpdyStatusCodes status) {
574     mutable_block()->status_ = htonl(static_cast<uint32>(status));
575   }
576 
577   // Returns the size of the SpdyRstStreamControlFrameBlock structure.
578   // Note: this is not the size of the SpdyRstStreamControlFrame class.
size()579   static size_t size() { return sizeof(SpdyRstStreamControlFrameBlock); }
580 
581  private:
block()582   const struct SpdyRstStreamControlFrameBlock* block() const {
583     return static_cast<SpdyRstStreamControlFrameBlock*>(frame_);
584   }
mutable_block()585   struct SpdyRstStreamControlFrameBlock* mutable_block() {
586     return static_cast<SpdyRstStreamControlFrameBlock*>(frame_);
587   }
588   DISALLOW_COPY_AND_ASSIGN(SpdyRstStreamControlFrame);
589 };
590 
591 class SpdySettingsControlFrame : public SpdyControlFrame {
592  public:
SpdySettingsControlFrame()593   SpdySettingsControlFrame() : SpdyControlFrame(size()) {}
SpdySettingsControlFrame(char * data,bool owns_buffer)594   SpdySettingsControlFrame(char* data, bool owns_buffer)
595       : SpdyControlFrame(data, owns_buffer) {}
596 
num_entries()597   uint32 num_entries() const {
598     return ntohl(block()->num_entries_);
599   }
600 
set_num_entries(int val)601   void set_num_entries(int val) {
602     mutable_block()->num_entries_ = htonl(val);
603   }
604 
header_block_len()605   int header_block_len() const {
606     return length() - (size() - SpdyFrame::size());
607   }
608 
header_block()609   const char* header_block() const {
610     return reinterpret_cast<const char*>(block()) + size();
611   }
612 
613   // Returns the size of the SpdySettingsControlFrameBlock structure.
614   // Note: this is not the size of the SpdySettingsControlFrameBlock class.
size()615   static size_t size() { return sizeof(SpdySettingsControlFrameBlock); }
616 
617  private:
block()618   const struct SpdySettingsControlFrameBlock* block() const {
619     return static_cast<SpdySettingsControlFrameBlock*>(frame_);
620   }
mutable_block()621   struct SpdySettingsControlFrameBlock* mutable_block() {
622     return static_cast<SpdySettingsControlFrameBlock*>(frame_);
623   }
624   DISALLOW_COPY_AND_ASSIGN(SpdySettingsControlFrame);
625 };
626 
627 class SpdyGoAwayControlFrame : public SpdyControlFrame {
628  public:
SpdyGoAwayControlFrame()629   SpdyGoAwayControlFrame() : SpdyControlFrame(size()) {}
SpdyGoAwayControlFrame(char * data,bool owns_buffer)630   SpdyGoAwayControlFrame(char* data, bool owns_buffer)
631       : SpdyControlFrame(data, owns_buffer) {}
632 
last_accepted_stream_id()633   SpdyStreamId last_accepted_stream_id() const {
634     return ntohl(block()->last_accepted_stream_id_) & kStreamIdMask;
635   }
636 
set_last_accepted_stream_id(SpdyStreamId id)637   void set_last_accepted_stream_id(SpdyStreamId id) {
638     mutable_block()->last_accepted_stream_id_ = htonl(id & kStreamIdMask);
639   }
640 
size()641   static size_t size() { return sizeof(SpdyGoAwayControlFrameBlock); }
642 
643  private:
block()644   const struct SpdyGoAwayControlFrameBlock* block() const {
645     return static_cast<SpdyGoAwayControlFrameBlock*>(frame_);
646   }
mutable_block()647   struct SpdyGoAwayControlFrameBlock* mutable_block() {
648     return static_cast<SpdyGoAwayControlFrameBlock*>(frame_);
649   }
650   DISALLOW_COPY_AND_ASSIGN(SpdyGoAwayControlFrame);
651 };
652 
653 // A HEADERS frame.
654 class SpdyHeadersControlFrame : public SpdyControlFrame {
655  public:
SpdyHeadersControlFrame()656   SpdyHeadersControlFrame() : SpdyControlFrame(size()) {}
SpdyHeadersControlFrame(char * data,bool owns_buffer)657   SpdyHeadersControlFrame(char* data, bool owns_buffer)
658       : SpdyControlFrame(data, owns_buffer) {}
659 
stream_id()660   SpdyStreamId stream_id() const {
661     return ntohl(block()->stream_id_) & kStreamIdMask;
662   }
663 
set_stream_id(SpdyStreamId id)664   void set_stream_id(SpdyStreamId id) {
665     mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
666   }
667 
668   // The number of bytes in the header block beyond the frame header length.
header_block_len()669   int header_block_len() const {
670     return length() - (size() - SpdyFrame::size());
671   }
672 
header_block()673   const char* header_block() const {
674     return reinterpret_cast<const char*>(block()) + size();
675   }
676 
677   // Returns the size of the SpdyHeadersControlFrameBlock structure.
678   // Note: this is not the size of the SpdyHeadersControlFrame class.
size()679   static size_t size() { return sizeof(SpdyHeadersControlFrameBlock); }
680 
681  private:
block()682   const struct SpdyHeadersControlFrameBlock* block() const {
683     return static_cast<SpdyHeadersControlFrameBlock*>(frame_);
684   }
mutable_block()685   struct SpdyHeadersControlFrameBlock* mutable_block() {
686     return static_cast<SpdyHeadersControlFrameBlock*>(frame_);
687   }
688   DISALLOW_COPY_AND_ASSIGN(SpdyHeadersControlFrame);
689 };
690 
691 // A WINDOW_UPDATE frame.
692 class SpdyWindowUpdateControlFrame : public SpdyControlFrame {
693  public:
SpdyWindowUpdateControlFrame()694   SpdyWindowUpdateControlFrame() : SpdyControlFrame(size()) {}
SpdyWindowUpdateControlFrame(char * data,bool owns_buffer)695   SpdyWindowUpdateControlFrame(char* data, bool owns_buffer)
696       : SpdyControlFrame(data, owns_buffer) {}
697 
stream_id()698   SpdyStreamId stream_id() const {
699     return ntohl(block()->stream_id_) & kStreamIdMask;
700   }
701 
set_stream_id(SpdyStreamId id)702   void set_stream_id(SpdyStreamId id) {
703     mutable_block()->stream_id_ = htonl(id & kStreamIdMask);
704   }
705 
delta_window_size()706   uint32 delta_window_size() const {
707     return ntohl(block()->delta_window_size_);
708   }
709 
set_delta_window_size(uint32 delta_window_size)710   void set_delta_window_size(uint32 delta_window_size) {
711     mutable_block()->delta_window_size_ = htonl(delta_window_size);
712   }
713 
714   // Returns the size of the SpdyWindowUpdateControlFrameBlock structure.
715   // Note: this is not the size of the SpdyWindowUpdateControlFrame class.
size()716   static size_t size() { return sizeof(SpdyWindowUpdateControlFrameBlock); }
717 
718  private:
block()719   const struct SpdyWindowUpdateControlFrameBlock* block() const {
720     return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_);
721   }
mutable_block()722   struct SpdyWindowUpdateControlFrameBlock* mutable_block() {
723     return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_);
724   }
725 
726   DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateControlFrame);
727 };
728 
729 }  // namespace spdy
730 
731 #endif  // NET_SPDY_SPDY_PROTOCOL_H_
732