| 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 <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <iterator> | 10 #include <iterator> |
| (...skipping 1701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1712 const SpdyHeaderBlock& block = GetHpackDecoder()->decoded_block(); | 1712 const SpdyHeaderBlock& block = GetHpackDecoder()->decoded_block(); |
| 1713 if (block.empty()) { | 1713 if (block.empty()) { |
| 1714 // Special-case this to make tests happy. | 1714 // Special-case this to make tests happy. |
| 1715 ProcessControlFrameHeaderBlock(NULL, 0, false); | 1715 ProcessControlFrameHeaderBlock(NULL, 0, false); |
| 1716 return; | 1716 return; |
| 1717 } | 1717 } |
| 1718 size_t payload_len = GetSerializedLength(protocol_version_, &block); | 1718 size_t payload_len = GetSerializedLength(protocol_version_, &block); |
| 1719 SpdyFrameBuilder builder(payload_len, SPDY3); | 1719 SpdyFrameBuilder builder(payload_len, SPDY3); |
| 1720 | 1720 |
| 1721 SerializeHeaderBlockWithoutCompression(&builder, block); | 1721 SerializeHeaderBlockWithoutCompression(&builder, block); |
| 1722 scoped_ptr<SpdyFrame> frame(builder.take()); | 1722 SpdySerializedFrame frame = builder.take(); |
| 1723 | 1723 |
| 1724 // Preserve padding length, and reset it after the re-entrant call. | 1724 // Preserve padding length, and reset it after the re-entrant call. |
| 1725 size_t remaining_padding = remaining_padding_payload_length_; | 1725 size_t remaining_padding = remaining_padding_payload_length_; |
| 1726 | 1726 |
| 1727 remaining_padding_payload_length_ = 0; | 1727 remaining_padding_payload_length_ = 0; |
| 1728 remaining_data_length_ = frame->size(); | 1728 remaining_data_length_ = frame.size(); |
| 1729 | 1729 |
| 1730 if (payload_len != 0) { | 1730 if (payload_len != 0) { |
| 1731 int compression_pct = 100 - (100 * compressed_len) / payload_len; | 1731 int compression_pct = 100 - (100 * compressed_len) / payload_len; |
| 1732 DVLOG(1) << "Net.SpdyHpackDecompressionPercentage: " << compression_pct; | 1732 DVLOG(1) << "Net.SpdyHpackDecompressionPercentage: " << compression_pct; |
| 1733 UMA_HISTOGRAM_PERCENTAGE("Net.SpdyHpackDecompressionPercentage", | 1733 UMA_HISTOGRAM_PERCENTAGE("Net.SpdyHpackDecompressionPercentage", |
| 1734 compression_pct); | 1734 compression_pct); |
| 1735 } | 1735 } |
| 1736 | 1736 |
| 1737 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false); | 1737 ProcessControlFrameHeaderBlock(frame.data(), frame.size(), false); |
| 1738 | 1738 |
| 1739 remaining_padding_payload_length_ = remaining_padding; | 1739 remaining_padding_payload_length_ = remaining_padding; |
| 1740 remaining_data_length_ = remaining_padding; | 1740 remaining_data_length_ = remaining_padding; |
| 1741 } | 1741 } |
| 1742 | 1742 |
| 1743 bool SpdyFramer::ProcessSetting(const char* data) { | 1743 bool SpdyFramer::ProcessSetting(const char* data) { |
| 1744 int id_field; | 1744 int id_field; |
| 1745 SpdySettingsIds id; | 1745 SpdySettingsIds id; |
| 1746 uint8_t flags = 0; | 1746 uint8_t flags = 0; |
| 1747 uint32_t value; | 1747 uint32_t value; |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2199 if (reader.GetBytesConsumed() != header_length) { | 2199 if (reader.GetBytesConsumed() != header_length) { |
| 2200 LOG(DFATAL) << "Buffer expected to consist entirely of headers, but only " | 2200 LOG(DFATAL) << "Buffer expected to consist entirely of headers, but only " |
| 2201 << reader.GetBytesConsumed() << " bytes consumed, from " | 2201 << reader.GetBytesConsumed() << " bytes consumed, from " |
| 2202 << header_length; | 2202 << header_length; |
| 2203 return false; | 2203 return false; |
| 2204 } | 2204 } |
| 2205 | 2205 |
| 2206 return true; | 2206 return true; |
| 2207 } | 2207 } |
| 2208 | 2208 |
| 2209 SpdySerializedFrame* SpdyFramer::SerializeData( | 2209 SpdySerializedFrame SpdyFramer::SerializeData(const SpdyDataIR& data_ir) const { |
| 2210 const SpdyDataIR& data_ir) const { | |
| 2211 uint8_t flags = DATA_FLAG_NONE; | 2210 uint8_t flags = DATA_FLAG_NONE; |
| 2212 if (data_ir.fin()) { | 2211 if (data_ir.fin()) { |
| 2213 flags = DATA_FLAG_FIN; | 2212 flags = DATA_FLAG_FIN; |
| 2214 } | 2213 } |
| 2215 | 2214 |
| 2216 if (protocol_version_ == SPDY3) { | 2215 if (protocol_version_ == SPDY3) { |
| 2217 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length(); | 2216 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length(); |
| 2218 SpdyFrameBuilder builder(size, protocol_version_); | 2217 SpdyFrameBuilder builder(size, protocol_version_); |
| 2219 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); | 2218 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); |
| 2220 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); | 2219 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2238 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); | 2237 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); |
| 2239 if (data_ir.padding_payload_len() > 0) { | 2238 if (data_ir.padding_payload_len() > 0) { |
| 2240 string padding(data_ir.padding_payload_len(), 0); | 2239 string padding(data_ir.padding_payload_len(), 0); |
| 2241 builder.WriteBytes(padding.data(), padding.length()); | 2240 builder.WriteBytes(padding.data(), padding.length()); |
| 2242 } | 2241 } |
| 2243 DCHECK_EQ(size_with_padding, builder.length()); | 2242 DCHECK_EQ(size_with_padding, builder.length()); |
| 2244 return builder.take(); | 2243 return builder.take(); |
| 2245 } | 2244 } |
| 2246 } | 2245 } |
| 2247 | 2246 |
| 2248 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField( | 2247 SpdySerializedFrame SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField( |
| 2249 const SpdyDataIR& data_ir) const { | 2248 const SpdyDataIR& data_ir) const { |
| 2250 uint8_t flags = DATA_FLAG_NONE; | 2249 uint8_t flags = DATA_FLAG_NONE; |
| 2251 if (data_ir.fin()) { | 2250 if (data_ir.fin()) { |
| 2252 flags = DATA_FLAG_FIN; | 2251 flags = DATA_FLAG_FIN; |
| 2253 } | 2252 } |
| 2254 | 2253 |
| 2255 size_t frame_size = GetDataFrameMinimumSize(); | 2254 size_t frame_size = GetDataFrameMinimumSize(); |
| 2256 size_t num_padding_fields = 0; | 2255 size_t num_padding_fields = 0; |
| 2257 if (protocol_version_ == HTTP2) { | 2256 if (protocol_version_ == HTTP2) { |
| 2258 if (data_ir.padded()) { | 2257 if (data_ir.padded()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2270 } | 2269 } |
| 2271 builder.OverwriteLength(*this, num_padding_fields + | 2270 builder.OverwriteLength(*this, num_padding_fields + |
| 2272 data_ir.data().length() + data_ir.padding_payload_len()); | 2271 data_ir.data().length() + data_ir.padding_payload_len()); |
| 2273 } else { | 2272 } else { |
| 2274 builder.OverwriteLength(*this, data_ir.data().length()); | 2273 builder.OverwriteLength(*this, data_ir.data().length()); |
| 2275 } | 2274 } |
| 2276 DCHECK_EQ(frame_size, builder.length()); | 2275 DCHECK_EQ(frame_size, builder.length()); |
| 2277 return builder.take(); | 2276 return builder.take(); |
| 2278 } | 2277 } |
| 2279 | 2278 |
| 2280 SpdySerializedFrame* SpdyFramer::SerializeSynStream( | 2279 SpdySerializedFrame SpdyFramer::SerializeSynStream( |
| 2281 const SpdySynStreamIR& syn_stream) { | 2280 const SpdySynStreamIR& syn_stream) { |
| 2282 DCHECK_EQ(SPDY3, protocol_version_); | 2281 DCHECK_EQ(SPDY3, protocol_version_); |
| 2283 uint8_t flags = 0; | 2282 uint8_t flags = 0; |
| 2284 if (syn_stream.fin()) { | 2283 if (syn_stream.fin()) { |
| 2285 flags |= CONTROL_FLAG_FIN; | 2284 flags |= CONTROL_FLAG_FIN; |
| 2286 } | 2285 } |
| 2287 if (syn_stream.unidirectional()) { | 2286 if (syn_stream.unidirectional()) { |
| 2288 flags |= CONTROL_FLAG_UNIDIRECTIONAL; | 2287 flags |= CONTROL_FLAG_UNIDIRECTIONAL; |
| 2289 } | 2288 } |
| 2290 | 2289 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2313 GetSerializedLength(protocol_version_, &(syn_stream.header_block())); | 2312 GetSerializedLength(protocol_version_, &(syn_stream.header_block())); |
| 2314 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(), | 2313 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(), |
| 2315 SYN_STREAM, | 2314 SYN_STREAM, |
| 2316 payload_len, | 2315 payload_len, |
| 2317 builder.length()); | 2316 builder.length()); |
| 2318 } | 2317 } |
| 2319 | 2318 |
| 2320 return builder.take(); | 2319 return builder.take(); |
| 2321 } | 2320 } |
| 2322 | 2321 |
| 2323 SpdySerializedFrame* SpdyFramer::SerializeSynReply( | 2322 SpdySerializedFrame SpdyFramer::SerializeSynReply( |
| 2324 const SpdySynReplyIR& syn_reply) { | 2323 const SpdySynReplyIR& syn_reply) { |
| 2325 DCHECK_EQ(SPDY3, protocol_version_); | 2324 DCHECK_EQ(SPDY3, protocol_version_); |
| 2326 uint8_t flags = 0; | 2325 uint8_t flags = 0; |
| 2327 if (syn_reply.fin()) { | 2326 if (syn_reply.fin()) { |
| 2328 flags |= CONTROL_FLAG_FIN; | 2327 flags |= CONTROL_FLAG_FIN; |
| 2329 } | 2328 } |
| 2330 | 2329 |
| 2331 // The size of this frame, including variable-length header block. | 2330 // The size of this frame, including variable-length header block. |
| 2332 const size_t size = | 2331 const size_t size = |
| 2333 GetSynReplyMinimumSize() + GetSerializedLength(syn_reply.header_block()); | 2332 GetSynReplyMinimumSize() + GetSerializedLength(syn_reply.header_block()); |
| 2334 | 2333 |
| 2335 SpdyFrameBuilder builder(size, protocol_version_); | 2334 SpdyFrameBuilder builder(size, protocol_version_); |
| 2336 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); | 2335 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); |
| 2337 builder.WriteUInt32(syn_reply.stream_id()); | 2336 builder.WriteUInt32(syn_reply.stream_id()); |
| 2338 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); | 2337 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); |
| 2339 SerializeHeaderBlock(&builder, syn_reply); | 2338 SerializeHeaderBlock(&builder, syn_reply); |
| 2340 | 2339 |
| 2341 if (debug_visitor_) { | 2340 if (debug_visitor_) { |
| 2342 const size_t payload_len = | 2341 const size_t payload_len = |
| 2343 GetSerializedLength(protocol_version_, &(syn_reply.header_block())); | 2342 GetSerializedLength(protocol_version_, &(syn_reply.header_block())); |
| 2344 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(), | 2343 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(), |
| 2345 SYN_REPLY, | 2344 SYN_REPLY, |
| 2346 payload_len, | 2345 payload_len, |
| 2347 builder.length()); | 2346 builder.length()); |
| 2348 } | 2347 } |
| 2349 | 2348 |
| 2350 return builder.take(); | 2349 return builder.take(); |
| 2351 } | 2350 } |
| 2352 | 2351 |
| 2353 SpdySerializedFrame* SpdyFramer::SerializeRstStream( | 2352 SpdySerializedFrame SpdyFramer::SerializeRstStream( |
| 2354 const SpdyRstStreamIR& rst_stream) const { | 2353 const SpdyRstStreamIR& rst_stream) const { |
| 2355 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM | 2354 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM |
| 2356 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2, | 2355 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2, |
| 2357 // which doesn't currently include RST_STREAM payloads. GFE flags have been | 2356 // which doesn't currently include RST_STREAM payloads. GFE flags have been |
| 2358 // commented but left in place to simplify future patching. | 2357 // commented but left in place to simplify future patching. |
| 2359 // Compute the output buffer size, taking opaque data into account. | 2358 // Compute the output buffer size, taking opaque data into account. |
| 2360 size_t expected_length = GetRstStreamMinimumSize(); | 2359 size_t expected_length = GetRstStreamMinimumSize(); |
| 2361 SpdyFrameBuilder builder(expected_length, protocol_version_); | 2360 SpdyFrameBuilder builder(expected_length, protocol_version_); |
| 2362 | 2361 |
| 2363 // Serialize the RST_STREAM frame. | 2362 // Serialize the RST_STREAM frame. |
| 2364 if (protocol_version_ == SPDY3) { | 2363 if (protocol_version_ == SPDY3) { |
| 2365 builder.WriteControlFrameHeader(*this, RST_STREAM, 0); | 2364 builder.WriteControlFrameHeader(*this, RST_STREAM, 0); |
| 2366 builder.WriteUInt32(rst_stream.stream_id()); | 2365 builder.WriteUInt32(rst_stream.stream_id()); |
| 2367 } else { | 2366 } else { |
| 2368 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id()); | 2367 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id()); |
| 2369 } | 2368 } |
| 2370 | 2369 |
| 2371 builder.WriteUInt32(SpdyConstants::SerializeRstStreamStatus( | 2370 builder.WriteUInt32(SpdyConstants::SerializeRstStreamStatus( |
| 2372 protocol_version_, rst_stream.status())); | 2371 protocol_version_, rst_stream.status())); |
| 2373 | 2372 |
| 2374 DCHECK_EQ(expected_length, builder.length()); | 2373 DCHECK_EQ(expected_length, builder.length()); |
| 2375 return builder.take(); | 2374 return builder.take(); |
| 2376 } | 2375 } |
| 2377 | 2376 |
| 2378 SpdySerializedFrame* SpdyFramer::SerializeSettings( | 2377 SpdySerializedFrame SpdyFramer::SerializeSettings( |
| 2379 const SpdySettingsIR& settings) const { | 2378 const SpdySettingsIR& settings) const { |
| 2380 uint8_t flags = 0; | 2379 uint8_t flags = 0; |
| 2381 | 2380 |
| 2382 if (protocol_version_ == SPDY3) { | 2381 if (protocol_version_ == SPDY3) { |
| 2383 if (settings.clear_settings()) { | 2382 if (settings.clear_settings()) { |
| 2384 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; | 2383 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; |
| 2385 } | 2384 } |
| 2386 } else { | 2385 } else { |
| 2387 if (settings.is_ack()) { | 2386 if (settings.is_ack()) { |
| 2388 flags |= SETTINGS_FLAG_ACK; | 2387 flags |= SETTINGS_FLAG_ACK; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2430 builder.WriteBytes(&id_and_flags_wire, 4); | 2429 builder.WriteBytes(&id_and_flags_wire, 4); |
| 2431 } else { | 2430 } else { |
| 2432 builder.WriteUInt16(static_cast<uint16_t>(setting_id)); | 2431 builder.WriteUInt16(static_cast<uint16_t>(setting_id)); |
| 2433 } | 2432 } |
| 2434 builder.WriteUInt32(it->second.value); | 2433 builder.WriteUInt32(it->second.value); |
| 2435 } | 2434 } |
| 2436 DCHECK_EQ(size, builder.length()); | 2435 DCHECK_EQ(size, builder.length()); |
| 2437 return builder.take(); | 2436 return builder.take(); |
| 2438 } | 2437 } |
| 2439 | 2438 |
| 2440 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { | 2439 SpdySerializedFrame SpdyFramer::SerializePing(const SpdyPingIR& ping) const { |
| 2441 SpdyFrameBuilder builder(GetPingSize(), protocol_version_); | 2440 SpdyFrameBuilder builder(GetPingSize(), protocol_version_); |
| 2442 if (protocol_version_ == SPDY3) { | 2441 if (protocol_version_ == SPDY3) { |
| 2443 builder.WriteControlFrameHeader(*this, PING, kNoFlags); | 2442 builder.WriteControlFrameHeader(*this, PING, kNoFlags); |
| 2444 builder.WriteUInt32(static_cast<uint32_t>(ping.id())); | 2443 builder.WriteUInt32(static_cast<uint32_t>(ping.id())); |
| 2445 } else { | 2444 } else { |
| 2446 uint8_t flags = 0; | 2445 uint8_t flags = 0; |
| 2447 if (ping.is_ack()) { | 2446 if (ping.is_ack()) { |
| 2448 flags |= PING_FLAG_ACK; | 2447 flags |= PING_FLAG_ACK; |
| 2449 } | 2448 } |
| 2450 builder.BeginNewFrame(*this, PING, flags, 0); | 2449 builder.BeginNewFrame(*this, PING, flags, 0); |
| 2451 builder.WriteUInt64(ping.id()); | 2450 builder.WriteUInt64(ping.id()); |
| 2452 } | 2451 } |
| 2453 DCHECK_EQ(GetPingSize(), builder.length()); | 2452 DCHECK_EQ(GetPingSize(), builder.length()); |
| 2454 return builder.take(); | 2453 return builder.take(); |
| 2455 } | 2454 } |
| 2456 | 2455 |
| 2457 SpdySerializedFrame* SpdyFramer::SerializeGoAway( | 2456 SpdySerializedFrame SpdyFramer::SerializeGoAway( |
| 2458 const SpdyGoAwayIR& goaway) const { | 2457 const SpdyGoAwayIR& goaway) const { |
| 2459 | |
| 2460 // Compute the output buffer size, take opaque data into account. | 2458 // Compute the output buffer size, take opaque data into account. |
| 2461 size_t expected_length = GetGoAwayMinimumSize(); | 2459 size_t expected_length = GetGoAwayMinimumSize(); |
| 2462 if (protocol_version_ == HTTP2) { | 2460 if (protocol_version_ == HTTP2) { |
| 2463 expected_length += goaway.description().size(); | 2461 expected_length += goaway.description().size(); |
| 2464 } | 2462 } |
| 2465 SpdyFrameBuilder builder(expected_length, protocol_version_); | 2463 SpdyFrameBuilder builder(expected_length, protocol_version_); |
| 2466 | 2464 |
| 2467 // Serialize the GOAWAY frame. | 2465 // Serialize the GOAWAY frame. |
| 2468 if (protocol_version_ == SPDY3) { | 2466 if (protocol_version_ == SPDY3) { |
| 2469 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags); | 2467 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2481 // In HTTP2, GOAWAY frames may also specify opaque data. | 2479 // In HTTP2, GOAWAY frames may also specify opaque data. |
| 2482 if ((protocol_version_ == HTTP2) && (goaway.description().size() > 0)) { | 2480 if ((protocol_version_ == HTTP2) && (goaway.description().size() > 0)) { |
| 2483 builder.WriteBytes(goaway.description().data(), | 2481 builder.WriteBytes(goaway.description().data(), |
| 2484 goaway.description().size()); | 2482 goaway.description().size()); |
| 2485 } | 2483 } |
| 2486 | 2484 |
| 2487 DCHECK_EQ(expected_length, builder.length()); | 2485 DCHECK_EQ(expected_length, builder.length()); |
| 2488 return builder.take(); | 2486 return builder.take(); |
| 2489 } | 2487 } |
| 2490 | 2488 |
| 2491 SpdySerializedFrame* SpdyFramer::SerializeHeaders( | 2489 SpdySerializedFrame SpdyFramer::SerializeHeaders(const SpdyHeadersIR& headers) { |
| 2492 const SpdyHeadersIR& headers) { | |
| 2493 uint8_t flags = 0; | 2490 uint8_t flags = 0; |
| 2494 if (headers.fin()) { | 2491 if (headers.fin()) { |
| 2495 flags |= CONTROL_FLAG_FIN; | 2492 flags |= CONTROL_FLAG_FIN; |
| 2496 } | 2493 } |
| 2497 if (protocol_version_ == HTTP2) { | 2494 if (protocol_version_ == HTTP2) { |
| 2498 // This will get overwritten if we overflow into a CONTINUATION frame. | 2495 // This will get overwritten if we overflow into a CONTINUATION frame. |
| 2499 flags |= HEADERS_FLAG_END_HEADERS; | 2496 flags |= HEADERS_FLAG_END_HEADERS; |
| 2500 if (headers.has_priority()) { | 2497 if (headers.has_priority()) { |
| 2501 flags |= HEADERS_FLAG_PRIORITY; | 2498 flags |= HEADERS_FLAG_PRIORITY; |
| 2502 } | 2499 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2582 GetSerializedLength(protocol_version_, &(headers.header_block())); | 2579 GetSerializedLength(protocol_version_, &(headers.header_block())); |
| 2583 debug_visitor_->OnSendCompressedFrame(headers.stream_id(), | 2580 debug_visitor_->OnSendCompressedFrame(headers.stream_id(), |
| 2584 HEADERS, | 2581 HEADERS, |
| 2585 payload_len, | 2582 payload_len, |
| 2586 builder.length()); | 2583 builder.length()); |
| 2587 } | 2584 } |
| 2588 | 2585 |
| 2589 return builder.take(); | 2586 return builder.take(); |
| 2590 } | 2587 } |
| 2591 | 2588 |
| 2592 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( | 2589 SpdySerializedFrame SpdyFramer::SerializeWindowUpdate( |
| 2593 const SpdyWindowUpdateIR& window_update) const { | 2590 const SpdyWindowUpdateIR& window_update) const { |
| 2594 SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version_); | 2591 SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version_); |
| 2595 if (protocol_version_ == SPDY3) { | 2592 if (protocol_version_ == SPDY3) { |
| 2596 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); | 2593 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); |
| 2597 builder.WriteUInt32(window_update.stream_id()); | 2594 builder.WriteUInt32(window_update.stream_id()); |
| 2598 } else { | 2595 } else { |
| 2599 builder.BeginNewFrame(*this, | 2596 builder.BeginNewFrame(*this, |
| 2600 WINDOW_UPDATE, | 2597 WINDOW_UPDATE, |
| 2601 kNoFlags, | 2598 kNoFlags, |
| 2602 window_update.stream_id()); | 2599 window_update.stream_id()); |
| 2603 } | 2600 } |
| 2604 builder.WriteUInt32(window_update.delta()); | 2601 builder.WriteUInt32(window_update.delta()); |
| 2605 DCHECK_EQ(GetWindowUpdateSize(), builder.length()); | 2602 DCHECK_EQ(GetWindowUpdateSize(), builder.length()); |
| 2606 return builder.take(); | 2603 return builder.take(); |
| 2607 } | 2604 } |
| 2608 | 2605 |
| 2609 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const { | 2606 SpdySerializedFrame SpdyFramer::SerializeBlocked( |
| 2607 const SpdyBlockedIR& blocked) const { |
| 2610 DCHECK_EQ(HTTP2, protocol_version_); | 2608 DCHECK_EQ(HTTP2, protocol_version_); |
| 2611 SpdyFrameBuilder builder(GetBlockedSize(), protocol_version_); | 2609 SpdyFrameBuilder builder(GetBlockedSize(), protocol_version_); |
| 2612 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id()); | 2610 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id()); |
| 2613 return builder.take(); | 2611 return builder.take(); |
| 2614 } | 2612 } |
| 2615 | 2613 |
| 2616 SpdyFrame* SpdyFramer::SerializePushPromise( | 2614 SpdySerializedFrame SpdyFramer::SerializePushPromise( |
| 2617 const SpdyPushPromiseIR& push_promise) { | 2615 const SpdyPushPromiseIR& push_promise) { |
| 2618 DCHECK_EQ(HTTP2, protocol_version_); | 2616 DCHECK_EQ(HTTP2, protocol_version_); |
| 2619 uint8_t flags = 0; | 2617 uint8_t flags = 0; |
| 2620 // This will get overwritten if we overflow into a CONTINUATION frame. | 2618 // This will get overwritten if we overflow into a CONTINUATION frame. |
| 2621 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 2619 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
| 2622 // The size of this frame, including variable-length name-value block. | 2620 // The size of this frame, including variable-length name-value block. |
| 2623 size_t size = GetPushPromiseMinimumSize(); | 2621 size_t size = GetPushPromiseMinimumSize(); |
| 2624 | 2622 |
| 2625 if (push_promise.padded()) { | 2623 if (push_promise.padded()) { |
| 2626 flags |= PUSH_PROMISE_FLAG_PADDED; | 2624 flags |= PUSH_PROMISE_FLAG_PADDED; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2678 payload_len, | 2676 payload_len, |
| 2679 builder.length()); | 2677 builder.length()); |
| 2680 } | 2678 } |
| 2681 | 2679 |
| 2682 return builder.take(); | 2680 return builder.take(); |
| 2683 } | 2681 } |
| 2684 | 2682 |
| 2685 // TODO(jgraettinger): This implementation is incorrect. The continuation | 2683 // TODO(jgraettinger): This implementation is incorrect. The continuation |
| 2686 // frame continues a previously-begun HPACK encoding; it doesn't begin a | 2684 // frame continues a previously-begun HPACK encoding; it doesn't begin a |
| 2687 // new one. Figure out whether it makes sense to keep SerializeContinuation(). | 2685 // new one. Figure out whether it makes sense to keep SerializeContinuation(). |
| 2688 SpdyFrame* SpdyFramer::SerializeContinuation( | 2686 SpdySerializedFrame SpdyFramer::SerializeContinuation( |
| 2689 const SpdyContinuationIR& continuation) { | 2687 const SpdyContinuationIR& continuation) { |
| 2690 CHECK_EQ(HTTP2, protocol_version_); | 2688 CHECK_EQ(HTTP2, protocol_version_); |
| 2691 uint8_t flags = 0; | 2689 uint8_t flags = 0; |
| 2692 if (continuation.end_headers()) { | 2690 if (continuation.end_headers()) { |
| 2693 flags |= HEADERS_FLAG_END_HEADERS; | 2691 flags |= HEADERS_FLAG_END_HEADERS; |
| 2694 } | 2692 } |
| 2695 | 2693 |
| 2696 // The size of this frame, including variable-length name-value block. | 2694 // The size of this frame, including variable-length name-value block. |
| 2697 size_t size = GetContinuationMinimumSize(); | 2695 size_t size = GetContinuationMinimumSize(); |
| 2698 string hpack_encoding; | 2696 string hpack_encoding; |
| 2699 if (enable_compression_) { | 2697 if (enable_compression_) { |
| 2700 GetHpackEncoder()->EncodeHeaderSet(continuation.header_block(), | 2698 GetHpackEncoder()->EncodeHeaderSet(continuation.header_block(), |
| 2701 &hpack_encoding); | 2699 &hpack_encoding); |
| 2702 } else { | 2700 } else { |
| 2703 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( | 2701 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( |
| 2704 continuation.header_block(), &hpack_encoding); | 2702 continuation.header_block(), &hpack_encoding); |
| 2705 } | 2703 } |
| 2706 size += hpack_encoding.size(); | 2704 size += hpack_encoding.size(); |
| 2707 | 2705 |
| 2708 SpdyFrameBuilder builder(size, protocol_version_); | 2706 SpdyFrameBuilder builder(size, protocol_version_); |
| 2709 builder.BeginNewFrame(*this, CONTINUATION, flags, | 2707 builder.BeginNewFrame(*this, CONTINUATION, flags, |
| 2710 continuation.stream_id()); | 2708 continuation.stream_id()); |
| 2711 DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); | 2709 DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); |
| 2712 | 2710 |
| 2713 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2711 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); |
| 2714 return builder.take(); | 2712 return builder.take(); |
| 2715 } | 2713 } |
| 2716 | 2714 |
| 2717 SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) { | 2715 SpdySerializedFrame SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) { |
| 2718 DCHECK_EQ(HTTP2, protocol_version_); | 2716 DCHECK_EQ(HTTP2, protocol_version_); |
| 2719 | 2717 |
| 2720 size_t size = GetAltSvcMinimumSize(); | 2718 size_t size = GetAltSvcMinimumSize(); |
| 2721 size += altsvc_ir.origin().length(); | 2719 size += altsvc_ir.origin().length(); |
| 2722 string value = SpdyAltSvcWireFormat::SerializeHeaderFieldValue( | 2720 string value = SpdyAltSvcWireFormat::SerializeHeaderFieldValue( |
| 2723 altsvc_ir.altsvc_vector()); | 2721 altsvc_ir.altsvc_vector()); |
| 2724 size += value.length(); | 2722 size += value.length(); |
| 2725 | 2723 |
| 2726 SpdyFrameBuilder builder(size, protocol_version_); | 2724 SpdyFrameBuilder builder(size, protocol_version_); |
| 2727 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc_ir.stream_id()); | 2725 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc_ir.stream_id()); |
| 2728 | 2726 |
| 2729 builder.WriteUInt16(altsvc_ir.origin().length()); | 2727 builder.WriteUInt16(altsvc_ir.origin().length()); |
| 2730 builder.WriteBytes(altsvc_ir.origin().data(), altsvc_ir.origin().length()); | 2728 builder.WriteBytes(altsvc_ir.origin().data(), altsvc_ir.origin().length()); |
| 2731 builder.WriteBytes(value.data(), value.length()); | 2729 builder.WriteBytes(value.data(), value.length()); |
| 2732 DCHECK_LT(GetAltSvcMinimumSize(), builder.length()); | 2730 DCHECK_LT(GetAltSvcMinimumSize(), builder.length()); |
| 2733 return builder.take(); | 2731 return builder.take(); |
| 2734 } | 2732 } |
| 2735 | 2733 |
| 2736 SpdyFrame* SpdyFramer::SerializePriority(const SpdyPriorityIR& priority) const { | 2734 SpdySerializedFrame SpdyFramer::SerializePriority( |
| 2735 const SpdyPriorityIR& priority) const { |
| 2737 DCHECK_EQ(HTTP2, protocol_version_); | 2736 DCHECK_EQ(HTTP2, protocol_version_); |
| 2738 size_t size = GetPrioritySize(); | 2737 size_t size = GetPrioritySize(); |
| 2739 | 2738 |
| 2740 SpdyFrameBuilder builder(size, protocol_version_); | 2739 SpdyFrameBuilder builder(size, protocol_version_); |
| 2741 builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id()); | 2740 builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id()); |
| 2742 | 2741 |
| 2743 builder.WriteUInt32(PackStreamDependencyValues(priority.exclusive(), | 2742 builder.WriteUInt32(PackStreamDependencyValues(priority.exclusive(), |
| 2744 priority.parent_stream_id())); | 2743 priority.parent_stream_id())); |
| 2745 builder.WriteUInt8(priority.weight()); | 2744 builder.WriteUInt8(priority.weight()); |
| 2746 DCHECK_EQ(GetPrioritySize(), builder.length()); | 2745 DCHECK_EQ(GetPrioritySize(), builder.length()); |
| 2747 return builder.take(); | 2746 return builder.take(); |
| 2748 } | 2747 } |
| 2749 | 2748 |
| 2750 namespace { | 2749 namespace { |
| 2751 | 2750 |
| 2752 class FrameSerializationVisitor : public SpdyFrameVisitor { | 2751 class FrameSerializationVisitor : public SpdyFrameVisitor { |
| 2753 public: | 2752 public: |
| 2754 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {} | 2753 explicit FrameSerializationVisitor(SpdyFramer* framer) |
| 2754 : framer_(framer), frame_() {} |
| 2755 ~FrameSerializationVisitor() override {} | 2755 ~FrameSerializationVisitor() override {} |
| 2756 | 2756 |
| 2757 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); } | 2757 SpdySerializedFrame ReleaseSerializedFrame() { return std::move(frame_); } |
| 2758 | 2758 |
| 2759 void VisitData(const SpdyDataIR& data) override { | 2759 void VisitData(const SpdyDataIR& data) override { |
| 2760 frame_.reset(framer_->SerializeData(data)); | 2760 frame_ = framer_->SerializeData(data); |
| 2761 } | 2761 } |
| 2762 void VisitSynStream(const SpdySynStreamIR& syn_stream) override { | 2762 void VisitSynStream(const SpdySynStreamIR& syn_stream) override { |
| 2763 frame_.reset(framer_->SerializeSynStream(syn_stream)); | 2763 frame_ = framer_->SerializeSynStream(syn_stream); |
| 2764 } | 2764 } |
| 2765 void VisitSynReply(const SpdySynReplyIR& syn_reply) override { | 2765 void VisitSynReply(const SpdySynReplyIR& syn_reply) override { |
| 2766 frame_.reset(framer_->SerializeSynReply(syn_reply)); | 2766 frame_ = framer_->SerializeSynReply(syn_reply); |
| 2767 } | 2767 } |
| 2768 void VisitRstStream(const SpdyRstStreamIR& rst_stream) override { | 2768 void VisitRstStream(const SpdyRstStreamIR& rst_stream) override { |
| 2769 frame_.reset(framer_->SerializeRstStream(rst_stream)); | 2769 frame_ = framer_->SerializeRstStream(rst_stream); |
| 2770 } | 2770 } |
| 2771 void VisitSettings(const SpdySettingsIR& settings) override { | 2771 void VisitSettings(const SpdySettingsIR& settings) override { |
| 2772 frame_.reset(framer_->SerializeSettings(settings)); | 2772 frame_ = framer_->SerializeSettings(settings); |
| 2773 } | 2773 } |
| 2774 void VisitPing(const SpdyPingIR& ping) override { | 2774 void VisitPing(const SpdyPingIR& ping) override { |
| 2775 frame_.reset(framer_->SerializePing(ping)); | 2775 frame_ = framer_->SerializePing(ping); |
| 2776 } | 2776 } |
| 2777 void VisitGoAway(const SpdyGoAwayIR& goaway) override { | 2777 void VisitGoAway(const SpdyGoAwayIR& goaway) override { |
| 2778 frame_.reset(framer_->SerializeGoAway(goaway)); | 2778 frame_ = framer_->SerializeGoAway(goaway); |
| 2779 } | 2779 } |
| 2780 void VisitHeaders(const SpdyHeadersIR& headers) override { | 2780 void VisitHeaders(const SpdyHeadersIR& headers) override { |
| 2781 frame_.reset(framer_->SerializeHeaders(headers)); | 2781 frame_ = framer_->SerializeHeaders(headers); |
| 2782 } | 2782 } |
| 2783 void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override { | 2783 void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override { |
| 2784 frame_.reset(framer_->SerializeWindowUpdate(window_update)); | 2784 frame_ = framer_->SerializeWindowUpdate(window_update); |
| 2785 } | 2785 } |
| 2786 void VisitBlocked(const SpdyBlockedIR& blocked) override { | 2786 void VisitBlocked(const SpdyBlockedIR& blocked) override { |
| 2787 frame_.reset(framer_->SerializeBlocked(blocked)); | 2787 frame_ = framer_->SerializeBlocked(blocked); |
| 2788 } | 2788 } |
| 2789 void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override { | 2789 void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override { |
| 2790 frame_.reset(framer_->SerializePushPromise(push_promise)); | 2790 frame_ = framer_->SerializePushPromise(push_promise); |
| 2791 } | 2791 } |
| 2792 void VisitContinuation(const SpdyContinuationIR& continuation) override { | 2792 void VisitContinuation(const SpdyContinuationIR& continuation) override { |
| 2793 frame_.reset(framer_->SerializeContinuation(continuation)); | 2793 frame_ = framer_->SerializeContinuation(continuation); |
| 2794 } | 2794 } |
| 2795 void VisitAltSvc(const SpdyAltSvcIR& altsvc) override { | 2795 void VisitAltSvc(const SpdyAltSvcIR& altsvc) override { |
| 2796 frame_.reset(framer_->SerializeAltSvc(altsvc)); | 2796 frame_ = framer_->SerializeAltSvc(altsvc); |
| 2797 } | 2797 } |
| 2798 void VisitPriority(const SpdyPriorityIR& priority) override { | 2798 void VisitPriority(const SpdyPriorityIR& priority) override { |
| 2799 frame_.reset(framer_->SerializePriority(priority)); | 2799 frame_ = framer_->SerializePriority(priority); |
| 2800 } | 2800 } |
| 2801 | 2801 |
| 2802 private: | 2802 private: |
| 2803 SpdyFramer* framer_; | 2803 SpdyFramer* framer_; |
| 2804 scoped_ptr<SpdySerializedFrame> frame_; | 2804 SpdySerializedFrame frame_; |
| 2805 }; | 2805 }; |
| 2806 | 2806 |
| 2807 } // namespace | 2807 } // namespace |
| 2808 | 2808 |
| 2809 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) { | 2809 SpdySerializedFrame SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) { |
| 2810 FrameSerializationVisitor visitor(this); | 2810 FrameSerializationVisitor visitor(this); |
| 2811 frame.Visit(&visitor); | 2811 frame.Visit(&visitor); |
| 2812 return visitor.ReleaseSerializedFrame(); | 2812 return visitor.ReleaseSerializedFrame(); |
| 2813 } | 2813 } |
| 2814 | 2814 |
| 2815 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) { | 2815 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) { |
| 2816 const size_t uncompressed_length = | 2816 const size_t uncompressed_length = |
| 2817 GetSerializedLength(protocol_version_, &headers); | 2817 GetSerializedLength(protocol_version_, &headers); |
| 2818 if (!enable_compression_) { | 2818 if (!enable_compression_) { |
| 2819 return uncompressed_length; | 2819 return uncompressed_length; |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3090 return SerializeHeaderBlockWithoutCompression(builder, | 3090 return SerializeHeaderBlockWithoutCompression(builder, |
| 3091 frame.header_block()); | 3091 frame.header_block()); |
| 3092 } | 3092 } |
| 3093 | 3093 |
| 3094 // First build an uncompressed version to be fed into the compressor. | 3094 // First build an uncompressed version to be fed into the compressor. |
| 3095 const size_t uncompressed_len = | 3095 const size_t uncompressed_len = |
| 3096 GetSerializedLength(protocol_version_, &(frame.header_block())); | 3096 GetSerializedLength(protocol_version_, &(frame.header_block())); |
| 3097 SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version_); | 3097 SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version_); |
| 3098 SerializeHeaderBlockWithoutCompression(&uncompressed_builder, | 3098 SerializeHeaderBlockWithoutCompression(&uncompressed_builder, |
| 3099 frame.header_block()); | 3099 frame.header_block()); |
| 3100 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); | 3100 SpdySerializedFrame uncompressed_payload(uncompressed_builder.take()); |
| 3101 | 3101 |
| 3102 z_stream* compressor = GetHeaderCompressor(); | 3102 z_stream* compressor = GetHeaderCompressor(); |
| 3103 if (!compressor) { | 3103 if (!compressor) { |
| 3104 LOG(DFATAL) << "Could not obtain compressor."; | 3104 LOG(DFATAL) << "Could not obtain compressor."; |
| 3105 return; | 3105 return; |
| 3106 } | 3106 } |
| 3107 // Create an output frame. | 3107 // Create an output frame. |
| 3108 // Since we'll be performing lots of flushes when compressing the data, | 3108 // Since we'll be performing lots of flushes when compressing the data, |
| 3109 // zlib's lower bounds may be insufficient. | 3109 // zlib's lower bounds may be insufficient. |
| 3110 // | 3110 // |
| 3111 // TODO(akalin): Avoid the duplicate calculation with | 3111 // TODO(akalin): Avoid the duplicate calculation with |
| 3112 // GetSerializedLength(const SpdyHeaderBlock&). | 3112 // GetSerializedLength(const SpdyHeaderBlock&). |
| 3113 const int compressed_max_size = | 3113 const int compressed_max_size = |
| 3114 2 * deflateBound(compressor, uncompressed_len); | 3114 2 * deflateBound(compressor, uncompressed_len); |
| 3115 | 3115 |
| 3116 // TODO(phajdan.jr): Clean up after we no longer need | 3116 // TODO(phajdan.jr): Clean up after we no longer need |
| 3117 // to workaround http://crbug.com/139744. | 3117 // to workaround http://crbug.com/139744. |
| 3118 #if defined(USE_SYSTEM_ZLIB) | 3118 #if defined(USE_SYSTEM_ZLIB) |
| 3119 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data()); | 3119 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload.data()); |
| 3120 compressor->avail_in = uncompressed_len; | 3120 compressor->avail_in = uncompressed_len; |
| 3121 #endif // defined(USE_SYSTEM_ZLIB) | 3121 #endif // defined(USE_SYSTEM_ZLIB) |
| 3122 compressor->next_out = reinterpret_cast<Bytef*>( | 3122 compressor->next_out = reinterpret_cast<Bytef*>( |
| 3123 builder->GetWritableBuffer(compressed_max_size)); | 3123 builder->GetWritableBuffer(compressed_max_size)); |
| 3124 compressor->avail_out = compressed_max_size; | 3124 compressor->avail_out = compressed_max_size; |
| 3125 | 3125 |
| 3126 // TODO(phajdan.jr): Clean up after we no longer need | 3126 // TODO(phajdan.jr): Clean up after we no longer need |
| 3127 // to workaround http://crbug.com/139744. | 3127 // to workaround http://crbug.com/139744. |
| 3128 #if defined(USE_SYSTEM_ZLIB) | 3128 #if defined(USE_SYSTEM_ZLIB) |
| 3129 int rv = deflate(compressor, Z_SYNC_FLUSH); | 3129 int rv = deflate(compressor, Z_SYNC_FLUSH); |
| 3130 if (rv != Z_OK) { // How can we know that it compressed everything? | 3130 if (rv != Z_OK) { // How can we know that it compressed everything? |
| 3131 // This shouldn't happen, right? | 3131 // This shouldn't happen, right? |
| 3132 LOG(WARNING) << "deflate failure: " << rv; | 3132 LOG(WARNING) << "deflate failure: " << rv; |
| 3133 // TODO(akalin): Upstream this return. | 3133 // TODO(akalin): Upstream this return. |
| 3134 return; | 3134 return; |
| 3135 } | 3135 } |
| 3136 #else | 3136 #else |
| 3137 WriteHeaderBlockToZ(&frame.header_block(), compressor); | 3137 WriteHeaderBlockToZ(&frame.header_block(), compressor); |
| 3138 #endif // defined(USE_SYSTEM_ZLIB) | 3138 #endif // defined(USE_SYSTEM_ZLIB) |
| 3139 | 3139 |
| 3140 int compressed_size = compressed_max_size - compressor->avail_out; | 3140 int compressed_size = compressed_max_size - compressor->avail_out; |
| 3141 builder->Seek(compressed_size); | 3141 builder->Seek(compressed_size); |
| 3142 builder->RewriteLength(*this); | 3142 builder->RewriteLength(*this); |
| 3143 } | 3143 } |
| 3144 | 3144 |
| 3145 } // namespace net | 3145 } // namespace net |
| OLD | NEW |