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 #include "net/spdy/spdy_framer.h" | 5 #include "net/spdy/spdy_framer.h" |
6 | 6 |
7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/metrics/stats_counters.h" | 9 #include "base/metrics/stats_counters.h" |
10 #include "base/third_party/valgrind/memcheck.h" | 10 #include "base/third_party/valgrind/memcheck.h" |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 // initialized lazily to avoid static initializers. | 63 // initialized lazily to avoid static initializers. |
64 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; | 64 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; |
65 | 65 |
66 // Used to indicate no flags in a SPDY flags field. | 66 // Used to indicate no flags in a SPDY flags field. |
67 const uint8 kNoFlags = 0; | 67 const uint8 kNoFlags = 0; |
68 | 68 |
69 // Wire sizes of priority payloads. | 69 // Wire sizes of priority payloads. |
70 const size_t kPriorityDependencyPayloadSize = 4; | 70 const size_t kPriorityDependencyPayloadSize = 4; |
71 const size_t kPriorityWeightPayloadSize = 1; | 71 const size_t kPriorityWeightPayloadSize = 1; |
72 | 72 |
| 73 // Wire size of pad length field. |
| 74 const size_t kPadLengthFieldSize = 1; |
| 75 |
73 } // namespace | 76 } // namespace |
74 | 77 |
75 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1); | 78 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1); |
76 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; | 79 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; |
77 // The size of the control frame buffer. Must be >= the minimum size of the | 80 // The size of the control frame buffer. Must be >= the minimum size of the |
78 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for | 81 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for |
79 // calculation details. | 82 // calculation details. |
80 const size_t SpdyFramer::kControlFrameBufferSize = 19; | 83 const size_t SpdyFramer::kControlFrameBufferSize = 19; |
81 | 84 |
82 #ifdef DEBUG_SPDY_STATE_CHANGES | 85 #ifdef DEBUG_SPDY_STATE_CHANGES |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 case SPDY_ERROR: | 375 case SPDY_ERROR: |
373 return "ERROR"; | 376 return "ERROR"; |
374 case SPDY_AUTO_RESET: | 377 case SPDY_AUTO_RESET: |
375 return "AUTO_RESET"; | 378 return "AUTO_RESET"; |
376 case SPDY_RESET: | 379 case SPDY_RESET: |
377 return "RESET"; | 380 return "RESET"; |
378 case SPDY_READING_COMMON_HEADER: | 381 case SPDY_READING_COMMON_HEADER: |
379 return "READING_COMMON_HEADER"; | 382 return "READING_COMMON_HEADER"; |
380 case SPDY_CONTROL_FRAME_PAYLOAD: | 383 case SPDY_CONTROL_FRAME_PAYLOAD: |
381 return "CONTROL_FRAME_PAYLOAD"; | 384 return "CONTROL_FRAME_PAYLOAD"; |
382 case SPDY_READ_PADDING_LENGTH: | 385 case SPDY_READ_DATA_FRAME_PADDING_LENGTH: |
383 return "SPDY_READ_PADDING_LENGTH"; | 386 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH"; |
384 case SPDY_CONSUME_PADDING: | 387 case SPDY_CONSUME_PADDING: |
385 return "SPDY_CONSUME_PADDING"; | 388 return "SPDY_CONSUME_PADDING"; |
386 case SPDY_IGNORE_REMAINING_PAYLOAD: | 389 case SPDY_IGNORE_REMAINING_PAYLOAD: |
387 return "IGNORE_REMAINING_PAYLOAD"; | 390 return "IGNORE_REMAINING_PAYLOAD"; |
388 case SPDY_FORWARD_STREAM_FRAME: | 391 case SPDY_FORWARD_STREAM_FRAME: |
389 return "FORWARD_STREAM_FRAME"; | 392 return "FORWARD_STREAM_FRAME"; |
390 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: | 393 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: |
391 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK"; | 394 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK"; |
392 case SPDY_CONTROL_FRAME_HEADER_BLOCK: | 395 case SPDY_CONTROL_FRAME_HEADER_BLOCK: |
393 return "SPDY_CONTROL_FRAME_HEADER_BLOCK"; | 396 return "SPDY_CONTROL_FRAME_HEADER_BLOCK"; |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 break; | 597 break; |
595 } | 598 } |
596 | 599 |
597 case SPDY_CONTROL_FRAME_PAYLOAD: { | 600 case SPDY_CONTROL_FRAME_PAYLOAD: { |
598 size_t bytes_read = ProcessControlFramePayload(data, len); | 601 size_t bytes_read = ProcessControlFramePayload(data, len); |
599 len -= bytes_read; | 602 len -= bytes_read; |
600 data += bytes_read; | 603 data += bytes_read; |
601 break; | 604 break; |
602 } | 605 } |
603 | 606 |
604 case SPDY_READ_PADDING_LENGTH: { | 607 case SPDY_READ_DATA_FRAME_PADDING_LENGTH: { |
605 size_t bytes_read = ProcessFramePaddingLength(data, len); | 608 size_t bytes_read = ProcessDataFramePaddingLength(data, len); |
606 len -= bytes_read; | 609 len -= bytes_read; |
607 data += bytes_read; | 610 data += bytes_read; |
608 break; | 611 break; |
609 } | 612 } |
610 | 613 |
611 case SPDY_CONSUME_PADDING: { | 614 case SPDY_CONSUME_PADDING: { |
612 size_t bytes_read = ProcessFramePadding(data, len); | 615 size_t bytes_read = ProcessFramePadding(data, len); |
613 len -= bytes_read; | 616 len -= bytes_read; |
614 data += bytes_read; | 617 data += bytes_read; |
615 break; | 618 break; |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 valid_data_flags = DATA_FLAG_FIN; | 805 valid_data_flags = DATA_FLAG_FIN; |
803 } | 806 } |
804 | 807 |
805 if (current_frame_flags_ & ~valid_data_flags) { | 808 if (current_frame_flags_ & ~valid_data_flags) { |
806 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); | 809 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); |
807 } else { | 810 } else { |
808 visitor_->OnDataFrameHeader(current_frame_stream_id_, | 811 visitor_->OnDataFrameHeader(current_frame_stream_id_, |
809 remaining_data_length_, | 812 remaining_data_length_, |
810 current_frame_flags_ & DATA_FLAG_FIN); | 813 current_frame_flags_ & DATA_FLAG_FIN); |
811 if (remaining_data_length_ > 0) { | 814 if (remaining_data_length_ > 0) { |
812 CHANGE_STATE(SPDY_READ_PADDING_LENGTH); | 815 CHANGE_STATE(SPDY_READ_DATA_FRAME_PADDING_LENGTH); |
813 } else { | 816 } else { |
814 // Empty data frame. | 817 // Empty data frame. |
815 if (current_frame_flags_ & DATA_FLAG_FIN) { | 818 if (current_frame_flags_ & DATA_FLAG_FIN) { |
816 visitor_->OnStreamFrameData( | 819 visitor_->OnStreamFrameData( |
817 current_frame_stream_id_, NULL, 0, true); | 820 current_frame_stream_id_, NULL, 0, true); |
818 } | 821 } |
819 CHANGE_STATE(SPDY_AUTO_RESET); | 822 CHANGE_STATE(SPDY_AUTO_RESET); |
820 } | 823 } |
821 } | 824 } |
822 } else { | 825 } else { |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1076 break; | 1079 break; |
1077 case SYN_REPLY: | 1080 case SYN_REPLY: |
1078 syn_frame_processed_ = true; | 1081 syn_frame_processed_ = true; |
1079 frame_size_without_variable_data = GetSynReplyMinimumSize(); | 1082 frame_size_without_variable_data = GetSynReplyMinimumSize(); |
1080 break; | 1083 break; |
1081 case SETTINGS: | 1084 case SETTINGS: |
1082 frame_size_without_variable_data = GetSettingsMinimumSize(); | 1085 frame_size_without_variable_data = GetSettingsMinimumSize(); |
1083 break; | 1086 break; |
1084 case HEADERS: | 1087 case HEADERS: |
1085 frame_size_without_variable_data = GetHeadersMinimumSize(); | 1088 frame_size_without_variable_data = GetHeadersMinimumSize(); |
1086 if (protocol_version() > SPDY3 && | 1089 if (protocol_version() > SPDY3) { |
1087 current_frame_flags_ & HEADERS_FLAG_PRIORITY) { | 1090 if (current_frame_flags_ & HEADERS_FLAG_PADDED) { |
| 1091 frame_size_without_variable_data += kPadLengthFieldSize; |
| 1092 } |
| 1093 if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) { |
1088 frame_size_without_variable_data += | 1094 frame_size_without_variable_data += |
1089 kPriorityDependencyPayloadSize + | 1095 kPriorityDependencyPayloadSize + |
1090 kPriorityWeightPayloadSize; | 1096 kPriorityWeightPayloadSize; |
| 1097 } |
1091 } | 1098 } |
1092 break; | 1099 break; |
1093 case PUSH_PROMISE: | 1100 case PUSH_PROMISE: |
1094 frame_size_without_variable_data = GetPushPromiseMinimumSize(); | 1101 frame_size_without_variable_data = GetPushPromiseMinimumSize(); |
| 1102 if (protocol_version() > SPDY3 && |
| 1103 current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) { |
| 1104 frame_size_without_variable_data += kPadLengthFieldSize; |
| 1105 } |
1095 break; | 1106 break; |
1096 case CONTINUATION: | 1107 case CONTINUATION: |
1097 frame_size_without_variable_data = GetContinuationMinimumSize(); | 1108 frame_size_without_variable_data = GetContinuationMinimumSize(); |
1098 break; | 1109 break; |
1099 default: | 1110 default: |
1100 frame_size_without_variable_data = -1; | 1111 frame_size_without_variable_data = -1; |
1101 break; | 1112 break; |
1102 } | 1113 } |
1103 | 1114 |
1104 if ((frame_size_without_variable_data == -1) && | 1115 if ((frame_size_without_variable_data == -1) && |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1450 if (protocol_version() <= SPDY2) { | 1461 if (protocol_version() <= SPDY2) { |
1451 // SPDY 2 had two unused bytes here. Seek past them. | 1462 // SPDY 2 had two unused bytes here. Seek past them. |
1452 reader.Seek(2); | 1463 reader.Seek(2); |
1453 } | 1464 } |
1454 if (protocol_version() > SPDY3 && | 1465 if (protocol_version() > SPDY3 && |
1455 !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) && | 1466 !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) && |
1456 current_frame_type_ == HEADERS) { | 1467 current_frame_type_ == HEADERS) { |
1457 expect_continuation_ = current_frame_stream_id_; | 1468 expect_continuation_ = current_frame_stream_id_; |
1458 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN; | 1469 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN; |
1459 } | 1470 } |
| 1471 if (protocol_version() > SPDY3 && |
| 1472 current_frame_flags_ & HEADERS_FLAG_PADDED) { |
| 1473 uint8 pad_payload_len = 0; |
| 1474 DCHECK_EQ(remaining_padding_payload_length_, 0u); |
| 1475 successful_read = reader.ReadUInt8(&pad_payload_len); |
| 1476 DCHECK(successful_read); |
| 1477 remaining_padding_payload_length_ = pad_payload_len; |
| 1478 } |
1460 const bool has_priority = | 1479 const bool has_priority = |
1461 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0; | 1480 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0; |
1462 uint32 priority = 0; | 1481 uint32 priority = 0; |
1463 if (protocol_version() > SPDY3 && has_priority) { | 1482 if (protocol_version() > SPDY3 && has_priority) { |
1464 // TODO(jgraettinger): Process dependency rather than ignoring it. | 1483 // TODO(jgraettinger): Process dependency rather than ignoring it. |
1465 reader.Seek(kPriorityDependencyPayloadSize); | 1484 reader.Seek(kPriorityDependencyPayloadSize); |
1466 uint8 weight = 0; | 1485 uint8 weight = 0; |
1467 successful_read = reader.ReadUInt8(&weight); | 1486 successful_read = reader.ReadUInt8(&weight); |
1468 if (successful_read) { | 1487 if (successful_read) { |
1469 priority = MapWeightToPriority(weight); | 1488 priority = MapWeightToPriority(weight); |
(...skipping 25 matching lines...) Expand all Loading... |
1495 priority, | 1514 priority, |
1496 current_frame_flags_ & CONTROL_FLAG_FIN, | 1515 current_frame_flags_ & CONTROL_FLAG_FIN, |
1497 false); // unidirectional | 1516 false); // unidirectional |
1498 } else { | 1517 } else { |
1499 visitor_->OnHeaders( | 1518 visitor_->OnHeaders( |
1500 current_frame_stream_id_, | 1519 current_frame_stream_id_, |
1501 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, | 1520 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, |
1502 expect_continuation_ == 0); | 1521 expect_continuation_ == 0); |
1503 } | 1522 } |
1504 } | 1523 } |
1505 CHANGE_STATE(SPDY_READ_PADDING_LENGTH); | 1524 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); |
1506 break; | 1525 break; |
1507 case PUSH_PROMISE: | 1526 case PUSH_PROMISE: |
1508 { | 1527 { |
1509 DCHECK_LT(SPDY3, protocol_version()); | 1528 DCHECK_LT(SPDY3, protocol_version()); |
1510 if (current_frame_stream_id_ == 0) { | 1529 if (current_frame_stream_id_ == 0) { |
1511 set_error(SPDY_INVALID_CONTROL_FRAME); | 1530 set_error(SPDY_INVALID_CONTROL_FRAME); |
1512 break; | 1531 break; |
1513 } | 1532 } |
| 1533 bool successful_read = true; |
| 1534 if (protocol_version() > SPDY3 && |
| 1535 current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) { |
| 1536 DCHECK_EQ(remaining_padding_payload_length_, 0u); |
| 1537 uint8 pad_payload_len = 0; |
| 1538 successful_read = reader.ReadUInt8(&pad_payload_len); |
| 1539 DCHECK(successful_read); |
| 1540 remaining_padding_payload_length_ = pad_payload_len; |
| 1541 } |
| 1542 } |
| 1543 { |
1514 SpdyStreamId promised_stream_id = kInvalidStream; | 1544 SpdyStreamId promised_stream_id = kInvalidStream; |
1515 bool successful_read = reader.ReadUInt31(&promised_stream_id); | 1545 bool successful_read = reader.ReadUInt31(&promised_stream_id); |
1516 DCHECK(successful_read); | 1546 DCHECK(successful_read); |
1517 DCHECK(reader.IsDoneReading()); | 1547 DCHECK(reader.IsDoneReading()); |
1518 if (promised_stream_id == 0) { | 1548 if (promised_stream_id == 0) { |
1519 set_error(SPDY_INVALID_CONTROL_FRAME); | 1549 set_error(SPDY_INVALID_CONTROL_FRAME); |
1520 break; | 1550 break; |
1521 } | 1551 } |
1522 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) { | 1552 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) { |
1523 expect_continuation_ = current_frame_stream_id_; | 1553 expect_continuation_ = current_frame_stream_id_; |
1524 } | 1554 } |
1525 if (debug_visitor_) { | 1555 if (debug_visitor_) { |
1526 debug_visitor_->OnReceiveCompressedFrame( | 1556 debug_visitor_->OnReceiveCompressedFrame( |
1527 current_frame_stream_id_, | 1557 current_frame_stream_id_, |
1528 current_frame_type_, | 1558 current_frame_type_, |
1529 current_frame_length_); | 1559 current_frame_length_); |
1530 } | 1560 } |
1531 visitor_->OnPushPromise(current_frame_stream_id_, | 1561 visitor_->OnPushPromise(current_frame_stream_id_, |
1532 promised_stream_id, | 1562 promised_stream_id, |
1533 (current_frame_flags_ & | 1563 (current_frame_flags_ & |
1534 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0); | 1564 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0); |
1535 } | 1565 } |
1536 CHANGE_STATE(SPDY_READ_PADDING_LENGTH); | 1566 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); |
1537 break; | 1567 break; |
1538 case CONTINUATION: | 1568 case CONTINUATION: |
1539 { | 1569 { |
1540 // Check to make sure the stream id of the current frame is | 1570 // Check to make sure the stream id of the current frame is |
1541 // the same as that of the preceding frame. | 1571 // the same as that of the preceding frame. |
1542 // If we're at this point we should already know that | 1572 // If we're at this point we should already know that |
1543 // expect_continuation_ != 0, so this doubles as a check | 1573 // expect_continuation_ != 0, so this doubles as a check |
1544 // that current_frame_stream_id != 0. | 1574 // that current_frame_stream_id != 0. |
1545 if (current_frame_stream_id_ != expect_continuation_) { | 1575 if (current_frame_stream_id_ != expect_continuation_) { |
1546 set_error(SPDY_INVALID_CONTROL_FRAME); | 1576 set_error(SPDY_INVALID_CONTROL_FRAME); |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2113 StringPiece(altsvc_scratch_.host.get(), | 2143 StringPiece(altsvc_scratch_.host.get(), |
2114 altsvc_scratch_.host_len), | 2144 altsvc_scratch_.host_len), |
2115 StringPiece(altsvc_scratch_.origin.get(), | 2145 StringPiece(altsvc_scratch_.origin.get(), |
2116 altsvc_scratch_.origin_len)); | 2146 altsvc_scratch_.origin_len)); |
2117 CHANGE_STATE(SPDY_AUTO_RESET); | 2147 CHANGE_STATE(SPDY_AUTO_RESET); |
2118 } | 2148 } |
2119 | 2149 |
2120 return processed_bytes; | 2150 return processed_bytes; |
2121 } | 2151 } |
2122 | 2152 |
2123 // TODO(raullenchai): ProcessFramePaddingLength should be able to deal with | 2153 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) { |
2124 // HEADERS_FLAG_PADDED and PUSH_PROMISE_FLAG_PADDED as well (see b/15777051). | 2154 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH, state_); |
2125 size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) { | 2155 DCHECK_EQ(0u, remaining_padding_payload_length_); |
2126 DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_); | 2156 DCHECK_EQ(DATA, current_frame_type_); |
2127 DCHECK_EQ(remaining_padding_payload_length_, 0u); | |
2128 | 2157 |
2129 size_t original_len = len; | 2158 size_t original_len = len; |
2130 if (current_frame_flags_ & DATA_FLAG_PADDED) { | 2159 if (current_frame_flags_ & DATA_FLAG_PADDED) { |
2131 if (len != 0) { | 2160 if (len != 0) { |
2132 if (remaining_data_length_ < 1) { | 2161 if (remaining_data_length_ < 1) { |
2133 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); | 2162 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); |
2134 return 0; | 2163 return 0; |
2135 } | 2164 } |
2136 | 2165 |
2137 remaining_padding_payload_length_ = *reinterpret_cast<const uint8*>(data); | 2166 remaining_padding_payload_length_ = *reinterpret_cast<const uint8*>(data); |
2138 ++data; | 2167 ++data; |
2139 --len; | 2168 --len; |
2140 --remaining_data_length_; | 2169 --remaining_data_length_; |
2141 } else { | 2170 } else { |
2142 // We don't have the data available for parsing the pad length field. Keep | 2171 // We don't have the data available for parsing the pad length field. Keep |
2143 // waiting. | 2172 // waiting. |
2144 return 0; | 2173 return 0; |
2145 } | 2174 } |
2146 } | 2175 } |
2147 | 2176 |
2148 if (remaining_padding_payload_length_ > remaining_data_length_) { | 2177 if (remaining_padding_payload_length_ > remaining_data_length_) { |
2149 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); | 2178 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); |
2150 return 0; | 2179 return 0; |
2151 } | 2180 } |
2152 if (current_frame_type_ == DATA) { | 2181 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); |
2153 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); | |
2154 } else { | |
2155 DCHECK(current_frame_type_ == HEADERS || | |
2156 current_frame_type_ == PUSH_PROMISE || | |
2157 current_frame_type_ == SYN_STREAM || | |
2158 current_frame_type_ == SYN_REPLY) | |
2159 << current_frame_type_; | |
2160 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); | |
2161 } | |
2162 return original_len - len; | 2182 return original_len - len; |
2163 } | 2183 } |
2164 | 2184 |
2165 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) { | 2185 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) { |
2166 DCHECK_EQ(SPDY_CONSUME_PADDING, state_); | 2186 DCHECK_EQ(SPDY_CONSUME_PADDING, state_); |
2167 | 2187 |
2168 size_t original_len = len; | 2188 size_t original_len = len; |
2169 if (remaining_padding_payload_length_ > 0) { | 2189 if (remaining_padding_payload_length_ > 0) { |
2170 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_); | 2190 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_); |
2171 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len); | 2191 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len); |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2599 uint8 flags = 0; | 2619 uint8 flags = 0; |
2600 if (headers.fin()) { | 2620 if (headers.fin()) { |
2601 flags |= CONTROL_FLAG_FIN; | 2621 flags |= CONTROL_FLAG_FIN; |
2602 } | 2622 } |
2603 if (protocol_version() > SPDY3) { | 2623 if (protocol_version() > SPDY3) { |
2604 // This will get overwritten if we overflow into a CONTINUATION frame. | 2624 // This will get overwritten if we overflow into a CONTINUATION frame. |
2605 flags |= HEADERS_FLAG_END_HEADERS; | 2625 flags |= HEADERS_FLAG_END_HEADERS; |
2606 if (headers.has_priority()) { | 2626 if (headers.has_priority()) { |
2607 flags |= HEADERS_FLAG_PRIORITY; | 2627 flags |= HEADERS_FLAG_PRIORITY; |
2608 } | 2628 } |
| 2629 if (headers.padded()) { |
| 2630 flags |= HEADERS_FLAG_PADDED; |
| 2631 } |
2609 } | 2632 } |
2610 | 2633 |
2611 // The size of this frame, including variable-length name-value block. | 2634 // The size of this frame, including padding (if there is any) |
| 2635 // and variable-length name-value block. |
2612 size_t size = GetHeadersMinimumSize(); | 2636 size_t size = GetHeadersMinimumSize(); |
2613 | 2637 |
| 2638 if (protocol_version() > SPDY3 && headers.padded()) { |
| 2639 size += kPadLengthFieldSize; |
| 2640 size += headers.padding_payload_len(); |
| 2641 } |
| 2642 |
2614 uint32 priority = headers.priority(); | 2643 uint32 priority = headers.priority(); |
2615 if (headers.has_priority()) { | 2644 if (headers.has_priority()) { |
2616 if (priority > GetLowestPriority()) { | 2645 if (priority > GetLowestPriority()) { |
2617 DLOG(DFATAL) << "Priority out-of-bounds."; | 2646 DLOG(DFATAL) << "Priority out-of-bounds."; |
2618 priority = GetLowestPriority(); | 2647 priority = GetLowestPriority(); |
2619 } | 2648 } |
2620 size += 5; | 2649 size += 5; |
2621 } | 2650 } |
2622 | 2651 |
2623 string hpack_encoding; | 2652 string hpack_encoding; |
(...skipping 24 matching lines...) Expand all Loading... |
2648 HEADERS, | 2677 HEADERS, |
2649 flags, | 2678 flags, |
2650 headers.stream_id()); | 2679 headers.stream_id()); |
2651 } | 2680 } |
2652 if (protocol_version() <= SPDY2) { | 2681 if (protocol_version() <= SPDY2) { |
2653 builder.WriteUInt16(0); // Unused. | 2682 builder.WriteUInt16(0); // Unused. |
2654 } | 2683 } |
2655 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); | 2684 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); |
2656 | 2685 |
2657 if (protocol_version() > SPDY3) { | 2686 if (protocol_version() > SPDY3) { |
| 2687 int padding_payload_len = 0; |
| 2688 if (headers.padded()) { |
| 2689 builder.WriteUInt8(headers.padding_payload_len()); |
| 2690 padding_payload_len = headers.padding_payload_len(); |
| 2691 } |
2658 if (headers.has_priority()) { | 2692 if (headers.has_priority()) { |
2659 // TODO(jgraettinger): Plumb priorities and stream dependencies. | 2693 // TODO(jgraettinger): Plumb priorities and stream dependencies. |
2660 builder.WriteUInt32(0); // Non-exclusive bit and root stream ID. | 2694 builder.WriteUInt32(0); // Non-exclusive bit and root stream ID. |
2661 builder.WriteUInt8(MapPriorityToWeight(priority)); | 2695 builder.WriteUInt8(MapPriorityToWeight(priority)); |
2662 } | 2696 } |
2663 WritePayloadWithContinuation(&builder, | 2697 WritePayloadWithContinuation(&builder, |
2664 hpack_encoding, | 2698 hpack_encoding, |
2665 headers.stream_id(), | 2699 headers.stream_id(), |
2666 HEADERS); | 2700 HEADERS, |
| 2701 padding_payload_len); |
2667 } else { | 2702 } else { |
2668 SerializeNameValueBlock(&builder, headers); | 2703 SerializeNameValueBlock(&builder, headers); |
2669 } | 2704 } |
2670 | 2705 |
2671 if (debug_visitor_) { | 2706 if (debug_visitor_) { |
2672 // SPDY4 uses HPACK for header compression. However, continue to | 2707 // SPDY4 uses HPACK for header compression. However, continue to |
2673 // use GetSerializedLength() for an apples-to-apples comparision of | 2708 // use GetSerializedLength() for an apples-to-apples comparision of |
2674 // compression performance between HPACK and SPDY w/ deflate. | 2709 // compression performance between HPACK and SPDY w/ deflate. |
2675 const size_t payload_len = | 2710 const size_t payload_len = |
2676 GetSerializedLength(protocol_version(), | 2711 GetSerializedLength(protocol_version(), |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2710 | 2745 |
2711 SpdyFrame* SpdyFramer::SerializePushPromise( | 2746 SpdyFrame* SpdyFramer::SerializePushPromise( |
2712 const SpdyPushPromiseIR& push_promise) { | 2747 const SpdyPushPromiseIR& push_promise) { |
2713 DCHECK_LT(SPDY3, protocol_version()); | 2748 DCHECK_LT(SPDY3, protocol_version()); |
2714 uint8 flags = 0; | 2749 uint8 flags = 0; |
2715 // This will get overwritten if we overflow into a CONTINUATION frame. | 2750 // This will get overwritten if we overflow into a CONTINUATION frame. |
2716 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 2751 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
2717 // The size of this frame, including variable-length name-value block. | 2752 // The size of this frame, including variable-length name-value block. |
2718 size_t size = GetPushPromiseMinimumSize(); | 2753 size_t size = GetPushPromiseMinimumSize(); |
2719 | 2754 |
| 2755 if (push_promise.padded()) { |
| 2756 flags |= PUSH_PROMISE_FLAG_PADDED; |
| 2757 size += kPadLengthFieldSize; |
| 2758 size += push_promise.padding_payload_len(); |
| 2759 } |
| 2760 |
2720 string hpack_encoding; | 2761 string hpack_encoding; |
2721 if (enable_compression_) { | 2762 if (enable_compression_) { |
2722 GetHpackEncoder()->EncodeHeaderSet( | 2763 GetHpackEncoder()->EncodeHeaderSet( |
2723 push_promise.name_value_block(), &hpack_encoding); | 2764 push_promise.name_value_block(), &hpack_encoding); |
2724 } else { | 2765 } else { |
2725 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( | 2766 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( |
2726 push_promise.name_value_block(), &hpack_encoding); | 2767 push_promise.name_value_block(), &hpack_encoding); |
2727 } | 2768 } |
2728 size += hpack_encoding.size(); | 2769 size += hpack_encoding.size(); |
2729 if (size > GetHeaderFragmentMaxSize()) { | 2770 if (size > GetHeaderFragmentMaxSize()) { |
2730 size += GetNumberRequiredContinuationFrames(size) * | 2771 size += GetNumberRequiredContinuationFrames(size) * |
2731 GetContinuationMinimumSize(); | 2772 GetContinuationMinimumSize(); |
2732 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 2773 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
2733 } | 2774 } |
2734 | 2775 |
2735 SpdyFrameBuilder builder(size, protocol_version()); | 2776 SpdyFrameBuilder builder(size, protocol_version()); |
2736 builder.BeginNewFrame(*this, | 2777 builder.BeginNewFrame(*this, |
2737 PUSH_PROMISE, | 2778 PUSH_PROMISE, |
2738 flags, | 2779 flags, |
2739 push_promise.stream_id()); | 2780 push_promise.stream_id()); |
2740 builder.WriteUInt32(push_promise.promised_stream_id()); | 2781 int padding_payload_len = 0; |
2741 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length()); | 2782 if (push_promise.padded()) { |
| 2783 builder.WriteUInt8(push_promise.padding_payload_len()); |
| 2784 builder.WriteUInt32(push_promise.promised_stream_id()); |
| 2785 DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize, |
| 2786 builder.length()); |
| 2787 |
| 2788 padding_payload_len = push_promise.padding_payload_len(); |
| 2789 } else { |
| 2790 builder.WriteUInt32(push_promise.promised_stream_id()); |
| 2791 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length()); |
| 2792 } |
2742 | 2793 |
2743 WritePayloadWithContinuation(&builder, | 2794 WritePayloadWithContinuation(&builder, |
2744 hpack_encoding, | 2795 hpack_encoding, |
2745 push_promise.stream_id(), | 2796 push_promise.stream_id(), |
2746 PUSH_PROMISE); | 2797 PUSH_PROMISE, |
| 2798 padding_payload_len); |
2747 | 2799 |
2748 if (debug_visitor_) { | 2800 if (debug_visitor_) { |
2749 // SPDY4 uses HPACK for header compression. However, continue to | 2801 // SPDY4 uses HPACK for header compression. However, continue to |
2750 // use GetSerializedLength() for an apples-to-apples comparision of | 2802 // use GetSerializedLength() for an apples-to-apples comparision of |
2751 // compression performance between HPACK and SPDY w/ deflate. | 2803 // compression performance between HPACK and SPDY w/ deflate. |
2752 const size_t payload_len = | 2804 const size_t payload_len = |
2753 GetSerializedLength(protocol_version(), | 2805 GetSerializedLength(protocol_version(), |
2754 &(push_promise.name_value_block())); | 2806 &(push_promise.name_value_block())); |
2755 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(), | 2807 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(), |
2756 PUSH_PROMISE, | 2808 PUSH_PROMISE, |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2916 const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize(); | 2968 const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize(); |
2917 DCHECK_GT(protocol_version(), SPDY3); | 2969 DCHECK_GT(protocol_version(), SPDY3); |
2918 DCHECK_GT(size, kMaxControlFrameSize); | 2970 DCHECK_GT(size, kMaxControlFrameSize); |
2919 size_t overflow = size - kMaxControlFrameSize; | 2971 size_t overflow = size - kMaxControlFrameSize; |
2920 return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1; | 2972 return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1; |
2921 } | 2973 } |
2922 | 2974 |
2923 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, | 2975 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, |
2924 const string& hpack_encoding, | 2976 const string& hpack_encoding, |
2925 SpdyStreamId stream_id, | 2977 SpdyStreamId stream_id, |
2926 SpdyFrameType type) { | 2978 SpdyFrameType type, |
| 2979 int padding_payload_len) { |
2927 const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize(); | 2980 const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize(); |
2928 | 2981 |
2929 // In addition to the prefix, fixed_field_size includes the size of | |
2930 // any fields that come before the variable-length name/value block. | |
2931 size_t fixed_field_size = 0; | |
2932 uint8 end_flag = 0; | 2982 uint8 end_flag = 0; |
2933 uint8 flags = 0; | 2983 uint8 flags = 0; |
2934 if (type == HEADERS) { | 2984 if (type == HEADERS) { |
2935 fixed_field_size = GetHeadersMinimumSize(); | |
2936 end_flag = HEADERS_FLAG_END_HEADERS; | 2985 end_flag = HEADERS_FLAG_END_HEADERS; |
2937 } else if (type == PUSH_PROMISE) { | 2986 } else if (type == PUSH_PROMISE) { |
2938 fixed_field_size = GetPushPromiseMinimumSize(); | |
2939 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 2987 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
2940 } else { | 2988 } else { |
2941 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " | 2989 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " |
2942 << FrameTypeToString(type); | 2990 << FrameTypeToString(type); |
2943 } | 2991 } |
2944 | 2992 |
2945 // Write as much of the payload as possible into the initial frame. | 2993 // Write all the padding payload and as much of the data payload as possible |
2946 size_t bytes_remaining = hpack_encoding.size() - | 2994 // into the initial frame. |
2947 std::min(hpack_encoding.size(), | 2995 size_t bytes_remaining = 0; |
2948 kMaxControlFrameSize - fixed_field_size); | 2996 bytes_remaining = hpack_encoding.size() - |
| 2997 std::min(hpack_encoding.size(), |
| 2998 kMaxControlFrameSize - builder->length() - |
| 2999 padding_payload_len); |
2949 builder->WriteBytes(&hpack_encoding[0], | 3000 builder->WriteBytes(&hpack_encoding[0], |
2950 hpack_encoding.size() - bytes_remaining); | 3001 hpack_encoding.size() - bytes_remaining); |
2951 | 3002 if (padding_payload_len > 0) { |
| 3003 string padding = string(padding_payload_len, 0); |
| 3004 builder->WriteBytes(padding.data(), padding.length()); |
| 3005 } |
2952 if (bytes_remaining > 0) { | 3006 if (bytes_remaining > 0) { |
2953 builder->OverwriteLength(*this, | 3007 builder->OverwriteLength(*this, |
2954 kMaxControlFrameSize - GetControlFrameHeaderSize()); | 3008 kMaxControlFrameSize - GetControlFrameHeaderSize()); |
2955 } | 3009 } |
2956 | 3010 |
2957 // Tack on CONTINUATION frames for the overflow. | 3011 // Tack on CONTINUATION frames for the overflow. |
2958 while (bytes_remaining > 0) { | 3012 while (bytes_remaining > 0) { |
2959 size_t bytes_to_write = std::min(bytes_remaining, | 3013 size_t bytes_to_write = std::min(bytes_remaining, |
2960 kMaxControlFrameSize - | 3014 kMaxControlFrameSize - |
2961 GetContinuationMinimumSize()); | 3015 GetContinuationMinimumSize()); |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3240 builder->Seek(compressed_size); | 3294 builder->Seek(compressed_size); |
3241 builder->RewriteLength(*this); | 3295 builder->RewriteLength(*this); |
3242 | 3296 |
3243 pre_compress_bytes.Add(uncompressed_len); | 3297 pre_compress_bytes.Add(uncompressed_len); |
3244 post_compress_bytes.Add(compressed_size); | 3298 post_compress_bytes.Add(compressed_size); |
3245 | 3299 |
3246 compressed_frames.Increment(); | 3300 compressed_frames.Increment(); |
3247 } | 3301 } |
3248 | 3302 |
3249 } // namespace net | 3303 } // namespace net |
OLD | NEW |