1 // Copyright (c) 2012 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 #include "net/spdy/spdy_protocol.h" 6 7 namespace net { 8 9 SpdyFrameWithNameValueBlockIR::SpdyFrameWithNameValueBlockIR( 10 SpdyStreamId stream_id) : SpdyFrameWithFinIR(stream_id) {} 11 12 SpdyFrameWithNameValueBlockIR::~SpdyFrameWithNameValueBlockIR() {} 13 14 SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id, const base::StringPiece& data) 15 : SpdyFrameWithFinIR(stream_id), 16 pad_low_(false), 17 pad_high_(false), 18 padding_payload_len_(0) { 19 SetDataDeep(data); 20 } 21 22 SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id) 23 : SpdyFrameWithFinIR(stream_id), 24 pad_low_(false), 25 pad_high_(false), 26 padding_payload_len_(0) {} 27 28 SpdyDataIR::~SpdyDataIR() {} 29 30 bool SpdyConstants::IsValidFrameType(SpdyMajorVersion version, 31 int frame_type_field) { 32 switch (version) { 33 case SPDY2: 34 case SPDY3: 35 // SYN_STREAM is the first valid frame. 36 if (frame_type_field < SerializeFrameType(version, SYN_STREAM)) { 37 return false; 38 } 39 40 // WINDOW_UPDATE is the last valid frame. 41 if (frame_type_field > SerializeFrameType(version, WINDOW_UPDATE)) { 42 return false; 43 } 44 45 // The valid range is non-contiguous. 46 if (frame_type_field == NOOP) { 47 return false; 48 } 49 50 return true; 51 case SPDY4: 52 case SPDY5: 53 // DATA is the first valid frame. 54 if (frame_type_field < SerializeFrameType(version, DATA)) { 55 return false; 56 } 57 58 // BLOCKED is the last valid frame. 59 if (frame_type_field > SerializeFrameType(version, BLOCKED)) { 60 return false; 61 } 62 63 return true; 64 } 65 66 LOG(DFATAL) << "Unhandled SPDY version " << version; 67 return false; 68 } 69 70 SpdyFrameType SpdyConstants::ParseFrameType(SpdyMajorVersion version, 71 int frame_type_field) { 72 switch (version) { 73 case SPDY2: 74 case SPDY3: 75 switch (frame_type_field) { 76 case 1: 77 return SYN_STREAM; 78 case 2: 79 return SYN_REPLY; 80 case 3: 81 return RST_STREAM; 82 case 4: 83 return SETTINGS; 84 case 6: 85 return PING; 86 case 7: 87 return GOAWAY; 88 case 8: 89 return HEADERS; 90 case 9: 91 return WINDOW_UPDATE; 92 } 93 break; 94 case SPDY4: 95 case SPDY5: 96 switch (frame_type_field) { 97 case 0: 98 return DATA; 99 case 1: 100 return HEADERS; 101 case 2: 102 return PRIORITY; 103 case 3: 104 return RST_STREAM; 105 case 4: 106 return SETTINGS; 107 case 5: 108 return PUSH_PROMISE; 109 case 6: 110 return PING; 111 case 7: 112 return GOAWAY; 113 case 8: 114 return WINDOW_UPDATE; 115 case 9: 116 return CONTINUATION; 117 case 10: 118 return ALTSVC; 119 case 11: 120 return BLOCKED; 121 } 122 break; 123 } 124 125 LOG(DFATAL) << "Unhandled frame type " << frame_type_field; 126 return DATA; 127 } 128 129 int SpdyConstants::SerializeFrameType(SpdyMajorVersion version, 130 SpdyFrameType frame_type) { 131 switch (version) { 132 case SPDY2: 133 case SPDY3: 134 switch (frame_type) { 135 case SYN_STREAM: 136 return 1; 137 case SYN_REPLY: 138 return 2; 139 case RST_STREAM: 140 return 3; 141 case SETTINGS: 142 return 4; 143 case PING: 144 return 6; 145 case GOAWAY: 146 return 7; 147 case HEADERS: 148 return 8; 149 case WINDOW_UPDATE: 150 return 9; 151 default: 152 LOG(DFATAL) << "Serializing unhandled frame type " << frame_type; 153 return -1; 154 } 155 case SPDY4: 156 case SPDY5: 157 switch (frame_type) { 158 case DATA: 159 return 0; 160 case HEADERS: 161 return 1; 162 case PRIORITY: 163 return 2; 164 case RST_STREAM: 165 return 3; 166 case SETTINGS: 167 return 4; 168 case PUSH_PROMISE: 169 return 5; 170 case PING: 171 return 6; 172 case GOAWAY: 173 return 7; 174 case WINDOW_UPDATE: 175 return 8; 176 case CONTINUATION: 177 return 9; 178 case ALTSVC: 179 return 10; 180 case BLOCKED: 181 return 11; 182 default: 183 LOG(DFATAL) << "Serializing unhandled frame type " << frame_type; 184 return -1; 185 } 186 } 187 188 LOG(DFATAL) << "Unhandled SPDY version " << version; 189 return -1; 190 } 191 192 bool SpdyConstants::IsValidSettingId(SpdyMajorVersion version, 193 int setting_id_field) { 194 switch (version) { 195 case SPDY2: 196 case SPDY3: 197 // UPLOAD_BANDWIDTH is the first valid setting id. 198 if (setting_id_field < 199 SerializeSettingId(version, SETTINGS_UPLOAD_BANDWIDTH)) { 200 return false; 201 } 202 203 // INITIAL_WINDOW_SIZE is the last valid setting id. 204 if (setting_id_field > 205 SerializeSettingId(version, SETTINGS_INITIAL_WINDOW_SIZE)) { 206 return false; 207 } 208 209 return true; 210 case SPDY4: 211 case SPDY5: 212 // HEADER_TABLE_SIZE is the first valid setting id. 213 if (setting_id_field < 214 SerializeSettingId(version, SETTINGS_HEADER_TABLE_SIZE)) { 215 return false; 216 } 217 218 // COMPRESS_DATA is the last valid setting id. 219 if (setting_id_field > 220 SerializeSettingId(version, SETTINGS_COMPRESS_DATA)) { 221 return false; 222 } 223 224 return true; 225 } 226 227 LOG(DFATAL) << "Unhandled SPDY version " << version; 228 return false; 229 } 230 231 SpdySettingsIds SpdyConstants::ParseSettingId(SpdyMajorVersion version, 232 int setting_id_field) { 233 switch (version) { 234 case SPDY2: 235 case SPDY3: 236 switch (setting_id_field) { 237 case 1: 238 return SETTINGS_UPLOAD_BANDWIDTH; 239 case 2: 240 return SETTINGS_DOWNLOAD_BANDWIDTH; 241 case 3: 242 return SETTINGS_ROUND_TRIP_TIME; 243 case 4: 244 return SETTINGS_MAX_CONCURRENT_STREAMS; 245 case 5: 246 return SETTINGS_CURRENT_CWND; 247 case 6: 248 return SETTINGS_DOWNLOAD_RETRANS_RATE; 249 case 7: 250 return SETTINGS_INITIAL_WINDOW_SIZE; 251 } 252 break; 253 case SPDY4: 254 case SPDY5: 255 switch (setting_id_field) { 256 case 1: 257 return SETTINGS_HEADER_TABLE_SIZE; 258 case 2: 259 return SETTINGS_ENABLE_PUSH; 260 case 3: 261 return SETTINGS_MAX_CONCURRENT_STREAMS; 262 case 4: 263 return SETTINGS_INITIAL_WINDOW_SIZE; 264 case 5: 265 return SETTINGS_COMPRESS_DATA; 266 } 267 break; 268 } 269 270 LOG(DFATAL) << "Unhandled setting ID " << setting_id_field; 271 return SETTINGS_UPLOAD_BANDWIDTH; 272 } 273 274 int SpdyConstants::SerializeSettingId(SpdyMajorVersion version, 275 SpdySettingsIds id) { 276 switch (version) { 277 case SPDY2: 278 case SPDY3: 279 switch (id) { 280 case SETTINGS_UPLOAD_BANDWIDTH: 281 return 1; 282 case SETTINGS_DOWNLOAD_BANDWIDTH: 283 return 2; 284 case SETTINGS_ROUND_TRIP_TIME: 285 return 3; 286 case SETTINGS_MAX_CONCURRENT_STREAMS: 287 return 4; 288 case SETTINGS_CURRENT_CWND: 289 return 5; 290 case SETTINGS_DOWNLOAD_RETRANS_RATE: 291 return 6; 292 case SETTINGS_INITIAL_WINDOW_SIZE: 293 return 7; 294 default: 295 LOG(DFATAL) << "Serializing unhandled setting id " << id; 296 return -1; 297 } 298 case SPDY4: 299 case SPDY5: 300 switch (id) { 301 case SETTINGS_HEADER_TABLE_SIZE: 302 return 1; 303 case SETTINGS_ENABLE_PUSH: 304 return 2; 305 case SETTINGS_MAX_CONCURRENT_STREAMS: 306 return 3; 307 case SETTINGS_INITIAL_WINDOW_SIZE: 308 return 4; 309 case SETTINGS_COMPRESS_DATA: 310 return 5; 311 default: 312 LOG(DFATAL) << "Serializing unhandled setting id " << id; 313 return -1; 314 } 315 } 316 LOG(DFATAL) << "Unhandled SPDY version " << version; 317 return -1; 318 } 319 320 bool SpdyConstants::IsValidRstStreamStatus(SpdyMajorVersion version, 321 int rst_stream_status_field) { 322 switch (version) { 323 case SPDY2: 324 case SPDY3: 325 // PROTOCOL_ERROR is the valid first status code. 326 if (rst_stream_status_field < 327 SerializeRstStreamStatus(version, RST_STREAM_PROTOCOL_ERROR)) { 328 return false; 329 } 330 331 // FRAME_TOO_LARGE is the valid last status code. 332 if (rst_stream_status_field > 333 SerializeRstStreamStatus(version, RST_STREAM_FRAME_TOO_LARGE)) { 334 return false; 335 } 336 337 return true; 338 case SPDY4: 339 case SPDY5: 340 // NO_ERROR is the first valid status code. 341 if (rst_stream_status_field < 342 SerializeRstStreamStatus(version, RST_STREAM_PROTOCOL_ERROR)) { 343 return false; 344 } 345 346 // TODO(hkhalil): Omit COMPRESSION_ERROR and SETTINGS_TIMEOUT 347 /* 348 // This works because GOAWAY and RST_STREAM share a namespace. 349 if (rst_stream_status_field == 350 SerializeGoAwayStatus(version, GOAWAY_COMPRESSION_ERROR) || 351 rst_stream_status_field == 352 SerializeGoAwayStatus(version, GOAWAY_SETTINGS_TIMEOUT)) { 353 return false; 354 } 355 */ 356 357 // ENHANCE_YOUR_CALM is the last valid status code. 358 if (rst_stream_status_field > 359 SerializeRstStreamStatus(version, RST_STREAM_ENHANCE_YOUR_CALM)) { 360 return false; 361 } 362 363 return true; 364 } 365 LOG(DFATAL) << "Unhandled SPDY version " << version; 366 return false; 367 } 368 369 SpdyRstStreamStatus SpdyConstants::ParseRstStreamStatus( 370 SpdyMajorVersion version, 371 int rst_stream_status_field) { 372 switch (version) { 373 case SPDY2: 374 case SPDY3: 375 switch (rst_stream_status_field) { 376 case 1: 377 return RST_STREAM_PROTOCOL_ERROR; 378 case 2: 379 return RST_STREAM_INVALID_STREAM; 380 case 3: 381 return RST_STREAM_REFUSED_STREAM; 382 case 4: 383 return RST_STREAM_UNSUPPORTED_VERSION; 384 case 5: 385 return RST_STREAM_CANCEL; 386 case 6: 387 return RST_STREAM_INTERNAL_ERROR; 388 case 7: 389 return RST_STREAM_FLOW_CONTROL_ERROR; 390 case 8: 391 return RST_STREAM_STREAM_IN_USE; 392 case 9: 393 return RST_STREAM_STREAM_ALREADY_CLOSED; 394 case 10: 395 return RST_STREAM_INVALID_CREDENTIALS; 396 case 11: 397 return RST_STREAM_FRAME_TOO_LARGE; 398 } 399 break; 400 case SPDY4: 401 case SPDY5: 402 switch (rst_stream_status_field) { 403 case 1: 404 return RST_STREAM_PROTOCOL_ERROR; 405 case 2: 406 return RST_STREAM_INTERNAL_ERROR; 407 case 3: 408 return RST_STREAM_FLOW_CONTROL_ERROR; 409 case 5: 410 return RST_STREAM_STREAM_CLOSED; 411 case 6: 412 return RST_STREAM_FRAME_SIZE_ERROR; 413 case 7: 414 return RST_STREAM_REFUSED_STREAM; 415 case 8: 416 return RST_STREAM_CANCEL; 417 case 10: 418 return RST_STREAM_CONNECT_ERROR; 419 case 11: 420 return RST_STREAM_ENHANCE_YOUR_CALM; 421 } 422 break; 423 } 424 425 LOG(DFATAL) << "Invalid RST_STREAM status " << rst_stream_status_field; 426 return RST_STREAM_PROTOCOL_ERROR; 427 } 428 429 int SpdyConstants::SerializeRstStreamStatus( 430 SpdyMajorVersion version, 431 SpdyRstStreamStatus rst_stream_status) { 432 switch (version) { 433 case SPDY2: 434 case SPDY3: 435 switch (rst_stream_status) { 436 case RST_STREAM_PROTOCOL_ERROR: 437 return 1; 438 case RST_STREAM_INVALID_STREAM: 439 return 2; 440 case RST_STREAM_REFUSED_STREAM: 441 return 3; 442 case RST_STREAM_UNSUPPORTED_VERSION: 443 return 4; 444 case RST_STREAM_CANCEL: 445 return 5; 446 case RST_STREAM_INTERNAL_ERROR: 447 return 6; 448 case RST_STREAM_FLOW_CONTROL_ERROR: 449 return 7; 450 case RST_STREAM_STREAM_IN_USE: 451 return 8; 452 case RST_STREAM_STREAM_ALREADY_CLOSED: 453 return 9; 454 case RST_STREAM_INVALID_CREDENTIALS: 455 return 10; 456 case RST_STREAM_FRAME_TOO_LARGE: 457 return 11; 458 default: 459 LOG(DFATAL) << "Unhandled RST_STREAM status " 460 << rst_stream_status; 461 return -1; 462 } 463 case SPDY4: 464 case SPDY5: 465 switch (rst_stream_status) { 466 case RST_STREAM_PROTOCOL_ERROR: 467 return 1; 468 case RST_STREAM_INTERNAL_ERROR: 469 return 2; 470 case RST_STREAM_FLOW_CONTROL_ERROR: 471 return 3; 472 case RST_STREAM_STREAM_CLOSED: 473 return 5; 474 case RST_STREAM_FRAME_SIZE_ERROR: 475 return 6; 476 case RST_STREAM_REFUSED_STREAM: 477 return 7; 478 case RST_STREAM_CANCEL: 479 return 8; 480 case RST_STREAM_CONNECT_ERROR: 481 return 10; 482 case RST_STREAM_ENHANCE_YOUR_CALM: 483 return 11; 484 default: 485 LOG(DFATAL) << "Unhandled RST_STREAM status " 486 << rst_stream_status; 487 return -1; 488 } 489 } 490 LOG(DFATAL) << "Unhandled SPDY version " << version; 491 return -1; 492 } 493 494 bool SpdyConstants::IsValidGoAwayStatus(SpdyMajorVersion version, 495 int goaway_status_field) { 496 switch (version) { 497 case SPDY2: 498 case SPDY3: 499 // GOAWAY_OK is the first valid status. 500 if (goaway_status_field < SerializeGoAwayStatus(version, GOAWAY_OK)) { 501 return false; 502 } 503 504 // GOAWAY_INTERNAL_ERROR is the last valid status. 505 if (goaway_status_field > SerializeGoAwayStatus(version, 506 GOAWAY_INTERNAL_ERROR)) { 507 return false; 508 } 509 510 return true; 511 case SPDY4: 512 case SPDY5: 513 // GOAWAY_NO_ERROR is the first valid status. 514 if (goaway_status_field < SerializeGoAwayStatus(version, 515 GOAWAY_NO_ERROR)) { 516 return false; 517 } 518 519 // GOAWAY_INADEQUATE_SECURITY is the last valid status. 520 if (goaway_status_field > 521 SerializeGoAwayStatus(version, GOAWAY_INADEQUATE_SECURITY)) { 522 return false; 523 } 524 525 return true; 526 } 527 LOG(DFATAL) << "Unknown SpdyMajorVersion " << version; 528 return false; 529 } 530 531 SpdyGoAwayStatus SpdyConstants::ParseGoAwayStatus(SpdyMajorVersion version, 532 int goaway_status_field) { 533 switch (version) { 534 case SPDY2: 535 case SPDY3: 536 switch (goaway_status_field) { 537 case 0: 538 return GOAWAY_OK; 539 case 1: 540 return GOAWAY_PROTOCOL_ERROR; 541 case 2: 542 return GOAWAY_INTERNAL_ERROR; 543 } 544 break; 545 case SPDY4: 546 case SPDY5: 547 switch (goaway_status_field) { 548 case 0: 549 return GOAWAY_NO_ERROR; 550 case 1: 551 return GOAWAY_PROTOCOL_ERROR; 552 case 2: 553 return GOAWAY_INTERNAL_ERROR; 554 case 3: 555 return GOAWAY_FLOW_CONTROL_ERROR; 556 case 4: 557 return GOAWAY_SETTINGS_TIMEOUT; 558 case 5: 559 return GOAWAY_STREAM_CLOSED; 560 case 6: 561 return GOAWAY_FRAME_SIZE_ERROR; 562 case 7: 563 return GOAWAY_REFUSED_STREAM; 564 case 8: 565 return GOAWAY_CANCEL; 566 case 9: 567 return GOAWAY_COMPRESSION_ERROR; 568 case 10: 569 return GOAWAY_CONNECT_ERROR; 570 case 11: 571 return GOAWAY_ENHANCE_YOUR_CALM; 572 case 12: 573 return GOAWAY_INADEQUATE_SECURITY; 574 } 575 break; 576 } 577 578 LOG(DFATAL) << "Unhandled GOAWAY status " << goaway_status_field; 579 return GOAWAY_PROTOCOL_ERROR; 580 } 581 582 SpdyMajorVersion SpdyConstants::ParseMajorVersion(int version_number) { 583 switch (version_number) { 584 case 2: 585 return SPDY2; 586 case 3: 587 return SPDY3; 588 case 4: 589 return SPDY4; 590 case 5: 591 return SPDY5; 592 default: 593 LOG(DFATAL) << "Unsupported SPDY version number: " << version_number; 594 return SPDY3; 595 } 596 } 597 598 int SpdyConstants::SerializeMajorVersion(SpdyMajorVersion version) { 599 switch (version) { 600 case SPDY2: 601 return 2; 602 case SPDY3: 603 return 3; 604 case SPDY4: 605 return 4; 606 case SPDY5: 607 return 5; 608 default: 609 LOG(DFATAL) << "Unsupported SPDY major version: " << version; 610 return -1; 611 } 612 } 613 614 std::string SpdyConstants::GetVersionString(SpdyMajorVersion version) { 615 switch (version) { 616 case SPDY2: 617 return "spdy/2"; 618 case SPDY3: 619 return "spdy/3"; 620 case SPDY4: 621 return "spdy/4"; 622 case SPDY5: 623 return "spdy/5"; 624 default: 625 LOG(DFATAL) << "Unsupported SPDY major version: " << version; 626 return "spdy/3"; 627 } 628 } 629 630 int SpdyConstants::SerializeGoAwayStatus(SpdyMajorVersion version, 631 SpdyGoAwayStatus status) { 632 switch (version) { 633 case SPDY2: 634 case SPDY3: 635 // TODO(jgraettinger): Merge this back to server-side. 636 switch (status) { 637 case GOAWAY_NO_ERROR: 638 return 0; 639 case GOAWAY_PROTOCOL_ERROR: 640 case GOAWAY_INTERNAL_ERROR: 641 case GOAWAY_FLOW_CONTROL_ERROR: 642 case GOAWAY_SETTINGS_TIMEOUT: 643 case GOAWAY_STREAM_CLOSED: 644 case GOAWAY_FRAME_SIZE_ERROR: 645 case GOAWAY_REFUSED_STREAM: 646 case GOAWAY_CANCEL: 647 case GOAWAY_COMPRESSION_ERROR: 648 case GOAWAY_CONNECT_ERROR: 649 case GOAWAY_ENHANCE_YOUR_CALM: 650 case GOAWAY_INADEQUATE_SECURITY: 651 return 1; // PROTOCOL_ERROR. 652 default: 653 LOG(DFATAL) << "Serializing unhandled GOAWAY status " << status; 654 return -1; 655 } 656 case SPDY4: 657 case SPDY5: 658 switch (status) { 659 case GOAWAY_NO_ERROR: 660 return 0; 661 case GOAWAY_PROTOCOL_ERROR: 662 return 1; 663 case GOAWAY_INTERNAL_ERROR: 664 return 2; 665 case GOAWAY_FLOW_CONTROL_ERROR: 666 return 3; 667 case GOAWAY_SETTINGS_TIMEOUT: 668 return 4; 669 case GOAWAY_STREAM_CLOSED: 670 return 5; 671 case GOAWAY_FRAME_SIZE_ERROR: 672 return 6; 673 case GOAWAY_REFUSED_STREAM: 674 return 7; 675 case GOAWAY_CANCEL: 676 return 8; 677 case GOAWAY_COMPRESSION_ERROR: 678 return 9; 679 case GOAWAY_CONNECT_ERROR: 680 return 10; 681 case GOAWAY_ENHANCE_YOUR_CALM: 682 return 11; 683 case GOAWAY_INADEQUATE_SECURITY: 684 return 12; 685 default: 686 LOG(DFATAL) << "Serializing unhandled GOAWAY status " << status; 687 return -1; 688 } 689 } 690 LOG(DFATAL) << "Unknown SpdyMajorVersion " << version; 691 return -1; 692 } 693 694 size_t SpdyConstants::GetDataFrameMinimumSize() { 695 return 8; 696 } 697 698 size_t SpdyConstants::GetControlFrameHeaderSize(SpdyMajorVersion version) { 699 switch (version) { 700 case SPDY2: 701 case SPDY3: 702 case SPDY4: 703 case SPDY5: 704 return 8; 705 } 706 LOG(DFATAL) << "Unhandled SPDY version."; 707 return 0; 708 } 709 710 size_t SpdyConstants::GetPrefixLength(SpdyFrameType type, 711 SpdyMajorVersion version) { 712 if (type != DATA) { 713 return GetControlFrameHeaderSize(version); 714 } else { 715 return GetDataFrameMinimumSize(); 716 } 717 } 718 719 size_t SpdyConstants::GetFrameMaximumSize(SpdyMajorVersion version) { 720 if (version < SPDY4) { 721 // 24-bit length field plus eight-byte frame header. 722 return ((1<<24) - 1) + 8; 723 } else { 724 // 14-bit length field. 725 return (1<<14) - 1; 726 } 727 } 728 729 size_t SpdyConstants::GetSizeOfSizeField(SpdyMajorVersion version) { 730 return (version < SPDY3) ? sizeof(uint16) : sizeof(uint32); 731 } 732 733 void SpdyDataIR::Visit(SpdyFrameVisitor* visitor) const { 734 return visitor->VisitData(*this); 735 } 736 737 void SpdySynStreamIR::Visit(SpdyFrameVisitor* visitor) const { 738 return visitor->VisitSynStream(*this); 739 } 740 741 void SpdySynReplyIR::Visit(SpdyFrameVisitor* visitor) const { 742 return visitor->VisitSynReply(*this); 743 } 744 745 SpdyRstStreamIR::SpdyRstStreamIR(SpdyStreamId stream_id, 746 SpdyRstStreamStatus status, 747 base::StringPiece description) 748 : SpdyFrameWithStreamIdIR(stream_id), 749 description_(description) { 750 set_status(status); 751 } 752 753 SpdyRstStreamIR::~SpdyRstStreamIR() {} 754 755 void SpdyRstStreamIR::Visit(SpdyFrameVisitor* visitor) const { 756 return visitor->VisitRstStream(*this); 757 } 758 759 SpdySettingsIR::SpdySettingsIR() 760 : clear_settings_(false), 761 is_ack_(false) {} 762 763 SpdySettingsIR::~SpdySettingsIR() {} 764 765 void SpdySettingsIR::Visit(SpdyFrameVisitor* visitor) const { 766 return visitor->VisitSettings(*this); 767 } 768 769 void SpdyPingIR::Visit(SpdyFrameVisitor* visitor) const { 770 return visitor->VisitPing(*this); 771 } 772 773 SpdyGoAwayIR::SpdyGoAwayIR(SpdyStreamId last_good_stream_id, 774 SpdyGoAwayStatus status, 775 const base::StringPiece& description) 776 : description_(description) { 777 set_last_good_stream_id(last_good_stream_id); 778 set_status(status); 779 } 780 781 SpdyGoAwayIR::~SpdyGoAwayIR() {} 782 783 const base::StringPiece& SpdyGoAwayIR::description() const { 784 return description_; 785 } 786 787 void SpdyGoAwayIR::Visit(SpdyFrameVisitor* visitor) const { 788 return visitor->VisitGoAway(*this); 789 } 790 791 void SpdyHeadersIR::Visit(SpdyFrameVisitor* visitor) const { 792 return visitor->VisitHeaders(*this); 793 } 794 795 void SpdyWindowUpdateIR::Visit(SpdyFrameVisitor* visitor) const { 796 return visitor->VisitWindowUpdate(*this); 797 } 798 799 void SpdyBlockedIR::Visit(SpdyFrameVisitor* visitor) const { 800 return visitor->VisitBlocked(*this); 801 } 802 803 void SpdyPushPromiseIR::Visit(SpdyFrameVisitor* visitor) const { 804 return visitor->VisitPushPromise(*this); 805 } 806 807 void SpdyContinuationIR::Visit(SpdyFrameVisitor* visitor) const { 808 return visitor->VisitContinuation(*this); 809 } 810 811 SpdyAltSvcIR::SpdyAltSvcIR(SpdyStreamId stream_id) 812 : SpdyFrameWithStreamIdIR(stream_id), 813 max_age_(0), 814 port_(0) {} 815 816 void SpdyAltSvcIR::Visit(SpdyFrameVisitor* visitor) const { 817 return visitor->VisitAltSvc(*this); 818 } 819 820 } // namespace net 821