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 |