OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "blimp/net/compressed_packet_writer.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/numerics/safe_conversions.h" | |
11 #include "base/sys_byteorder.h" | |
12 #include "blimp/net/common.h" | |
13 #include "net/base/io_buffer.h" | |
14 #include "third_party/zlib/zlib.h" | |
15 | |
16 namespace blimp { | |
17 namespace { | |
18 | |
19 // Allocate the maxmimum amount of memory to deflate (512KB) for higher | |
20 // compression. (See zconf.h for details on memLevel semantics.) | |
21 const int kZlibMemoryLevel = 9; | |
22 | |
23 } // namespace | |
24 | |
25 CompressedPacketWriter::CompressedPacketWriter(scoped_ptr<PacketWriter> sink) | |
26 : sink_(std::move(sink)), compressed_buf_(new net::GrowableIOBuffer) { | |
27 DCHECK(sink_); | |
28 | |
29 // MAX_WBITS means we are using the maximal window size for decompression; | |
30 // negating it means that we are ignoring headers and CRC checks. | |
31 int init_error = | |
32 deflateInit2(&zlib_stream_, Z_BEST_COMPRESSION, Z_DEFLATED, | |
33 -MAX_WBITS, // Negative value = no headers or CRC. | |
34 kZlibMemoryLevel, Z_DEFAULT_STRATEGY); | |
35 CHECK_EQ(init_error, Z_OK); | |
Wez
2016/03/29 23:59:15
nit: CHECK_EQ(expected, result)
| |
36 } | |
37 | |
38 CompressedPacketWriter::~CompressedPacketWriter() { | |
39 deflateEnd(&zlib_stream_); | |
40 } | |
41 | |
42 void CompressedPacketWriter::WritePacket( | |
43 const scoped_refptr<net::DrainableIOBuffer>& write_buffer, | |
44 const net::CompletionCallback& callback) { | |
45 DCHECK(write_buffer); | |
46 DCHECK(!callback.is_null()); | |
47 size_t uncompressed_size = | |
48 base::checked_cast<size_t>(write_buffer->BytesRemaining()); | |
49 | |
50 // Zero-length input => zero-length output. | |
51 if (uncompressed_size == 0) { | |
52 sink_->WritePacket(write_buffer, callback); | |
53 return; | |
54 } | |
55 | |
56 // Don't compress anything that's bigger than the maximum allowable payload | |
57 // size. | |
58 if (uncompressed_size > kMaxPacketPayloadSizeBytes) { | |
59 callback.Run(net::ERR_FILE_TOO_BIG); | |
60 return; | |
61 } | |
62 | |
63 int compress_result = Compress(write_buffer, compressed_buf_); | |
64 if (compress_result < 0) { | |
65 callback.Run(compress_result); | |
66 return; | |
67 } | |
68 | |
69 #if !defined(NDEBUG) | |
70 uncompressed_size_total_ += uncompressed_size; | |
71 compressed_size_total_ += compress_result; | |
72 #endif // !defined(NDEBUG) | |
73 | |
74 scoped_refptr<net::DrainableIOBuffer> compressed_outbuf( | |
75 new net::DrainableIOBuffer(compressed_buf_.get(), compress_result)); | |
76 sink_->WritePacket(compressed_outbuf, callback); | |
77 DVLOG(4) << "deflate packet: " << uncompressed_size << " in, " | |
78 << compress_result << " out."; | |
79 DVLOG(3) << "deflate total: " << uncompressed_size_total_ << " in, " | |
80 << compressed_size_total_ << " out."; | |
81 } | |
82 | |
83 int CompressedPacketWriter::Compress( | |
84 const scoped_refptr<net::DrainableIOBuffer>& src_buf, | |
85 const scoped_refptr<net::GrowableIOBuffer>& dest_buf) { | |
86 DCHECK_EQ(0, dest_buf->offset()); | |
87 | |
88 const int zlib_output_ubound = | |
89 deflateBound(&zlib_stream_, src_buf->BytesRemaining()); | |
90 if (dest_buf->capacity() < zlib_output_ubound) { | |
91 dest_buf->SetCapacity(zlib_output_ubound); | |
92 } | |
93 | |
94 zlib_stream_.next_in = reinterpret_cast<uint8_t*>(src_buf->data()); | |
95 zlib_stream_.avail_in = static_cast<unsigned>(src_buf->BytesRemaining()); | |
96 zlib_stream_.next_out = reinterpret_cast<uint8_t*>(dest_buf->data()); | |
97 zlib_stream_.avail_out = static_cast<unsigned>(zlib_output_ubound); | |
98 int deflate_error = deflate(&zlib_stream_, Z_SYNC_FLUSH); | |
99 | |
100 if (deflate_error != Z_OK) { | |
101 DLOG(FATAL) << "Unexpected deflate() return value: " << deflate_error; | |
102 return net::ERR_UNEXPECTED; | |
103 } | |
104 if (zlib_stream_.avail_in > 0) { | |
105 DLOG(ERROR) << "deflate() did not consume all data, remainder: " | |
106 << zlib_stream_.avail_in << " bytes."; | |
107 return net::ERR_UNEXPECTED; | |
108 } | |
109 | |
110 return zlib_output_ubound - zlib_stream_.avail_out; | |
111 } | |
112 | |
113 } // namespace blimp | |
OLD | NEW |