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