| 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 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 | 664 |
| 665 // Determine the frame size without variable-length data. | 665 // Determine the frame size without variable-length data. |
| 666 int32 frame_size_without_variable_data; | 666 int32 frame_size_without_variable_data; |
| 667 switch (current_control_frame.type()) { | 667 switch (current_control_frame.type()) { |
| 668 case SYN_STREAM: | 668 case SYN_STREAM: |
| 669 syn_frame_processed_ = true; | 669 syn_frame_processed_ = true; |
| 670 frame_size_without_variable_data = SpdySynStreamControlFrame::size(); | 670 frame_size_without_variable_data = SpdySynStreamControlFrame::size(); |
| 671 break; | 671 break; |
| 672 case SYN_REPLY: | 672 case SYN_REPLY: |
| 673 syn_frame_processed_ = true; | 673 syn_frame_processed_ = true; |
| 674 frame_size_without_variable_data = SpdySynReplyControlFrame::size(); | 674 frame_size_without_variable_data = GetSynReplyMinimumSize(); |
| 675 // SPDY 2 had two bytes of unused space preceeding payload. | |
| 676 if (spdy_version_ < 3) { | |
| 677 frame_size_without_variable_data += 2; | |
| 678 } | |
| 679 break; | 675 break; |
| 680 case HEADERS: | 676 case HEADERS: |
| 681 frame_size_without_variable_data = SpdyHeadersControlFrame::size(); | 677 frame_size_without_variable_data = SpdyHeadersControlFrame::size(); |
| 682 // SPDY 2 had two bytes of unused space preceeding payload. | 678 // SPDY 2 had two bytes of unused space preceeding payload. |
| 683 if (spdy_version_ < 3) { | 679 if (spdy_version_ < 3) { |
| 684 frame_size_without_variable_data += 2; | 680 frame_size_without_variable_data += 2; |
| 685 } | 681 } |
| 686 break; | 682 break; |
| 687 case SETTINGS: | 683 case SETTINGS: |
| 688 frame_size_without_variable_data = SpdySettingsControlFrame::size(); | 684 frame_size_without_variable_data = SpdySettingsControlFrame::size(); |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 963 syn_stream_frame->associated_stream_id(), | 959 syn_stream_frame->associated_stream_id(), |
| 964 syn_stream_frame->priority(), | 960 syn_stream_frame->priority(), |
| 965 syn_stream_frame->credential_slot(), | 961 syn_stream_frame->credential_slot(), |
| 966 (syn_stream_frame->flags() & CONTROL_FLAG_FIN) != 0, | 962 (syn_stream_frame->flags() & CONTROL_FLAG_FIN) != 0, |
| 967 (syn_stream_frame->flags() & CONTROL_FLAG_UNIDIRECTIONAL) != 0); | 963 (syn_stream_frame->flags() & CONTROL_FLAG_UNIDIRECTIONAL) != 0); |
| 968 } | 964 } |
| 969 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); | 965 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); |
| 970 break; | 966 break; |
| 971 case SYN_REPLY: | 967 case SYN_REPLY: |
| 972 { | 968 { |
| 973 SpdySynReplyControlFrame* syn_reply_frame = | 969 SpdyFrameReader reader(current_frame_buffer_.get(), |
| 974 reinterpret_cast<SpdySynReplyControlFrame*>(&control_frame); | 970 current_frame_len_); |
| 975 visitor_->OnSynReply( | 971 reader.Seek(4); // Seek past control bit, type and version. |
| 976 syn_reply_frame->stream_id(), | 972 uint8 flags; |
| 977 (syn_reply_frame->flags() & CONTROL_FLAG_FIN) != 0); | 973 bool successful_read = reader.ReadUInt8(&flags); |
| 974 DCHECK(successful_read); |
| 975 reader.Seek(3); // Seek past length. |
| 976 SpdyStreamId stream_id = kInvalidStream; |
| 977 successful_read = reader.ReadUInt31(&stream_id); |
| 978 DCHECK(successful_read); |
| 979 if (protocol_version() < 3) { |
| 980 // SPDY 2 had two unused bytes here. Seek past them. |
| 981 reader.Seek(2); |
| 982 } |
| 983 DCHECK(reader.IsDoneReading()); |
| 984 visitor_->OnSynReply(stream_id, (flags & CONTROL_FLAG_FIN) != 0); |
| 978 } | 985 } |
| 979 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); | 986 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); |
| 980 break; | 987 break; |
| 981 case HEADERS: | 988 case HEADERS: |
| 982 { | 989 { |
| 983 SpdyHeadersControlFrame* headers_frame = | 990 SpdyHeadersControlFrame* headers_frame = |
| 984 reinterpret_cast<SpdyHeadersControlFrame*>(&control_frame); | 991 reinterpret_cast<SpdyHeadersControlFrame*>(&control_frame); |
| 985 visitor_->OnHeaders( | 992 visitor_->OnHeaders( |
| 986 headers_frame->stream_id(), | 993 headers_frame->stream_id(), |
| 987 (headers_frame->flags() & CONTROL_FLAG_FIN) != 0); | 994 (headers_frame->flags() & CONTROL_FLAG_FIN) != 0); |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1187 } | 1194 } |
| 1188 break; | 1195 break; |
| 1189 case RST_STREAM: { | 1196 case RST_STREAM: { |
| 1190 SpdyRstStreamControlFrame* rst_stream_frame = | 1197 SpdyRstStreamControlFrame* rst_stream_frame = |
| 1191 reinterpret_cast<SpdyRstStreamControlFrame*>(&control_frame); | 1198 reinterpret_cast<SpdyRstStreamControlFrame*>(&control_frame); |
| 1192 visitor_->OnRstStream(rst_stream_frame->stream_id(), | 1199 visitor_->OnRstStream(rst_stream_frame->stream_id(), |
| 1193 rst_stream_frame->status()); | 1200 rst_stream_frame->status()); |
| 1194 } | 1201 } |
| 1195 break; | 1202 break; |
| 1196 case GOAWAY: { | 1203 case GOAWAY: { |
| 1197 SpdyGoAwayControlFrame* go_away_frame = | 1204 SpdyFrameReader reader(current_frame_buffer_.get(), |
| 1198 reinterpret_cast<SpdyGoAwayControlFrame*>(&control_frame); | 1205 current_frame_len_); |
| 1199 if (spdy_version_ < 3) { | 1206 reader.Seek(GetControlFrameMinimumSize()); // Skip frame header. |
| 1200 visitor_->OnGoAway(go_away_frame->last_accepted_stream_id(), | 1207 SpdyStreamId last_accepted_stream_id = kInvalidStream; |
| 1201 GOAWAY_OK); | 1208 bool successful_read = reader.ReadUInt32(&last_accepted_stream_id); |
| 1202 } else { | 1209 DCHECK(successful_read); |
| 1203 visitor_->OnGoAway(go_away_frame->last_accepted_stream_id(), | 1210 SpdyGoAwayStatus status = GOAWAY_OK; |
| 1204 go_away_frame->status()); | 1211 if (spdy_version_ >= 3) { |
| 1212 uint32 status_raw = GOAWAY_OK; |
| 1213 successful_read = reader.ReadUInt32(&status_raw); |
| 1214 DCHECK(successful_read); |
| 1215 if (status_raw > static_cast<uint32>(GOAWAY_INVALID) && |
| 1216 status_raw < static_cast<uint32>(GOAWAY_NUM_STATUS_CODES)) { |
| 1217 status = static_cast<SpdyGoAwayStatus>(status_raw); |
| 1218 } else { |
| 1219 // TODO(hkhalil): Probably best to OnError here, depending on |
| 1220 // our interpretation of the spec. Keeping with existing liberal |
| 1221 // behavior for now. |
| 1222 } |
| 1205 } | 1223 } |
| 1224 DCHECK(reader.IsDoneReading()); |
| 1225 visitor_->OnGoAway(last_accepted_stream_id, status); |
| 1206 } | 1226 } |
| 1207 break; | 1227 break; |
| 1208 default: | 1228 default: |
| 1209 // Unreachable. | 1229 // Unreachable. |
| 1210 LOG(FATAL) << "Unhandled control frame " << control_frame.type(); | 1230 LOG(FATAL) << "Unhandled control frame " << control_frame.type(); |
| 1211 } | 1231 } |
| 1212 | 1232 |
| 1213 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); | 1233 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); |
| 1214 } | 1234 } |
| 1215 } | 1235 } |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 priority = GetLowestPriority(); | 1447 priority = GetLowestPriority(); |
| 1428 } | 1448 } |
| 1429 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); | 1449 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); |
| 1430 builder.WriteUInt8(syn_stream.slot()); | 1450 builder.WriteUInt8(syn_stream.slot()); |
| 1431 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); | 1451 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); |
| 1432 SerializeNameValueBlock(&builder, syn_stream); | 1452 SerializeNameValueBlock(&builder, syn_stream); |
| 1433 | 1453 |
| 1434 return builder.take(); | 1454 return builder.take(); |
| 1435 } | 1455 } |
| 1436 | 1456 |
| 1437 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply( | 1457 SpdyFrame* SpdyFramer::CreateSynReply( |
| 1438 SpdyStreamId stream_id, | 1458 SpdyStreamId stream_id, |
| 1439 SpdyControlFlags flags, | 1459 SpdyControlFlags flags, |
| 1440 bool compressed, | 1460 bool compressed, |
| 1441 const SpdyHeaderBlock* headers) { | 1461 const SpdyHeaderBlock* headers) { |
| 1442 DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN); | 1462 DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN); |
| 1443 | 1463 |
| 1444 SpdySynReplyIR syn_reply(stream_id); | 1464 SpdySynReplyIR syn_reply(stream_id); |
| 1445 syn_reply.set_fin(flags & CONTROL_FLAG_FIN); | 1465 syn_reply.set_fin(flags & CONTROL_FLAG_FIN); |
| 1446 // TODO(hkhalil): Avoid copy here. | 1466 // TODO(hkhalil): Avoid copy here. |
| 1447 *(syn_reply.GetMutableNameValueBlock()) = *headers; | 1467 *(syn_reply.GetMutableNameValueBlock()) = *headers; |
| 1448 | 1468 |
| 1449 scoped_ptr<SpdySynReplyControlFrame> reply_frame( | 1469 scoped_ptr<SpdyControlFrame> reply_frame( |
| 1450 reinterpret_cast<SpdySynReplyControlFrame*>(SerializeSynReply( | 1470 reinterpret_cast<SpdyControlFrame*>(SerializeSynReply(syn_reply))); |
| 1451 syn_reply))); | |
| 1452 if (compressed) { | 1471 if (compressed) { |
| 1453 return reinterpret_cast<SpdySynReplyControlFrame*>( | 1472 return CompressControlFrame(*reply_frame.get(), headers); |
| 1454 CompressControlFrame(*reply_frame.get(), headers)); | |
| 1455 } | 1473 } |
| 1456 return reply_frame.release(); | 1474 return reply_frame.release(); |
| 1457 } | 1475 } |
| 1458 | 1476 |
| 1459 SpdySerializedFrame* SpdyFramer::SerializeSynReply( | 1477 SpdySerializedFrame* SpdyFramer::SerializeSynReply( |
| 1460 const SpdySynReplyIR& syn_reply) { | 1478 const SpdySynReplyIR& syn_reply) { |
| 1461 uint8 flags = 0; | 1479 uint8 flags = 0; |
| 1462 if (syn_reply.fin()) { | 1480 if (syn_reply.fin()) { |
| 1463 flags |= CONTROL_FLAG_FIN; | 1481 flags |= CONTROL_FLAG_FIN; |
| 1464 } | 1482 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1552 return reinterpret_cast<SpdyPingControlFrame*>(SerializePing(ping)); | 1570 return reinterpret_cast<SpdyPingControlFrame*>(SerializePing(ping)); |
| 1553 } | 1571 } |
| 1554 | 1572 |
| 1555 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { | 1573 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { |
| 1556 SpdyFrameBuilder builder(PING, 0, protocol_version(), GetPingSize()); | 1574 SpdyFrameBuilder builder(PING, 0, protocol_version(), GetPingSize()); |
| 1557 builder.WriteUInt32(ping.id()); | 1575 builder.WriteUInt32(ping.id()); |
| 1558 DCHECK_EQ(GetPingSize(), builder.length()); | 1576 DCHECK_EQ(GetPingSize(), builder.length()); |
| 1559 return builder.take(); | 1577 return builder.take(); |
| 1560 } | 1578 } |
| 1561 | 1579 |
| 1562 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( | 1580 SpdyFrame* SpdyFramer::CreateGoAway( |
| 1563 SpdyStreamId last_accepted_stream_id, | 1581 SpdyStreamId last_accepted_stream_id, |
| 1564 SpdyGoAwayStatus status) const { | 1582 SpdyGoAwayStatus status) const { |
| 1565 SpdyGoAwayIR goaway(last_accepted_stream_id, status); | 1583 SpdyGoAwayIR goaway(last_accepted_stream_id, status); |
| 1566 return reinterpret_cast<SpdyGoAwayControlFrame*>(SerializeGoAway(goaway)); | 1584 return SerializeGoAway(goaway); |
| 1567 } | 1585 } |
| 1568 | 1586 |
| 1569 SpdySerializedFrame* SpdyFramer::SerializeGoAway( | 1587 SpdySerializedFrame* SpdyFramer::SerializeGoAway( |
| 1570 const SpdyGoAwayIR& goaway) const { | 1588 const SpdyGoAwayIR& goaway) const { |
| 1571 SpdyFrameBuilder builder(GOAWAY, 0, protocol_version(), GetGoAwaySize()); | 1589 SpdyFrameBuilder builder(GOAWAY, 0, protocol_version(), GetGoAwaySize()); |
| 1572 builder.WriteUInt32(goaway.last_good_stream_id()); | 1590 builder.WriteUInt32(goaway.last_good_stream_id()); |
| 1573 if (protocol_version() >= 3) { | 1591 if (protocol_version() >= 3) { |
| 1574 builder.WriteUInt32(goaway.status()); | 1592 builder.WriteUInt32(goaway.status()); |
| 1575 } | 1593 } |
| 1576 DCHECK_EQ(GetGoAwaySize(), builder.length()); | 1594 DCHECK_EQ(GetGoAwaySize(), builder.length()); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1784 const SpdySynStreamControlFrame& syn_frame = | 1802 const SpdySynStreamControlFrame& syn_frame = |
| 1785 reinterpret_cast<const SpdySynStreamControlFrame&>(frame); | 1803 reinterpret_cast<const SpdySynStreamControlFrame&>(frame); |
| 1786 frame_size = SpdySynStreamControlFrame::size(); | 1804 frame_size = SpdySynStreamControlFrame::size(); |
| 1787 *payload_length = syn_frame.header_block_len(); | 1805 *payload_length = syn_frame.header_block_len(); |
| 1788 *header_length = frame_size; | 1806 *header_length = frame_size; |
| 1789 *payload = frame.data() + *header_length; | 1807 *payload = frame.data() + *header_length; |
| 1790 } | 1808 } |
| 1791 break; | 1809 break; |
| 1792 case SYN_REPLY: | 1810 case SYN_REPLY: |
| 1793 { | 1811 { |
| 1794 const SpdySynReplyControlFrame& syn_frame = | 1812 *header_length = GetSynReplyMinimumSize(); |
| 1795 reinterpret_cast<const SpdySynReplyControlFrame&>(frame); | 1813 *payload_length = frame.length() - |
| 1796 frame_size = SpdySynReplyControlFrame::size(); | 1814 (*header_length - GetControlFrameMinimumSize()); |
| 1797 *payload_length = syn_frame.header_block_len(); | |
| 1798 *header_length = frame_size; | |
| 1799 *payload = frame.data() + *header_length; | 1815 *payload = frame.data() + *header_length; |
| 1800 // SPDY 2 had two bytes of unused space preceeding payload. | |
| 1801 if (spdy_version_ < 3) { | |
| 1802 *header_length += 2; | |
| 1803 *payload += 2; | |
| 1804 } | |
| 1805 } | 1816 } |
| 1806 break; | 1817 break; |
| 1807 case HEADERS: | 1818 case HEADERS: |
| 1808 { | 1819 { |
| 1809 const SpdyHeadersControlFrame& headers_frame = | 1820 const SpdyHeadersControlFrame& headers_frame = |
| 1810 reinterpret_cast<const SpdyHeadersControlFrame&>(frame); | 1821 reinterpret_cast<const SpdyHeadersControlFrame&>(frame); |
| 1811 frame_size = SpdyHeadersControlFrame::size(); | 1822 frame_size = SpdyHeadersControlFrame::size(); |
| 1812 *payload_length = headers_frame.header_block_len(); | 1823 *payload_length = headers_frame.header_block_len(); |
| 1813 *header_length = frame_size; | 1824 *header_length = frame_size; |
| 1814 *payload = frame.data() + *header_length; | 1825 *payload = frame.data() + *header_length; |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2049 builder->WriteString(it->first); | 2060 builder->WriteString(it->first); |
| 2050 builder->WriteString(it->second); | 2061 builder->WriteString(it->second); |
| 2051 } else { | 2062 } else { |
| 2052 builder->WriteStringPiece32(it->first); | 2063 builder->WriteStringPiece32(it->first); |
| 2053 builder->WriteStringPiece32(it->second); | 2064 builder->WriteStringPiece32(it->second); |
| 2054 } | 2065 } |
| 2055 } | 2066 } |
| 2056 } | 2067 } |
| 2057 | 2068 |
| 2058 } // namespace net | 2069 } // namespace net |
| OLD | NEW |