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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 current_frame_type_ = DATA; | 160 current_frame_type_ = DATA; |
161 current_frame_flags_ = 0; | 161 current_frame_flags_ = 0; |
162 current_frame_length_ = 0; | 162 current_frame_length_ = 0; |
163 current_frame_stream_id_ = kInvalidStream; | 163 current_frame_stream_id_ = kInvalidStream; |
164 settings_scratch_.Reset(); | 164 settings_scratch_.Reset(); |
165 remaining_padding_payload_length_ = 0; | 165 remaining_padding_payload_length_ = 0; |
166 remaining_padding_length_fields_ = 0; | 166 remaining_padding_length_fields_ = 0; |
167 } | 167 } |
168 | 168 |
169 size_t SpdyFramer::GetDataFrameMinimumSize() const { | 169 size_t SpdyFramer::GetDataFrameMinimumSize() const { |
170 // Size, in bytes, of the data frame header. Future versions of SPDY | 170 return SpdyConstants::GetDataFrameMinimumSize(); |
171 // will likely vary this, so we allow for the flexibility of a function call | |
172 // for this value as opposed to a constant. | |
173 return 8; | |
174 } | 171 } |
175 | 172 |
176 // Size, in bytes, of the control frame header. | 173 // Size, in bytes, of the control frame header. |
177 size_t SpdyFramer::GetControlFrameHeaderSize() const { | 174 size_t SpdyFramer::GetControlFrameHeaderSize() const { |
178 switch (protocol_version()) { | 175 return SpdyConstants::GetControlFrameHeaderSize(protocol_version()); |
179 case SPDY2: | |
180 case SPDY3: | |
181 case SPDY4: | |
182 return 8; | |
183 } | |
184 LOG(DFATAL) << "Unhandled SPDY version."; | |
185 return 0; | |
186 } | 176 } |
187 | 177 |
188 size_t SpdyFramer::GetSynStreamMinimumSize() const { | 178 size_t SpdyFramer::GetSynStreamMinimumSize() const { |
189 // Size, in bytes, of a SYN_STREAM frame not including the variable-length | 179 // Size, in bytes, of a SYN_STREAM frame not including the variable-length |
190 // name-value block. | 180 // name-value block. |
191 if (protocol_version() <= SPDY3) { | 181 if (protocol_version() <= SPDY3) { |
192 // Calculated as: | 182 // Calculated as: |
193 // control frame header + 2 * 4 (stream IDs) + 1 (priority) | 183 // control frame header + 2 * 4 (stream IDs) + 1 (priority) |
194 // + 1 (unused, was credential slot) | 184 // + 1 (unused, was credential slot) |
195 return GetControlFrameHeaderSize() + 10; | 185 return GetControlFrameHeaderSize() + 10; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 // Size, in bytes, of a CONTINUATION frame not including the variable-length | 310 // Size, in bytes, of a CONTINUATION frame not including the variable-length |
321 // headers fragments. | 311 // headers fragments. |
322 return GetControlFrameHeaderSize(); | 312 return GetControlFrameHeaderSize(); |
323 } | 313 } |
324 | 314 |
325 size_t SpdyFramer::GetFrameMinimumSize() const { | 315 size_t SpdyFramer::GetFrameMinimumSize() const { |
326 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize()); | 316 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize()); |
327 } | 317 } |
328 | 318 |
329 size_t SpdyFramer::GetFrameMaximumSize() const { | 319 size_t SpdyFramer::GetFrameMaximumSize() const { |
330 if (protocol_version() <= SPDY3) { | 320 return SpdyConstants::GetFrameMaximumSize(protocol_version()); |
331 // 24-bit length field plus eight-byte frame header. | |
332 return ((1<<24) - 1) + 8; | |
333 } else { | |
334 // 14-bit length field. | |
335 return (1<<14) - 1; | |
336 } | |
337 } | 321 } |
338 | 322 |
339 size_t SpdyFramer::GetDataFrameMaximumPayload() const { | 323 size_t SpdyFramer::GetDataFrameMaximumPayload() const { |
340 return GetFrameMaximumSize() - GetDataFrameMinimumSize(); | 324 return GetFrameMaximumSize() - GetDataFrameMinimumSize(); |
341 } | 325 } |
342 | 326 |
| 327 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const { |
| 328 return SpdyConstants::GetPrefixLength(type, protocol_version()); |
| 329 } |
| 330 |
343 const char* SpdyFramer::StateToString(int state) { | 331 const char* SpdyFramer::StateToString(int state) { |
344 switch (state) { | 332 switch (state) { |
345 case SPDY_ERROR: | 333 case SPDY_ERROR: |
346 return "ERROR"; | 334 return "ERROR"; |
347 case SPDY_AUTO_RESET: | 335 case SPDY_AUTO_RESET: |
348 return "AUTO_RESET"; | 336 return "AUTO_RESET"; |
349 case SPDY_RESET: | 337 case SPDY_RESET: |
350 return "RESET"; | 338 return "RESET"; |
351 case SPDY_READING_COMMON_HEADER: | 339 case SPDY_READING_COMMON_HEADER: |
352 return "READING_COMMON_HEADER"; | 340 return "READING_COMMON_HEADER"; |
(...skipping 1248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1601 DCHECK_LT(SPDY3, protocol_version()); | 1589 DCHECK_LT(SPDY3, protocol_version()); |
1602 DCHECK_EQ(0u, remaining_data_length_); | 1590 DCHECK_EQ(0u, remaining_data_length_); |
1603 | 1591 |
1604 const SpdyNameValueBlock& block = hpack_decoder_.decoded_block(); | 1592 const SpdyNameValueBlock& block = hpack_decoder_.decoded_block(); |
1605 if (block.empty()) { | 1593 if (block.empty()) { |
1606 // Special-case this to make tests happy. | 1594 // Special-case this to make tests happy. |
1607 ProcessControlFrameHeaderBlock(NULL, 0, false); | 1595 ProcessControlFrameHeaderBlock(NULL, 0, false); |
1608 return; | 1596 return; |
1609 } | 1597 } |
1610 SpdyFrameBuilder builder( | 1598 SpdyFrameBuilder builder( |
1611 GetSerializedLength(protocol_version(), &block)); | 1599 GetSerializedLength(protocol_version(), &block), |
| 1600 SPDY3); |
1612 | 1601 |
1613 SerializeNameValueBlockWithoutCompression(&builder, block); | 1602 SerializeNameValueBlockWithoutCompression(&builder, block); |
1614 scoped_ptr<SpdyFrame> frame(builder.take()); | 1603 scoped_ptr<SpdyFrame> frame(builder.take()); |
1615 | 1604 |
1616 remaining_data_length_ = frame->size(); | 1605 remaining_data_length_ = frame->size(); |
1617 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false); | 1606 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false); |
1618 } | 1607 } |
1619 | 1608 |
1620 bool SpdyFramer::ProcessSetting(const char* data) { | 1609 bool SpdyFramer::ProcessSetting(const char* data) { |
1621 int id_field; | 1610 int id_field; |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2045 ++num_padding_fields; | 2034 ++num_padding_fields; |
2046 } | 2035 } |
2047 if (data_ir.pad_high()) { | 2036 if (data_ir.pad_high()) { |
2048 flags |= DATA_FLAG_PAD_HIGH; | 2037 flags |= DATA_FLAG_PAD_HIGH; |
2049 ++num_padding_fields; | 2038 ++num_padding_fields; |
2050 } | 2039 } |
2051 | 2040 |
2052 const size_t size_with_padding = num_padding_fields + | 2041 const size_t size_with_padding = num_padding_fields + |
2053 data_ir.data().length() + data_ir.padding_payload_len() + | 2042 data_ir.data().length() + data_ir.padding_payload_len() + |
2054 GetDataFrameMinimumSize(); | 2043 GetDataFrameMinimumSize(); |
2055 SpdyFrameBuilder builder(size_with_padding); | 2044 SpdyFrameBuilder builder(size_with_padding, protocol_version()); |
2056 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); | 2045 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); |
2057 if (data_ir.pad_high()) { | 2046 if (data_ir.pad_high()) { |
2058 builder.WriteUInt8(data_ir.padding_payload_len() >> 8); | 2047 builder.WriteUInt8(data_ir.padding_payload_len() >> 8); |
2059 } | 2048 } |
2060 if (data_ir.pad_low()) { | 2049 if (data_ir.pad_low()) { |
2061 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); | 2050 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); |
2062 } | 2051 } |
2063 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); | 2052 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); |
2064 if (data_ir.padding_payload_len() > 0) { | 2053 if (data_ir.padding_payload_len() > 0) { |
2065 string padding = string(data_ir.padding_payload_len(), '0'); | 2054 string padding = string(data_ir.padding_payload_len(), '0'); |
2066 builder.WriteBytes(padding.data(), padding.length()); | 2055 builder.WriteBytes(padding.data(), padding.length()); |
2067 } | 2056 } |
2068 DCHECK_EQ(size_with_padding, builder.length()); | 2057 DCHECK_EQ(size_with_padding, builder.length()); |
2069 return builder.take(); | 2058 return builder.take(); |
2070 } else { | 2059 } else { |
2071 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length(); | 2060 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length(); |
2072 SpdyFrameBuilder builder(size); | 2061 SpdyFrameBuilder builder(size, protocol_version()); |
2073 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); | 2062 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); |
2074 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); | 2063 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); |
2075 DCHECK_EQ(size, builder.length()); | 2064 DCHECK_EQ(size, builder.length()); |
2076 return builder.take(); | 2065 return builder.take(); |
2077 } | 2066 } |
2078 } | 2067 } |
2079 | 2068 |
2080 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField( | 2069 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField( |
2081 const SpdyDataIR& data_ir) const { | 2070 const SpdyDataIR& data_ir) const { |
2082 uint8 flags = DATA_FLAG_NONE; | 2071 uint8 flags = DATA_FLAG_NONE; |
2083 if (data_ir.fin()) { | 2072 if (data_ir.fin()) { |
2084 flags = DATA_FLAG_FIN; | 2073 flags = DATA_FLAG_FIN; |
2085 } | 2074 } |
2086 | 2075 |
2087 size_t frame_size = GetDataFrameMinimumSize(); | 2076 size_t frame_size = GetDataFrameMinimumSize(); |
2088 size_t num_padding_fields = 0; | 2077 size_t num_padding_fields = 0; |
2089 if (protocol_version() > SPDY3) { | 2078 if (protocol_version() > SPDY3) { |
2090 if (data_ir.pad_low()) { | 2079 if (data_ir.pad_low()) { |
2091 flags |= DATA_FLAG_PAD_LOW; | 2080 flags |= DATA_FLAG_PAD_LOW; |
2092 ++num_padding_fields; | 2081 ++num_padding_fields; |
2093 } | 2082 } |
2094 if (data_ir.pad_high()) { | 2083 if (data_ir.pad_high()) { |
2095 flags |= DATA_FLAG_PAD_HIGH; | 2084 flags |= DATA_FLAG_PAD_HIGH; |
2096 ++num_padding_fields; | 2085 ++num_padding_fields; |
2097 } | 2086 } |
2098 frame_size += num_padding_fields; | 2087 frame_size += num_padding_fields; |
2099 } | 2088 } |
2100 | 2089 |
2101 SpdyFrameBuilder builder(frame_size); | 2090 SpdyFrameBuilder builder(frame_size, protocol_version()); |
2102 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); | 2091 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); |
2103 if (protocol_version() > SPDY3) { | 2092 if (protocol_version() > SPDY3) { |
2104 if (data_ir.pad_high()) { | 2093 if (data_ir.pad_high()) { |
2105 builder.WriteUInt8(data_ir.padding_payload_len() >> 8); | 2094 builder.WriteUInt8(data_ir.padding_payload_len() >> 8); |
2106 } | 2095 } |
2107 if (data_ir.pad_low()) { | 2096 if (data_ir.pad_low()) { |
2108 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); | 2097 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); |
2109 } | 2098 } |
2110 builder.OverwriteLength(*this, num_padding_fields + | 2099 builder.OverwriteLength(*this, num_padding_fields + |
2111 data_ir.data().length() + data_ir.padding_payload_len()); | 2100 data_ir.data().length() + data_ir.padding_payload_len()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2145 | 2134 |
2146 string hpack_encoding; | 2135 string hpack_encoding; |
2147 if (protocol_version() > SPDY3) { | 2136 if (protocol_version() > SPDY3) { |
2148 hpack_encoder_.EncodeHeaderSet(syn_stream.name_value_block(), | 2137 hpack_encoder_.EncodeHeaderSet(syn_stream.name_value_block(), |
2149 &hpack_encoding); | 2138 &hpack_encoding); |
2150 size += hpack_encoding.size(); | 2139 size += hpack_encoding.size(); |
2151 } else { | 2140 } else { |
2152 size += GetSerializedLength(syn_stream.name_value_block()); | 2141 size += GetSerializedLength(syn_stream.name_value_block()); |
2153 } | 2142 } |
2154 | 2143 |
2155 SpdyFrameBuilder builder(size); | 2144 SpdyFrameBuilder builder(size, protocol_version()); |
2156 if (protocol_version() <= SPDY3) { | 2145 if (protocol_version() <= SPDY3) { |
2157 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); | 2146 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); |
2158 builder.WriteUInt32(syn_stream.stream_id()); | 2147 builder.WriteUInt32(syn_stream.stream_id()); |
2159 builder.WriteUInt32(syn_stream.associated_to_stream_id()); | 2148 builder.WriteUInt32(syn_stream.associated_to_stream_id()); |
2160 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5)); | 2149 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5)); |
2161 builder.WriteUInt8(0); // Unused byte where credential slot used to be. | 2150 builder.WriteUInt8(0); // Unused byte where credential slot used to be. |
2162 } else { | 2151 } else { |
2163 builder.WriteFramePrefix(*this, | 2152 builder.BeginNewFrame(*this, |
2164 HEADERS, | 2153 HEADERS, |
2165 flags, | 2154 flags, |
2166 syn_stream.stream_id()); | 2155 syn_stream.stream_id()); |
2167 builder.WriteUInt32(priority); | 2156 builder.WriteUInt32(priority); |
2168 } | 2157 } |
2169 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); | 2158 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); |
2170 if (protocol_version() > SPDY3) { | 2159 if (protocol_version() > SPDY3) { |
2171 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2160 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); |
2172 } else { | 2161 } else { |
2173 SerializeNameValueBlock(&builder, syn_stream); | 2162 SerializeNameValueBlock(&builder, syn_stream); |
2174 } | 2163 } |
2175 | 2164 |
2176 if (debug_visitor_) { | 2165 if (debug_visitor_) { |
(...skipping 28 matching lines...) Expand all Loading... |
2205 | 2194 |
2206 string hpack_encoding; | 2195 string hpack_encoding; |
2207 if (protocol_version() > SPDY3) { | 2196 if (protocol_version() > SPDY3) { |
2208 hpack_encoder_.EncodeHeaderSet(syn_reply.name_value_block(), | 2197 hpack_encoder_.EncodeHeaderSet(syn_reply.name_value_block(), |
2209 &hpack_encoding); | 2198 &hpack_encoding); |
2210 size += hpack_encoding.size(); | 2199 size += hpack_encoding.size(); |
2211 } else { | 2200 } else { |
2212 size += GetSerializedLength(syn_reply.name_value_block()); | 2201 size += GetSerializedLength(syn_reply.name_value_block()); |
2213 } | 2202 } |
2214 | 2203 |
2215 SpdyFrameBuilder builder(size); | 2204 SpdyFrameBuilder builder(size, protocol_version()); |
2216 if (protocol_version() <= SPDY3) { | 2205 if (protocol_version() <= SPDY3) { |
2217 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); | 2206 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); |
2218 builder.WriteUInt32(syn_reply.stream_id()); | 2207 builder.WriteUInt32(syn_reply.stream_id()); |
2219 } else { | 2208 } else { |
2220 builder.WriteFramePrefix(*this, | 2209 builder.BeginNewFrame(*this, |
2221 HEADERS, | 2210 HEADERS, |
2222 flags, | 2211 flags, |
2223 syn_reply.stream_id()); | 2212 syn_reply.stream_id()); |
2224 } | 2213 } |
2225 if (protocol_version() < SPDY3) { | 2214 if (protocol_version() < SPDY3) { |
2226 builder.WriteUInt16(0); // Unused. | 2215 builder.WriteUInt16(0); // Unused. |
2227 } | 2216 } |
2228 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); | 2217 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); |
2229 if (protocol_version() > SPDY3) { | 2218 if (protocol_version() > SPDY3) { |
2230 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2219 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); |
2231 } else { | 2220 } else { |
2232 SerializeNameValueBlock(&builder, syn_reply); | 2221 SerializeNameValueBlock(&builder, syn_reply); |
2233 } | 2222 } |
(...skipping 16 matching lines...) Expand all Loading... |
2250 const SpdyRstStreamIR& rst_stream) const { | 2239 const SpdyRstStreamIR& rst_stream) const { |
2251 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM | 2240 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM |
2252 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2, | 2241 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2, |
2253 // which doesn't currently include RST_STREAM payloads. GFE flags have been | 2242 // which doesn't currently include RST_STREAM payloads. GFE flags have been |
2254 // commented but left in place to simplify future patching. | 2243 // commented but left in place to simplify future patching. |
2255 // Compute the output buffer size, taking opaque data into account. | 2244 // Compute the output buffer size, taking opaque data into account. |
2256 uint16 expected_length = GetRstStreamMinimumSize(); | 2245 uint16 expected_length = GetRstStreamMinimumSize(); |
2257 if (protocol_version() > SPDY3) { | 2246 if (protocol_version() > SPDY3) { |
2258 expected_length += rst_stream.description().size(); | 2247 expected_length += rst_stream.description().size(); |
2259 } | 2248 } |
2260 SpdyFrameBuilder builder(expected_length); | 2249 SpdyFrameBuilder builder(expected_length, protocol_version()); |
2261 | 2250 |
2262 // Serialize the RST_STREAM frame. | 2251 // Serialize the RST_STREAM frame. |
2263 if (protocol_version() <= SPDY3) { | 2252 if (protocol_version() <= SPDY3) { |
2264 builder.WriteControlFrameHeader(*this, RST_STREAM, 0); | 2253 builder.WriteControlFrameHeader(*this, RST_STREAM, 0); |
2265 builder.WriteUInt32(rst_stream.stream_id()); | 2254 builder.WriteUInt32(rst_stream.stream_id()); |
2266 } else { | 2255 } else { |
2267 builder.WriteFramePrefix(*this, RST_STREAM, 0, rst_stream.stream_id()); | 2256 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id()); |
2268 } | 2257 } |
2269 | 2258 |
2270 builder.WriteUInt32(rst_stream.status()); | 2259 builder.WriteUInt32(rst_stream.status()); |
2271 | 2260 |
2272 // In SPDY4 and up, RST_STREAM frames may also specify opaque data. | 2261 // In SPDY4 and up, RST_STREAM frames may also specify opaque data. |
2273 if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) { | 2262 if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) { |
2274 builder.WriteBytes(rst_stream.description().data(), | 2263 builder.WriteBytes(rst_stream.description().data(), |
2275 rst_stream.description().size()); | 2264 rst_stream.description().size()); |
2276 } | 2265 } |
2277 | 2266 |
(...skipping 13 matching lines...) Expand all Loading... |
2291 if (settings.is_ack()) { | 2280 if (settings.is_ack()) { |
2292 flags |= SETTINGS_FLAG_ACK; | 2281 flags |= SETTINGS_FLAG_ACK; |
2293 } | 2282 } |
2294 } | 2283 } |
2295 const SpdySettingsIR::ValueMap* values = &(settings.values()); | 2284 const SpdySettingsIR::ValueMap* values = &(settings.values()); |
2296 | 2285 |
2297 size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5); | 2286 size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5); |
2298 // Size, in bytes, of this SETTINGS frame. | 2287 // Size, in bytes, of this SETTINGS frame. |
2299 const size_t size = GetSettingsMinimumSize() + | 2288 const size_t size = GetSettingsMinimumSize() + |
2300 (values->size() * setting_size); | 2289 (values->size() * setting_size); |
2301 SpdyFrameBuilder builder(size); | 2290 SpdyFrameBuilder builder(size, protocol_version()); |
2302 if (protocol_version() <= SPDY3) { | 2291 if (protocol_version() <= SPDY3) { |
2303 builder.WriteControlFrameHeader(*this, SETTINGS, flags); | 2292 builder.WriteControlFrameHeader(*this, SETTINGS, flags); |
2304 } else { | 2293 } else { |
2305 builder.WriteFramePrefix(*this, SETTINGS, flags, 0); | 2294 builder.BeginNewFrame(*this, SETTINGS, flags, 0); |
2306 } | 2295 } |
2307 | 2296 |
2308 // If this is an ACK, payload should be empty. | 2297 // If this is an ACK, payload should be empty. |
2309 if (protocol_version() > SPDY3 && settings.is_ack()) { | 2298 if (protocol_version() > SPDY3 && settings.is_ack()) { |
2310 return builder.take(); | 2299 return builder.take(); |
2311 } | 2300 } |
2312 | 2301 |
2313 if (protocol_version() <= SPDY3) { | 2302 if (protocol_version() <= SPDY3) { |
2314 builder.WriteUInt32(values->size()); | 2303 builder.WriteUInt32(values->size()); |
2315 } | 2304 } |
(...skipping 17 matching lines...) Expand all Loading... |
2333 } else { | 2322 } else { |
2334 builder.WriteUInt8(SpdyConstants::SerializeSettingId(protocol_version(), | 2323 builder.WriteUInt8(SpdyConstants::SerializeSettingId(protocol_version(), |
2335 it->first)); | 2324 it->first)); |
2336 } | 2325 } |
2337 builder.WriteUInt32(it->second.value); | 2326 builder.WriteUInt32(it->second.value); |
2338 } | 2327 } |
2339 DCHECK_EQ(size, builder.length()); | 2328 DCHECK_EQ(size, builder.length()); |
2340 return builder.take(); | 2329 return builder.take(); |
2341 } | 2330 } |
2342 | 2331 |
2343 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const { | |
2344 DCHECK_LT(SPDY3, protocol_version()); | |
2345 SpdyFrameBuilder builder(GetBlockedSize()); | |
2346 builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id()); | |
2347 return builder.take(); | |
2348 } | |
2349 | |
2350 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { | 2332 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { |
2351 SpdyFrameBuilder builder(GetPingSize()); | 2333 SpdyFrameBuilder builder(GetPingSize(), protocol_version()); |
2352 if (protocol_version() <= SPDY3) { | 2334 if (protocol_version() <= SPDY3) { |
2353 builder.WriteControlFrameHeader(*this, PING, kNoFlags); | 2335 builder.WriteControlFrameHeader(*this, PING, kNoFlags); |
2354 builder.WriteUInt32(static_cast<uint32>(ping.id())); | 2336 builder.WriteUInt32(static_cast<uint32>(ping.id())); |
2355 } else { | 2337 } else { |
2356 uint8 flags = 0; | 2338 uint8 flags = 0; |
2357 if (ping.is_ack()) { | 2339 if (ping.is_ack()) { |
2358 flags |= PING_FLAG_ACK; | 2340 flags |= PING_FLAG_ACK; |
2359 } | 2341 } |
2360 builder.WriteFramePrefix(*this, PING, flags, 0); | 2342 builder.BeginNewFrame(*this, PING, flags, 0); |
2361 builder.WriteUInt64(ping.id()); | 2343 builder.WriteUInt64(ping.id()); |
2362 } | 2344 } |
2363 DCHECK_EQ(GetPingSize(), builder.length()); | 2345 DCHECK_EQ(GetPingSize(), builder.length()); |
2364 return builder.take(); | 2346 return builder.take(); |
2365 } | 2347 } |
2366 | 2348 |
2367 SpdySerializedFrame* SpdyFramer::SerializeGoAway( | 2349 SpdySerializedFrame* SpdyFramer::SerializeGoAway( |
2368 const SpdyGoAwayIR& goaway) const { | 2350 const SpdyGoAwayIR& goaway) const { |
2369 | 2351 |
2370 // Compute the output buffer size, take opaque data into account. | 2352 // Compute the output buffer size, take opaque data into account. |
2371 uint16 expected_length = GetGoAwayMinimumSize(); | 2353 uint16 expected_length = GetGoAwayMinimumSize(); |
2372 if (protocol_version() > SPDY3) { | 2354 if (protocol_version() > SPDY3) { |
2373 expected_length += goaway.description().size(); | 2355 expected_length += goaway.description().size(); |
2374 } | 2356 } |
2375 SpdyFrameBuilder builder(expected_length); | 2357 SpdyFrameBuilder builder(expected_length, protocol_version()); |
2376 | 2358 |
2377 // Serialize the GOAWAY frame. | 2359 // Serialize the GOAWAY frame. |
2378 if (protocol_version() <= SPDY3) { | 2360 if (protocol_version() <= SPDY3) { |
2379 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags); | 2361 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags); |
2380 } else { | 2362 } else { |
2381 builder.WriteFramePrefix(*this, GOAWAY, 0, 0); | 2363 builder.BeginNewFrame(*this, GOAWAY, 0, 0); |
2382 } | 2364 } |
2383 | 2365 |
2384 // GOAWAY frames specify the last good stream id for all SPDY versions. | 2366 // GOAWAY frames specify the last good stream id for all SPDY versions. |
2385 builder.WriteUInt32(goaway.last_good_stream_id()); | 2367 builder.WriteUInt32(goaway.last_good_stream_id()); |
2386 | 2368 |
2387 // In SPDY3 and up, GOAWAY frames also specify the error status code. | 2369 // In SPDY3 and up, GOAWAY frames also specify the error status code. |
2388 if (protocol_version() >= SPDY3) { | 2370 if (protocol_version() >= SPDY3) { |
2389 builder.WriteUInt32(goaway.status()); | 2371 builder.WriteUInt32(goaway.status()); |
2390 } | 2372 } |
2391 | 2373 |
2392 // In SPDY4 and up, GOAWAY frames may also specify opaque data. | 2374 // In SPDY4 and up, GOAWAY frames may also specify opaque data. |
2393 if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) { | 2375 if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) { |
2394 builder.WriteBytes(goaway.description().data(), | 2376 builder.WriteBytes(goaway.description().data(), |
2395 goaway.description().size()); | 2377 goaway.description().size()); |
2396 } | 2378 } |
2397 | 2379 |
2398 DCHECK_EQ(expected_length, builder.length()); | 2380 DCHECK_EQ(expected_length, builder.length()); |
2399 return builder.take(); | 2381 return builder.take(); |
2400 } | 2382 } |
2401 | 2383 |
2402 SpdySerializedFrame* SpdyFramer::SerializeHeaders( | 2384 SpdySerializedFrame* SpdyFramer::SerializeHeaders( |
2403 const SpdyHeadersIR& headers) { | 2385 const SpdyHeadersIR& headers) { |
2404 uint8 flags = 0; | 2386 uint8 flags = 0; |
2405 if (headers.fin()) { | 2387 if (headers.fin()) { |
2406 flags |= CONTROL_FLAG_FIN; | 2388 flags |= CONTROL_FLAG_FIN; |
2407 } | 2389 } |
2408 if (protocol_version() > SPDY3) { | 2390 if (protocol_version() > SPDY3) { |
| 2391 // TODO(mlavan): If we overflow into a CONTINUATION frame, this will |
| 2392 // get overwritten below, so we should probably just get rid of the |
| 2393 // end_headers field. |
2409 if (headers.end_headers()) { | 2394 if (headers.end_headers()) { |
2410 flags |= HEADERS_FLAG_END_HEADERS; | 2395 flags |= HEADERS_FLAG_END_HEADERS; |
2411 } | 2396 } |
2412 if (headers.has_priority()) { | 2397 if (headers.has_priority()) { |
2413 flags |= HEADERS_FLAG_PRIORITY; | 2398 flags |= HEADERS_FLAG_PRIORITY; |
2414 } | 2399 } |
2415 } | 2400 } |
2416 | 2401 |
2417 // The size of this frame, including variable-length name-value block. | 2402 // The size of this frame, including variable-length name-value block. |
2418 size_t size = GetHeadersMinimumSize(); | 2403 size_t size = GetHeadersMinimumSize(); |
2419 | 2404 |
2420 uint32 priority = headers.priority(); | 2405 uint32 priority = headers.priority(); |
2421 if (headers.has_priority()) { | 2406 if (headers.has_priority()) { |
2422 if (priority > GetLowestPriority()) { | 2407 if (priority > GetLowestPriority()) { |
2423 DLOG(DFATAL) << "Priority out-of-bounds."; | 2408 DLOG(DFATAL) << "Priority out-of-bounds."; |
2424 priority = GetLowestPriority(); | 2409 priority = GetLowestPriority(); |
2425 } | 2410 } |
2426 size += 4; | 2411 size += 4; |
2427 } | 2412 } |
2428 | 2413 |
2429 string hpack_encoding; | 2414 string hpack_encoding; |
2430 if (protocol_version() > SPDY3) { | 2415 if (protocol_version() > SPDY3) { |
2431 hpack_encoder_.EncodeHeaderSet(headers.name_value_block(), &hpack_encoding); | 2416 hpack_encoder_.EncodeHeaderSet(headers.name_value_block(), &hpack_encoding); |
2432 size += hpack_encoding.size(); | 2417 size += hpack_encoding.size(); |
| 2418 if (size > GetControlFrameBufferMaxSize()) { |
| 2419 size += GetNumberRequiredContinuationFrames(size) * |
| 2420 GetContinuationMinimumSize(); |
| 2421 flags &= ~HEADERS_FLAG_END_HEADERS; |
| 2422 } |
2433 } else { | 2423 } else { |
2434 size += GetSerializedLength(headers.name_value_block()); | 2424 size += GetSerializedLength(headers.name_value_block()); |
2435 } | 2425 } |
2436 | 2426 |
2437 SpdyFrameBuilder builder(size); | 2427 SpdyFrameBuilder builder(size, protocol_version()); |
2438 if (protocol_version() <= SPDY3) { | 2428 if (protocol_version() <= SPDY3) { |
2439 builder.WriteControlFrameHeader(*this, HEADERS, flags); | 2429 builder.WriteControlFrameHeader(*this, HEADERS, flags); |
2440 builder.WriteUInt32(headers.stream_id()); | 2430 builder.WriteUInt32(headers.stream_id()); |
2441 } else { | 2431 } else { |
2442 builder.WriteFramePrefix(*this, | 2432 builder.BeginNewFrame(*this, |
2443 HEADERS, | 2433 HEADERS, |
2444 flags, | 2434 flags, |
2445 headers.stream_id()); | 2435 headers.stream_id()); |
2446 if (headers.has_priority()) { | 2436 if (headers.has_priority()) { |
2447 builder.WriteUInt32(priority); | 2437 builder.WriteUInt32(priority); |
2448 } | 2438 } |
2449 } | 2439 } |
2450 if (protocol_version() <= SPDY2) { | 2440 if (protocol_version() <= SPDY2) { |
2451 builder.WriteUInt16(0); // Unused. | 2441 builder.WriteUInt16(0); // Unused. |
2452 } | 2442 } |
2453 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); | 2443 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); |
2454 | 2444 |
2455 if (protocol_version() > SPDY3) { | 2445 if (protocol_version() > SPDY3) { |
2456 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2446 WritePayloadWithContinuation(&builder, |
| 2447 hpack_encoding, |
| 2448 headers.stream_id(), |
| 2449 HEADERS); |
2457 } else { | 2450 } else { |
2458 SerializeNameValueBlock(&builder, headers); | 2451 SerializeNameValueBlock(&builder, headers); |
2459 } | 2452 } |
2460 | 2453 |
2461 if (debug_visitor_) { | 2454 if (debug_visitor_) { |
2462 const size_t payload_len = protocol_version() > SPDY3 ? | 2455 const size_t payload_len = protocol_version() > SPDY3 ? |
2463 hpack_encoding.size() : | 2456 hpack_encoding.size() : |
2464 GetSerializedLength(protocol_version(), | 2457 GetSerializedLength(protocol_version(), |
2465 &(headers.name_value_block())); | 2458 &(headers.name_value_block())); |
2466 debug_visitor_->OnSendCompressedFrame(headers.stream_id(), | 2459 debug_visitor_->OnSendCompressedFrame(headers.stream_id(), |
2467 HEADERS, | 2460 HEADERS, |
2468 payload_len, | 2461 payload_len, |
2469 builder.length()); | 2462 builder.length()); |
2470 } | 2463 } |
2471 | 2464 |
2472 return builder.take(); | 2465 return builder.take(); |
2473 } | 2466 } |
2474 | 2467 |
2475 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( | 2468 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( |
2476 const SpdyWindowUpdateIR& window_update) const { | 2469 const SpdyWindowUpdateIR& window_update) const { |
2477 SpdyFrameBuilder builder(GetWindowUpdateSize()); | 2470 SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version()); |
2478 if (protocol_version() <= SPDY3) { | 2471 if (protocol_version() <= SPDY3) { |
2479 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); | 2472 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); |
2480 builder.WriteUInt32(window_update.stream_id()); | 2473 builder.WriteUInt32(window_update.stream_id()); |
2481 } else { | 2474 } else { |
2482 builder.WriteFramePrefix(*this, | 2475 builder.BeginNewFrame(*this, |
2483 WINDOW_UPDATE, | 2476 WINDOW_UPDATE, |
2484 kNoFlags, | 2477 kNoFlags, |
2485 window_update.stream_id()); | 2478 window_update.stream_id()); |
2486 } | 2479 } |
2487 builder.WriteUInt32(window_update.delta()); | 2480 builder.WriteUInt32(window_update.delta()); |
2488 DCHECK_EQ(GetWindowUpdateSize(), builder.length()); | 2481 DCHECK_EQ(GetWindowUpdateSize(), builder.length()); |
2489 return builder.take(); | 2482 return builder.take(); |
2490 } | 2483 } |
2491 | 2484 |
| 2485 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const { |
| 2486 DCHECK_LT(SPDY3, protocol_version()); |
| 2487 SpdyFrameBuilder builder(GetBlockedSize(), protocol_version()); |
| 2488 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id()); |
| 2489 return builder.take(); |
| 2490 } |
| 2491 |
2492 SpdyFrame* SpdyFramer::SerializePushPromise( | 2492 SpdyFrame* SpdyFramer::SerializePushPromise( |
2493 const SpdyPushPromiseIR& push_promise) { | 2493 const SpdyPushPromiseIR& push_promise) { |
2494 DCHECK_LT(SPDY3, protocol_version()); | 2494 DCHECK_LT(SPDY3, protocol_version()); |
2495 uint8 flags = 0; | 2495 uint8 flags = 0; |
| 2496 // TODO(mlavan): If we overflow into a CONTINUATION frame, this will |
| 2497 // get overwritten below, so we should probably just get rid of the |
| 2498 // end_push_promise field. |
2496 if (push_promise.end_push_promise()) { | 2499 if (push_promise.end_push_promise()) { |
2497 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 2500 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
2498 } | 2501 } |
2499 // The size of this frame, including variable-length name-value block. | 2502 // The size of this frame, including variable-length name-value block. |
2500 size_t size = GetPushPromiseMinimumSize(); | 2503 size_t size = GetPushPromiseMinimumSize(); |
2501 | 2504 |
2502 string hpack_encoding; | 2505 string hpack_encoding; |
2503 if (protocol_version() > SPDY3) { | 2506 if (protocol_version() > SPDY3) { |
2504 hpack_encoder_.EncodeHeaderSet(push_promise.name_value_block(), | 2507 hpack_encoder_.EncodeHeaderSet(push_promise.name_value_block(), |
2505 &hpack_encoding); | 2508 &hpack_encoding); |
2506 size += hpack_encoding.size(); | 2509 size += hpack_encoding.size(); |
| 2510 if (size > GetControlFrameBufferMaxSize()) { |
| 2511 size += GetNumberRequiredContinuationFrames(size) * |
| 2512 GetContinuationMinimumSize(); |
| 2513 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
| 2514 } |
2507 } else { | 2515 } else { |
2508 size += GetSerializedLength(push_promise.name_value_block()); | 2516 size += GetSerializedLength(push_promise.name_value_block()); |
2509 } | 2517 } |
2510 | 2518 |
2511 SpdyFrameBuilder builder(size); | 2519 SpdyFrameBuilder builder(size, protocol_version()); |
2512 builder.WriteFramePrefix(*this, PUSH_PROMISE, flags, | 2520 builder.BeginNewFrame(*this, |
2513 push_promise.stream_id()); | 2521 PUSH_PROMISE, |
| 2522 flags, |
| 2523 push_promise.stream_id()); |
2514 builder.WriteUInt32(push_promise.promised_stream_id()); | 2524 builder.WriteUInt32(push_promise.promised_stream_id()); |
2515 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length()); | 2525 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length()); |
2516 | 2526 |
2517 if (protocol_version() > SPDY3) { | 2527 if (protocol_version() > SPDY3) { |
2518 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2528 WritePayloadWithContinuation(&builder, |
| 2529 hpack_encoding, |
| 2530 push_promise.stream_id(), |
| 2531 PUSH_PROMISE); |
2519 } else { | 2532 } else { |
2520 SerializeNameValueBlock(&builder, push_promise); | 2533 SerializeNameValueBlock(&builder, push_promise); |
2521 } | 2534 } |
2522 | 2535 |
2523 if (debug_visitor_) { | 2536 if (debug_visitor_) { |
2524 const size_t payload_len = protocol_version() > SPDY3 ? | 2537 const size_t payload_len = protocol_version() > SPDY3 ? |
2525 hpack_encoding.size() : | 2538 hpack_encoding.size() : |
2526 GetSerializedLength(protocol_version(), | 2539 GetSerializedLength(protocol_version(), |
2527 &(push_promise.name_value_block())); | 2540 &(push_promise.name_value_block())); |
2528 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(), | 2541 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(), |
(...skipping 14 matching lines...) Expand all Loading... |
2543 flags |= HEADERS_FLAG_END_HEADERS; | 2556 flags |= HEADERS_FLAG_END_HEADERS; |
2544 } | 2557 } |
2545 | 2558 |
2546 // The size of this frame, including variable-length name-value block. | 2559 // The size of this frame, including variable-length name-value block. |
2547 size_t size = GetContinuationMinimumSize(); | 2560 size_t size = GetContinuationMinimumSize(); |
2548 string hpack_encoding; | 2561 string hpack_encoding; |
2549 hpack_encoder_.EncodeHeaderSet(continuation.name_value_block(), | 2562 hpack_encoder_.EncodeHeaderSet(continuation.name_value_block(), |
2550 &hpack_encoding); | 2563 &hpack_encoding); |
2551 size += hpack_encoding.size(); | 2564 size += hpack_encoding.size(); |
2552 | 2565 |
2553 SpdyFrameBuilder builder(size); | 2566 SpdyFrameBuilder builder(size, protocol_version()); |
2554 builder.WriteFramePrefix(*this, CONTINUATION, flags, | 2567 builder.BeginNewFrame(*this, CONTINUATION, flags, |
2555 continuation.stream_id()); | 2568 continuation.stream_id()); |
2556 DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); | 2569 DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); |
2557 | 2570 |
2558 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2571 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); |
2559 | 2572 |
2560 if (debug_visitor_) { | 2573 if (debug_visitor_) { |
2561 const size_t payload_len = hpack_encoding.size(); | 2574 const size_t payload_len = hpack_encoding.size(); |
2562 debug_visitor_->OnSendCompressedFrame(continuation.stream_id(), | 2575 debug_visitor_->OnSendCompressedFrame(continuation.stream_id(), |
2563 CONTINUATION, payload_len, builder.length()); | 2576 CONTINUATION, payload_len, builder.length()); |
2564 } | 2577 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2634 GetSerializedLength(protocol_version(), &headers); | 2647 GetSerializedLength(protocol_version(), &headers); |
2635 if (!enable_compression_) { | 2648 if (!enable_compression_) { |
2636 return uncompressed_length; | 2649 return uncompressed_length; |
2637 } | 2650 } |
2638 z_stream* compressor = GetHeaderCompressor(); | 2651 z_stream* compressor = GetHeaderCompressor(); |
2639 // Since we'll be performing lots of flushes when compressing the data, | 2652 // Since we'll be performing lots of flushes when compressing the data, |
2640 // zlib's lower bounds may be insufficient. | 2653 // zlib's lower bounds may be insufficient. |
2641 return 2 * deflateBound(compressor, uncompressed_length); | 2654 return 2 * deflateBound(compressor, uncompressed_length); |
2642 } | 2655 } |
2643 | 2656 |
| 2657 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) { |
| 2658 const size_t kMaxControlFrameSize = GetControlFrameBufferMaxSize(); |
| 2659 DCHECK_GT(protocol_version(), net::SPDY3); |
| 2660 DCHECK_GT(size, kMaxControlFrameSize); |
| 2661 size_t overflow = size - kMaxControlFrameSize; |
| 2662 return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1; |
| 2663 } |
| 2664 |
| 2665 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, |
| 2666 const string& hpack_encoding, |
| 2667 SpdyStreamId stream_id, |
| 2668 SpdyFrameType type) { |
| 2669 const size_t kMaxControlFrameSize = GetControlFrameBufferMaxSize(); |
| 2670 |
| 2671 // In addition to the prefix, fixed_field_size includes the size of |
| 2672 // any fields that come before the variable-length name/value block. |
| 2673 size_t fixed_field_size = 0; |
| 2674 uint8 end_flag = 0; |
| 2675 uint8 flags = 0; |
| 2676 if (type == HEADERS) { |
| 2677 fixed_field_size = GetHeadersMinimumSize(); |
| 2678 end_flag = HEADERS_FLAG_END_HEADERS; |
| 2679 } else if (type == PUSH_PROMISE) { |
| 2680 fixed_field_size = GetPushPromiseMinimumSize(); |
| 2681 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
| 2682 } else { |
| 2683 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " |
| 2684 << FrameTypeToString(type); |
| 2685 } |
| 2686 |
| 2687 // Write as much of the payload as possible into the initial frame. |
| 2688 size_t bytes_remaining = hpack_encoding.size() - |
| 2689 std::min(hpack_encoding.size(), |
| 2690 kMaxControlFrameSize - fixed_field_size); |
| 2691 builder->WriteBytes(&hpack_encoding[0], |
| 2692 hpack_encoding.size() - bytes_remaining); |
| 2693 |
| 2694 if (bytes_remaining > 0) { |
| 2695 builder->OverwriteLength(*this, |
| 2696 kMaxControlFrameSize - GetControlFrameHeaderSize()); |
| 2697 } |
| 2698 |
| 2699 // Tack on CONTINUATION frames for the overflow. |
| 2700 while (bytes_remaining > 0) { |
| 2701 size_t bytes_to_write = std::min(bytes_remaining, |
| 2702 kMaxControlFrameSize - |
| 2703 GetContinuationMinimumSize()); |
| 2704 // Write CONTINUATION frame prefix. |
| 2705 if (bytes_remaining == bytes_to_write) { |
| 2706 flags |= end_flag; |
| 2707 } |
| 2708 builder->BeginNewFrame(*this, |
| 2709 CONTINUATION, |
| 2710 flags, |
| 2711 stream_id); |
| 2712 // Write payload fragment. |
| 2713 builder->WriteBytes(&hpack_encoding[hpack_encoding.size() - |
| 2714 bytes_remaining], |
| 2715 bytes_to_write); |
| 2716 bytes_remaining -= bytes_to_write; |
| 2717 } |
| 2718 } |
| 2719 |
2644 // The following compression setting are based on Brian Olson's analysis. See | 2720 // The following compression setting are based on Brian Olson's analysis. See |
2645 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 | 2721 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 |
2646 // for more details. | 2722 // for more details. |
2647 #if defined(USE_SYSTEM_ZLIB) | 2723 #if defined(USE_SYSTEM_ZLIB) |
2648 // System zlib is not expected to have workaround for http://crbug.com/139744, | 2724 // System zlib is not expected to have workaround for http://crbug.com/139744, |
2649 // so disable compression in that case. | 2725 // so disable compression in that case. |
2650 // TODO(phajdan.jr): Remove the special case when it's no longer necessary. | 2726 // TODO(phajdan.jr): Remove the special case when it's no longer necessary. |
2651 static const int kCompressorLevel = 0; | 2727 static const int kCompressorLevel = 0; |
2652 #else // !defined(USE_SYSTEM_ZLIB) | 2728 #else // !defined(USE_SYSTEM_ZLIB) |
2653 static const int kCompressorLevel = 9; | 2729 static const int kCompressorLevel = 9; |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2824 const SpdyFrameWithNameValueBlockIR& frame) { | 2900 const SpdyFrameWithNameValueBlockIR& frame) { |
2825 CHECK_GE(SPDY3, protocol_version()); | 2901 CHECK_GE(SPDY3, protocol_version()); |
2826 if (!enable_compression_) { | 2902 if (!enable_compression_) { |
2827 return SerializeNameValueBlockWithoutCompression(builder, | 2903 return SerializeNameValueBlockWithoutCompression(builder, |
2828 frame.name_value_block()); | 2904 frame.name_value_block()); |
2829 } | 2905 } |
2830 | 2906 |
2831 // First build an uncompressed version to be fed into the compressor. | 2907 // First build an uncompressed version to be fed into the compressor. |
2832 const size_t uncompressed_len = GetSerializedLength( | 2908 const size_t uncompressed_len = GetSerializedLength( |
2833 protocol_version(), &(frame.name_value_block())); | 2909 protocol_version(), &(frame.name_value_block())); |
2834 SpdyFrameBuilder uncompressed_builder(uncompressed_len); | 2910 SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version()); |
2835 SerializeNameValueBlockWithoutCompression(&uncompressed_builder, | 2911 SerializeNameValueBlockWithoutCompression(&uncompressed_builder, |
2836 frame.name_value_block()); | 2912 frame.name_value_block()); |
2837 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); | 2913 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); |
2838 | 2914 |
2839 z_stream* compressor = GetHeaderCompressor(); | 2915 z_stream* compressor = GetHeaderCompressor(); |
2840 if (!compressor) { | 2916 if (!compressor) { |
2841 LOG(DFATAL) << "Could not obtain compressor."; | 2917 LOG(DFATAL) << "Could not obtain compressor."; |
2842 return; | 2918 return; |
2843 } | 2919 } |
2844 | 2920 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2883 builder->Seek(compressed_size); | 2959 builder->Seek(compressed_size); |
2884 builder->RewriteLength(*this); | 2960 builder->RewriteLength(*this); |
2885 | 2961 |
2886 pre_compress_bytes.Add(uncompressed_len); | 2962 pre_compress_bytes.Add(uncompressed_len); |
2887 post_compress_bytes.Add(compressed_size); | 2963 post_compress_bytes.Add(compressed_size); |
2888 | 2964 |
2889 compressed_frames.Increment(); | 2965 compressed_frames.Increment(); |
2890 } | 2966 } |
2891 | 2967 |
2892 } // namespace net | 2968 } // namespace net |
OLD | NEW |