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