| 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 <algorithm> |
| 8 #include <limits> |
| 9 #include <string> |
| 10 |
| 7 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
| 8 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/third_party/valgrind/memcheck.h" | 13 #include "base/third_party/valgrind/memcheck.h" |
| 14 #include "net/spdy/spdy_alt_svc_wire_format.h" |
| 10 #include "net/spdy/spdy_frame_builder.h" | 15 #include "net/spdy/spdy_frame_builder.h" |
| 11 #include "net/spdy/spdy_frame_reader.h" | 16 #include "net/spdy/spdy_frame_reader.h" |
| 12 #include "net/spdy/spdy_bitmasks.h" | 17 #include "net/spdy/spdy_bitmasks.h" |
| 13 #include "third_party/zlib/zlib.h" | 18 #include "third_party/zlib/zlib.h" |
| 14 | 19 |
| 15 using base::StringPiece; | 20 using base::StringPiece; |
| 16 using std::string; | 21 using std::string; |
| 17 using std::vector; | 22 using std::vector; |
| 18 | 23 |
| 19 namespace net { | 24 namespace net { |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 return GetControlFrameHeaderSize() + 4; | 341 return GetControlFrameHeaderSize() + 4; |
| 337 } | 342 } |
| 338 | 343 |
| 339 size_t SpdyFramer::GetContinuationMinimumSize() const { | 344 size_t SpdyFramer::GetContinuationMinimumSize() const { |
| 340 // Size, in bytes, of a CONTINUATION frame not including the variable-length | 345 // Size, in bytes, of a CONTINUATION frame not including the variable-length |
| 341 // headers fragments. | 346 // headers fragments. |
| 342 return GetControlFrameHeaderSize(); | 347 return GetControlFrameHeaderSize(); |
| 343 } | 348 } |
| 344 | 349 |
| 345 size_t SpdyFramer::GetAltSvcMinimumSize() const { | 350 size_t SpdyFramer::GetAltSvcMinimumSize() const { |
| 346 // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and | 351 // Size, in bytes, of an ALTSVC frame not including the Field-Value and |
| 347 // (optional) Origin fields, all of which can vary in length. | 352 // (optional) Origin fields, both of which can vary in length. Note that this |
| 348 // Note that this gives a lower bound on the frame size rather than a true | 353 // gives a lower bound on the frame size rather than a true minimum; the |
| 349 // minimum; the actual frame should always be larger than this. | 354 // actual frame should always be larger than this. |
| 350 // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte) | 355 // Calculated as frame prefix + 2 (origin_len). |
| 351 // + 1 (pid_len) + 1 (host_len). | 356 return GetControlFrameHeaderSize() + 2; |
| 352 return GetControlFrameHeaderSize() + 9; | |
| 353 } | 357 } |
| 354 | 358 |
| 355 size_t SpdyFramer::GetPrioritySize() const { | 359 size_t SpdyFramer::GetPrioritySize() const { |
| 356 // Size, in bytes, of a PRIORITY frame. | 360 // Size, in bytes, of a PRIORITY frame. |
| 357 return GetControlFrameHeaderSize() + | 361 return GetControlFrameHeaderSize() + |
| 358 kPriorityDependencyPayloadSize + | 362 kPriorityDependencyPayloadSize + |
| 359 kPriorityWeightPayloadSize; | 363 kPriorityWeightPayloadSize; |
| 360 } | 364 } |
| 361 | 365 |
| 362 size_t SpdyFramer::GetFrameMinimumSize() const { | 366 size_t SpdyFramer::GetFrameMinimumSize() const { |
| (...skipping 1659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2022 } | 2026 } |
| 2023 | 2027 |
| 2024 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) { | 2028 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) { |
| 2025 if (len == 0) { | 2029 if (len == 0) { |
| 2026 return 0; | 2030 return 0; |
| 2027 } | 2031 } |
| 2028 | 2032 |
| 2029 // Clamp to the actual remaining payload. | 2033 // Clamp to the actual remaining payload. |
| 2030 len = std::min(len, remaining_data_length_); | 2034 len = std::min(len, remaining_data_length_); |
| 2031 | 2035 |
| 2032 size_t processed_bytes = 0; | 2036 if (altsvc_scratch_.buffer.get() == nullptr) { |
| 2033 size_t processing = 0; | 2037 altsvc_scratch_.buffer.reset( |
| 2034 size_t bytes_remaining; | 2038 new char[current_frame_length_ - GetControlFrameHeaderSize()]); |
| 2035 char* buffer; | 2039 altsvc_scratch_.buffer_length = 0; |
| 2036 size_t* buffer_len; | 2040 } |
| 2037 | 2041 memcpy(altsvc_scratch_.buffer.get() + altsvc_scratch_.buffer_length, data, |
| 2038 while (len > 0) { | 2042 len); |
| 2039 if (altsvc_scratch_.pid_len == 0) { | 2043 altsvc_scratch_.buffer_length += len; |
| 2040 // The size of the frame up to the PID_LEN field. | 2044 remaining_data_length_ -= len; |
| 2041 size_t fixed_len_portion = GetAltSvcMinimumSize() - 1; | 2045 if (remaining_data_length_ > 0) { |
| 2042 bytes_remaining = fixed_len_portion - current_frame_buffer_length_; | 2046 return len; |
| 2043 processing = std::min(len, bytes_remaining); | |
| 2044 // Buffer the new ALTSVC bytes we got. | |
| 2045 UpdateCurrentFrameBuffer(&data, &len, processing); | |
| 2046 | |
| 2047 // Do we have enough to parse the length of the protocol id? | |
| 2048 if (current_frame_buffer_length_ == fixed_len_portion) { | |
| 2049 // Parse out the max age, port, and pid_len. | |
| 2050 SpdyFrameReader reader(current_frame_buffer_.get(), | |
| 2051 current_frame_buffer_length_); | |
| 2052 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. | |
| 2053 bool successful_read = reader.ReadUInt32(&altsvc_scratch_.max_age); | |
| 2054 reader.ReadUInt16(&altsvc_scratch_.port); | |
| 2055 reader.Seek(1); // Reserved byte. | |
| 2056 successful_read = successful_read && | |
| 2057 reader.ReadUInt8(&altsvc_scratch_.pid_len); | |
| 2058 DCHECK(successful_read); | |
| 2059 // Sanity check length value. | |
| 2060 if (altsvc_scratch_.pid_len == 0 || | |
| 2061 GetAltSvcMinimumSize() + altsvc_scratch_.pid_len >= | |
| 2062 current_frame_length_) { | |
| 2063 set_error(SPDY_INVALID_CONTROL_FRAME); | |
| 2064 return 0; | |
| 2065 } | |
| 2066 altsvc_scratch_.protocol_id.reset( | |
| 2067 new char[size_t(altsvc_scratch_.pid_len)]); | |
| 2068 } | |
| 2069 processed_bytes += processing; | |
| 2070 continue; | |
| 2071 } else if (altsvc_scratch_.pid_buf_len < altsvc_scratch_.pid_len) { | |
| 2072 // Buffer protocol id field as in comes in. | |
| 2073 buffer = altsvc_scratch_.protocol_id.get(); | |
| 2074 buffer_len = &altsvc_scratch_.pid_buf_len; | |
| 2075 bytes_remaining = altsvc_scratch_.pid_len - altsvc_scratch_.pid_buf_len; | |
| 2076 } else if (altsvc_scratch_.host_len == 0) { | |
| 2077 // Parse out the host length. | |
| 2078 processing = 1; | |
| 2079 altsvc_scratch_.host_len = *reinterpret_cast<const uint8*>(data); | |
| 2080 // Sanity check length value. | |
| 2081 if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len + | |
| 2082 altsvc_scratch_.host_len > current_frame_length_) { | |
| 2083 set_error(SPDY_INVALID_CONTROL_FRAME); | |
| 2084 return 0; | |
| 2085 } | |
| 2086 altsvc_scratch_.host.reset(new char[altsvc_scratch_.host_len]); | |
| 2087 // Once we have host length, we can also determine the origin length | |
| 2088 // by process of elimination. | |
| 2089 altsvc_scratch_.origin_len = current_frame_length_ - | |
| 2090 GetAltSvcMinimumSize() - | |
| 2091 altsvc_scratch_.pid_len - | |
| 2092 altsvc_scratch_.host_len; | |
| 2093 if (altsvc_scratch_.origin_len > 0) { | |
| 2094 altsvc_scratch_.origin.reset(new char[altsvc_scratch_.origin_len]); | |
| 2095 } | |
| 2096 data += processing; | |
| 2097 processed_bytes += processing; | |
| 2098 len -= processing; | |
| 2099 continue; | |
| 2100 } else if (altsvc_scratch_.host_buf_len < altsvc_scratch_.host_len) { | |
| 2101 // Buffer host field as it comes in. | |
| 2102 // TODO(mlavan): check formatting for host and origin | |
| 2103 buffer = altsvc_scratch_.host.get(); | |
| 2104 buffer_len = &altsvc_scratch_.host_buf_len; | |
| 2105 bytes_remaining = altsvc_scratch_.host_len - altsvc_scratch_.host_buf_len; | |
| 2106 } else { | |
| 2107 // Buffer (optional) origin field as it comes in. | |
| 2108 if (altsvc_scratch_.origin_len <= 0) { | |
| 2109 set_error(SPDY_INVALID_CONTROL_FRAME); | |
| 2110 return 0; | |
| 2111 } | |
| 2112 buffer = altsvc_scratch_.origin.get(); | |
| 2113 buffer_len = &altsvc_scratch_.origin_buf_len; | |
| 2114 bytes_remaining = remaining_data_length_ - | |
| 2115 processed_bytes - | |
| 2116 altsvc_scratch_.origin_buf_len; | |
| 2117 if (len > bytes_remaining) { | |
| 2118 // This is our last field; there shouldn't be any more bytes. | |
| 2119 set_error(SPDY_INVALID_CONTROL_FRAME); | |
| 2120 return 0; | |
| 2121 } | |
| 2122 } | |
| 2123 | |
| 2124 // Copy data bytes into the appropriate field. | |
| 2125 processing = std::min(len, bytes_remaining); | |
| 2126 memcpy(buffer + *buffer_len, | |
| 2127 data, | |
| 2128 processing); | |
| 2129 *buffer_len += processing; | |
| 2130 data += processing; | |
| 2131 processed_bytes += processing; | |
| 2132 len -= processing; | |
| 2133 } | 2047 } |
| 2134 | 2048 |
| 2135 remaining_data_length_ -= processed_bytes; | 2049 SpdyFrameReader reader(altsvc_scratch_.buffer.get(), |
| 2136 if (remaining_data_length_ == 0) { | 2050 altsvc_scratch_.buffer_length); |
| 2137 visitor_->OnAltSvc(current_frame_stream_id_, | 2051 StringPiece origin; |
| 2138 altsvc_scratch_.max_age, | 2052 bool successful_read = reader.ReadStringPiece16(&origin); |
| 2139 altsvc_scratch_.port, | 2053 if (!successful_read) { |
| 2140 StringPiece(altsvc_scratch_.protocol_id.get(), | 2054 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 2141 altsvc_scratch_.pid_len), | 2055 return 0; |
| 2142 StringPiece(altsvc_scratch_.host.get(), | 2056 } |
| 2143 altsvc_scratch_.host_len), | 2057 StringPiece value(altsvc_scratch_.buffer.get() + reader.GetBytesConsumed(), |
| 2144 StringPiece(altsvc_scratch_.origin.get(), | 2058 altsvc_scratch_.buffer_length - reader.GetBytesConsumed()); |
| 2145 altsvc_scratch_.origin_len)); | 2059 |
| 2146 CHANGE_STATE(SPDY_AUTO_RESET); | 2060 string protocol_id; |
| 2061 string host; |
| 2062 uint16 port; |
| 2063 uint32 max_age; |
| 2064 double p; |
| 2065 bool success = SpdyAltSvcWireFormat::ParseHeaderFieldValue( |
| 2066 value, &protocol_id, &host, &port, &max_age, &p); |
| 2067 if (!success || protocol_id.length() == 0) { |
| 2068 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 2069 return 0; |
| 2147 } | 2070 } |
| 2148 | 2071 |
| 2149 return processed_bytes; | 2072 // TODO(bnc): Pass on |p|. |
| 2073 visitor_->OnAltSvc(current_frame_stream_id_, max_age, port, protocol_id, host, |
| 2074 origin); |
| 2075 CHANGE_STATE(SPDY_AUTO_RESET); |
| 2076 return len; |
| 2150 } | 2077 } |
| 2151 | 2078 |
| 2152 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) { | 2079 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) { |
| 2153 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH, state_); | 2080 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH, state_); |
| 2154 DCHECK_EQ(0u, remaining_padding_payload_length_); | 2081 DCHECK_EQ(0u, remaining_padding_payload_length_); |
| 2155 DCHECK_EQ(DATA, current_frame_type_); | 2082 DCHECK_EQ(DATA, current_frame_type_); |
| 2156 | 2083 |
| 2157 size_t original_len = len; | 2084 size_t original_len = len; |
| 2158 if (current_frame_flags_ & DATA_FLAG_PADDED) { | 2085 if (current_frame_flags_ & DATA_FLAG_PADDED) { |
| 2159 if (len != 0) { | 2086 if (len != 0) { |
| (...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2840 builder.BeginNewFrame(*this, CONTINUATION, flags, | 2767 builder.BeginNewFrame(*this, CONTINUATION, flags, |
| 2841 continuation.stream_id()); | 2768 continuation.stream_id()); |
| 2842 DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); | 2769 DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); |
| 2843 | 2770 |
| 2844 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2771 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); |
| 2845 return builder.take(); | 2772 return builder.take(); |
| 2846 } | 2773 } |
| 2847 | 2774 |
| 2848 SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc) { | 2775 SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc) { |
| 2849 DCHECK_LT(SPDY3, protocol_version()); | 2776 DCHECK_LT(SPDY3, protocol_version()); |
| 2777 |
| 2850 size_t size = GetAltSvcMinimumSize(); | 2778 size_t size = GetAltSvcMinimumSize(); |
| 2851 size += altsvc.protocol_id().length(); | |
| 2852 size += altsvc.host().length(); | |
| 2853 size += altsvc.origin().length(); | 2779 size += altsvc.origin().length(); |
| 2780 // TODO(bnc): Add probability to SpdyAltSvcIR and pass it on. |
| 2781 string value = SpdyAltSvcWireFormat::SerializeHeaderFieldValue( |
| 2782 altsvc.protocol_id(), altsvc.host(), altsvc.port(), altsvc.max_age(), |
| 2783 1.0); |
| 2784 size += value.length(); |
| 2854 | 2785 |
| 2855 SpdyFrameBuilder builder(size, protocol_version()); | 2786 SpdyFrameBuilder builder(size, protocol_version()); |
| 2856 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc.stream_id()); | 2787 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc.stream_id()); |
| 2857 | 2788 |
| 2858 // TODO(bnc): http://crbug.com/438263 | 2789 builder.WriteUInt16(altsvc.origin().length()); |
| 2859 // Update the binary format here to the new text-based payload format. | |
| 2860 builder.WriteUInt32(altsvc.max_age()); | |
| 2861 builder.WriteUInt16(altsvc.port()); | |
| 2862 builder.WriteUInt8(0); // Reserved. | |
| 2863 builder.WriteUInt8(static_cast<uint8>(altsvc.protocol_id().length())); | |
| 2864 builder.WriteBytes(altsvc.protocol_id().data(), | |
| 2865 altsvc.protocol_id().length()); | |
| 2866 builder.WriteUInt8(static_cast<uint8>(altsvc.host().length())); | |
| 2867 builder.WriteBytes(altsvc.host().data(), altsvc.host().length()); | |
| 2868 builder.WriteBytes(altsvc.origin().data(), altsvc.origin().length()); | 2790 builder.WriteBytes(altsvc.origin().data(), altsvc.origin().length()); |
| 2791 builder.WriteBytes(value.data(), value.length()); |
| 2869 DCHECK_LT(GetAltSvcMinimumSize(), builder.length()); | 2792 DCHECK_LT(GetAltSvcMinimumSize(), builder.length()); |
| 2870 return builder.take(); | 2793 return builder.take(); |
| 2871 } | 2794 } |
| 2872 | 2795 |
| 2873 SpdyFrame* SpdyFramer::SerializePriority(const SpdyPriorityIR& priority) const { | 2796 SpdyFrame* SpdyFramer::SerializePriority(const SpdyPriorityIR& priority) const { |
| 2874 DCHECK_LT(SPDY3, protocol_version()); | 2797 DCHECK_LT(SPDY3, protocol_version()); |
| 2875 size_t size = GetPrioritySize(); | 2798 size_t size = GetPrioritySize(); |
| 2876 | 2799 |
| 2877 SpdyFrameBuilder builder(size, protocol_version()); | 2800 SpdyFrameBuilder builder(size, protocol_version()); |
| 2878 builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id()); | 2801 builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id()); |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3292 #else | 3215 #else |
| 3293 WriteHeaderBlockToZ(&frame.name_value_block(), compressor); | 3216 WriteHeaderBlockToZ(&frame.name_value_block(), compressor); |
| 3294 #endif // defined(USE_SYSTEM_ZLIB) | 3217 #endif // defined(USE_SYSTEM_ZLIB) |
| 3295 | 3218 |
| 3296 int compressed_size = compressed_max_size - compressor->avail_out; | 3219 int compressed_size = compressed_max_size - compressor->avail_out; |
| 3297 builder->Seek(compressed_size); | 3220 builder->Seek(compressed_size); |
| 3298 builder->RewriteLength(*this); | 3221 builder->RewriteLength(*this); |
| 3299 } | 3222 } |
| 3300 | 3223 |
| 3301 } // namespace net | 3224 } // namespace net |
| OLD | NEW |