| 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 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't | 5 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't |
| 6 // constantly adding and subtracting header sizes; this is ugly and error- | 6 // constantly adding and subtracting header sizes; this is ugly and error- |
| 7 // prone. | 7 // prone. |
| 8 | 8 |
| 9 #include "net/spdy/spdy_framer.h" | 9 #include "net/spdy/spdy_framer.h" |
| 10 | 10 |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 case SPDY2: | 164 case SPDY2: |
| 165 case SPDY3: | 165 case SPDY3: |
| 166 case SPDY4: | 166 case SPDY4: |
| 167 return 8; | 167 return 8; |
| 168 } | 168 } |
| 169 LOG(DFATAL) << "Unhandled SPDY version."; | 169 LOG(DFATAL) << "Unhandled SPDY version."; |
| 170 return 0; | 170 return 0; |
| 171 } | 171 } |
| 172 | 172 |
| 173 size_t SpdyFramer::GetSynStreamMinimumSize() const { | 173 size_t SpdyFramer::GetSynStreamMinimumSize() const { |
| 174 if (spdy_version_ >= SPDY4) |
| 175 return GetSynReplyMinimumSize(); |
| 176 |
| 177 DCHECK_LT(spdy_version_, SPDY4); |
| 174 // Size, in bytes, of a SYN_STREAM frame not including the variable-length | 178 // Size, in bytes, of a SYN_STREAM frame not including the variable-length |
| 175 // name-value block. | 179 // name-value block. |
| 176 if (spdy_version_ < 4) { | 180 // Calculated as: |
| 177 // Calculated as: | 181 // control frame header + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot) |
| 178 // control frame header + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot) | 182 return GetControlFrameHeaderSize() + 10; |
| 179 return GetControlFrameHeaderSize() + 10; | |
| 180 } else { | |
| 181 // Calculated as: | |
| 182 // frame prefix + 4 (associated stream ID) + 1 (priority) + 1 (slot) | |
| 183 return GetControlFrameHeaderSize() + 6; | |
| 184 } | |
| 185 } | 183 } |
| 186 | 184 |
| 187 size_t SpdyFramer::GetSynReplyMinimumSize() const { | 185 size_t SpdyFramer::GetSynReplyMinimumSize() const { |
| 188 // Size, in bytes, of a SYN_REPLY frame not including the variable-length | 186 // Size, in bytes, of a SYN_REPLY frame not including the variable-length |
| 189 // name-value block. | 187 // name-value block. |
| 190 size_t size = GetControlFrameHeaderSize(); | 188 size_t size = GetControlFrameHeaderSize(); |
| 191 if (spdy_version_ < 4) { | 189 if (spdy_version_ < 4) { |
| 192 // Calculated as: | 190 // Calculated as: |
| 193 // control frame header + 4 (stream IDs) | 191 // control frame header + 4 (stream IDs) |
| 194 size += 4; | 192 size += 4; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 209 // control frame header + 4 (stream id) + 4 (status code) | 207 // control frame header + 4 (stream id) + 4 (status code) |
| 210 return GetControlFrameHeaderSize() + 8; | 208 return GetControlFrameHeaderSize() + 8; |
| 211 } else { | 209 } else { |
| 212 // Calculated as: | 210 // Calculated as: |
| 213 // frame prefix + 4 (status code) | 211 // frame prefix + 4 (status code) |
| 214 return GetControlFrameHeaderSize() + 4; | 212 return GetControlFrameHeaderSize() + 4; |
| 215 } | 213 } |
| 216 } | 214 } |
| 217 | 215 |
| 218 size_t SpdyFramer::GetSettingsMinimumSize() const { | 216 size_t SpdyFramer::GetSettingsMinimumSize() const { |
| 219 // Size, in bytes, of a SETTINGS frame not including the IDs and values | 217 if (spdy_version_ < 4) { |
| 220 // from the variable-length value block. Calculated as: | 218 // Size, in bytes, of a SETTINGS frame not including the IDs and values |
| 221 // control frame header + 4 (number of ID/value pairs) | 219 // from the variable-length value block. Calculated as: |
| 222 return GetControlFrameHeaderSize() + 4; | 220 // control frame header + 4 (number of ID/value pairs) |
| 221 return GetControlFrameHeaderSize() + 4; |
| 222 } else { |
| 223 return GetControlFrameHeaderSize(); |
| 224 } |
| 223 } | 225 } |
| 224 | 226 |
| 225 size_t SpdyFramer::GetPingSize() const { | 227 size_t SpdyFramer::GetPingSize() const { |
| 226 // Size, in bytes, of this PING frame. Calculated as: | 228 // Size, in bytes, of this PING frame. Calculated as: |
| 227 // control frame header + 4 (id) | 229 // control frame header + 4 (id) (or 8 for SPDY4) |
| 228 return GetControlFrameHeaderSize() + 4; | 230 if (spdy_version_ < SPDY4) { |
| 231 return GetControlFrameHeaderSize() + 4; |
| 232 } else { |
| 233 return GetControlFrameHeaderSize() + 8; |
| 234 } |
| 229 } | 235 } |
| 230 | 236 |
| 231 size_t SpdyFramer::GetGoAwaySize() const { | 237 size_t SpdyFramer::GetGoAwaySize() const { |
| 232 // Size, in bytes, of this GOAWAY frame. Calculated as: | 238 // Size, in bytes, of this GOAWAY frame. Calculated as: |
| 233 // control frame header + 4 (last good stream id) | 239 // control frame header + 4 (last good stream id) |
| 234 size_t size = GetControlFrameHeaderSize() + 4; | 240 size_t size = GetControlFrameHeaderSize() + 4; |
| 235 | 241 |
| 236 // SPDY 3+ GOAWAY frames also contain a status. | 242 // SPDY 3+ GOAWAY frames also contain a status. |
| 237 if (protocol_version() >= 3) { | 243 if (protocol_version() >= 3) { |
| 238 size += 4; | 244 size += 4; |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 uint32 length_field = 0; | 590 uint32 length_field = 0; |
| 585 successful_read = reader->ReadUInt24(&length_field); | 591 successful_read = reader->ReadUInt24(&length_field); |
| 586 DCHECK(successful_read); | 592 DCHECK(successful_read); |
| 587 remaining_data_length_ = length_field; | 593 remaining_data_length_ = length_field; |
| 588 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed(); | 594 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed(); |
| 589 } else { | 595 } else { |
| 590 version = protocol_version(); | 596 version = protocol_version(); |
| 591 uint16 length_field = 0; | 597 uint16 length_field = 0; |
| 592 bool successful_read = reader->ReadUInt16(&length_field); | 598 bool successful_read = reader->ReadUInt16(&length_field); |
| 593 DCHECK(successful_read); | 599 DCHECK(successful_read); |
| 594 current_frame_length_ = length_field; | |
| 595 | 600 |
| 596 uint8 control_frame_type_field_uint8 = DATA; | 601 uint8 control_frame_type_field_uint8 = DATA; |
| 597 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8); | 602 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8); |
| 598 DCHECK(successful_read); | 603 DCHECK(successful_read); |
| 599 // We check control_frame_type_field's validity in | 604 // We check control_frame_type_field's validity in |
| 600 // ProcessControlFrameHeader(). | 605 // ProcessControlFrameHeader(). |
| 601 control_frame_type_field = control_frame_type_field_uint8; | 606 control_frame_type_field = control_frame_type_field_uint8; |
| 602 is_control_frame = (control_frame_type_field != DATA); | 607 is_control_frame = (control_frame_type_field != DATA); |
| 603 | 608 |
| 604 successful_read = reader->ReadUInt8(¤t_frame_flags_); | 609 successful_read = reader->ReadUInt8(¤t_frame_flags_); |
| 605 DCHECK(successful_read); | 610 DCHECK(successful_read); |
| 606 | 611 |
| 607 successful_read = reader->ReadUInt31(¤t_frame_stream_id_); | 612 successful_read = reader->ReadUInt31(¤t_frame_stream_id_); |
| 608 DCHECK(successful_read); | 613 DCHECK(successful_read); |
| 609 | 614 |
| 610 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed(); | 615 remaining_data_length_ = length_field; |
| 616 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed(); |
| 611 } | 617 } |
| 612 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize() | 618 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize() |
| 613 : GetDataFrameMinimumSize(), | 619 : GetDataFrameMinimumSize(), |
| 614 reader->GetBytesConsumed()); | 620 reader->GetBytesConsumed()); |
| 615 DCHECK_EQ(current_frame_length_, | 621 DCHECK_EQ(current_frame_length_, |
| 616 remaining_data_length_ + reader->GetBytesConsumed()); | 622 remaining_data_length_ + reader->GetBytesConsumed()); |
| 617 | 623 |
| 618 // This is just a sanity check for help debugging early frame errors. | 624 // This is just a sanity check for help debugging early frame errors. |
| 619 if (remaining_data_length_ > 1000000u) { | 625 if (remaining_data_length_ > 1000000u) { |
| 620 // The strncmp for 5 is safe because we only hit this point if we | 626 // The strncmp for 5 is safe because we only hit this point if we |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_); | 673 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_); |
| 668 | 674 |
| 669 if (control_frame_type_field < FIRST_CONTROL_TYPE || | 675 if (control_frame_type_field < FIRST_CONTROL_TYPE || |
| 670 control_frame_type_field > LAST_CONTROL_TYPE) { | 676 control_frame_type_field > LAST_CONTROL_TYPE) { |
| 671 set_error(SPDY_INVALID_CONTROL_FRAME); | 677 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 672 return; | 678 return; |
| 673 } | 679 } |
| 674 | 680 |
| 675 current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field); | 681 current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field); |
| 676 | 682 |
| 683 if (spdy_version_ >= SPDY4 && current_frame_type_ == SYN_STREAM) { |
| 684 current_frame_type_ = HEADERS; |
| 685 } |
| 686 |
| 677 if (current_frame_type_ == NOOP) { | 687 if (current_frame_type_ == NOOP) { |
| 678 DLOG(INFO) << "NOOP control frame found. Ignoring."; | 688 DLOG(INFO) << "NOOP control frame found. Ignoring."; |
| 679 CHANGE_STATE(SPDY_AUTO_RESET); | 689 CHANGE_STATE(SPDY_AUTO_RESET); |
| 680 return; | 690 return; |
| 681 } | 691 } |
| 682 | 692 |
| 683 // Do some sanity checking on the control frame sizes and flags. | 693 // Do some sanity checking on the control frame sizes and flags. |
| 684 switch (current_frame_type_) { | 694 switch (current_frame_type_) { |
| 685 case SYN_STREAM: | 695 case SYN_STREAM: |
| 686 if (current_frame_length_ < GetSynStreamMinimumSize()) { | 696 if (current_frame_length_ < GetSynStreamMinimumSize()) { |
| 687 set_error(SPDY_INVALID_CONTROL_FRAME); | 697 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 688 } else if (current_frame_flags_ & | 698 } else if (spdy_version_ < SPDY4 && current_frame_flags_ & |
| 689 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { | 699 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { |
| 690 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 700 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 691 } | 701 } |
| 692 break; | 702 break; |
| 693 case SYN_REPLY: | 703 case SYN_REPLY: |
| 694 if (current_frame_length_ < GetSynReplyMinimumSize()) { | 704 if (current_frame_length_ < GetSynReplyMinimumSize()) { |
| 695 set_error(SPDY_INVALID_CONTROL_FRAME); | 705 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 696 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) { | 706 } else if (spdy_version_ < SPDY4 && current_frame_flags_ & |
| 707 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { |
| 697 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 708 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 698 } | 709 } |
| 699 break; | 710 break; |
| 700 case RST_STREAM: | 711 case RST_STREAM: |
| 701 if (current_frame_length_ != GetRstStreamSize()) { | 712 if (current_frame_length_ != GetRstStreamSize()) { |
| 702 set_error(SPDY_INVALID_CONTROL_FRAME); | 713 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 703 } else if (current_frame_flags_ != 0) { | 714 } else if (current_frame_flags_ != 0) { |
| 704 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 715 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 705 } | 716 } |
| 706 break; | 717 break; |
| 707 case SETTINGS: | 718 case SETTINGS: |
| 708 // Make sure that we have an integral number of 8-byte key/value pairs, | 719 // Make sure that we have an integral number of 8-byte key/value pairs, |
| 709 // plus a 4-byte length field. | 720 // plus a 4-byte length field. |
| 710 if (current_frame_length_ < GetSettingsMinimumSize() || | 721 if (current_frame_length_ < GetSettingsMinimumSize() || |
| 711 (current_frame_length_ - GetControlFrameHeaderSize()) % 8 != 4) { | 722 ((spdy_version_ < SPDY4) && |
| 723 ((current_frame_length_ - GetControlFrameHeaderSize()) % 8 != 4)) || |
| 724 ((spdy_version_ >= SPDY4) && (current_frame_length_ % 8 != 0))) { |
| 712 DLOG(WARNING) << "Invalid length for SETTINGS frame: " | 725 DLOG(WARNING) << "Invalid length for SETTINGS frame: " |
| 713 << current_frame_length_; | 726 << current_frame_length_; |
| 714 set_error(SPDY_INVALID_CONTROL_FRAME); | 727 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 715 } else if (current_frame_flags_ & | 728 } else if (current_frame_flags_ & |
| 716 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) { | 729 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) { |
| 717 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 730 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 718 } | 731 } |
| 719 break; | 732 break; |
| 720 case PING: | 733 case PING: |
| 721 if (current_frame_length_ != GetPingSize()) { | 734 if (current_frame_length_ != GetPingSize()) { |
| 722 set_error(SPDY_INVALID_CONTROL_FRAME); | 735 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 723 } else if (current_frame_flags_ != 0) { | 736 } else if (spdy_version_ < SPDY4 && current_frame_flags_ != 0) { |
| 724 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 737 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 738 } else if (spdy_version_ >= SPDY4 && (current_frame_flags_ & ~0x1) != 0) { |
| 739 // TODO(akalin): Unignore this. |
| 740 // set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 725 } | 741 } |
| 726 break; | 742 break; |
| 727 case GOAWAY: | 743 case GOAWAY: |
| 728 { | 744 { |
| 729 if (current_frame_length_ != GetGoAwaySize()) { | 745 if (current_frame_length_ != GetGoAwaySize()) { |
| 730 set_error(SPDY_INVALID_CONTROL_FRAME); | 746 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 731 } else if (current_frame_flags_ != 0) { | 747 } else if (current_frame_flags_ != 0) { |
| 732 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 748 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 733 } | 749 } |
| 734 break; | 750 break; |
| 735 } | 751 } |
| 736 case HEADERS: | 752 case HEADERS: |
| 737 if (current_frame_length_ < GetHeadersMinimumSize()) { | 753 { |
| 738 set_error(SPDY_INVALID_CONTROL_FRAME); | 754 size_t min_size = GetHeadersMinimumSize(); |
| 739 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) { | 755 if (spdy_version_ > 3 && current_frame_flags_ & HEADERS_FLAG_PRIORITY) { |
| 740 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 756 min_size += 4; |
| 757 } |
| 758 if (current_frame_length_ < min_size) { |
| 759 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 760 } else if (spdy_version_ < 4 && |
| 761 current_frame_flags_ & ~CONTROL_FLAG_FIN) { |
| 762 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 763 } else if (spdy_version_ > 3 && current_frame_flags_ & |
| 764 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY | |
| 765 HEADERS_FLAG_END_HEADERS)) { |
| 766 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 767 } |
| 741 } | 768 } |
| 742 break; | 769 break; |
| 743 case WINDOW_UPDATE: | 770 case WINDOW_UPDATE: |
| 744 if (current_frame_length_ != GetWindowUpdateSize()) { | 771 if (current_frame_length_ != GetWindowUpdateSize()) { |
| 745 set_error(SPDY_INVALID_CONTROL_FRAME); | 772 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 746 } else if (current_frame_flags_ != 0) { | 773 } else if (current_frame_flags_ != 0) { |
| 747 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 774 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 748 } | 775 } |
| 749 break; | 776 break; |
| 750 case CREDENTIAL: | 777 case CREDENTIAL: |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 806 break; | 833 break; |
| 807 case SYN_REPLY: | 834 case SYN_REPLY: |
| 808 syn_frame_processed_ = true; | 835 syn_frame_processed_ = true; |
| 809 frame_size_without_variable_data = GetSynReplyMinimumSize(); | 836 frame_size_without_variable_data = GetSynReplyMinimumSize(); |
| 810 break; | 837 break; |
| 811 case SETTINGS: | 838 case SETTINGS: |
| 812 frame_size_without_variable_data = GetSettingsMinimumSize(); | 839 frame_size_without_variable_data = GetSettingsMinimumSize(); |
| 813 break; | 840 break; |
| 814 case HEADERS: | 841 case HEADERS: |
| 815 frame_size_without_variable_data = GetHeadersMinimumSize(); | 842 frame_size_without_variable_data = GetHeadersMinimumSize(); |
| 843 if (spdy_version_ > 3 && current_frame_flags_ & HEADERS_FLAG_PRIORITY) { |
| 844 frame_size_without_variable_data += 4; // priority |
| 845 } |
| 816 break; | 846 break; |
| 817 case PUSH_PROMISE: | 847 case PUSH_PROMISE: |
| 818 frame_size_without_variable_data = GetPushPromiseMinimumSize(); | 848 frame_size_without_variable_data = GetPushPromiseMinimumSize(); |
| 819 break; | 849 break; |
| 820 default: | 850 default: |
| 821 frame_size_without_variable_data = -1; | 851 frame_size_without_variable_data = -1; |
| 822 break; | 852 break; |
| 823 } | 853 } |
| 824 | 854 |
| 825 if ((frame_size_without_variable_data == -1) && | 855 if ((frame_size_without_variable_data == -1) && |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1068 z->avail_in = 0; | 1098 z->avail_in = 0; |
| 1069 int rv = deflate(z, Z_SYNC_FLUSH); | 1099 int rv = deflate(z, Z_SYNC_FLUSH); |
| 1070 DCHECK_EQ(Z_OK, rv); | 1100 DCHECK_EQ(Z_OK, rv); |
| 1071 z->clas = kZStandardData; | 1101 z->clas = kZStandardData; |
| 1072 } | 1102 } |
| 1073 #endif // !defined(USE_SYSTEM_ZLIB) | 1103 #endif // !defined(USE_SYSTEM_ZLIB) |
| 1074 | 1104 |
| 1075 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, | 1105 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, |
| 1076 size_t len) { | 1106 size_t len) { |
| 1077 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); | 1107 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); |
| 1078 size_t original_len = len; | 1108 const size_t original_len = len; |
| 1079 | 1109 |
| 1080 if (remaining_control_header_ > 0) { | 1110 if (remaining_control_header_ > 0) { |
| 1081 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, | 1111 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, |
| 1082 remaining_control_header_); | 1112 remaining_control_header_); |
| 1083 remaining_control_header_ -= bytes_read; | 1113 remaining_control_header_ -= bytes_read; |
| 1084 remaining_data_length_ -= bytes_read; | 1114 remaining_data_length_ -= bytes_read; |
| 1085 } | 1115 } |
| 1086 | 1116 |
| 1087 if (remaining_control_header_ == 0) { | 1117 if (remaining_control_header_ == 0) { |
| 1088 SpdyFrameReader reader(current_frame_buffer_.get(), | 1118 SpdyFrameReader reader(current_frame_buffer_.get(), |
| 1089 current_frame_buffer_length_); | 1119 current_frame_buffer_length_); |
| 1090 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. | 1120 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. |
| 1091 | 1121 |
| 1092 switch (current_frame_type_) { | 1122 switch (current_frame_type_) { |
| 1093 case SYN_STREAM: | 1123 case SYN_STREAM: |
| 1094 { | 1124 { |
| 1125 DCHECK_GT(4, spdy_version_); |
| 1095 bool successful_read = true; | 1126 bool successful_read = true; |
| 1096 if (spdy_version_ < 4) { | 1127 if (spdy_version_ < 4) { |
| 1097 successful_read = reader.ReadUInt31(¤t_frame_stream_id_); | 1128 successful_read = reader.ReadUInt31(¤t_frame_stream_id_); |
| 1098 DCHECK(successful_read); | 1129 DCHECK(successful_read); |
| 1099 } | 1130 } |
| 1100 if (current_frame_stream_id_ == 0) { | 1131 if (current_frame_stream_id_ == 0) { |
| 1101 set_error(SPDY_INVALID_CONTROL_FRAME); | 1132 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 1102 break; | 1133 break; |
| 1103 } | 1134 } |
| 1104 | 1135 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1156 DCHECK(successful_read); | 1187 DCHECK(successful_read); |
| 1157 } | 1188 } |
| 1158 if (current_frame_stream_id_ == 0) { | 1189 if (current_frame_stream_id_ == 0) { |
| 1159 set_error(SPDY_INVALID_CONTROL_FRAME); | 1190 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 1160 break; | 1191 break; |
| 1161 } | 1192 } |
| 1162 if (protocol_version() < 3) { | 1193 if (protocol_version() < 3) { |
| 1163 // SPDY 2 had two unused bytes here. Seek past them. | 1194 // SPDY 2 had two unused bytes here. Seek past them. |
| 1164 reader.Seek(2); | 1195 reader.Seek(2); |
| 1165 } | 1196 } |
| 1197 const bool has_priority = |
| 1198 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0; |
| 1199 uint32 priority = 0; |
| 1200 if (protocol_version() > 3 && has_priority) { |
| 1201 successful_read = reader.ReadUInt31(&priority); |
| 1202 DCHECK(successful_read); |
| 1203 } |
| 1166 DCHECK(reader.IsDoneReading()); | 1204 DCHECK(reader.IsDoneReading()); |
| 1167 if (debug_visitor_) { | 1205 if (debug_visitor_) { |
| 1206 // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM. |
| 1207 SpdyFrameType reported_type = current_frame_type_; |
| 1208 if (protocol_version() > 3 && has_priority) { |
| 1209 reported_type = SYN_STREAM; |
| 1210 } |
| 1168 debug_visitor_->OnReceiveCompressedFrame( | 1211 debug_visitor_->OnReceiveCompressedFrame( |
| 1169 current_frame_stream_id_, | 1212 current_frame_stream_id_, |
| 1170 current_frame_type_, | 1213 reported_type, |
| 1171 current_frame_length_); | 1214 current_frame_length_); |
| 1172 } | 1215 } |
| 1173 if (current_frame_type_ == SYN_REPLY) { | 1216 // TODO(akalin): Fix this hack. |
| 1217 if (current_frame_type_ == SYN_REPLY || |
| 1218 (spdy_version_ >= SPDY4 && current_frame_type_ == HEADERS)) { |
| 1174 visitor_->OnSynReply( | 1219 visitor_->OnSynReply( |
| 1175 current_frame_stream_id_, | 1220 current_frame_stream_id_, |
| 1176 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); | 1221 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); |
| 1222 } else if (spdy_version_ > 3 && |
| 1223 current_frame_flags_ & HEADERS_FLAG_PRIORITY) { |
| 1224 // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes |
| 1225 // can be made independent of wire changes. |
| 1226 visitor_->OnSynStream( |
| 1227 current_frame_stream_id_, |
| 1228 0, // associated_to_stream_id |
| 1229 priority, |
| 1230 0, // TODO(hkhalil): handle slot for SPDY 4+? |
| 1231 current_frame_flags_ & CONTROL_FLAG_FIN, |
| 1232 false); // unidirectional |
| 1177 } else { | 1233 } else { |
| 1178 visitor_->OnHeaders( | 1234 visitor_->OnHeaders( |
| 1179 current_frame_stream_id_, | 1235 current_frame_stream_id_, |
| 1180 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); | 1236 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); |
| 1181 } | 1237 } |
| 1182 } | 1238 } |
| 1183 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); | 1239 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); |
| 1184 break; | 1240 break; |
| 1185 case PUSH_PROMISE: | 1241 case PUSH_PROMISE: |
| 1186 { | 1242 { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1396 // TODO(hkhalil): Probably best to OnError here, depending on | 1452 // TODO(hkhalil): Probably best to OnError here, depending on |
| 1397 // our interpretation of the spec. Keeping with existing liberal | 1453 // our interpretation of the spec. Keeping with existing liberal |
| 1398 // behavior for now. | 1454 // behavior for now. |
| 1399 } | 1455 } |
| 1400 DCHECK(reader.IsDoneReading()); | 1456 DCHECK(reader.IsDoneReading()); |
| 1401 visitor_->OnRstStream(current_frame_stream_id_, status); | 1457 visitor_->OnRstStream(current_frame_stream_id_, status); |
| 1402 } | 1458 } |
| 1403 break; | 1459 break; |
| 1404 case PING: { | 1460 case PING: { |
| 1405 SpdyPingId id = 0; | 1461 SpdyPingId id = 0; |
| 1406 bool successful_read = reader.ReadUInt32(&id); | 1462 uint32 zero_expected = 0x01; |
| 1407 DCHECK(successful_read); | 1463 bool successful_read = |
| 1408 DCHECK(reader.IsDoneReading()); | 1464 reader.ReadUInt32(&id) && reader.ReadUInt32(&zero_expected); |
| 1409 visitor_->OnPing(id); | 1465 if (successful_read && reader.IsDoneReading() && zero_expected == 0) { |
| 1466 visitor_->OnPing(id); |
| 1467 } else { |
| 1468 // Can't set_error() here, so just warn, I guess. But this |
| 1469 // breaks spec. |
| 1470 // |
| 1471 // TODO(akalin): Fix this. |
| 1472 LOG(WARNING) << "Dropping invalid ping frame"; |
| 1473 } |
| 1410 } | 1474 } |
| 1411 break; | 1475 break; |
| 1412 case GOAWAY: { | 1476 case GOAWAY: { |
| 1413 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); | 1477 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); |
| 1414 DCHECK(successful_read); | 1478 DCHECK(successful_read); |
| 1415 SpdyGoAwayStatus status = GOAWAY_OK; | 1479 SpdyGoAwayStatus status = GOAWAY_OK; |
| 1416 if (spdy_version_ >= 3) { | 1480 if (spdy_version_ >= 3) { |
| 1417 uint32 status_raw = GOAWAY_OK; | 1481 uint32 status_raw = GOAWAY_OK; |
| 1418 successful_read = reader.ReadUInt32(&status_raw); | 1482 successful_read = reader.ReadUInt32(&status_raw); |
| 1419 DCHECK(successful_read); | 1483 DCHECK(successful_read); |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 | 1719 |
| 1656 return SerializeSynStream(syn_stream); | 1720 return SerializeSynStream(syn_stream); |
| 1657 } | 1721 } |
| 1658 | 1722 |
| 1659 SpdySerializedFrame* SpdyFramer::SerializeSynStream( | 1723 SpdySerializedFrame* SpdyFramer::SerializeSynStream( |
| 1660 const SpdySynStreamIR& syn_stream) { | 1724 const SpdySynStreamIR& syn_stream) { |
| 1661 uint8 flags = 0; | 1725 uint8 flags = 0; |
| 1662 if (syn_stream.fin()) { | 1726 if (syn_stream.fin()) { |
| 1663 flags |= CONTROL_FLAG_FIN; | 1727 flags |= CONTROL_FLAG_FIN; |
| 1664 } | 1728 } |
| 1665 if (syn_stream.unidirectional()) { | 1729 if (spdy_version_ <= SPDY4 && syn_stream.unidirectional()) { |
| 1666 flags |= CONTROL_FLAG_UNIDIRECTIONAL; | 1730 flags |= CONTROL_FLAG_UNIDIRECTIONAL; |
| 1667 } | 1731 } |
| 1732 if (spdy_version_ >= SPDY4) { |
| 1733 flags |= HEADERS_FLAG_END_HEADERS; |
| 1734 flags |= HEADERS_FLAG_PRIORITY; |
| 1735 } |
| 1736 |
| 1737 // Sanitize priority. |
| 1738 uint8 priority = syn_stream.priority(); |
| 1739 if (priority > GetLowestPriority()) { |
| 1740 DLOG(DFATAL) << "Priority out-of-bounds."; |
| 1741 priority = GetLowestPriority(); |
| 1742 } |
| 1668 | 1743 |
| 1669 // The size of this frame, including variable-length name-value block. | 1744 // The size of this frame, including variable-length name-value block. |
| 1670 const size_t size = GetSynStreamMinimumSize() | 1745 size_t size = GetSynStreamMinimumSize() |
| 1671 + GetSerializedLength(syn_stream.name_value_block()); | 1746 + GetSerializedLength(syn_stream.name_value_block()); |
| 1672 | 1747 |
| 1748 if (spdy_version_ >= SPDY4 && (flags & HEADERS_FLAG_PRIORITY)) { |
| 1749 size += 4; |
| 1750 } |
| 1751 |
| 1673 SpdyFrameBuilder builder(size); | 1752 SpdyFrameBuilder builder(size); |
| 1674 if (spdy_version_ < 4) { | 1753 if (spdy_version_ < 4) { |
| 1675 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); | 1754 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); |
| 1676 builder.WriteUInt32(syn_stream.stream_id()); | 1755 builder.WriteUInt32(syn_stream.stream_id()); |
| 1756 builder.WriteUInt32(syn_stream.associated_to_stream_id()); |
| 1757 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); |
| 1758 builder.WriteUInt8(syn_stream.slot()); |
| 1759 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); |
| 1677 } else { | 1760 } else { |
| 1678 builder.WriteFramePrefix(*this, | 1761 builder.WriteFramePrefix(*this, |
| 1679 SYN_STREAM, | 1762 HTTP2_HEADERS, |
| 1680 flags, | 1763 flags, |
| 1681 syn_stream.stream_id()); | 1764 syn_stream.stream_id()); |
| 1765 builder.WriteUInt32(priority); |
| 1682 } | 1766 } |
| 1683 builder.WriteUInt32(syn_stream.associated_to_stream_id()); | |
| 1684 uint8 priority = syn_stream.priority(); | |
| 1685 if (priority > GetLowestPriority()) { | |
| 1686 DLOG(DFATAL) << "Priority out-of-bounds."; | |
| 1687 priority = GetLowestPriority(); | |
| 1688 } | |
| 1689 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); | |
| 1690 builder.WriteUInt8(syn_stream.slot()); | |
| 1691 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); | |
| 1692 SerializeNameValueBlock(&builder, syn_stream); | 1767 SerializeNameValueBlock(&builder, syn_stream); |
| 1693 | 1768 |
| 1694 if (debug_visitor_) { | 1769 if (debug_visitor_) { |
| 1695 const size_t payload_len = GetSerializedLength( | 1770 const size_t payload_len = GetSerializedLength( |
| 1696 protocol_version(), &(syn_stream.name_value_block())); | 1771 protocol_version(), &(syn_stream.name_value_block())); |
| 1697 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(), | 1772 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(), |
| 1698 SYN_STREAM, | 1773 SYN_STREAM, |
| 1699 payload_len, | 1774 payload_len, |
| 1700 builder.length()); | 1775 builder.length()); |
| 1701 } | 1776 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1729 // The size of this frame, including variable-length name-value block. | 1804 // The size of this frame, including variable-length name-value block. |
| 1730 size_t size = GetSynReplyMinimumSize() | 1805 size_t size = GetSynReplyMinimumSize() |
| 1731 + GetSerializedLength(syn_reply.name_value_block()); | 1806 + GetSerializedLength(syn_reply.name_value_block()); |
| 1732 | 1807 |
| 1733 SpdyFrameBuilder builder(size); | 1808 SpdyFrameBuilder builder(size); |
| 1734 if (spdy_version_ < 4) { | 1809 if (spdy_version_ < 4) { |
| 1735 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); | 1810 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); |
| 1736 builder.WriteUInt32(syn_reply.stream_id()); | 1811 builder.WriteUInt32(syn_reply.stream_id()); |
| 1737 } else { | 1812 } else { |
| 1738 builder.WriteFramePrefix(*this, | 1813 builder.WriteFramePrefix(*this, |
| 1739 SYN_REPLY, | 1814 HEADERS, |
| 1740 flags, | 1815 flags, |
| 1741 syn_reply.stream_id()); | 1816 syn_reply.stream_id()); |
| 1742 } | 1817 } |
| 1743 if (protocol_version() < 3) { | 1818 if (protocol_version() < 3) { |
| 1744 builder.WriteUInt16(0); // Unused. | 1819 builder.WriteUInt16(0); // Unused. |
| 1745 } | 1820 } |
| 1746 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); | 1821 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); |
| 1747 SerializeNameValueBlock(&builder, syn_reply); | 1822 SerializeNameValueBlock(&builder, syn_reply); |
| 1748 | 1823 |
| 1749 if (debug_visitor_) { | 1824 if (debug_visitor_) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1803 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; | 1878 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; |
| 1804 } | 1879 } |
| 1805 const SpdySettingsIR::ValueMap* values = &(settings.values()); | 1880 const SpdySettingsIR::ValueMap* values = &(settings.values()); |
| 1806 | 1881 |
| 1807 // Size, in bytes, of this SETTINGS frame. | 1882 // Size, in bytes, of this SETTINGS frame. |
| 1808 const size_t size = GetSettingsMinimumSize() + (values->size() * 8); | 1883 const size_t size = GetSettingsMinimumSize() + (values->size() * 8); |
| 1809 | 1884 |
| 1810 SpdyFrameBuilder builder(size); | 1885 SpdyFrameBuilder builder(size); |
| 1811 if (spdy_version_ < 4) { | 1886 if (spdy_version_ < 4) { |
| 1812 builder.WriteControlFrameHeader(*this, SETTINGS, flags); | 1887 builder.WriteControlFrameHeader(*this, SETTINGS, flags); |
| 1888 builder.WriteUInt32(values->size()); |
| 1813 } else { | 1889 } else { |
| 1814 builder.WriteFramePrefix(*this, SETTINGS, flags, 0); | 1890 builder.WriteFramePrefix(*this, SETTINGS, flags, 0); |
| 1815 } | 1891 } |
| 1816 builder.WriteUInt32(values->size()); | |
| 1817 DCHECK_EQ(GetSettingsMinimumSize(), builder.length()); | 1892 DCHECK_EQ(GetSettingsMinimumSize(), builder.length()); |
| 1818 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); | 1893 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); |
| 1819 it != values->end(); | 1894 it != values->end(); |
| 1820 ++it) { | 1895 ++it) { |
| 1821 uint8 setting_flags = 0; | 1896 uint8 setting_flags = 0; |
| 1822 if (it->second.persist_value) { | 1897 if (spdy_version_ < SPDY4) { |
| 1823 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST; | 1898 if (it->second.persist_value) { |
| 1899 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST; |
| 1900 } |
| 1901 if (it->second.persisted) { |
| 1902 setting_flags |= SETTINGS_FLAG_PERSISTED; |
| 1903 } |
| 1904 SettingsFlagsAndId flags_and_id(setting_flags, it->first); |
| 1905 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version()); |
| 1906 builder.WriteBytes(&id_and_flags_wire, 4); |
| 1907 } else { |
| 1908 builder.WriteUInt8(0); |
| 1909 builder.WriteUInt24(it->first); |
| 1824 } | 1910 } |
| 1825 if (it->second.persisted) { | |
| 1826 setting_flags |= SETTINGS_FLAG_PERSISTED; | |
| 1827 } | |
| 1828 SettingsFlagsAndId flags_and_id(setting_flags, it->first); | |
| 1829 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version()); | |
| 1830 builder.WriteBytes(&id_and_flags_wire, 4); | |
| 1831 builder.WriteUInt32(it->second.value); | 1911 builder.WriteUInt32(it->second.value); |
| 1832 } | 1912 } |
| 1833 DCHECK_EQ(size, builder.length()); | 1913 DCHECK_EQ(size, builder.length()); |
| 1834 return builder.take(); | 1914 return builder.take(); |
| 1835 } | 1915 } |
| 1836 | 1916 |
| 1837 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const { | 1917 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const { |
| 1838 DCHECK_LE(4, protocol_version()); | 1918 DCHECK_LE(4, protocol_version()); |
| 1839 SpdyFrameBuilder builder(GetBlockedSize()); | 1919 SpdyFrameBuilder builder(GetBlockedSize()); |
| 1840 builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id()); | 1920 builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id()); |
| 1841 return builder.take(); | 1921 return builder.take(); |
| 1842 } | 1922 } |
| 1843 | 1923 |
| 1844 SpdyFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { | 1924 SpdyFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { |
| 1845 SpdyPingIR ping(unique_id); | 1925 SpdyPingIR ping(unique_id); |
| 1846 return SerializePing(ping); | 1926 return SerializePing(ping); |
| 1847 } | 1927 } |
| 1848 | 1928 |
| 1849 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { | 1929 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { |
| 1850 SpdyFrameBuilder builder(GetPingSize()); | 1930 SpdyFrameBuilder builder(GetPingSize()); |
| 1851 if (spdy_version_ < 4) { | 1931 if (spdy_version_ < SPDY4) { |
| 1852 builder.WriteControlFrameHeader(*this, PING, kNoFlags); | 1932 builder.WriteControlFrameHeader(*this, PING, kNoFlags); |
| 1853 } else { | 1933 } else { |
| 1854 builder.WriteFramePrefix(*this, PING, 0, 0); | 1934 builder.WriteFramePrefix(*this, PING, 0, 0); |
| 1855 } | 1935 } |
| 1856 builder.WriteUInt32(ping.id()); | 1936 builder.WriteUInt32(ping.id()); |
| 1937 if (spdy_version_ >= SPDY4) { |
| 1938 builder.WriteUInt32(0); |
| 1939 } |
| 1857 DCHECK_EQ(GetPingSize(), builder.length()); | 1940 DCHECK_EQ(GetPingSize(), builder.length()); |
| 1858 return builder.take(); | 1941 return builder.take(); |
| 1859 } | 1942 } |
| 1860 | 1943 |
| 1861 SpdyFrame* SpdyFramer::CreateGoAway( | 1944 SpdyFrame* SpdyFramer::CreateGoAway( |
| 1862 SpdyStreamId last_accepted_stream_id, | 1945 SpdyStreamId last_accepted_stream_id, |
| 1863 SpdyGoAwayStatus status) const { | 1946 SpdyGoAwayStatus status) const { |
| 1864 SpdyGoAwayIR goaway(last_accepted_stream_id, status); | 1947 SpdyGoAwayIR goaway(last_accepted_stream_id, status); |
| 1865 return SerializeGoAway(goaway); | 1948 return SerializeGoAway(goaway); |
| 1866 } | 1949 } |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2352 builder->Seek(compressed_size); | 2435 builder->Seek(compressed_size); |
| 2353 builder->RewriteLength(*this); | 2436 builder->RewriteLength(*this); |
| 2354 | 2437 |
| 2355 pre_compress_bytes.Add(uncompressed_len); | 2438 pre_compress_bytes.Add(uncompressed_len); |
| 2356 post_compress_bytes.Add(compressed_size); | 2439 post_compress_bytes.Add(compressed_size); |
| 2357 | 2440 |
| 2358 compressed_frames.Increment(); | 2441 compressed_frames.Increment(); |
| 2359 } | 2442 } |
| 2360 | 2443 |
| 2361 } // namespace net | 2444 } // namespace net |
| OLD | NEW |