Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Side by Side Diff: net/spdy/spdy_framer.cc

Issue 21820003: DO NOT COMMIT: SPDY 4: Hack SpdyFramer to turn SYN_STREAM and SYN_REPLY into HEADERS semi-transpare… Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase for draft 06 Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/spdy/spdy_frame_builder.cc ('k') | net/spdy/spdy_framer_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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(&current_frame_flags_); 609 successful_read = reader->ReadUInt8(&current_frame_flags_);
605 DCHECK(successful_read); 610 DCHECK(successful_read);
606 611
607 successful_read = reader->ReadUInt31(&current_frame_stream_id_); 612 successful_read = reader->ReadUInt31(&current_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
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
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
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(&current_frame_stream_id_); 1128 successful_read = reader.ReadUInt31(&current_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
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
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(&current_frame_stream_id_); 1477 bool successful_read = reader.ReadUInt31(&current_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
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
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
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
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
OLDNEW
« no previous file with comments | « net/spdy/spdy_frame_builder.cc ('k') | net/spdy/spdy_framer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698