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 { 300 SettingsFlagsAndId(uint32 val) : id_(val) {} 301 uint8 flags() const { return flags_[0]; } 302 void set_flags(uint8 flags) { flags_[0] = flags; } 303 uint32 id() const { return (ntohl(id_) & kSettingsIdMask); } 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. 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. 337 SpdyFrame(char* data, bool owns_buffer) 338 : frame_(reinterpret_cast<struct SpdyFrameBlock*>(data)), 339 owns_buffer_(owns_buffer) { 340 DCHECK(frame_); 341 } 342 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. 353 char* data() const { return reinterpret_cast<char*>(frame_); } 354 355 uint8 flags() const { return frame_->flags_length_.flags_[0]; } 356 void set_flags(uint8 flags) { frame_->flags_length_.flags_[0] = flags; } 357 358 uint32 length() const { 359 return ntohl(frame_->flags_length_.length_) & kLengthMask; 360 } 361 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 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). 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: 390 SpdyDataFrame() : SpdyFrame(size()) {} 391 SpdyDataFrame(char* data, bool owns_buffer) 392 : SpdyFrame(data, owns_buffer) {} 393 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. 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. 408 static size_t size() { return SpdyFrame::size(); } 409 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: 421 explicit SpdyControlFrame(size_t size) : SpdyFrame(size) {} 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. 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 433 uint16 version() const { 434 const int kVersionMask = 0x7fff; 435 return ntohs(block()->control_.version_) & kVersionMask; 436 } 437 438 void set_version(uint16 version) { 439 DCHECK_EQ(0u, version & kControlFlagMask); 440 mutable_block()->control_.version_ = htons(kControlFlagMask | version); 441 } 442 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 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. 456 static size_t size() { return sizeof(SpdyFrameBlock); } 457 458 private: 459 const struct SpdyFrameBlock* block() const { 460 return frame_; 461 } 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: 471 SpdySynStreamControlFrame() : SpdyControlFrame(size()) {} 472 SpdySynStreamControlFrame(char* data, bool owns_buffer) 473 : SpdyControlFrame(data, owns_buffer) {} 474 475 SpdyStreamId stream_id() const { 476 return ntohl(block()->stream_id_) & kStreamIdMask; 477 } 478 479 void set_stream_id(SpdyStreamId id) { 480 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 481 } 482 483 SpdyStreamId associated_stream_id() const { 484 return ntohl(block()->associated_stream_id_) & kStreamIdMask; 485 } 486 487 void set_associated_stream_id(SpdyStreamId id) { 488 mutable_block()->associated_stream_id_ = htonl(id & kStreamIdMask); 489 } 490 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. 496 int header_block_len() const { 497 return length() - (size() - SpdyFrame::size()); 498 } 499 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. 506 static size_t size() { return sizeof(SpdySynStreamControlFrameBlock); } 507 508 private: 509 const struct SpdySynStreamControlFrameBlock* block() const { 510 return static_cast<SpdySynStreamControlFrameBlock*>(frame_); 511 } 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: 521 SpdySynReplyControlFrame() : SpdyControlFrame(size()) {} 522 SpdySynReplyControlFrame(char* data, bool owns_buffer) 523 : SpdyControlFrame(data, owns_buffer) {} 524 525 SpdyStreamId stream_id() const { 526 return ntohl(block()->stream_id_) & kStreamIdMask; 527 } 528 529 void set_stream_id(SpdyStreamId id) { 530 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 531 } 532 533 int header_block_len() const { 534 return length() - (size() - SpdyFrame::size()); 535 } 536 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. 543 static size_t size() { return sizeof(SpdySynReplyControlFrameBlock); } 544 545 private: 546 const struct SpdySynReplyControlFrameBlock* block() const { 547 return static_cast<SpdySynReplyControlFrameBlock*>(frame_); 548 } 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: 558 SpdyRstStreamControlFrame() : SpdyControlFrame(size()) {} 559 SpdyRstStreamControlFrame(char* data, bool owns_buffer) 560 : SpdyControlFrame(data, owns_buffer) {} 561 562 SpdyStreamId stream_id() const { 563 return ntohl(block()->stream_id_) & kStreamIdMask; 564 } 565 566 void set_stream_id(SpdyStreamId id) { 567 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 568 } 569 570 SpdyStatusCodes status() const { 571 return static_cast<SpdyStatusCodes>(ntohl(block()->status_)); 572 } 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. 579 static size_t size() { return sizeof(SpdyRstStreamControlFrameBlock); } 580 581 private: 582 const struct SpdyRstStreamControlFrameBlock* block() const { 583 return static_cast<SpdyRstStreamControlFrameBlock*>(frame_); 584 } 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: 593 SpdySettingsControlFrame() : SpdyControlFrame(size()) {} 594 SpdySettingsControlFrame(char* data, bool owns_buffer) 595 : SpdyControlFrame(data, owns_buffer) {} 596 597 uint32 num_entries() const { 598 return ntohl(block()->num_entries_); 599 } 600 601 void set_num_entries(int val) { 602 mutable_block()->num_entries_ = htonl(val); 603 } 604 605 int header_block_len() const { 606 return length() - (size() - SpdyFrame::size()); 607 } 608 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. 615 static size_t size() { return sizeof(SpdySettingsControlFrameBlock); } 616 617 private: 618 const struct SpdySettingsControlFrameBlock* block() const { 619 return static_cast<SpdySettingsControlFrameBlock*>(frame_); 620 } 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: 629 SpdyGoAwayControlFrame() : SpdyControlFrame(size()) {} 630 SpdyGoAwayControlFrame(char* data, bool owns_buffer) 631 : SpdyControlFrame(data, owns_buffer) {} 632 633 SpdyStreamId last_accepted_stream_id() const { 634 return ntohl(block()->last_accepted_stream_id_) & kStreamIdMask; 635 } 636 637 void set_last_accepted_stream_id(SpdyStreamId id) { 638 mutable_block()->last_accepted_stream_id_ = htonl(id & kStreamIdMask); 639 } 640 641 static size_t size() { return sizeof(SpdyGoAwayControlFrameBlock); } 642 643 private: 644 const struct SpdyGoAwayControlFrameBlock* block() const { 645 return static_cast<SpdyGoAwayControlFrameBlock*>(frame_); 646 } 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: 656 SpdyHeadersControlFrame() : SpdyControlFrame(size()) {} 657 SpdyHeadersControlFrame(char* data, bool owns_buffer) 658 : SpdyControlFrame(data, owns_buffer) {} 659 660 SpdyStreamId stream_id() const { 661 return ntohl(block()->stream_id_) & kStreamIdMask; 662 } 663 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. 669 int header_block_len() const { 670 return length() - (size() - SpdyFrame::size()); 671 } 672 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. 679 static size_t size() { return sizeof(SpdyHeadersControlFrameBlock); } 680 681 private: 682 const struct SpdyHeadersControlFrameBlock* block() const { 683 return static_cast<SpdyHeadersControlFrameBlock*>(frame_); 684 } 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: 694 SpdyWindowUpdateControlFrame() : SpdyControlFrame(size()) {} 695 SpdyWindowUpdateControlFrame(char* data, bool owns_buffer) 696 : SpdyControlFrame(data, owns_buffer) {} 697 698 SpdyStreamId stream_id() const { 699 return ntohl(block()->stream_id_) & kStreamIdMask; 700 } 701 702 void set_stream_id(SpdyStreamId id) { 703 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 704 } 705 706 uint32 delta_window_size() const { 707 return ntohl(block()->delta_window_size_); 708 } 709 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. 716 static size_t size() { return sizeof(SpdyWindowUpdateControlFrameBlock); } 717 718 private: 719 const struct SpdyWindowUpdateControlFrameBlock* block() const { 720 return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_); 721 } 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