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 312 SettingsFlagsAndId(uint32 val) : id_(val) {} 313 uint8 flags() const { return flags_[0]; } 314 void set_flags(uint8 flags) { flags_[0] = flags; } 315 uint32 id() const { return (ntohl(id_) & kSettingsIdMask); } 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. 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. 349 SpdyFrame(char* data, bool owns_buffer) 350 : frame_(reinterpret_cast<struct SpdyFrameBlock*>(data)), 351 owns_buffer_(owns_buffer) { 352 DCHECK(frame_); 353 } 354 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. 365 char* data() const { return reinterpret_cast<char*>(frame_); } 366 367 uint8 flags() const { return frame_->flags_length_.flags_[0]; } 368 void set_flags(uint8 flags) { frame_->flags_length_.flags_[0] = flags; } 369 370 uint32 length() const { 371 return ntohl(frame_->flags_length_.length_) & kLengthMask; 372 } 373 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 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). 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: 402 SpdyDataFrame() : SpdyFrame(size()) {} 403 SpdyDataFrame(char* data, bool owns_buffer) 404 : SpdyFrame(data, owns_buffer) {} 405 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. 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. 420 static size_t size() { return SpdyFrame::size(); } 421 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: 433 explicit SpdyControlFrame(size_t size) : SpdyFrame(size) {} 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. 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 445 uint16 version() const { 446 const int kVersionMask = 0x7fff; 447 return ntohs(block()->control_.version_) & kVersionMask; 448 } 449 450 void set_version(uint16 version) { 451 DCHECK_EQ(0u, version & kControlFlagMask); 452 mutable_block()->control_.version_ = htons(kControlFlagMask | version); 453 } 454 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 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. 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. 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: 486 const struct SpdyFrameBlock* block() const { 487 return frame_; 488 } 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: 498 SpdySynStreamControlFrame() : SpdyControlFrame(size()) {} 499 SpdySynStreamControlFrame(char* data, bool owns_buffer) 500 : SpdyControlFrame(data, owns_buffer) {} 501 502 SpdyStreamId stream_id() const { 503 return ntohl(block()->stream_id_) & kStreamIdMask; 504 } 505 506 void set_stream_id(SpdyStreamId id) { 507 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 508 } 509 510 SpdyStreamId associated_stream_id() const { 511 return ntohl(block()->associated_stream_id_) & kStreamIdMask; 512 } 513 514 void set_associated_stream_id(SpdyStreamId id) { 515 mutable_block()->associated_stream_id_ = htonl(id & kStreamIdMask); 516 } 517 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. 523 int header_block_len() const { 524 return length() - (size() - SpdyFrame::size()); 525 } 526 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. 533 static size_t size() { return sizeof(SpdySynStreamControlFrameBlock); } 534 535 private: 536 const struct SpdySynStreamControlFrameBlock* block() const { 537 return static_cast<SpdySynStreamControlFrameBlock*>(frame_); 538 } 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: 548 SpdySynReplyControlFrame() : SpdyControlFrame(size()) {} 549 SpdySynReplyControlFrame(char* data, bool owns_buffer) 550 : SpdyControlFrame(data, owns_buffer) {} 551 552 SpdyStreamId stream_id() const { 553 return ntohl(block()->stream_id_) & kStreamIdMask; 554 } 555 556 void set_stream_id(SpdyStreamId id) { 557 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 558 } 559 560 int header_block_len() const { 561 return length() - (size() - SpdyFrame::size()); 562 } 563 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. 570 static size_t size() { return sizeof(SpdySynReplyControlFrameBlock); } 571 572 private: 573 const struct SpdySynReplyControlFrameBlock* block() const { 574 return static_cast<SpdySynReplyControlFrameBlock*>(frame_); 575 } 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: 585 SpdyRstStreamControlFrame() : SpdyControlFrame(size()) {} 586 SpdyRstStreamControlFrame(char* data, bool owns_buffer) 587 : SpdyControlFrame(data, owns_buffer) {} 588 589 SpdyStreamId stream_id() const { 590 return ntohl(block()->stream_id_) & kStreamIdMask; 591 } 592 593 void set_stream_id(SpdyStreamId id) { 594 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 595 } 596 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 } 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. 611 static size_t size() { return sizeof(SpdyRstStreamControlFrameBlock); } 612 613 private: 614 const struct SpdyRstStreamControlFrameBlock* block() const { 615 return static_cast<SpdyRstStreamControlFrameBlock*>(frame_); 616 } 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: 625 SpdySettingsControlFrame() : SpdyControlFrame(size()) {} 626 SpdySettingsControlFrame(char* data, bool owns_buffer) 627 : SpdyControlFrame(data, owns_buffer) {} 628 629 uint32 num_entries() const { 630 return ntohl(block()->num_entries_); 631 } 632 633 void set_num_entries(int val) { 634 mutable_block()->num_entries_ = htonl(val); 635 } 636 637 int header_block_len() const { 638 return length() - (size() - SpdyFrame::size()); 639 } 640 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. 647 static size_t size() { return sizeof(SpdySettingsControlFrameBlock); } 648 649 private: 650 const struct SpdySettingsControlFrameBlock* block() const { 651 return static_cast<SpdySettingsControlFrameBlock*>(frame_); 652 } 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: 661 SpdyNoOpControlFrame() : SpdyControlFrame(size()) {} 662 SpdyNoOpControlFrame(char* data, bool owns_buffer) 663 : SpdyControlFrame(data, owns_buffer) {} 664 665 static size_t size() { return sizeof(SpdyNoopControlFrameBlock); } 666 }; 667 668 class SpdyPingControlFrame : public SpdyControlFrame { 669 public: 670 SpdyPingControlFrame() : SpdyControlFrame(size()) {} 671 SpdyPingControlFrame(char* data, bool owns_buffer) 672 : SpdyControlFrame(data, owns_buffer) {} 673 674 uint32 unique_id() const { 675 return ntohl(block()->unique_id_); 676 } 677 678 void set_unique_id(uint32 unique_id) { 679 mutable_block()->unique_id_ = htonl(unique_id); 680 } 681 682 static size_t size() { return sizeof(SpdyPingControlFrameBlock); } 683 684 private: 685 const struct SpdyPingControlFrameBlock* block() const { 686 return static_cast<SpdyPingControlFrameBlock*>(frame_); 687 } 688 struct SpdyPingControlFrameBlock* mutable_block() { 689 return static_cast<SpdyPingControlFrameBlock*>(frame_); 690 } 691 }; 692 693 class SpdyGoAwayControlFrame : public SpdyControlFrame { 694 public: 695 SpdyGoAwayControlFrame() : SpdyControlFrame(size()) {} 696 SpdyGoAwayControlFrame(char* data, bool owns_buffer) 697 : SpdyControlFrame(data, owns_buffer) {} 698 699 SpdyStreamId last_accepted_stream_id() const { 700 return ntohl(block()->last_accepted_stream_id_) & kStreamIdMask; 701 } 702 703 void set_last_accepted_stream_id(SpdyStreamId id) { 704 mutable_block()->last_accepted_stream_id_ = htonl(id & kStreamIdMask); 705 } 706 707 static size_t size() { return sizeof(SpdyGoAwayControlFrameBlock); } 708 709 private: 710 const struct SpdyGoAwayControlFrameBlock* block() const { 711 return static_cast<SpdyGoAwayControlFrameBlock*>(frame_); 712 } 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: 722 SpdyHeadersControlFrame() : SpdyControlFrame(size()) {} 723 SpdyHeadersControlFrame(char* data, bool owns_buffer) 724 : SpdyControlFrame(data, owns_buffer) {} 725 726 SpdyStreamId stream_id() const { 727 return ntohl(block()->stream_id_) & kStreamIdMask; 728 } 729 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. 735 int header_block_len() const { 736 return length() - (size() - SpdyFrame::size()); 737 } 738 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. 745 static size_t size() { return sizeof(SpdyHeadersControlFrameBlock); } 746 747 private: 748 const struct SpdyHeadersControlFrameBlock* block() const { 749 return static_cast<SpdyHeadersControlFrameBlock*>(frame_); 750 } 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: 760 SpdyWindowUpdateControlFrame() : SpdyControlFrame(size()) {} 761 SpdyWindowUpdateControlFrame(char* data, bool owns_buffer) 762 : SpdyControlFrame(data, owns_buffer) {} 763 764 SpdyStreamId stream_id() const { 765 return ntohl(block()->stream_id_) & kStreamIdMask; 766 } 767 768 void set_stream_id(SpdyStreamId id) { 769 mutable_block()->stream_id_ = htonl(id & kStreamIdMask); 770 } 771 772 uint32 delta_window_size() const { 773 return ntohl(block()->delta_window_size_); 774 } 775 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. 782 static size_t size() { return sizeof(SpdyWindowUpdateControlFrameBlock); } 783 784 private: 785 const struct SpdyWindowUpdateControlFrameBlock* block() const { 786 return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_); 787 } 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