| 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 |