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 911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
922 size_t min_size = GetHeadersMinimumSize(); | 922 size_t min_size = GetHeadersMinimumSize(); |
923 if (protocol_version() > SPDY3 && | 923 if (protocol_version() > SPDY3 && |
924 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) { | 924 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) { |
925 min_size += 4; | 925 min_size += 4; |
926 } | 926 } |
927 if (current_frame_length_ < min_size) { | 927 if (current_frame_length_ < min_size) { |
928 set_error(SPDY_INVALID_CONTROL_FRAME); | 928 set_error(SPDY_INVALID_CONTROL_FRAME); |
929 } else if (protocol_version() <= SPDY3 && | 929 } else if (protocol_version() <= SPDY3 && |
930 current_frame_flags_ & ~CONTROL_FLAG_FIN) { | 930 current_frame_flags_ & ~CONTROL_FLAG_FIN) { |
931 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 931 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
932 } else if (protocol_version() > SPDY3 && current_frame_flags_ & | 932 } else if (protocol_version() > SPDY3 && |
933 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY | | 933 current_frame_flags_ & |
934 HEADERS_FLAG_END_HEADERS)) { | 934 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY | |
| 935 HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT | |
| 936 HEADERS_FLAG_PAD_LOW | HEADERS_FLAG_PAD_HIGH)) { |
935 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 937 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
936 } | 938 } |
937 } | 939 } |
938 break; | 940 break; |
939 case WINDOW_UPDATE: | 941 case WINDOW_UPDATE: |
940 if (current_frame_length_ != GetWindowUpdateSize()) { | 942 if (current_frame_length_ != GetWindowUpdateSize()) { |
941 set_error(SPDY_INVALID_CONTROL_FRAME); | 943 set_error(SPDY_INVALID_CONTROL_FRAME); |
942 } else if (current_frame_flags_ != 0) { | 944 } else if (current_frame_flags_ != 0) { |
943 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 945 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
944 } | 946 } |
945 break; | 947 break; |
946 case BLOCKED: | 948 case BLOCKED: |
947 if (current_frame_length_ != GetBlockedSize() || | 949 if (current_frame_length_ != GetBlockedSize() || |
948 protocol_version() <= SPDY3) { | 950 protocol_version() <= SPDY3) { |
949 // TODO(mlavan): BLOCKED frames are no longer part of SPDY4. | 951 // TODO(mlavan): BLOCKED frames are no longer part of SPDY4. |
950 set_error(SPDY_INVALID_CONTROL_FRAME); | 952 set_error(SPDY_INVALID_CONTROL_FRAME); |
951 } else if (current_frame_flags_ != 0) { | 953 } else if (current_frame_flags_ != 0) { |
952 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 954 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
953 } | 955 } |
954 break; | 956 break; |
955 case PUSH_PROMISE: | 957 case PUSH_PROMISE: |
956 if (current_frame_length_ < GetPushPromiseMinimumSize()) { | 958 if (current_frame_length_ < GetPushPromiseMinimumSize()) { |
957 set_error(SPDY_INVALID_CONTROL_FRAME); | 959 set_error(SPDY_INVALID_CONTROL_FRAME); |
958 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) { | 960 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) { |
959 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 961 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
960 } else if (protocol_version() > SPDY3 && current_frame_flags_ & | 962 } else if (protocol_version() > SPDY3 && |
961 ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE) { | 963 current_frame_flags_ & |
| 964 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | |
| 965 HEADERS_FLAG_PAD_LOW | HEADERS_FLAG_PAD_HIGH)) { |
962 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 966 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
963 } | 967 } |
964 break; | 968 break; |
965 case CONTINUATION: | 969 case CONTINUATION: |
966 if (current_frame_length_ < GetContinuationMinimumSize() || | 970 if (current_frame_length_ < GetContinuationMinimumSize() || |
967 protocol_version() <= SPDY3) { | 971 protocol_version() <= SPDY3) { |
968 set_error(SPDY_INVALID_CONTROL_FRAME); | 972 set_error(SPDY_INVALID_CONTROL_FRAME); |
969 } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) { | 973 } else if (current_frame_flags_ & |
| 974 ~(HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_PAD_LOW | |
| 975 HEADERS_FLAG_PAD_HIGH)) { |
970 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 976 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
971 } | 977 } |
972 break; | 978 break; |
973 case ALTSVC: | 979 case ALTSVC: |
974 if (current_frame_length_ <= GetAltSvcMinimumSize()) { | 980 if (current_frame_length_ <= GetAltSvcMinimumSize()) { |
975 set_error(SPDY_INVALID_CONTROL_FRAME); | 981 set_error(SPDY_INVALID_CONTROL_FRAME); |
976 } else if (current_frame_flags_ != 0) { | 982 } else if (current_frame_flags_ != 0) { |
977 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 983 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
978 } | 984 } |
979 break; | 985 break; |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1437 priority, | 1443 priority, |
1438 current_frame_flags_ & CONTROL_FLAG_FIN, | 1444 current_frame_flags_ & CONTROL_FLAG_FIN, |
1439 false); // unidirectional | 1445 false); // unidirectional |
1440 } else { | 1446 } else { |
1441 visitor_->OnHeaders( | 1447 visitor_->OnHeaders( |
1442 current_frame_stream_id_, | 1448 current_frame_stream_id_, |
1443 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, | 1449 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, |
1444 expect_continuation_ == 0); | 1450 expect_continuation_ == 0); |
1445 } | 1451 } |
1446 } | 1452 } |
1447 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); | 1453 CHANGE_STATE(SPDY_READ_PADDING_LENGTH); |
1448 break; | 1454 break; |
1449 case PUSH_PROMISE: | 1455 case PUSH_PROMISE: |
1450 { | 1456 { |
1451 DCHECK_LT(SPDY3, protocol_version()); | 1457 DCHECK_LT(SPDY3, protocol_version()); |
1452 if (current_frame_stream_id_ == 0) { | 1458 if (current_frame_stream_id_ == 0) { |
1453 set_error(SPDY_INVALID_CONTROL_FRAME); | 1459 set_error(SPDY_INVALID_CONTROL_FRAME); |
1454 break; | 1460 break; |
1455 } | 1461 } |
1456 SpdyStreamId promised_stream_id = kInvalidStream; | 1462 SpdyStreamId promised_stream_id = kInvalidStream; |
1457 bool successful_read = reader.ReadUInt31(&promised_stream_id); | 1463 bool successful_read = reader.ReadUInt31(&promised_stream_id); |
(...skipping 10 matching lines...) Expand all Loading... |
1468 debug_visitor_->OnReceiveCompressedFrame( | 1474 debug_visitor_->OnReceiveCompressedFrame( |
1469 current_frame_stream_id_, | 1475 current_frame_stream_id_, |
1470 current_frame_type_, | 1476 current_frame_type_, |
1471 current_frame_length_); | 1477 current_frame_length_); |
1472 } | 1478 } |
1473 visitor_->OnPushPromise(current_frame_stream_id_, | 1479 visitor_->OnPushPromise(current_frame_stream_id_, |
1474 promised_stream_id, | 1480 promised_stream_id, |
1475 (current_frame_flags_ & | 1481 (current_frame_flags_ & |
1476 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0); | 1482 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0); |
1477 } | 1483 } |
1478 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); | 1484 CHANGE_STATE(SPDY_READ_PADDING_LENGTH); |
1479 break; | 1485 break; |
1480 case CONTINUATION: | 1486 case CONTINUATION: |
1481 { | 1487 { |
1482 // Check to make sure the stream id of the current frame is | 1488 // Check to make sure the stream id of the current frame is |
1483 // the same as that of the preceding frame. | 1489 // the same as that of the preceding frame. |
1484 // If we're at this point we should already know that | 1490 // If we're at this point we should already know that |
1485 // expect_continuation_ != 0, so this doubles as a check | 1491 // expect_continuation_ != 0, so this doubles as a check |
1486 // that current_frame_stream_id != 0. | 1492 // that current_frame_stream_id != 0. |
1487 if (current_frame_stream_id_ != expect_continuation_) { | 1493 if (current_frame_stream_id_ != expect_continuation_) { |
1488 set_error(SPDY_INVALID_CONTROL_FRAME); | 1494 set_error(SPDY_INVALID_CONTROL_FRAME); |
1489 break; | 1495 break; |
1490 } | 1496 } |
1491 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) { | 1497 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) { |
1492 expect_continuation_ = 0; | 1498 expect_continuation_ = 0; |
1493 } | 1499 } |
1494 if (debug_visitor_) { | 1500 if (debug_visitor_) { |
1495 debug_visitor_->OnReceiveCompressedFrame( | 1501 debug_visitor_->OnReceiveCompressedFrame( |
1496 current_frame_stream_id_, | 1502 current_frame_stream_id_, |
1497 current_frame_type_, | 1503 current_frame_type_, |
1498 current_frame_length_); | 1504 current_frame_length_); |
1499 } | 1505 } |
1500 visitor_->OnContinuation(current_frame_stream_id_, | 1506 visitor_->OnContinuation(current_frame_stream_id_, |
1501 (current_frame_flags_ & | 1507 (current_frame_flags_ & |
1502 HEADERS_FLAG_END_HEADERS) != 0); | 1508 HEADERS_FLAG_END_HEADERS) != 0); |
1503 } | 1509 } |
1504 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); | 1510 CHANGE_STATE(SPDY_READ_PADDING_LENGTH); |
1505 break; | 1511 break; |
1506 default: | 1512 default: |
1507 DCHECK(false); | 1513 DCHECK(false); |
1508 } | 1514 } |
1509 } | 1515 } |
1510 return original_len - len; | 1516 return original_len - len; |
1511 } | 1517 } |
1512 | 1518 |
1513 // Does not buffer the control payload. Instead, either passes directly to the | 1519 // Does not buffer the control payload. Instead, either passes directly to the |
1514 // visitor or decompresses and then passes directly to the visitor, via | 1520 // visitor or decompresses and then passes directly to the visitor, via |
1515 // IncrementallyDeliverControlFrameHeaderData() or | 1521 // IncrementallyDeliverControlFrameHeaderData() or |
1516 // IncrementallyDecompressControlFrameHeaderData() respectively. | 1522 // IncrementallyDecompressControlFrameHeaderData() respectively. |
1517 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, | 1523 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, |
1518 size_t data_len, | 1524 size_t data_len, |
1519 bool is_hpack_header_block) { | 1525 bool is_hpack_header_block) { |
1520 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); | 1526 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); |
1521 | 1527 |
1522 bool processed_successfully = true; | 1528 bool processed_successfully = true; |
1523 if (current_frame_type_ != SYN_STREAM && | 1529 if (current_frame_type_ != SYN_STREAM && |
1524 current_frame_type_ != SYN_REPLY && | 1530 current_frame_type_ != SYN_REPLY && |
1525 current_frame_type_ != HEADERS && | 1531 current_frame_type_ != HEADERS && |
1526 current_frame_type_ != PUSH_PROMISE && | 1532 current_frame_type_ != PUSH_PROMISE && |
1527 current_frame_type_ != CONTINUATION) { | 1533 current_frame_type_ != CONTINUATION) { |
1528 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; | 1534 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; |
1529 } | 1535 } |
1530 size_t process_bytes = std::min(data_len, remaining_data_length_); | 1536 size_t process_bytes = std::min( |
| 1537 data_len, remaining_data_length_ - remaining_padding_payload_length_); |
1531 if (is_hpack_header_block) { | 1538 if (is_hpack_header_block) { |
1532 if (!GetHpackDecoder()->HandleControlFrameHeadersData( | 1539 if (!GetHpackDecoder()->HandleControlFrameHeadersData( |
1533 current_frame_stream_id_, data, process_bytes)) { | 1540 current_frame_stream_id_, data, process_bytes)) { |
1534 // TODO(jgraettinger): Finer-grained HPACK error codes. | 1541 // TODO(jgraettinger): Finer-grained HPACK error codes. |
1535 set_error(SPDY_DECOMPRESS_FAILURE); | 1542 set_error(SPDY_DECOMPRESS_FAILURE); |
1536 processed_successfully = false; | 1543 processed_successfully = false; |
1537 } | 1544 } |
1538 } else if (process_bytes > 0) { | 1545 } else if (process_bytes > 0) { |
1539 if (enable_compression_ && protocol_version() <= SPDY3) { | 1546 if (enable_compression_ && protocol_version() <= SPDY3) { |
1540 processed_successfully = IncrementallyDecompressControlFrameHeaderData( | 1547 processed_successfully = IncrementallyDecompressControlFrameHeaderData( |
1541 current_frame_stream_id_, data, process_bytes); | 1548 current_frame_stream_id_, data, process_bytes); |
1542 } else { | 1549 } else { |
1543 processed_successfully = IncrementallyDeliverControlFrameHeaderData( | 1550 processed_successfully = IncrementallyDeliverControlFrameHeaderData( |
1544 current_frame_stream_id_, data, process_bytes); | 1551 current_frame_stream_id_, data, process_bytes); |
1545 } | 1552 } |
1546 } | 1553 } |
1547 remaining_data_length_ -= process_bytes; | 1554 remaining_data_length_ -= process_bytes; |
1548 | 1555 |
1549 // Handle the case that there is no futher data in this frame. | 1556 // Handle the case that there is no futher data in this frame. |
1550 if (remaining_data_length_ == 0 && processed_successfully) { | 1557 if (remaining_data_length_ == remaining_padding_payload_length_ && |
| 1558 processed_successfully) { |
1551 if (expect_continuation_ == 0) { | 1559 if (expect_continuation_ == 0) { |
1552 if (is_hpack_header_block) { | 1560 if (is_hpack_header_block) { |
1553 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete( | 1561 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete( |
1554 current_frame_stream_id_)) { | 1562 current_frame_stream_id_)) { |
1555 set_error(SPDY_DECOMPRESS_FAILURE); | 1563 set_error(SPDY_DECOMPRESS_FAILURE); |
1556 processed_successfully = false; | 1564 processed_successfully = false; |
1557 } else { | 1565 } else { |
1558 // TODO(jgraettinger): To be removed with migration to | 1566 // TODO(jgraettinger): To be removed with migration to |
1559 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3 | 1567 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3 |
1560 // block, delivered via reentrant call to | 1568 // block, delivered via reentrant call to |
1561 // ProcessControlFrameHeaderBlock(). | 1569 // ProcessControlFrameHeaderBlock(). |
1562 DeliverHpackBlockAsSpdy3Block(); | 1570 DeliverHpackBlockAsSpdy3Block(); |
1563 return process_bytes; | 1571 return process_bytes; |
1564 } | 1572 } |
1565 } else { | 1573 } else { |
1566 // The complete header block has been delivered. We send a zero-length | 1574 // The complete header block has been delivered. We send a zero-length |
1567 // OnControlFrameHeaderData() to indicate this. | 1575 // OnControlFrameHeaderData() to indicate this. |
1568 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0); | 1576 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0); |
1569 } | 1577 } |
1570 // If this is a FIN, tell the caller. | |
1571 if ((current_frame_flags_ & CONTROL_FLAG_FIN) || end_stream_when_done_) { | |
1572 end_stream_when_done_ = false; | |
1573 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); | |
1574 } | |
1575 } | 1578 } |
1576 if (processed_successfully) | 1579 if (processed_successfully) { |
1577 CHANGE_STATE(SPDY_AUTO_RESET); | 1580 CHANGE_STATE(SPDY_CONSUME_PADDING); |
| 1581 } |
1578 } | 1582 } |
1579 | 1583 |
1580 // Handle error. | 1584 // Handle error. |
1581 if (!processed_successfully) { | 1585 if (!processed_successfully) { |
1582 return data_len; | 1586 return data_len; |
1583 } | 1587 } |
1584 | 1588 |
1585 // Return amount processed. | 1589 // Return amount processed. |
1586 return process_bytes; | 1590 return process_bytes; |
1587 } | 1591 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1637 if (remaining_data_length_ == 0) { | 1641 if (remaining_data_length_ == 0) { |
1638 visitor_->OnSettingsEnd(); | 1642 visitor_->OnSettingsEnd(); |
1639 CHANGE_STATE(SPDY_AUTO_RESET); | 1643 CHANGE_STATE(SPDY_AUTO_RESET); |
1640 } | 1644 } |
1641 | 1645 |
1642 return processed_bytes; | 1646 return processed_bytes; |
1643 } | 1647 } |
1644 | 1648 |
1645 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() { | 1649 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() { |
1646 DCHECK_LT(SPDY3, protocol_version()); | 1650 DCHECK_LT(SPDY3, protocol_version()); |
1647 DCHECK_EQ(0u, remaining_data_length_); | 1651 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_); |
1648 | 1652 |
1649 const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block(); | 1653 const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block(); |
1650 if (block.empty()) { | 1654 if (block.empty()) { |
1651 // Special-case this to make tests happy. | 1655 // Special-case this to make tests happy. |
1652 ProcessControlFrameHeaderBlock(NULL, 0, false); | 1656 ProcessControlFrameHeaderBlock(NULL, 0, false); |
1653 return; | 1657 return; |
1654 } | 1658 } |
1655 SpdyFrameBuilder builder( | 1659 SpdyFrameBuilder builder( |
1656 GetSerializedLength(protocol_version(), &block), | 1660 GetSerializedLength(protocol_version(), &block), |
1657 SPDY3); | 1661 SPDY3); |
1658 | 1662 |
1659 SerializeNameValueBlockWithoutCompression(&builder, block); | 1663 SerializeNameValueBlockWithoutCompression(&builder, block); |
1660 scoped_ptr<SpdyFrame> frame(builder.take()); | 1664 scoped_ptr<SpdyFrame> frame(builder.take()); |
1661 | 1665 |
| 1666 // Preserve padding length, and reset it after the re-entrant call. |
| 1667 size_t remaining_padding = remaining_padding_payload_length_; |
| 1668 |
| 1669 remaining_padding_payload_length_ = 0; |
1662 remaining_data_length_ = frame->size(); | 1670 remaining_data_length_ = frame->size(); |
| 1671 |
1663 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false); | 1672 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false); |
| 1673 |
| 1674 remaining_padding_payload_length_ = remaining_padding; |
| 1675 remaining_data_length_ = remaining_padding; |
1664 } | 1676 } |
1665 | 1677 |
1666 bool SpdyFramer::ProcessSetting(const char* data) { | 1678 bool SpdyFramer::ProcessSetting(const char* data) { |
1667 int id_field; | 1679 int id_field; |
1668 SpdySettingsIds id; | 1680 SpdySettingsIds id; |
1669 uint8 flags = 0; | 1681 uint8 flags = 0; |
1670 uint32 value; | 1682 uint32 value; |
1671 | 1683 |
1672 // Extract fields. | 1684 // Extract fields. |
1673 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id. | 1685 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id. |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2076 --len; | 2088 --len; |
2077 --remaining_padding_length_fields_; | 2089 --remaining_padding_length_fields_; |
2078 --remaining_data_length_; | 2090 --remaining_data_length_; |
2079 } | 2091 } |
2080 | 2092 |
2081 if (remaining_padding_length_fields_ == 0) { | 2093 if (remaining_padding_length_fields_ == 0) { |
2082 if (remaining_padding_payload_length_ > remaining_data_length_) { | 2094 if (remaining_padding_payload_length_ > remaining_data_length_) { |
2083 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); | 2095 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); |
2084 return 0; | 2096 return 0; |
2085 } | 2097 } |
2086 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); | 2098 if (current_frame_type_ == DATA) { |
| 2099 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); |
| 2100 } else { |
| 2101 DCHECK(current_frame_type_ == HEADERS || |
| 2102 current_frame_type_ == PUSH_PROMISE || |
| 2103 current_frame_type_ == CONTINUATION || |
| 2104 current_frame_type_ == SYN_STREAM || |
| 2105 current_frame_type_ == SYN_REPLY) |
| 2106 << current_frame_type_; |
| 2107 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); |
| 2108 } |
2087 } | 2109 } |
2088 return original_len - len; | 2110 return original_len - len; |
2089 } | 2111 } |
2090 | 2112 |
2091 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) { | 2113 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) { |
2092 DCHECK_EQ(SPDY_CONSUME_PADDING, state_); | 2114 DCHECK_EQ(SPDY_CONSUME_PADDING, state_); |
2093 | 2115 |
2094 size_t original_len = len; | 2116 size_t original_len = len; |
2095 if (remaining_padding_payload_length_ > 0) { | 2117 if (remaining_padding_payload_length_ > 0) { |
2096 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_); | 2118 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_); |
2097 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len); | 2119 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len); |
2098 // The visitor needs to know about padding so it can send window updates. | 2120 if (current_frame_type_ == DATA && amount_to_discard > 0) { |
2099 // Communicate the padding to the visitor through a NULL data pointer, with | 2121 // The visitor needs to know about padding so it can send window updates. |
2100 // a nonzero size. | 2122 // Communicate the padding to the visitor through a NULL data pointer, |
2101 if (amount_to_discard) { | 2123 // with a nonzero size. |
2102 visitor_->OnStreamFrameData( | 2124 visitor_->OnStreamFrameData( |
2103 current_frame_stream_id_, NULL, amount_to_discard, false); | 2125 current_frame_stream_id_, NULL, amount_to_discard, false); |
2104 } | 2126 } |
2105 data += amount_to_discard; | 2127 data += amount_to_discard; |
2106 len -= amount_to_discard; | 2128 len -= amount_to_discard; |
2107 remaining_padding_payload_length_ -= amount_to_discard; | 2129 remaining_padding_payload_length_ -= amount_to_discard; |
2108 remaining_data_length_ -= amount_to_discard; | 2130 remaining_data_length_ -= amount_to_discard; |
2109 } | 2131 } |
2110 | 2132 |
2111 if (remaining_data_length_ == 0) { | 2133 if (remaining_data_length_ == 0) { |
2112 // If the FIN flag is set, and there is no more data in this data frame, | 2134 // If the FIN flag is set, or this ends a header block which set FIN, |
2113 // inform the visitor of EOF via a 0-length data frame. | 2135 // inform the visitor of EOF via a 0-length data frame. |
2114 if (current_frame_flags_ & DATA_FLAG_FIN) { | 2136 if (expect_continuation_ == 0 && |
| 2137 ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 || |
| 2138 end_stream_when_done_)) { |
| 2139 end_stream_when_done_ = false; |
2115 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); | 2140 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); |
2116 } | 2141 } |
2117 | |
2118 CHANGE_STATE(SPDY_AUTO_RESET); | 2142 CHANGE_STATE(SPDY_AUTO_RESET); |
2119 } | 2143 } |
2120 return original_len - len; | 2144 return original_len - len; |
2121 } | 2145 } |
2122 | 2146 |
2123 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { | 2147 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { |
2124 size_t original_len = len; | 2148 size_t original_len = len; |
2125 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) { | 2149 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) { |
2126 size_t amount_to_forward = std::min( | 2150 size_t amount_to_forward = std::min( |
2127 remaining_data_length_ - remaining_padding_payload_length_, len); | 2151 remaining_data_length_ - remaining_padding_payload_length_, len); |
(...skipping 1082 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3210 builder->Seek(compressed_size); | 3234 builder->Seek(compressed_size); |
3211 builder->RewriteLength(*this); | 3235 builder->RewriteLength(*this); |
3212 | 3236 |
3213 pre_compress_bytes.Add(uncompressed_len); | 3237 pre_compress_bytes.Add(uncompressed_len); |
3214 post_compress_bytes.Add(compressed_size); | 3238 post_compress_bytes.Add(compressed_size); |
3215 | 3239 |
3216 compressed_frames.Increment(); | 3240 compressed_frames.Increment(); |
3217 } | 3241 } |
3218 | 3242 |
3219 } // namespace net | 3243 } // namespace net |
OLD | NEW |