OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This file contains some protocol structures for use with Spdy. | 5 // This file contains some protocol structures for use with Spdy. |
6 | 6 |
7 #ifndef NET_SPDY_SPDY_PROTOCOL_H_ | 7 #ifndef NET_SPDY_SPDY_PROTOCOL_H_ |
8 #define NET_SPDY_SPDY_PROTOCOL_H_ | 8 #define NET_SPDY_SPDY_PROTOCOL_H_ |
9 | 9 |
10 #include <limits> | 10 #include <limits> |
| 11 #include <map> |
| 12 #include <vector> |
11 | 13 |
12 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
13 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/string_piece.h" |
14 #include "base/sys_byteorder.h" | 17 #include "base/sys_byteorder.h" |
15 #include "net/spdy/spdy_bitmasks.h" | 18 #include "net/spdy/spdy_bitmasks.h" |
16 | 19 |
17 // Data Frame Format | 20 // Data Frame Format |
18 // +----------------------------------+ | 21 // +----------------------------------+ |
19 // |0| Stream-ID (31bits) | | 22 // |0| Stream-ID (31bits) | |
20 // +----------------------------------+ | 23 // +----------------------------------+ |
21 // | flags (8) | Length (24 bits) | | 24 // | flags (8) | Length (24 bits) | |
22 // +----------------------------------+ | 25 // +----------------------------------+ |
23 // | Data | | 26 // | Data | |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // harset.i | 351 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // harset.i |
349 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // so-8859- | 352 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // so-8859- |
350 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1.utf-.. | 353 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1.utf-.. |
351 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // .enq.0. | 354 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // .enq.0. |
352 }; | 355 }; |
353 const int kV3DictionarySize = arraysize(kV3Dictionary); | 356 const int kV3DictionarySize = arraysize(kV3Dictionary); |
354 | 357 |
355 // Note: all protocol data structures are on-the-wire format. That means that | 358 // Note: all protocol data structures are on-the-wire format. That means that |
356 // data is stored in network-normalized order. Readers must use the | 359 // data is stored in network-normalized order. Readers must use the |
357 // accessors provided or call ntohX() functions. | 360 // accessors provided or call ntohX() functions. |
| 361 // TODO(hkhalil): remove above note. |
358 | 362 |
359 // Types of Spdy Control Frames. | 363 // Types of Spdy Control Frames. |
360 enum SpdyControlType { | 364 enum SpdyControlType { |
361 SYN_STREAM = 1, | 365 SYN_STREAM = 1, |
362 SYN_REPLY, | 366 SYN_REPLY, |
363 RST_STREAM, | 367 RST_STREAM, |
364 SETTINGS, | 368 SETTINGS, |
365 NOOP, // Because it is valid in SPDY/2, kept for identifiability/enum order. | 369 NOOP, // Because it is valid in SPDY/2, kept for identifiability/enum order. |
366 PING, | 370 PING, |
367 GOAWAY, | 371 GOAWAY, |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 }; | 442 }; |
439 | 443 |
440 // A SPDY stream id is a 31 bit entity. | 444 // A SPDY stream id is a 31 bit entity. |
441 typedef uint32 SpdyStreamId; | 445 typedef uint32 SpdyStreamId; |
442 | 446 |
443 // A SPDY priority is a number between 0 and 7 (inclusive). | 447 // A SPDY priority is a number between 0 and 7 (inclusive). |
444 // SPDY priority range is version-dependant. For SPDY 2 and below, priority is a | 448 // SPDY priority range is version-dependant. For SPDY 2 and below, priority is a |
445 // number between 0 and 3. | 449 // number between 0 and 3. |
446 typedef uint8 SpdyPriority; | 450 typedef uint8 SpdyPriority; |
447 | 451 |
| 452 typedef uint8 SpdyCredentialSlot; |
| 453 |
| 454 typedef std::map<std::string, std::string> SpdyNameValueBlock; |
| 455 |
| 456 typedef uint32 SpdyPingId; |
| 457 |
448 // ------------------------------------------------------------------------- | 458 // ------------------------------------------------------------------------- |
449 // These structures mirror the protocol structure definitions. | 459 // These structures mirror the protocol structure definitions. |
450 | 460 |
451 // For the control data structures, we pack so that sizes match the | 461 // For the control data structures, we pack so that sizes match the |
452 // protocol over-the-wire sizes. | 462 // protocol over-the-wire sizes. |
453 #pragma pack(push) | 463 #pragma pack(push) |
454 #pragma pack(1) | 464 #pragma pack(1) |
455 | 465 |
456 // A special structure for the 8 bit flags and 24 bit length fields. | 466 // A special structure for the 8 bit flags and 24 bit length fields. |
457 union FlagsAndLength { | 467 union FlagsAndLength { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 }; | 535 }; |
526 | 536 |
527 // A WINDOW_UPDATE Control Frame structure | 537 // A WINDOW_UPDATE Control Frame structure |
528 struct SpdyWindowUpdateControlFrameBlock : SpdyFrameBlock { | 538 struct SpdyWindowUpdateControlFrameBlock : SpdyFrameBlock { |
529 SpdyStreamId stream_id_; | 539 SpdyStreamId stream_id_; |
530 uint32 delta_window_size_; | 540 uint32 delta_window_size_; |
531 }; | 541 }; |
532 | 542 |
533 #pragma pack(pop) | 543 #pragma pack(pop) |
534 | 544 |
| 545 class SpdyFrame; |
| 546 typedef SpdyFrame SpdySerializedFrame; |
| 547 |
| 548 class SpdyFramer; |
| 549 class SpdyFrameBuilder; |
| 550 |
| 551 // Intermediate representation for SPDY frames. |
| 552 // TODO(hkhalil): Rename this class to SpdyFrame when the existing SpdyFrame is |
| 553 // gone. |
| 554 class SpdyFrameIR { |
| 555 public: |
| 556 virtual ~SpdyFrameIR() {} |
| 557 |
| 558 protected: |
| 559 SpdyFrameIR() {} |
| 560 |
| 561 private: |
| 562 DISALLOW_COPY_AND_ASSIGN(SpdyFrameIR); |
| 563 }; |
| 564 |
| 565 // Abstract class intended to be inherited by IRs that have a stream associated |
| 566 // to them. |
| 567 class SpdyFrameWithStreamIdIR : public SpdyFrameIR { |
| 568 public: |
| 569 virtual ~SpdyFrameWithStreamIdIR() {} |
| 570 SpdyStreamId stream_id() const { return stream_id_; } |
| 571 void set_stream_id(SpdyStreamId stream_id) { |
| 572 // TODO(hkhalil): DCHECK_LT(0u, stream_id); |
| 573 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
| 574 stream_id_ = stream_id; |
| 575 } |
| 576 |
| 577 protected: |
| 578 explicit SpdyFrameWithStreamIdIR(SpdyStreamId stream_id) { |
| 579 set_stream_id(stream_id); |
| 580 } |
| 581 |
| 582 private: |
| 583 SpdyStreamId stream_id_; |
| 584 |
| 585 DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithStreamIdIR); |
| 586 }; |
| 587 |
| 588 // Abstract class intended to be inherited by IRs that have the option of a FIN |
| 589 // flag. Implies SpdyFrameWithStreamIdIR. |
| 590 class SpdyFrameWithFinIR : public SpdyFrameWithStreamIdIR { |
| 591 public: |
| 592 virtual ~SpdyFrameWithFinIR() {} |
| 593 bool fin() const { return fin_; } |
| 594 void set_fin(bool fin) { fin_ = fin; } |
| 595 |
| 596 protected: |
| 597 explicit SpdyFrameWithFinIR(SpdyStreamId stream_id) |
| 598 : SpdyFrameWithStreamIdIR(stream_id), |
| 599 fin_(false) {} |
| 600 |
| 601 private: |
| 602 bool fin_; |
| 603 |
| 604 DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithFinIR); |
| 605 }; |
| 606 |
| 607 // Abstract class intended to be inherited by IRs that contain a name-value |
| 608 // block. Implies SpdyFrameWithFinIR. |
| 609 class SpdyFrameWithNameValueBlockIR : public SpdyFrameWithFinIR { |
| 610 public: |
| 611 const SpdyNameValueBlock& name_value_block() const { |
| 612 return name_value_block_; |
| 613 } |
| 614 SpdyNameValueBlock* GetMutableNameValueBlock() { return &name_value_block_; } |
| 615 |
| 616 protected: |
| 617 explicit SpdyFrameWithNameValueBlockIR(SpdyStreamId stream_id); |
| 618 virtual ~SpdyFrameWithNameValueBlockIR(); |
| 619 |
| 620 private: |
| 621 SpdyNameValueBlock name_value_block_; |
| 622 |
| 623 DISALLOW_COPY_AND_ASSIGN(SpdyFrameWithNameValueBlockIR); |
| 624 }; |
| 625 |
| 626 class SpdyDataIR : public SpdyFrameWithFinIR { |
| 627 public: |
| 628 SpdyDataIR(SpdyStreamId stream_id, const base::StringPiece& data) |
| 629 : SpdyFrameWithFinIR(stream_id) { |
| 630 set_data(data); |
| 631 } |
| 632 base::StringPiece data() const { return data_; } |
| 633 void set_data(const base::StringPiece& data) { data.CopyToString(&data_); } |
| 634 |
| 635 private: |
| 636 std::string data_; |
| 637 |
| 638 DISALLOW_COPY_AND_ASSIGN(SpdyDataIR); |
| 639 }; |
| 640 |
| 641 class SpdySynStreamIR : public SpdyFrameWithNameValueBlockIR { |
| 642 public: |
| 643 explicit SpdySynStreamIR(SpdyStreamId stream_id) |
| 644 : SpdyFrameWithNameValueBlockIR(stream_id), |
| 645 associated_to_stream_id_(0), |
| 646 priority_(0), |
| 647 slot_(0), |
| 648 unidirectional_(false) {} |
| 649 SpdyStreamId associated_to_stream_id() const { |
| 650 return associated_to_stream_id_; |
| 651 } |
| 652 void set_associated_to_stream_id(SpdyStreamId stream_id) { |
| 653 associated_to_stream_id_ = stream_id; |
| 654 } |
| 655 SpdyPriority priority() const { return priority_; } |
| 656 void set_priority(SpdyPriority priority) { priority_ = priority; } |
| 657 SpdyCredentialSlot slot() const { return slot_; } |
| 658 void set_slot(SpdyCredentialSlot slot) { slot_ = slot; } |
| 659 bool unidirectional() const { return unidirectional_; } |
| 660 void set_unidirectional(bool unidirectional) { |
| 661 unidirectional_ = unidirectional; |
| 662 } |
| 663 |
| 664 private: |
| 665 SpdyStreamId associated_to_stream_id_; |
| 666 SpdyPriority priority_; |
| 667 SpdyCredentialSlot slot_; |
| 668 bool unidirectional_; |
| 669 |
| 670 DISALLOW_COPY_AND_ASSIGN(SpdySynStreamIR); |
| 671 }; |
| 672 |
| 673 class SpdySynReplyIR : public SpdyFrameWithNameValueBlockIR { |
| 674 public: |
| 675 explicit SpdySynReplyIR(SpdyStreamId stream_id) |
| 676 : SpdyFrameWithNameValueBlockIR(stream_id) {} |
| 677 |
| 678 private: |
| 679 DISALLOW_COPY_AND_ASSIGN(SpdySynReplyIR); |
| 680 }; |
| 681 |
| 682 class SpdyRstStreamIR : public SpdyFrameWithStreamIdIR { |
| 683 public: |
| 684 SpdyRstStreamIR(SpdyStreamId stream_id, SpdyRstStreamStatus status) |
| 685 : SpdyFrameWithStreamIdIR(stream_id) { |
| 686 set_status(status); |
| 687 } |
| 688 SpdyRstStreamStatus status() const { |
| 689 return status_; |
| 690 } |
| 691 void set_status(SpdyRstStreamStatus status) { |
| 692 DCHECK_NE(status, RST_STREAM_INVALID); |
| 693 DCHECK_LT(status, RST_STREAM_NUM_STATUS_CODES); |
| 694 status_ = status; |
| 695 } |
| 696 |
| 697 private: |
| 698 SpdyRstStreamStatus status_; |
| 699 |
| 700 DISALLOW_COPY_AND_ASSIGN(SpdyRstStreamIR); |
| 701 }; |
| 702 |
| 703 class SpdySettingsIR : public SpdyFrameIR { |
| 704 public: |
| 705 // Associates flags with a value. |
| 706 struct Value { |
| 707 Value() : persist_value(false), |
| 708 persisted(false), |
| 709 value(0) {} |
| 710 bool persist_value; |
| 711 bool persisted; |
| 712 int32 value; |
| 713 }; |
| 714 typedef std::map<SpdySettingsIds, Value> ValueMap; |
| 715 |
| 716 SpdySettingsIR(); |
| 717 |
| 718 virtual ~SpdySettingsIR(); |
| 719 |
| 720 // Overwrites as appropriate. |
| 721 const ValueMap& values() const { return values_; } |
| 722 void AddSetting(SpdySettingsIds id, |
| 723 bool persist_value, |
| 724 bool persisted, |
| 725 int32 value) { |
| 726 // TODO(hkhalil): DCHECK_LE(SETTINGS_UPLOAD_BANDWIDTH, id); |
| 727 // TODO(hkhalil): DCHECK_GE(SETTINGS_INITIAL_WINDOW_SIZE, id); |
| 728 values_[id].persist_value = persist_value; |
| 729 values_[id].persisted = persisted; |
| 730 values_[id].value = value; |
| 731 } |
| 732 bool clear_settings() const { return clear_settings_; } |
| 733 void set_clear_settings(bool clear_settings) { |
| 734 clear_settings_ = clear_settings; |
| 735 } |
| 736 |
| 737 private: |
| 738 ValueMap values_; |
| 739 bool clear_settings_; |
| 740 |
| 741 DISALLOW_COPY_AND_ASSIGN(SpdySettingsIR); |
| 742 }; |
| 743 |
| 744 class SpdyPingIR : public SpdyFrameIR { |
| 745 public: |
| 746 explicit SpdyPingIR(SpdyPingId id) : id_(id) {} |
| 747 SpdyPingId id() const { return id_; } |
| 748 |
| 749 private: |
| 750 SpdyPingId id_; |
| 751 |
| 752 DISALLOW_COPY_AND_ASSIGN(SpdyPingIR); |
| 753 }; |
| 754 |
| 755 class SpdyGoAwayIR : public SpdyFrameIR { |
| 756 public: |
| 757 SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyGoAwayStatus status) { |
| 758 set_last_good_stream_id(last_good_stream_id); |
| 759 set_status(status); |
| 760 } |
| 761 SpdyStreamId last_good_stream_id() const { return last_good_stream_id_; } |
| 762 void set_last_good_stream_id(SpdyStreamId last_good_stream_id) { |
| 763 DCHECK_LE(0u, last_good_stream_id); |
| 764 DCHECK_EQ(0u, last_good_stream_id & ~kStreamIdMask); |
| 765 last_good_stream_id_ = last_good_stream_id; |
| 766 } |
| 767 SpdyGoAwayStatus status() const { return status_; } |
| 768 void set_status(SpdyGoAwayStatus status) { |
| 769 // TODO(hkhalil): Check valid ranges of status? |
| 770 status_ = status; |
| 771 } |
| 772 |
| 773 private: |
| 774 SpdyStreamId last_good_stream_id_; |
| 775 SpdyGoAwayStatus status_; |
| 776 |
| 777 DISALLOW_COPY_AND_ASSIGN(SpdyGoAwayIR); |
| 778 }; |
| 779 |
| 780 class SpdyHeadersIR : public SpdyFrameWithNameValueBlockIR { |
| 781 public: |
| 782 explicit SpdyHeadersIR(SpdyStreamId stream_id) |
| 783 : SpdyFrameWithNameValueBlockIR(stream_id) {} |
| 784 |
| 785 private: |
| 786 DISALLOW_COPY_AND_ASSIGN(SpdyHeadersIR); |
| 787 }; |
| 788 |
| 789 class SpdyWindowUpdateIR : public SpdyFrameWithStreamIdIR { |
| 790 public: |
| 791 SpdyWindowUpdateIR(SpdyStreamId stream_id, int32 delta) |
| 792 : SpdyFrameWithStreamIdIR(stream_id) { |
| 793 set_delta(delta); |
| 794 } |
| 795 int32 delta() const { return delta_; } |
| 796 void set_delta(int32 delta) { |
| 797 DCHECK_LT(0, delta); |
| 798 DCHECK_LE(delta, kSpdyStreamMaximumWindowSize); |
| 799 delta_ = delta; |
| 800 } |
| 801 |
| 802 private: |
| 803 int32 delta_; |
| 804 |
| 805 DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateIR); |
| 806 }; |
| 807 |
| 808 class SpdyCredentialIR : public SpdyFrameIR { |
| 809 public: |
| 810 typedef std::vector<std::string> CertificateList; |
| 811 |
| 812 explicit SpdyCredentialIR(int16 slot); |
| 813 virtual ~SpdyCredentialIR(); |
| 814 |
| 815 int16 slot() const { return slot_; } |
| 816 void set_slot(int16 slot) { |
| 817 // TODO(hkhalil): Verify valid slot range? |
| 818 slot_ = slot; |
| 819 } |
| 820 base::StringPiece proof() const { return proof_; } |
| 821 void set_proof(const base::StringPiece& proof) { |
| 822 proof.CopyToString(&proof_); |
| 823 } |
| 824 const CertificateList* certificates() const { return &certificates_; } |
| 825 void AddCertificate(const base::StringPiece& certificate) { |
| 826 certificates_.push_back(certificate.as_string()); |
| 827 } |
| 828 |
| 829 private: |
| 830 int16 slot_; |
| 831 std::string proof_; |
| 832 CertificateList certificates_; |
| 833 |
| 834 DISALLOW_COPY_AND_ASSIGN(SpdyCredentialIR); |
| 835 }; |
| 836 |
535 // ------------------------------------------------------------------------- | 837 // ------------------------------------------------------------------------- |
536 // Wrapper classes for various SPDY frames. | 838 // Wrapper classes for various SPDY frames. |
537 | 839 |
538 // All Spdy Frame types derive from this SpdyFrame class. | 840 // All Spdy Frame types derive from this SpdyFrame class. |
539 class SpdyFrame { | 841 class SpdyFrame { |
540 public: | 842 public: |
541 // Create a SpdyFrame for a given sized buffer. | 843 // Create a SpdyFrame for a given sized buffer. |
542 explicit SpdyFrame(size_t size) : frame_(NULL), owns_buffer_(true) { | 844 explicit SpdyFrame(size_t size) : frame_(NULL), owns_buffer_(true) { |
543 DCHECK_GE(size, sizeof(struct SpdyFrameBlock)); | 845 DCHECK_GE(size, sizeof(struct SpdyFrameBlock)); |
544 char* buffer = new char[size]; | 846 char* buffer = new char[size]; |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
724 | 1026 |
725 uint8 credential_slot() const { | 1027 uint8 credential_slot() const { |
726 if (version() < 3) { | 1028 if (version() < 3) { |
727 return 0; | 1029 return 0; |
728 } else { | 1030 } else { |
729 return block()->credential_slot_; | 1031 return block()->credential_slot_; |
730 } | 1032 } |
731 } | 1033 } |
732 | 1034 |
733 void set_credential_slot(uint8 credential_slot) { | 1035 void set_credential_slot(uint8 credential_slot) { |
734 DCHECK(version() >= 3); | 1036 DCHECK_LE(3, version()); |
735 mutable_block()->credential_slot_ = credential_slot; | 1037 mutable_block()->credential_slot_ = credential_slot; |
736 } | 1038 } |
737 | 1039 |
738 // The number of bytes in the header block beyond the frame header length. | 1040 // The number of bytes in the header block beyond the frame header length. |
739 int header_block_len() const { | 1041 int header_block_len() const { |
740 return length() - (size() - SpdyFrame::kHeaderSize); | 1042 return length() - (size() - SpdyFrame::kHeaderSize); |
741 } | 1043 } |
742 | 1044 |
743 const char* header_block() const { | 1045 const char* header_block() const { |
744 return reinterpret_cast<const char*>(block()) + size(); | 1046 return reinterpret_cast<const char*>(block()) + size(); |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 struct SpdyWindowUpdateControlFrameBlock* mutable_block() { | 1317 struct SpdyWindowUpdateControlFrameBlock* mutable_block() { |
1016 return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_); | 1318 return static_cast<SpdyWindowUpdateControlFrameBlock*>(frame_); |
1017 } | 1319 } |
1018 | 1320 |
1019 DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateControlFrame); | 1321 DISALLOW_COPY_AND_ASSIGN(SpdyWindowUpdateControlFrame); |
1020 }; | 1322 }; |
1021 | 1323 |
1022 } // namespace net | 1324 } // namespace net |
1023 | 1325 |
1024 #endif // NET_SPDY_SPDY_PROTOCOL_H_ | 1326 #endif // NET_SPDY_SPDY_PROTOCOL_H_ |
OLD | NEW |