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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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. | 73 // Wire size of pad length field. |
74 const size_t kPadLengthFieldSize = 1; | 74 const size_t kPadLengthFieldSize = 1; |
75 | 75 |
76 } // namespace | 76 } // namespace |
77 | 77 |
78 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1); | 78 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1); |
79 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; | 79 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; |
| 80 // We fragment sent control frames at smaller payload boundaries. |
| 81 const size_t SpdyFramer::kMaxControlFrameSize = 1024; |
80 // The size of the control frame buffer. Must be >= the minimum size of the | 82 // The size of the control frame buffer. Must be >= the minimum size of the |
81 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for | 83 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for |
82 // calculation details. | 84 // calculation details. |
83 const size_t SpdyFramer::kControlFrameBufferSize = 19; | 85 const size_t SpdyFramer::kControlFrameBufferSize = 19; |
84 | 86 |
85 #ifdef DEBUG_SPDY_STATE_CHANGES | 87 #ifdef DEBUG_SPDY_STATE_CHANGES |
86 #define CHANGE_STATE(newstate) \ | 88 #define CHANGE_STATE(newstate) \ |
87 do { \ | 89 do { \ |
88 DVLOG(1) << "Changing state from: " \ | 90 DVLOG(1) << "Changing state from: " \ |
89 << StateToString(state_) \ | 91 << StateToString(state_) \ |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 visitor_(NULL), | 158 visitor_(NULL), |
157 debug_visitor_(NULL), | 159 debug_visitor_(NULL), |
158 display_protocol_("SPDY"), | 160 display_protocol_("SPDY"), |
159 spdy_version_(version), | 161 spdy_version_(version), |
160 syn_frame_processed_(false), | 162 syn_frame_processed_(false), |
161 probable_http_response_(false), | 163 probable_http_response_(false), |
162 expect_continuation_(0), | 164 expect_continuation_(0), |
163 end_stream_when_done_(false) { | 165 end_stream_when_done_(false) { |
164 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); | 166 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); |
165 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION); | 167 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION); |
| 168 DCHECK_LE(kMaxControlFrameSize, |
| 169 SpdyConstants::GetFrameMaximumSize(spdy_version_) + |
| 170 SpdyConstants::GetControlFrameHeaderSize(spdy_version_)); |
166 Reset(); | 171 Reset(); |
167 } | 172 } |
168 | 173 |
169 SpdyFramer::~SpdyFramer() { | 174 SpdyFramer::~SpdyFramer() { |
170 if (header_compressor_.get()) { | 175 if (header_compressor_.get()) { |
171 deflateEnd(header_compressor_.get()); | 176 deflateEnd(header_compressor_.get()); |
172 } | 177 } |
173 if (header_decompressor_.get()) { | 178 if (header_decompressor_.get()) { |
174 inflateEnd(header_decompressor_.get()); | 179 inflateEnd(header_decompressor_.get()); |
175 } | 180 } |
(...skipping 866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1042 // with spdy_protocol.h. | 1047 // with spdy_protocol.h. |
1043 DLOG(FATAL); | 1048 DLOG(FATAL); |
1044 set_error(SPDY_INVALID_CONTROL_FRAME); | 1049 set_error(SPDY_INVALID_CONTROL_FRAME); |
1045 break; | 1050 break; |
1046 } | 1051 } |
1047 | 1052 |
1048 if (state_ == SPDY_ERROR) { | 1053 if (state_ == SPDY_ERROR) { |
1049 return; | 1054 return; |
1050 } | 1055 } |
1051 | 1056 |
1052 if (current_frame_length_ > GetControlFrameBufferMaxSize()) { | 1057 if (current_frame_length_ > |
| 1058 SpdyConstants::GetFrameMaximumSize(protocol_version()) + |
| 1059 SpdyConstants::GetControlFrameHeaderSize(protocol_version())) { |
1053 DLOG(WARNING) << "Received control frame with way too big of a payload: " | 1060 DLOG(WARNING) << "Received control frame with way too big of a payload: " |
1054 << current_frame_length_; | 1061 << current_frame_length_; |
1055 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | 1062 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); |
1056 return; | 1063 return; |
1057 } | 1064 } |
1058 | 1065 |
1059 if (current_frame_type_ == GOAWAY) { | 1066 if (current_frame_type_ == GOAWAY) { |
1060 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD); | 1067 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD); |
1061 return; | 1068 return; |
1062 } | 1069 } |
(...skipping 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2151 } | 2158 } |
2152 | 2159 |
2153 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) { | 2160 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) { |
2154 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH, state_); | 2161 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH, state_); |
2155 DCHECK_EQ(0u, remaining_padding_payload_length_); | 2162 DCHECK_EQ(0u, remaining_padding_payload_length_); |
2156 DCHECK_EQ(DATA, current_frame_type_); | 2163 DCHECK_EQ(DATA, current_frame_type_); |
2157 | 2164 |
2158 size_t original_len = len; | 2165 size_t original_len = len; |
2159 if (current_frame_flags_ & DATA_FLAG_PADDED) { | 2166 if (current_frame_flags_ & DATA_FLAG_PADDED) { |
2160 if (len != 0) { | 2167 if (len != 0) { |
2161 if (remaining_data_length_ < 1) { | 2168 if (remaining_data_length_ < kPadLengthFieldSize) { |
2162 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); | 2169 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); |
2163 return 0; | 2170 return 0; |
2164 } | 2171 } |
2165 | 2172 |
2166 remaining_padding_payload_length_ = *reinterpret_cast<const uint8*>(data); | 2173 remaining_padding_payload_length_ = *reinterpret_cast<const uint8*>(data); |
2167 ++data; | 2174 ++data; |
2168 --len; | 2175 --len; |
2169 --remaining_data_length_; | 2176 --remaining_data_length_; |
2170 } else { | 2177 } else { |
2171 // We don't have the data available for parsing the pad length field. Keep | 2178 // We don't have the data available for parsing the pad length field. Keep |
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2652 string hpack_encoding; | 2659 string hpack_encoding; |
2653 if (protocol_version() > SPDY3) { | 2660 if (protocol_version() > SPDY3) { |
2654 if (enable_compression_) { | 2661 if (enable_compression_) { |
2655 GetHpackEncoder()->EncodeHeaderSet( | 2662 GetHpackEncoder()->EncodeHeaderSet( |
2656 headers.name_value_block(), &hpack_encoding); | 2663 headers.name_value_block(), &hpack_encoding); |
2657 } else { | 2664 } else { |
2658 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( | 2665 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( |
2659 headers.name_value_block(), &hpack_encoding); | 2666 headers.name_value_block(), &hpack_encoding); |
2660 } | 2667 } |
2661 size += hpack_encoding.size(); | 2668 size += hpack_encoding.size(); |
2662 if (size > GetHeaderFragmentMaxSize()) { | 2669 if (size > kMaxControlFrameSize) { |
2663 size += GetNumberRequiredContinuationFrames(size) * | 2670 size += GetNumberRequiredContinuationFrames(size) * |
2664 GetContinuationMinimumSize(); | 2671 GetContinuationMinimumSize(); |
2665 flags &= ~HEADERS_FLAG_END_HEADERS; | 2672 flags &= ~HEADERS_FLAG_END_HEADERS; |
2666 } | 2673 } |
2667 } else { | 2674 } else { |
2668 size += GetSerializedLength(headers.name_value_block()); | 2675 size += GetSerializedLength(headers.name_value_block()); |
2669 } | 2676 } |
2670 | 2677 |
2671 SpdyFrameBuilder builder(size, protocol_version()); | 2678 SpdyFrameBuilder builder(size, protocol_version()); |
2672 if (protocol_version() <= SPDY3) { | 2679 if (protocol_version() <= SPDY3) { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2760 | 2767 |
2761 string hpack_encoding; | 2768 string hpack_encoding; |
2762 if (enable_compression_) { | 2769 if (enable_compression_) { |
2763 GetHpackEncoder()->EncodeHeaderSet( | 2770 GetHpackEncoder()->EncodeHeaderSet( |
2764 push_promise.name_value_block(), &hpack_encoding); | 2771 push_promise.name_value_block(), &hpack_encoding); |
2765 } else { | 2772 } else { |
2766 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( | 2773 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( |
2767 push_promise.name_value_block(), &hpack_encoding); | 2774 push_promise.name_value_block(), &hpack_encoding); |
2768 } | 2775 } |
2769 size += hpack_encoding.size(); | 2776 size += hpack_encoding.size(); |
2770 if (size > GetHeaderFragmentMaxSize()) { | 2777 if (size > kMaxControlFrameSize) { |
2771 size += GetNumberRequiredContinuationFrames(size) * | 2778 size += GetNumberRequiredContinuationFrames(size) * |
2772 GetContinuationMinimumSize(); | 2779 GetContinuationMinimumSize(); |
2773 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 2780 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
2774 } | 2781 } |
2775 | 2782 |
2776 SpdyFrameBuilder builder(size, protocol_version()); | 2783 SpdyFrameBuilder builder(size, protocol_version()); |
2777 builder.BeginNewFrame(*this, | 2784 builder.BeginNewFrame(*this, |
2778 PUSH_PROMISE, | 2785 PUSH_PROMISE, |
2779 flags, | 2786 flags, |
2780 push_promise.stream_id()); | 2787 push_promise.stream_id()); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2958 if (!enable_compression_) { | 2965 if (!enable_compression_) { |
2959 return uncompressed_length; | 2966 return uncompressed_length; |
2960 } | 2967 } |
2961 z_stream* compressor = GetHeaderCompressor(); | 2968 z_stream* compressor = GetHeaderCompressor(); |
2962 // Since we'll be performing lots of flushes when compressing the data, | 2969 // Since we'll be performing lots of flushes when compressing the data, |
2963 // zlib's lower bounds may be insufficient. | 2970 // zlib's lower bounds may be insufficient. |
2964 return 2 * deflateBound(compressor, uncompressed_length); | 2971 return 2 * deflateBound(compressor, uncompressed_length); |
2965 } | 2972 } |
2966 | 2973 |
2967 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) { | 2974 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) { |
2968 const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize(); | |
2969 DCHECK_GT(protocol_version(), SPDY3); | 2975 DCHECK_GT(protocol_version(), SPDY3); |
2970 DCHECK_GT(size, kMaxControlFrameSize); | 2976 DCHECK_GT(size, kMaxControlFrameSize); |
2971 size_t overflow = size - kMaxControlFrameSize; | 2977 size_t overflow = size - kMaxControlFrameSize; |
2972 return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1; | 2978 return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1; |
2973 } | 2979 } |
2974 | 2980 |
2975 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, | 2981 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, |
2976 const string& hpack_encoding, | 2982 const string& hpack_encoding, |
2977 SpdyStreamId stream_id, | 2983 SpdyStreamId stream_id, |
2978 SpdyFrameType type, | 2984 SpdyFrameType type, |
2979 int padding_payload_len) { | 2985 int padding_payload_len) { |
2980 const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize(); | |
2981 | |
2982 uint8 end_flag = 0; | 2986 uint8 end_flag = 0; |
2983 uint8 flags = 0; | 2987 uint8 flags = 0; |
2984 if (type == HEADERS) { | 2988 if (type == HEADERS) { |
2985 end_flag = HEADERS_FLAG_END_HEADERS; | 2989 end_flag = HEADERS_FLAG_END_HEADERS; |
2986 } else if (type == PUSH_PROMISE) { | 2990 } else if (type == PUSH_PROMISE) { |
2987 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 2991 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
2988 } else { | 2992 } else { |
2989 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " | 2993 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " |
2990 << FrameTypeToString(type); | 2994 << FrameTypeToString(type); |
2991 } | 2995 } |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3294 builder->Seek(compressed_size); | 3298 builder->Seek(compressed_size); |
3295 builder->RewriteLength(*this); | 3299 builder->RewriteLength(*this); |
3296 | 3300 |
3297 pre_compress_bytes.Add(uncompressed_len); | 3301 pre_compress_bytes.Add(uncompressed_len); |
3298 post_compress_bytes.Add(compressed_size); | 3302 post_compress_bytes.Add(compressed_size); |
3299 | 3303 |
3300 compressed_frames.Increment(); | 3304 compressed_frames.Increment(); |
3301 } | 3305 } |
3302 | 3306 |
3303 } // namespace net | 3307 } // namespace net |
OLD | NEW |