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 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 return original_len - len; | 998 return original_len - len; |
999 } | 999 } |
1000 | 1000 |
1001 // Does not buffer the control payload. Instead, either passes directly to the | 1001 // Does not buffer the control payload. Instead, either passes directly to the |
1002 // visitor or decompresses and then passes directly to the visitor, via | 1002 // visitor or decompresses and then passes directly to the visitor, via |
1003 // IncrementallyDeliverControlFrameHeaderData() or | 1003 // IncrementallyDeliverControlFrameHeaderData() or |
1004 // IncrementallyDecompressControlFrameHeaderData() respectively. | 1004 // IncrementallyDecompressControlFrameHeaderData() respectively. |
1005 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, | 1005 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, |
1006 size_t data_len) { | 1006 size_t data_len) { |
1007 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); | 1007 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); |
1008 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); | 1008 const SpdyControlFrame control_frame(current_frame_buffer_.get(), false); |
1009 | 1009 |
1010 bool processed_successfully = true; | 1010 bool processed_successfully = true; |
1011 DCHECK(control_frame.type() == SYN_STREAM || | 1011 SpdyStreamId stream_id = kInvalidStream; |
1012 control_frame.type() == SYN_REPLY || | 1012 if (control_frame.type() == SYN_STREAM) { |
1013 control_frame.type() == HEADERS); | 1013 stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>( |
| 1014 &control_frame)->stream_id(); |
| 1015 } else if (control_frame.type() == SYN_REPLY) { |
| 1016 stream_id = reinterpret_cast<const SpdySynReplyControlFrame*>( |
| 1017 &control_frame)->stream_id(); |
| 1018 } else if (control_frame.type() == HEADERS) { |
| 1019 stream_id = reinterpret_cast<const SpdyHeadersControlFrame*>( |
| 1020 &control_frame)->stream_id(); |
| 1021 } else { |
| 1022 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; |
| 1023 } |
1014 size_t process_bytes = std::min(data_len, remaining_control_payload_); | 1024 size_t process_bytes = std::min(data_len, remaining_control_payload_); |
1015 if (process_bytes > 0) { | 1025 if (process_bytes > 0) { |
1016 if (enable_compression_) { | 1026 if (enable_compression_) { |
1017 processed_successfully = IncrementallyDecompressControlFrameHeaderData( | 1027 processed_successfully = IncrementallyDecompressControlFrameHeaderData( |
1018 &control_frame, data, process_bytes); | 1028 stream_id, data, process_bytes); |
1019 } else { | 1029 } else { |
1020 processed_successfully = IncrementallyDeliverControlFrameHeaderData( | 1030 processed_successfully = IncrementallyDeliverControlFrameHeaderData( |
1021 &control_frame, data, process_bytes); | 1031 stream_id, data, process_bytes); |
1022 } | 1032 } |
1023 | 1033 |
1024 remaining_control_payload_ -= process_bytes; | 1034 remaining_control_payload_ -= process_bytes; |
1025 remaining_data_ -= process_bytes; | 1035 remaining_data_ -= process_bytes; |
1026 } | 1036 } |
1027 | 1037 |
1028 // Handle the case that there is no futher data in this frame. | 1038 // Handle the case that there is no futher data in this frame. |
1029 if (remaining_control_payload_ == 0 && processed_successfully) { | 1039 if (remaining_control_payload_ == 0 && processed_successfully) { |
1030 // The complete header block has been delivered. We send a zero-length | 1040 // The complete header block has been delivered. We send a zero-length |
1031 // OnControlFrameHeaderData() to indicate this. | 1041 // OnControlFrameHeaderData() to indicate this. |
1032 visitor_->OnControlFrameHeaderData( | 1042 visitor_->OnControlFrameHeaderData(stream_id, NULL, 0); |
1033 GetControlFrameStreamId(&control_frame), NULL, 0); | |
1034 | 1043 |
1035 // If this is a FIN, tell the caller. | 1044 // If this is a FIN, tell the caller. |
1036 if (control_frame.flags() & CONTROL_FLAG_FIN) { | 1045 if (control_frame.flags() & CONTROL_FLAG_FIN) { |
1037 visitor_->OnStreamFrameData(GetControlFrameStreamId(&control_frame), | 1046 visitor_->OnStreamFrameData(stream_id, NULL, 0, DATA_FLAG_FIN); |
1038 NULL, 0, DATA_FLAG_FIN); | |
1039 } | 1047 } |
1040 | 1048 |
1041 CHANGE_STATE(SPDY_AUTO_RESET); | 1049 CHANGE_STATE(SPDY_AUTO_RESET); |
1042 } | 1050 } |
1043 | 1051 |
1044 // Handle error. | 1052 // Handle error. |
1045 if (!processed_successfully) { | 1053 if (!processed_successfully) { |
1046 return data_len; | 1054 return data_len; |
1047 } | 1055 } |
1048 | 1056 |
(...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1905 } | 1913 } |
1906 | 1914 |
1907 return new_frame.release(); | 1915 return new_frame.release(); |
1908 } | 1916 } |
1909 | 1917 |
1910 // Incrementally decompress the control frame's header block, feeding the | 1918 // Incrementally decompress the control frame's header block, feeding the |
1911 // result to the visitor in chunks. Continue this until the visitor | 1919 // result to the visitor in chunks. Continue this until the visitor |
1912 // indicates that it cannot process any more data, or (more commonly) we | 1920 // indicates that it cannot process any more data, or (more commonly) we |
1913 // run out of data to deliver. | 1921 // run out of data to deliver. |
1914 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( | 1922 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( |
1915 const SpdyControlFrame* control_frame, | 1923 SpdyStreamId stream_id, |
1916 const char* data, | 1924 const char* data, |
1917 size_t len) { | 1925 size_t len) { |
1918 // Get a decompressor or set error. | 1926 // Get a decompressor or set error. |
1919 z_stream* decomp = GetHeaderDecompressor(); | 1927 z_stream* decomp = GetHeaderDecompressor(); |
1920 if (decomp == NULL) { | 1928 if (decomp == NULL) { |
1921 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; | 1929 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; |
1922 set_error(SPDY_DECOMPRESS_FAILURE); | 1930 set_error(SPDY_DECOMPRESS_FAILURE); |
1923 return false; | 1931 return false; |
1924 } | 1932 } |
1925 | 1933 |
1926 bool processed_successfully = true; | 1934 bool processed_successfully = true; |
1927 char buffer[kHeaderDataChunkMaxSize]; | 1935 char buffer[kHeaderDataChunkMaxSize]; |
1928 | 1936 |
1929 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); | 1937 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); |
1930 decomp->avail_in = len; | 1938 decomp->avail_in = len; |
1931 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); | |
1932 DCHECK_LT(0u, stream_id); | 1939 DCHECK_LT(0u, stream_id); |
1933 while (decomp->avail_in > 0 && processed_successfully) { | 1940 while (decomp->avail_in > 0 && processed_successfully) { |
1934 decomp->next_out = reinterpret_cast<Bytef*>(buffer); | 1941 decomp->next_out = reinterpret_cast<Bytef*>(buffer); |
1935 decomp->avail_out = arraysize(buffer); | 1942 decomp->avail_out = arraysize(buffer); |
1936 | 1943 |
1937 int rv = inflate(decomp, Z_SYNC_FLUSH); | 1944 int rv = inflate(decomp, Z_SYNC_FLUSH); |
1938 if (rv == Z_NEED_DICT) { | 1945 if (rv == Z_NEED_DICT) { |
1939 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary | 1946 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary |
1940 : kV3Dictionary; | 1947 : kV3Dictionary; |
1941 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize | 1948 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1975 } else { | 1982 } else { |
1976 DLOG(WARNING) << "inflate failure: " << rv << " " << len; | 1983 DLOG(WARNING) << "inflate failure: " << rv << " " << len; |
1977 set_error(SPDY_DECOMPRESS_FAILURE); | 1984 set_error(SPDY_DECOMPRESS_FAILURE); |
1978 processed_successfully = false; | 1985 processed_successfully = false; |
1979 } | 1986 } |
1980 } | 1987 } |
1981 return processed_successfully; | 1988 return processed_successfully; |
1982 } | 1989 } |
1983 | 1990 |
1984 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( | 1991 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( |
1985 const SpdyControlFrame* control_frame, const char* data, size_t len) { | 1992 SpdyStreamId stream_id, const char* data, size_t len) { |
1986 bool read_successfully = true; | 1993 bool read_successfully = true; |
1987 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); | |
1988 while (read_successfully && len > 0) { | 1994 while (read_successfully && len > 0) { |
1989 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); | 1995 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); |
1990 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, | 1996 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, |
1991 bytes_to_deliver); | 1997 bytes_to_deliver); |
1992 data += bytes_to_deliver; | 1998 data += bytes_to_deliver; |
1993 len -= bytes_to_deliver; | 1999 len -= bytes_to_deliver; |
1994 if (!read_successfully) { | 2000 if (!read_successfully) { |
1995 // Assume that the problem was the header block was too large for the | 2001 // Assume that the problem was the header block was too large for the |
1996 // visitor. | 2002 // visitor. |
1997 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | 2003 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); |
(...skipping 18 matching lines...) Expand all Loading... |
2016 reinterpret_cast<const SpdyControlFrame&>(frame); | 2022 reinterpret_cast<const SpdyControlFrame&>(frame); |
2017 return control_frame.type() == SYN_STREAM || | 2023 return control_frame.type() == SYN_STREAM || |
2018 control_frame.type() == SYN_REPLY || | 2024 control_frame.type() == SYN_REPLY || |
2019 control_frame.type() == HEADERS; | 2025 control_frame.type() == HEADERS; |
2020 } | 2026 } |
2021 | 2027 |
2022 // We don't compress Data frames. | 2028 // We don't compress Data frames. |
2023 return false; | 2029 return false; |
2024 } | 2030 } |
2025 | 2031 |
2026 /* static */ | |
2027 SpdyStreamId SpdyFramer::GetControlFrameStreamId( | |
2028 const SpdyControlFrame* control_frame) { | |
2029 SpdyStreamId stream_id = kInvalidStream; | |
2030 if (control_frame != NULL) { | |
2031 switch (control_frame->type()) { | |
2032 case SYN_STREAM: | |
2033 stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>( | |
2034 control_frame)->stream_id(); | |
2035 break; | |
2036 case SYN_REPLY: | |
2037 stream_id = reinterpret_cast<const SpdySynReplyControlFrame*>( | |
2038 control_frame)->stream_id(); | |
2039 break; | |
2040 case HEADERS: | |
2041 stream_id = reinterpret_cast<const SpdyHeadersControlFrame*>( | |
2042 control_frame)->stream_id(); | |
2043 break; | |
2044 case RST_STREAM: | |
2045 stream_id = reinterpret_cast<const SpdyRstStreamControlFrame*>( | |
2046 control_frame)->stream_id(); | |
2047 break; | |
2048 case WINDOW_UPDATE: | |
2049 stream_id = reinterpret_cast<const SpdyWindowUpdateControlFrame*>( | |
2050 control_frame)->stream_id(); | |
2051 break; | |
2052 // All of the following types are not part of a particular stream. | |
2053 // They all fall through to the invalid control frame type case. | |
2054 // (The default case isn't used so that the compile will break if a new | |
2055 // control frame type is added but not included here.) | |
2056 case SETTINGS: | |
2057 case NOOP: | |
2058 case PING: | |
2059 case GOAWAY: | |
2060 case CREDENTIAL: | |
2061 case NUM_CONTROL_FRAME_TYPES: // makes compiler happy | |
2062 break; | |
2063 } | |
2064 } | |
2065 return stream_id; | |
2066 } | |
2067 | |
2068 void SpdyFramer::SerializeNameValueBlock( | 2032 void SpdyFramer::SerializeNameValueBlock( |
2069 SpdyFrameBuilder* builder, | 2033 SpdyFrameBuilder* builder, |
2070 const SpdyFrameWithNameValueBlockIR& frame) const { | 2034 const SpdyFrameWithNameValueBlockIR& frame) const { |
2071 const SpdyNameValueBlock* name_value_block = &(frame.name_value_block()); | 2035 const SpdyNameValueBlock* name_value_block = &(frame.name_value_block()); |
2072 | 2036 |
2073 // Serialize number of headers. | 2037 // Serialize number of headers. |
2074 if (protocol_version() < 3) { | 2038 if (protocol_version() < 3) { |
2075 builder->WriteUInt16(name_value_block->size()); | 2039 builder->WriteUInt16(name_value_block->size()); |
2076 } else { | 2040 } else { |
2077 builder->WriteUInt32(name_value_block->size()); | 2041 builder->WriteUInt32(name_value_block->size()); |
2078 } | 2042 } |
2079 | 2043 |
2080 // Serialize each header. | 2044 // Serialize each header. |
2081 for (SpdyHeaderBlock::const_iterator it = name_value_block->begin(); | 2045 for (SpdyHeaderBlock::const_iterator it = name_value_block->begin(); |
2082 it != name_value_block->end(); | 2046 it != name_value_block->end(); |
2083 ++it) { | 2047 ++it) { |
2084 if (protocol_version() < 3) { | 2048 if (protocol_version() < 3) { |
2085 builder->WriteString(it->first); | 2049 builder->WriteString(it->first); |
2086 builder->WriteString(it->second); | 2050 builder->WriteString(it->second); |
2087 } else { | 2051 } else { |
2088 builder->WriteStringPiece32(it->first); | 2052 builder->WriteStringPiece32(it->first); |
2089 builder->WriteStringPiece32(it->second); | 2053 builder->WriteStringPiece32(it->second); |
2090 } | 2054 } |
2091 } | 2055 } |
2092 } | 2056 } |
2093 | 2057 |
2094 } // namespace net | 2058 } // namespace net |
OLD | NEW |