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 |
| 11 #include <cstring> |
| 12 |
11 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
12 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
13 #include "base/metrics/stats_counters.h" | 15 #include "base/metrics/stats_counters.h" |
14 #include "base/third_party/valgrind/memcheck.h" | 16 #include "base/third_party/valgrind/memcheck.h" |
15 #include "net/spdy/spdy_frame_builder.h" | 17 #include "net/spdy/spdy_frame_builder.h" |
16 #include "net/spdy/spdy_frame_reader.h" | 18 #include "net/spdy/spdy_frame_reader.h" |
17 #include "net/spdy/spdy_bitmasks.h" | 19 #include "net/spdy/spdy_bitmasks.h" |
18 #include "third_party/zlib/zlib.h" | 20 #include "third_party/zlib/zlib.h" |
19 | 21 |
20 using std::vector; | 22 using std::vector; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 display_protocol_("SPDY"), | 124 display_protocol_("SPDY"), |
123 spdy_version_(version), | 125 spdy_version_(version), |
124 syn_frame_processed_(false), | 126 syn_frame_processed_(false), |
125 probable_http_response_(false) { | 127 probable_http_response_(false) { |
126 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); | 128 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); |
127 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION); | 129 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION); |
128 Reset(); | 130 Reset(); |
129 } | 131 } |
130 | 132 |
131 SpdyFramer::~SpdyFramer() { | 133 SpdyFramer::~SpdyFramer() { |
132 if (header_compressor_.get()) { | 134 if (spdy_header_compressor_.get()) { |
133 deflateEnd(header_compressor_.get()); | 135 deflateEnd(spdy_header_compressor_.get()); |
134 } | 136 } |
135 if (header_decompressor_.get()) { | 137 if (spdy_header_decompressor_.get()) { |
136 inflateEnd(header_decompressor_.get()); | 138 inflateEnd(spdy_header_decompressor_.get()); |
137 } | 139 } |
138 } | 140 } |
139 | 141 |
140 void SpdyFramer::Reset() { | 142 void SpdyFramer::Reset() { |
141 state_ = SPDY_RESET; | 143 state_ = SPDY_RESET; |
142 previous_state_ = SPDY_RESET; | 144 previous_state_ = SPDY_RESET; |
143 error_code_ = SPDY_NO_ERROR; | 145 error_code_ = SPDY_NO_ERROR; |
144 remaining_data_length_ = 0; | 146 remaining_data_length_ = 0; |
145 remaining_control_header_ = 0; | 147 remaining_control_header_ = 0; |
146 current_frame_buffer_length_ = 0; | 148 current_frame_buffer_length_ = 0; |
(...skipping 1132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); | 1281 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); |
1280 | 1282 |
1281 bool processed_successfully = true; | 1283 bool processed_successfully = true; |
1282 if (current_frame_type_ != SYN_STREAM && | 1284 if (current_frame_type_ != SYN_STREAM && |
1283 current_frame_type_ != SYN_REPLY && | 1285 current_frame_type_ != SYN_REPLY && |
1284 current_frame_type_ != HEADERS && | 1286 current_frame_type_ != HEADERS && |
1285 current_frame_type_ != PUSH_PROMISE) { | 1287 current_frame_type_ != PUSH_PROMISE) { |
1286 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; | 1288 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; |
1287 } | 1289 } |
1288 size_t process_bytes = std::min(data_len, remaining_data_length_); | 1290 size_t process_bytes = std::min(data_len, remaining_data_length_); |
1289 if (process_bytes > 0) { | 1291 if ((spdy_version_ < SPDY4 && process_bytes > 0) || |
| 1292 ((spdy_version_ >= SPDY4))) { |
1290 if (enable_compression_) { | 1293 if (enable_compression_) { |
1291 processed_successfully = IncrementallyDecompressControlFrameHeaderData( | 1294 processed_successfully = IncrementallyDecompressControlFrameHeaderData( |
1292 current_frame_stream_id_, data, process_bytes); | 1295 current_frame_stream_id_, data, process_bytes); |
1293 } else { | 1296 } else { |
1294 processed_successfully = IncrementallyDeliverControlFrameHeaderData( | 1297 processed_successfully = IncrementallyDeliverControlFrameHeaderData( |
1295 current_frame_stream_id_, data, process_bytes); | 1298 current_frame_stream_id_, data, process_bytes); |
1296 } | 1299 } |
1297 | 1300 |
1298 remaining_data_length_ -= process_bytes; | 1301 remaining_data_length_ -= process_bytes; |
1299 } | 1302 } |
1300 | 1303 |
1301 // Handle the case that there is no futher data in this frame. | 1304 // Handle the case that there is no futher data in this frame. |
1302 if (remaining_data_length_ == 0 && processed_successfully) { | 1305 if ((spdy_version_ < SPDY4 && |
| 1306 (remaining_data_length_ == 0 && processed_successfully)) || |
| 1307 (spdy_version_ >= SPDY4 && |
| 1308 ((current_frame_flags_ & HEADERS_FLAG_END_HEADERS) != 0) && |
| 1309 processed_successfully)) { |
1303 // The complete header block has been delivered. We send a zero-length | 1310 // The complete header block has been delivered. We send a zero-length |
1304 // OnControlFrameHeaderData() to indicate this. | 1311 // OnControlFrameHeaderData() to indicate this. |
1305 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0); | 1312 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0); |
1306 | 1313 |
1307 // If this is a FIN, tell the caller. | 1314 // If this is a FIN, tell the caller. |
1308 if (current_frame_flags_ & CONTROL_FLAG_FIN) { | 1315 if (current_frame_flags_ & CONTROL_FLAG_FIN) { |
1309 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); | 1316 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); |
1310 } | 1317 } |
1311 | 1318 |
1312 CHANGE_STATE(SPDY_AUTO_RESET); | 1319 CHANGE_STATE(SPDY_AUTO_RESET); |
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2184 frame.Visit(&visitor); | 2191 frame.Visit(&visitor); |
2185 return visitor.ReleaseSerializedFrame(); | 2192 return visitor.ReleaseSerializedFrame(); |
2186 } | 2193 } |
2187 | 2194 |
2188 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) { | 2195 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) { |
2189 const size_t uncompressed_length = | 2196 const size_t uncompressed_length = |
2190 GetSerializedLength(protocol_version(), &headers); | 2197 GetSerializedLength(protocol_version(), &headers); |
2191 if (!enable_compression_) { | 2198 if (!enable_compression_) { |
2192 return uncompressed_length; | 2199 return uncompressed_length; |
2193 } | 2200 } |
2194 z_stream* compressor = GetHeaderCompressor(); | 2201 if (spdy_version_ >= SPDY4) { |
| 2202 // TODO(akalin): Handle >= SPDY4 case properly. |
| 2203 return uncompressed_length; |
| 2204 } |
| 2205 z_stream* compressor = GetSpdyHeaderCompressor(); |
2195 // Since we'll be performing lots of flushes when compressing the data, | 2206 // Since we'll be performing lots of flushes when compressing the data, |
2196 // zlib's lower bounds may be insufficient. | 2207 // zlib's lower bounds may be insufficient. |
2197 return 2 * deflateBound(compressor, uncompressed_length); | 2208 return 2 * deflateBound(compressor, uncompressed_length); |
2198 } | 2209 } |
2199 | 2210 |
2200 // The following compression setting are based on Brian Olson's analysis. See | 2211 // The following compression setting are based on Brian Olson's analysis. See |
2201 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 | 2212 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 |
2202 // for more details. | 2213 // for more details. |
2203 #if defined(USE_SYSTEM_ZLIB) | 2214 #if defined(USE_SYSTEM_ZLIB) |
2204 // System zlib is not expected to have workaround for http://crbug.com/139744, | 2215 // System zlib is not expected to have workaround for http://crbug.com/139744, |
2205 // so disable compression in that case. | 2216 // so disable compression in that case. |
2206 // TODO(phajdan.jr): Remove the special case when it's no longer necessary. | 2217 // TODO(phajdan.jr): Remove the special case when it's no longer necessary. |
2207 static const int kCompressorLevel = 0; | 2218 static const int kCompressorLevel = 0; |
2208 #else // !defined(USE_SYSTEM_ZLIB) | 2219 #else // !defined(USE_SYSTEM_ZLIB) |
2209 static const int kCompressorLevel = 9; | 2220 static const int kCompressorLevel = 9; |
2210 #endif // !defined(USE_SYSTEM_ZLIB) | 2221 #endif // !defined(USE_SYSTEM_ZLIB) |
2211 static const int kCompressorWindowSizeInBits = 11; | 2222 static const int kCompressorWindowSizeInBits = 11; |
2212 static const int kCompressorMemLevel = 1; | 2223 static const int kCompressorMemLevel = 1; |
2213 | 2224 |
2214 z_stream* SpdyFramer::GetHeaderCompressor() { | 2225 z_stream* SpdyFramer::GetSpdyHeaderCompressor() { |
2215 if (header_compressor_.get()) | 2226 if (spdy_header_compressor_.get()) |
2216 return header_compressor_.get(); // Already initialized. | 2227 return spdy_header_compressor_.get(); // Already initialized. |
2217 | 2228 |
2218 header_compressor_.reset(new z_stream); | 2229 spdy_header_compressor_.reset(new z_stream); |
2219 memset(header_compressor_.get(), 0, sizeof(z_stream)); | 2230 memset(spdy_header_compressor_.get(), 0, sizeof(z_stream)); |
2220 | 2231 |
2221 int success = deflateInit2(header_compressor_.get(), | 2232 int success = deflateInit2(spdy_header_compressor_.get(), |
2222 kCompressorLevel, | 2233 kCompressorLevel, |
2223 Z_DEFLATED, | 2234 Z_DEFLATED, |
2224 kCompressorWindowSizeInBits, | 2235 kCompressorWindowSizeInBits, |
2225 kCompressorMemLevel, | 2236 kCompressorMemLevel, |
2226 Z_DEFAULT_STRATEGY); | 2237 Z_DEFAULT_STRATEGY); |
2227 if (success == Z_OK) { | 2238 if (success == Z_OK) { |
2228 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary | 2239 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary |
2229 : kV3Dictionary; | 2240 : kV3Dictionary; |
2230 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize | 2241 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize |
2231 : kV3DictionarySize; | 2242 : kV3DictionarySize; |
2232 success = deflateSetDictionary(header_compressor_.get(), | 2243 success = deflateSetDictionary(spdy_header_compressor_.get(), |
2233 reinterpret_cast<const Bytef*>(dictionary), | 2244 reinterpret_cast<const Bytef*>(dictionary), |
2234 dictionary_size); | 2245 dictionary_size); |
2235 } | 2246 } |
2236 if (success != Z_OK) { | 2247 if (success != Z_OK) { |
2237 LOG(WARNING) << "deflateSetDictionary failure: " << success; | 2248 LOG(WARNING) << "deflateSetDictionary failure: " << success; |
2238 header_compressor_.reset(NULL); | 2249 spdy_header_compressor_.reset(NULL); |
2239 return NULL; | 2250 return NULL; |
2240 } | 2251 } |
2241 return header_compressor_.get(); | 2252 return spdy_header_compressor_.get(); |
2242 } | 2253 } |
2243 | 2254 |
2244 z_stream* SpdyFramer::GetHeaderDecompressor() { | 2255 z_stream* SpdyFramer::GetSpdyHeaderDecompressor() { |
2245 if (header_decompressor_.get()) | 2256 if (spdy_header_decompressor_.get()) |
2246 return header_decompressor_.get(); // Already initialized. | 2257 return spdy_header_decompressor_.get(); // Already initialized. |
2247 | 2258 |
2248 header_decompressor_.reset(new z_stream); | 2259 spdy_header_decompressor_.reset(new z_stream); |
2249 memset(header_decompressor_.get(), 0, sizeof(z_stream)); | 2260 memset(spdy_header_decompressor_.get(), 0, sizeof(z_stream)); |
2250 | 2261 |
2251 int success = inflateInit(header_decompressor_.get()); | 2262 int success = inflateInit(spdy_header_decompressor_.get()); |
2252 if (success != Z_OK) { | 2263 if (success != Z_OK) { |
2253 LOG(WARNING) << "inflateInit failure: " << success; | 2264 LOG(WARNING) << "inflateInit failure: " << success; |
2254 header_decompressor_.reset(NULL); | 2265 spdy_header_decompressor_.reset(NULL); |
2255 return NULL; | 2266 return NULL; |
2256 } | 2267 } |
2257 return header_decompressor_.get(); | 2268 return spdy_header_decompressor_.get(); |
| 2269 } |
| 2270 |
| 2271 Http2Compressor* SpdyFramer::GetHttp2HeaderCompressor() { |
| 2272 if (!http2_header_compressor_) |
| 2273 http2_header_compressor_.reset(new Http2Compressor()); |
| 2274 return http2_header_compressor_.get(); |
| 2275 } |
| 2276 |
| 2277 Http2Decompressor* SpdyFramer::GetHttp2HeaderDecompressor() { |
| 2278 if (!http2_header_decompressor_) |
| 2279 http2_header_decompressor_.reset(new Http2Decompressor()); |
| 2280 return http2_header_decompressor_.get(); |
2258 } | 2281 } |
2259 | 2282 |
2260 // Incrementally decompress the control frame's header block, feeding the | 2283 // Incrementally decompress the control frame's header block, feeding the |
2261 // result to the visitor in chunks. Continue this until the visitor | 2284 // result to the visitor in chunks. Continue this until the visitor |
2262 // indicates that it cannot process any more data, or (more commonly) we | 2285 // indicates that it cannot process any more data, or (more commonly) we |
2263 // run out of data to deliver. | 2286 // run out of data to deliver. |
2264 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( | 2287 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( |
2265 SpdyStreamId stream_id, | 2288 SpdyStreamId stream_id, |
2266 const char* data, | 2289 const char* data, |
2267 size_t len) { | 2290 size_t len) { |
| 2291 if (spdy_version_ >= SPDY4) { |
| 2292 SpdyNameValueBlock name_value_block; |
| 2293 if (!GetHttp2HeaderDecompressor()->DecodeNameValueBlock( |
| 2294 data, len, &name_value_block)) { |
| 2295 set_error(SPDY_DECOMPRESS_FAILURE); |
| 2296 return false; |
| 2297 } |
| 2298 const size_t uncompressed_length = |
| 2299 GetSerializedLength(spdy_version_, &name_value_block); |
| 2300 SpdyFrameBuilder builder(uncompressed_length); |
| 2301 SerializeNameValueBlockWithoutCompression(&builder, name_value_block); |
| 2302 scoped_ptr<SpdyFrame> frame(builder.take()); |
| 2303 if (!visitor_->OnControlFrameHeaderData( |
| 2304 stream_id, frame->data(), frame->size())) |
| 2305 return false; |
| 2306 return true; |
| 2307 } |
| 2308 |
2268 // Get a decompressor or set error. | 2309 // Get a decompressor or set error. |
2269 z_stream* decomp = GetHeaderDecompressor(); | 2310 z_stream* decomp = GetSpdyHeaderDecompressor(); |
2270 if (decomp == NULL) { | 2311 if (decomp == NULL) { |
2271 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; | 2312 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; |
2272 set_error(SPDY_DECOMPRESS_FAILURE); | 2313 set_error(SPDY_DECOMPRESS_FAILURE); |
2273 return false; | 2314 return false; |
2274 } | 2315 } |
2275 | 2316 |
2276 bool processed_successfully = true; | 2317 bool processed_successfully = true; |
2277 char buffer[kHeaderDataChunkMaxSize]; | 2318 char buffer[kHeaderDataChunkMaxSize]; |
2278 | 2319 |
2279 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); | 2320 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2373 } | 2414 } |
2374 | 2415 |
2375 void SpdyFramer::SerializeNameValueBlock( | 2416 void SpdyFramer::SerializeNameValueBlock( |
2376 SpdyFrameBuilder* builder, | 2417 SpdyFrameBuilder* builder, |
2377 const SpdyFrameWithNameValueBlockIR& frame) { | 2418 const SpdyFrameWithNameValueBlockIR& frame) { |
2378 if (!enable_compression_) { | 2419 if (!enable_compression_) { |
2379 return SerializeNameValueBlockWithoutCompression(builder, | 2420 return SerializeNameValueBlockWithoutCompression(builder, |
2380 frame.name_value_block()); | 2421 frame.name_value_block()); |
2381 } | 2422 } |
2382 | 2423 |
2383 // First build an uncompressed version to be fed into the compressor. | |
2384 const size_t uncompressed_len = GetSerializedLength( | |
2385 protocol_version(), &(frame.name_value_block())); | |
2386 SpdyFrameBuilder uncompressed_builder(uncompressed_len); | |
2387 SerializeNameValueBlockWithoutCompression(&uncompressed_builder, | |
2388 frame.name_value_block()); | |
2389 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); | |
2390 | |
2391 z_stream* compressor = GetHeaderCompressor(); | |
2392 if (!compressor) { | |
2393 LOG(DFATAL) << "Could not obtain compressor."; | |
2394 return; | |
2395 } | |
2396 | |
2397 base::StatsCounter compressed_frames("spdy.CompressedFrames"); | 2424 base::StatsCounter compressed_frames("spdy.CompressedFrames"); |
2398 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize"); | 2425 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize"); |
2399 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); | 2426 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); |
2400 | 2427 |
2401 // Create an output frame. | 2428 // First build an uncompressed version to be fed into the compressor. |
2402 // Since we'll be performing lots of flushes when compressing the data, | 2429 const size_t uncompressed_len = GetSerializedLength( |
2403 // zlib's lower bounds may be insufficient. | 2430 protocol_version(), &(frame.name_value_block())); |
2404 // | 2431 int compressed_size = 0; |
2405 // TODO(akalin): Avoid the duplicate calculation with | |
2406 // GetSerializedLength(const SpdyHeaderBlock&). | |
2407 const int compressed_max_size = | |
2408 2 * deflateBound(compressor, uncompressed_len); | |
2409 | 2432 |
2410 // TODO(phajdan.jr): Clean up after we no longer need | 2433 if (spdy_version_ >= SPDY4) { |
2411 // to workaround http://crbug.com/139744. | 2434 Http2Compressor* compressor = GetHttp2HeaderCompressor(); |
| 2435 const std::string& compressed = |
| 2436 compressor->EncodeNameValueBlock(frame.name_value_block()); |
| 2437 char* out = builder->GetWritableBuffer(compressed.size()); |
| 2438 std::memcpy(out, compressed.data(), compressed.size()); |
| 2439 compressed_size = compressed.size(); |
| 2440 } else { |
| 2441 SpdyFrameBuilder uncompressed_builder(uncompressed_len); |
| 2442 SerializeNameValueBlockWithoutCompression(&uncompressed_builder, |
| 2443 frame.name_value_block()); |
| 2444 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); |
| 2445 |
| 2446 z_stream* compressor = GetSpdyHeaderCompressor(); |
| 2447 if (!compressor) { |
| 2448 LOG(DFATAL) << "Could not obtain compressor."; |
| 2449 return; |
| 2450 } |
| 2451 |
| 2452 // Create an output frame. |
| 2453 // Since we'll be performing lots of flushes when compressing the data, |
| 2454 // zlib's lower bounds may be insufficient. |
| 2455 // |
| 2456 // TODO(akalin): Avoid the duplicate calculation with |
| 2457 // GetSerializedLength(const SpdyHeaderBlock&). |
| 2458 const int compressed_max_size = |
| 2459 2 * deflateBound(compressor, uncompressed_len); |
| 2460 |
| 2461 // TODO(phajdan.jr): Clean up after we no longer need |
| 2462 // to workaround http://crbug.com/139744. |
2412 #if defined(USE_SYSTEM_ZLIB) | 2463 #if defined(USE_SYSTEM_ZLIB) |
2413 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data()); | 2464 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data())
; |
2414 compressor->avail_in = uncompressed_len; | 2465 compressor->avail_in = uncompressed_len; |
2415 #endif // defined(USE_SYSTEM_ZLIB) | 2466 #endif // defined(USE_SYSTEM_ZLIB) |
2416 compressor->next_out = reinterpret_cast<Bytef*>( | 2467 compressor->next_out = reinterpret_cast<Bytef*>( |
2417 builder->GetWritableBuffer(compressed_max_size)); | 2468 builder->GetWritableBuffer(compressed_max_size)); |
2418 compressor->avail_out = compressed_max_size; | 2469 compressor->avail_out = compressed_max_size; |
2419 | 2470 |
2420 // TODO(phajdan.jr): Clean up after we no longer need | 2471 // TODO(phajdan.jr): Clean up after we no longer need |
2421 // to workaround http://crbug.com/139744. | 2472 // to workaround http://crbug.com/139744. |
2422 #if defined(USE_SYSTEM_ZLIB) | 2473 #if defined(USE_SYSTEM_ZLIB) |
2423 int rv = deflate(compressor, Z_SYNC_FLUSH); | 2474 int rv = deflate(compressor, Z_SYNC_FLUSH); |
2424 if (rv != Z_OK) { // How can we know that it compressed everything? | 2475 if (rv != Z_OK) { // How can we know that it compressed everything? |
2425 // This shouldn't happen, right? | 2476 // This shouldn't happen, right? |
2426 LOG(WARNING) << "deflate failure: " << rv; | 2477 LOG(WARNING) << "deflate failure: " << rv; |
2427 // TODO(akalin): Upstream this return. | 2478 // TODO(akalin): Upstream this return. |
2428 return; | 2479 return; |
2429 } | 2480 } |
2430 #else | 2481 #else |
2431 WriteHeaderBlockToZ(&frame.name_value_block(), compressor); | 2482 WriteHeaderBlockToZ(&frame.name_value_block(), compressor); |
2432 #endif // defined(USE_SYSTEM_ZLIB) | 2483 #endif // defined(USE_SYSTEM_ZLIB) |
2433 | 2484 |
2434 int compressed_size = compressed_max_size - compressor->avail_out; | 2485 compressed_size = compressed_max_size - compressor->avail_out; |
| 2486 } |
| 2487 |
2435 builder->Seek(compressed_size); | 2488 builder->Seek(compressed_size); |
2436 builder->RewriteLength(*this); | 2489 builder->RewriteLength(*this); |
2437 | 2490 |
2438 pre_compress_bytes.Add(uncompressed_len); | 2491 pre_compress_bytes.Add(uncompressed_len); |
2439 post_compress_bytes.Add(compressed_size); | 2492 post_compress_bytes.Add(compressed_size); |
2440 | 2493 |
2441 compressed_frames.Increment(); | 2494 compressed_frames.Increment(); |
2442 } | 2495 } |
2443 | 2496 |
2444 } // namespace net | 2497 } // namespace net |
OLD | NEW |