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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 } // namespace | 73 } // namespace |
74 | 74 |
75 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1); | 75 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1); |
76 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; | 76 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; |
| 77 // The size of the control frame buffer. Must be >= the minimum size of the |
77 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for | 78 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for |
78 // calculation details. | 79 // calculation details. |
79 const size_t SpdyFramer::kControlFrameBufferSize = 18; | 80 const size_t SpdyFramer::kControlFrameBufferSize = 19; |
80 | 81 |
81 #ifdef DEBUG_SPDY_STATE_CHANGES | 82 #ifdef DEBUG_SPDY_STATE_CHANGES |
82 #define CHANGE_STATE(newstate) \ | 83 #define CHANGE_STATE(newstate) \ |
83 do { \ | 84 do { \ |
84 DVLOG(1) << "Changing state from: " \ | 85 DVLOG(1) << "Changing state from: " \ |
85 << StateToString(state_) \ | 86 << StateToString(state_) \ |
86 << " to " << StateToString(newstate) << "\n"; \ | 87 << " to " << StateToString(newstate) << "\n"; \ |
87 DCHECK(state_ != SPDY_ERROR); \ | 88 DCHECK(state_ != SPDY_ERROR); \ |
88 DCHECK_EQ(previous_state_, state_); \ | 89 DCHECK_EQ(previous_state_, state_); \ |
89 previous_state_ = state_; \ | 90 previous_state_ = state_; \ |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 current_frame_type_ = DATA; | 182 current_frame_type_ = DATA; |
182 current_frame_flags_ = 0; | 183 current_frame_flags_ = 0; |
183 current_frame_length_ = 0; | 184 current_frame_length_ = 0; |
184 current_frame_stream_id_ = kInvalidStream; | 185 current_frame_stream_id_ = kInvalidStream; |
185 settings_scratch_.Reset(); | 186 settings_scratch_.Reset(); |
186 altsvc_scratch_.Reset(); | 187 altsvc_scratch_.Reset(); |
187 remaining_padding_payload_length_ = 0; | 188 remaining_padding_payload_length_ = 0; |
188 } | 189 } |
189 | 190 |
190 size_t SpdyFramer::GetDataFrameMinimumSize() const { | 191 size_t SpdyFramer::GetDataFrameMinimumSize() const { |
191 return SpdyConstants::GetDataFrameMinimumSize(); | 192 return SpdyConstants::GetDataFrameMinimumSize(protocol_version()); |
192 } | 193 } |
193 | 194 |
194 // Size, in bytes, of the control frame header. | 195 // Size, in bytes, of the control frame header. |
195 size_t SpdyFramer::GetControlFrameHeaderSize() const { | 196 size_t SpdyFramer::GetControlFrameHeaderSize() const { |
196 return SpdyConstants::GetControlFrameHeaderSize(protocol_version()); | 197 return SpdyConstants::GetControlFrameHeaderSize(protocol_version()); |
197 } | 198 } |
198 | 199 |
199 size_t SpdyFramer::GetSynStreamMinimumSize() const { | 200 size_t SpdyFramer::GetSynStreamMinimumSize() const { |
200 // Size, in bytes, of a SYN_STREAM frame not including the variable-length | 201 // Size, in bytes, of a SYN_STREAM frame not including the variable-length |
201 // name-value block. | 202 // name-value block. |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 case PING: | 491 case PING: |
491 return "PING"; | 492 return "PING"; |
492 case GOAWAY: | 493 case GOAWAY: |
493 return "GOAWAY"; | 494 return "GOAWAY"; |
494 case HEADERS: | 495 case HEADERS: |
495 return "HEADERS"; | 496 return "HEADERS"; |
496 case WINDOW_UPDATE: | 497 case WINDOW_UPDATE: |
497 return "WINDOW_UPDATE"; | 498 return "WINDOW_UPDATE"; |
498 case CREDENTIAL: | 499 case CREDENTIAL: |
499 return "CREDENTIAL"; | 500 return "CREDENTIAL"; |
500 case BLOCKED: | |
501 return "BLOCKED"; | |
502 case PUSH_PROMISE: | 501 case PUSH_PROMISE: |
503 return "PUSH_PROMISE"; | 502 return "PUSH_PROMISE"; |
504 case CONTINUATION: | 503 case CONTINUATION: |
505 return "CONTINUATION"; | 504 return "CONTINUATION"; |
| 505 case PRIORITY: |
| 506 return "PRIORITY"; |
506 case ALTSVC: | 507 case ALTSVC: |
507 return "ALTSVC"; | 508 return "ALTSVC"; |
508 case PRIORITY: | 509 case BLOCKED: |
509 return "PRIORITY"; | 510 return "BLOCKED"; |
510 } | 511 } |
511 return "UNKNOWN_CONTROL_TYPE"; | 512 return "UNKNOWN_CONTROL_TYPE"; |
512 } | 513 } |
513 | 514 |
514 size_t SpdyFramer::ProcessInput(const char* data, size_t len) { | 515 size_t SpdyFramer::ProcessInput(const char* data, size_t len) { |
515 DCHECK(visitor_); | 516 DCHECK(visitor_); |
516 DCHECK(data); | 517 DCHECK(data); |
517 | 518 |
518 size_t original_len = len; | 519 size_t original_len = len; |
519 do { | 520 do { |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 successful_read = reader->ReadUInt8(¤t_frame_flags_); | 716 successful_read = reader->ReadUInt8(¤t_frame_flags_); |
716 DCHECK(successful_read); | 717 DCHECK(successful_read); |
717 | 718 |
718 uint32 length_field = 0; | 719 uint32 length_field = 0; |
719 successful_read = reader->ReadUInt24(&length_field); | 720 successful_read = reader->ReadUInt24(&length_field); |
720 DCHECK(successful_read); | 721 DCHECK(successful_read); |
721 remaining_data_length_ = length_field; | 722 remaining_data_length_ = length_field; |
722 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed(); | 723 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed(); |
723 } else { | 724 } else { |
724 version = protocol_version(); | 725 version = protocol_version(); |
725 uint16 length_field = 0; | 726 uint32 length_field = 0; |
726 bool successful_read = reader->ReadUInt16(&length_field); | 727 bool successful_read = reader->ReadUInt24(&length_field); |
727 DCHECK(successful_read); | 728 DCHECK(successful_read); |
728 | 729 |
729 uint8 control_frame_type_field_uint8 = | 730 uint8 control_frame_type_field_uint8 = |
730 SpdyConstants::DataFrameType(protocol_version()); | 731 SpdyConstants::DataFrameType(protocol_version()); |
731 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8); | 732 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8); |
732 DCHECK(successful_read); | 733 DCHECK(successful_read); |
733 // We check control_frame_type_field's validity in | 734 // We check control_frame_type_field's validity in |
734 // ProcessControlFrameHeader(). | 735 // ProcessControlFrameHeader(). |
735 control_frame_type_field = control_frame_type_field_uint8; | 736 control_frame_type_field = control_frame_type_field_uint8; |
736 is_control_frame = (protocol_version() > SPDY3) ? | 737 is_control_frame = (protocol_version() > SPDY3) ? |
737 control_frame_type_field != | 738 control_frame_type_field != |
738 SpdyConstants::SerializeFrameType(protocol_version(), DATA) : | 739 SpdyConstants::SerializeFrameType(protocol_version(), DATA) : |
739 control_frame_type_field != 0; | 740 control_frame_type_field != 0; |
740 | 741 |
741 if (is_control_frame) { | 742 if (is_control_frame) { |
742 current_frame_length_ = length_field + GetControlFrameHeaderSize(); | 743 current_frame_length_ = length_field + GetControlFrameHeaderSize(); |
743 } else { | 744 } else { |
744 current_frame_length_ = length_field + GetDataFrameMinimumSize(); | 745 current_frame_length_ = length_field + GetDataFrameMinimumSize(); |
745 } | 746 } |
746 | 747 |
747 successful_read = reader->ReadUInt8(¤t_frame_flags_); | 748 successful_read = reader->ReadUInt8(¤t_frame_flags_); |
748 DCHECK(successful_read); | 749 DCHECK(successful_read); |
749 | 750 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
830 } | 831 } |
831 | 832 |
832 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { | 833 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { |
833 DCHECK_EQ(SPDY_NO_ERROR, error_code_); | 834 DCHECK_EQ(SPDY_NO_ERROR, error_code_); |
834 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_); | 835 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_); |
835 | 836 |
836 // TODO(mlavan): Either remove credential frames from the code entirely, | 837 // TODO(mlavan): Either remove credential frames from the code entirely, |
837 // or add them to parsing + serialization methods for SPDY3. | 838 // or add them to parsing + serialization methods for SPDY3. |
838 // Early detection of deprecated frames that we ignore. | 839 // Early detection of deprecated frames that we ignore. |
839 if (protocol_version() <= SPDY3) { | 840 if (protocol_version() <= SPDY3) { |
840 | |
841 if (control_frame_type_field == CREDENTIAL) { | 841 if (control_frame_type_field == CREDENTIAL) { |
842 current_frame_type_ = CREDENTIAL; | 842 current_frame_type_ = CREDENTIAL; |
843 DCHECK_EQ(SPDY3, protocol_version()); | 843 DCHECK_EQ(SPDY3, protocol_version()); |
844 DVLOG(1) << "CREDENTIAL control frame found. Ignoring."; | 844 DVLOG(1) << "CREDENTIAL control frame found. Ignoring."; |
845 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); | 845 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); |
846 return; | 846 return; |
847 } | 847 } |
848 } | 848 } |
849 | 849 |
850 if (!SpdyConstants::IsValidFrameType(protocol_version(), | 850 if (!SpdyConstants::IsValidFrameType(protocol_version(), |
851 control_frame_type_field)) { | 851 control_frame_type_field)) { |
852 DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field | 852 if (protocol_version() <= SPDY3) { |
853 << " (protocol version: " << protocol_version() << ")"; | 853 DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field |
854 set_error(SPDY_INVALID_CONTROL_FRAME); | 854 << " (protocol version: " << protocol_version() << ")"; |
855 return; | 855 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 856 return; |
| 857 } else { |
| 858 // In HTTP2 we ignore unknown frame types for extensibility, as long as |
| 859 // the rest of the control frame header is valid. |
| 860 // We rely on the visitor to check validity of current_frame_stream_id_. |
| 861 bool valid_stream = visitor_->OnUnknownFrame(current_frame_stream_id_, |
| 862 control_frame_type_field); |
| 863 if (valid_stream) { |
| 864 DVLOG(1) << "Ignoring unknown frame type."; |
| 865 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); |
| 866 } else { |
| 867 // Report an invalid frame error and close the stream if the |
| 868 // stream_id is not valid. |
| 869 DLOG(WARNING) << "Unknown control frame type " |
| 870 << control_frame_type_field |
| 871 << " received on invalid stream " |
| 872 << current_frame_stream_id_; |
| 873 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 874 } |
| 875 return; |
| 876 } |
856 } | 877 } |
857 | 878 |
858 current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(), | 879 current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(), |
859 control_frame_type_field); | 880 control_frame_type_field); |
860 | 881 |
861 // Do some sanity checking on the control frame sizes and flags. | 882 // Do some sanity checking on the control frame sizes and flags. |
862 switch (current_frame_type_) { | 883 switch (current_frame_type_) { |
863 case SYN_STREAM: | 884 case SYN_STREAM: |
864 if (current_frame_length_ < GetSynStreamMinimumSize()) { | 885 if (current_frame_length_ < GetSynStreamMinimumSize()) { |
865 set_error(SPDY_INVALID_CONTROL_FRAME); | 886 set_error(SPDY_INVALID_CONTROL_FRAME); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
940 break; | 961 break; |
941 } | 962 } |
942 case HEADERS: | 963 case HEADERS: |
943 { | 964 { |
944 size_t min_size = GetHeadersMinimumSize(); | 965 size_t min_size = GetHeadersMinimumSize(); |
945 if (protocol_version() > SPDY3 && | 966 if (protocol_version() > SPDY3 && |
946 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) { | 967 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) { |
947 min_size += 4; | 968 min_size += 4; |
948 } | 969 } |
949 if (current_frame_length_ < min_size) { | 970 if (current_frame_length_ < min_size) { |
| 971 // TODO(mlavan): check here for HEADERS with no payload? |
| 972 // (not allowed in SPDY4) |
950 set_error(SPDY_INVALID_CONTROL_FRAME); | 973 set_error(SPDY_INVALID_CONTROL_FRAME); |
951 } else if (protocol_version() <= SPDY3 && | 974 } else if (protocol_version() <= SPDY3 && |
952 current_frame_flags_ & ~CONTROL_FLAG_FIN) { | 975 current_frame_flags_ & ~CONTROL_FLAG_FIN) { |
953 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 976 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
954 } else if (protocol_version() > SPDY3 && | 977 } else if (protocol_version() > SPDY3 && |
955 current_frame_flags_ & | 978 current_frame_flags_ & |
956 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY | | 979 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY | |
957 HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT | | 980 HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT | |
958 HEADERS_FLAG_PADDED)) { | 981 HEADERS_FLAG_PADDED)) { |
959 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 982 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
960 } | 983 } |
961 } | 984 } |
962 break; | 985 break; |
963 case WINDOW_UPDATE: | 986 case WINDOW_UPDATE: |
964 if (current_frame_length_ != GetWindowUpdateSize()) { | 987 if (current_frame_length_ != GetWindowUpdateSize()) { |
965 set_error(SPDY_INVALID_CONTROL_FRAME); | 988 set_error(SPDY_INVALID_CONTROL_FRAME); |
966 } else if (current_frame_flags_ != 0) { | 989 } else if (current_frame_flags_ != 0) { |
967 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 990 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
968 } | 991 } |
969 break; | 992 break; |
970 case BLOCKED: | 993 case BLOCKED: |
971 if (current_frame_length_ != GetBlockedSize() || | 994 if (current_frame_length_ != GetBlockedSize() || |
972 protocol_version() <= SPDY3) { | 995 protocol_version() <= SPDY3) { |
973 // TODO(mlavan): BLOCKED frames are no longer part of SPDY4. | |
974 set_error(SPDY_INVALID_CONTROL_FRAME); | 996 set_error(SPDY_INVALID_CONTROL_FRAME); |
975 } else if (current_frame_flags_ != 0) { | 997 } else if (current_frame_flags_ != 0) { |
976 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 998 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
977 } | 999 } |
978 break; | 1000 break; |
979 case PUSH_PROMISE: | 1001 case PUSH_PROMISE: |
980 if (current_frame_length_ < GetPushPromiseMinimumSize()) { | 1002 if (current_frame_length_ < GetPushPromiseMinimumSize()) { |
981 set_error(SPDY_INVALID_CONTROL_FRAME); | 1003 set_error(SPDY_INVALID_CONTROL_FRAME); |
982 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) { | 1004 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) { |
983 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 1005 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1725 flags = id_and_flags.flags(); | 1747 flags = id_and_flags.flags(); |
1726 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4))); | 1748 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4))); |
1727 } else { | 1749 } else { |
1728 id_field = ntohs(*(reinterpret_cast<const uint16*>(data))); | 1750 id_field = ntohs(*(reinterpret_cast<const uint16*>(data))); |
1729 value = ntohl(*(reinterpret_cast<const uint32*>(data + 2))); | 1751 value = ntohl(*(reinterpret_cast<const uint32*>(data + 2))); |
1730 } | 1752 } |
1731 | 1753 |
1732 // Validate id. | 1754 // Validate id. |
1733 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) { | 1755 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) { |
1734 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field; | 1756 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field; |
1735 return false; | 1757 if (protocol_version() <= SPDY3) { |
| 1758 return false; |
| 1759 } else { |
| 1760 // In HTTP2 we ignore unknown settings for extensibility. |
| 1761 return true; |
| 1762 } |
1736 } | 1763 } |
1737 id = SpdyConstants::ParseSettingId(protocol_version(), id_field); | 1764 id = SpdyConstants::ParseSettingId(protocol_version(), id_field); |
1738 | 1765 |
1739 if (protocol_version() <= SPDY3) { | 1766 if (protocol_version() <= SPDY3) { |
1740 // Detect duplicates. | 1767 // Detect duplicates. |
1741 if (id <= settings_scratch_.last_setting_id) { | 1768 if (id <= settings_scratch_.last_setting_id) { |
1742 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id | 1769 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id |
1743 << " in " << display_protocol_ << " SETTINGS frame " | 1770 << " in " << display_protocol_ << " SETTINGS frame " |
1744 << "(last setting id was " | 1771 << "(last setting id was " |
1745 << settings_scratch_.last_setting_id << ")."; | 1772 << settings_scratch_.last_setting_id << ")."; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1870 SpdyGoAwayStatus status = GOAWAY_OK; | 1897 SpdyGoAwayStatus status = GOAWAY_OK; |
1871 if (protocol_version() >= SPDY3) { | 1898 if (protocol_version() >= SPDY3) { |
1872 uint32 status_raw = GOAWAY_OK; | 1899 uint32 status_raw = GOAWAY_OK; |
1873 successful_read = reader.ReadUInt32(&status_raw); | 1900 successful_read = reader.ReadUInt32(&status_raw); |
1874 DCHECK(successful_read); | 1901 DCHECK(successful_read); |
1875 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(), | 1902 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(), |
1876 status_raw)) { | 1903 status_raw)) { |
1877 status = SpdyConstants::ParseGoAwayStatus(protocol_version(), | 1904 status = SpdyConstants::ParseGoAwayStatus(protocol_version(), |
1878 status_raw); | 1905 status_raw); |
1879 } else { | 1906 } else { |
1880 DCHECK(false); | |
1881 // Throw an error for SPDY4+, keep liberal behavior | |
1882 // for earlier versions. | |
1883 if (protocol_version() > SPDY3) { | 1907 if (protocol_version() > SPDY3) { |
1884 DLOG(WARNING) << "Invalid GO_AWAY status " << status_raw; | 1908 // Treat unrecognized status codes as INTERNAL_ERROR as |
1885 set_error(SPDY_INVALID_CONTROL_FRAME); | 1909 // recommended by the HTTP/2 spec. |
1886 return 0; | 1910 status = GOAWAY_INTERNAL_ERROR; |
1887 } | 1911 } |
1888 } | 1912 } |
1889 } | 1913 } |
1890 // Finished parsing the GOAWAY header, call frame handler. | 1914 // Finished parsing the GOAWAY header, call frame handler. |
1891 visitor_->OnGoAway(current_frame_stream_id_, status); | 1915 visitor_->OnGoAway(current_frame_stream_id_, status); |
1892 } | 1916 } |
1893 } | 1917 } |
1894 | 1918 |
1895 // Handle remaining data as opaque. | 1919 // Handle remaining data as opaque. |
1896 bool processed_successfully = true; | 1920 bool processed_successfully = true; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1939 } | 1963 } |
1940 | 1964 |
1941 SpdyRstStreamStatus status = RST_STREAM_INVALID; | 1965 SpdyRstStreamStatus status = RST_STREAM_INVALID; |
1942 uint32 status_raw = status; | 1966 uint32 status_raw = status; |
1943 bool successful_read = reader.ReadUInt32(&status_raw); | 1967 bool successful_read = reader.ReadUInt32(&status_raw); |
1944 DCHECK(successful_read); | 1968 DCHECK(successful_read); |
1945 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(), | 1969 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(), |
1946 status_raw)) { | 1970 status_raw)) { |
1947 status = static_cast<SpdyRstStreamStatus>(status_raw); | 1971 status = static_cast<SpdyRstStreamStatus>(status_raw); |
1948 } else { | 1972 } else { |
1949 // Throw an error for SPDY4+, keep liberal behavior | |
1950 // for earlier versions. | |
1951 if (protocol_version() > SPDY3) { | 1973 if (protocol_version() > SPDY3) { |
1952 DLOG(WARNING) << "Invalid RST_STREAM status " << status_raw; | 1974 // Treat unrecognized status codes as INTERNAL_ERROR as |
1953 set_error(SPDY_INVALID_CONTROL_FRAME); | 1975 // recommended by the HTTP/2 spec. |
1954 return 0; | 1976 status = RST_STREAM_INTERNAL_ERROR; |
1955 } | 1977 } |
1956 } | 1978 } |
1957 // Finished parsing the RST_STREAM header, call frame handler. | 1979 // Finished parsing the RST_STREAM header, call frame handler. |
1958 visitor_->OnRstStream(current_frame_stream_id_, status); | 1980 visitor_->OnRstStream(current_frame_stream_id_, status); |
1959 } | 1981 } |
1960 } | 1982 } |
1961 | 1983 |
1962 // Handle remaining data as opaque. | 1984 // Handle remaining data as opaque. |
1963 bool processed_successfully = true; | 1985 bool processed_successfully = true; |
1964 if (len > 0) { | 1986 if (len > 0) { |
(...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3225 builder->Seek(compressed_size); | 3247 builder->Seek(compressed_size); |
3226 builder->RewriteLength(*this); | 3248 builder->RewriteLength(*this); |
3227 | 3249 |
3228 pre_compress_bytes.Add(uncompressed_len); | 3250 pre_compress_bytes.Add(uncompressed_len); |
3229 post_compress_bytes.Add(compressed_size); | 3251 post_compress_bytes.Add(compressed_size); |
3230 | 3252 |
3231 compressed_frames.Increment(); | 3253 compressed_frames.Increment(); |
3232 } | 3254 } |
3233 | 3255 |
3234 } // namespace net | 3256 } // namespace net |
OLD | NEW |