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 |