|
@@ -92,10 +92,27 @@ tor_zlib_get_header_version_str(void)
|
|
|
|
|
|
|
|
|
static INLINE int
|
|
|
-method_bits(compress_method_t method)
|
|
|
+method_bits(compress_method_t method, zlib_compression_level_t level)
|
|
|
{
|
|
|
|
|
|
- return method == GZIP_METHOD ? 15+16 : 15;
|
|
|
+ const int flag = method == GZIP_METHOD ? 16 : 0;
|
|
|
+ switch (level) {
|
|
|
+ default:
|
|
|
+ case HIGH_COMPRESSION: return flag + 15;
|
|
|
+ case MEDIUM_COMPRESSION: return flag + 13;
|
|
|
+ case LOW_COMPRESSION: return flag + 11;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static INLINE int
|
|
|
+get_memlevel(zlib_compression_level_t level)
|
|
|
+{
|
|
|
+ switch (level) {
|
|
|
+ default:
|
|
|
+ case HIGH_COMPRESSION: return 8;
|
|
|
+ case MEDIUM_COMPRESSION: return 7;
|
|
|
+ case LOW_COMPRESSION: return 6;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
@@ -162,8 +179,9 @@ tor_gzip_compress(char **out, size_t *out_len,
|
|
|
stream->avail_in = (unsigned int)in_len;
|
|
|
|
|
|
if (deflateInit2(stream, Z_BEST_COMPRESSION, Z_DEFLATED,
|
|
|
- method_bits(method),
|
|
|
- 8, Z_DEFAULT_STRATEGY) != Z_OK) {
|
|
|
+ method_bits(method, HIGH_COMPRESSION),
|
|
|
+ get_memlevel(HIGH_COMPRESSION),
|
|
|
+ Z_DEFAULT_STRATEGY) != Z_OK) {
|
|
|
log_warn(LD_GENERAL, "Error from deflateInit2: %s",
|
|
|
stream->msg?stream->msg:"<no message>");
|
|
|
goto err;
|
|
@@ -289,7 +307,7 @@ tor_gzip_uncompress(char **out, size_t *out_len,
|
|
|
stream->avail_in = (unsigned int)in_len;
|
|
|
|
|
|
if (inflateInit2(stream,
|
|
|
- method_bits(method)) != Z_OK) {
|
|
|
+ method_bits(method, HIGH_COMPRESSION)) != Z_OK) {
|
|
|
log_warn(LD_GENERAL, "Error from inflateInit2: %s",
|
|
|
stream->msg?stream->msg:"<no message>");
|
|
|
goto err;
|
|
@@ -315,7 +333,8 @@ tor_gzip_uncompress(char **out, size_t *out_len,
|
|
|
log_warn(LD_BUG, "Error freeing gzip structures");
|
|
|
goto err;
|
|
|
}
|
|
|
- if (inflateInit2(stream, method_bits(method)) != Z_OK) {
|
|
|
+ if (inflateInit2(stream,
|
|
|
+ method_bits(method,HIGH_COMPRESSION)) != Z_OK) {
|
|
|
log_warn(LD_GENERAL, "Error from second inflateInit2: %s",
|
|
|
stream->msg?stream->msg:"<no message>");
|
|
|
goto err;
|
|
@@ -426,10 +445,11 @@ struct tor_zlib_state_t {
|
|
|
* <b>compress</b>, it's for compression; otherwise it's for
|
|
|
* decompression. */
|
|
|
tor_zlib_state_t *
|
|
|
-tor_zlib_new(int compress, compress_method_t method)
|
|
|
+tor_zlib_new(int compress, compress_method_t method,
|
|
|
+ zlib_compression_level_t compression_level)
|
|
|
{
|
|
|
tor_zlib_state_t *out;
|
|
|
- int bits;
|
|
|
+ int bits, memlevel;
|
|
|
|
|
|
if (method == GZIP_METHOD && !is_gzip_supported()) {
|
|
|
|
|
@@ -437,21 +457,29 @@ tor_zlib_new(int compress, compress_method_t method)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+ if (! compress) {
|
|
|
+
|
|
|
+ * max number of window bits */
|
|
|
+ compression_level = HIGH_COMPRESSION;
|
|
|
+ }
|
|
|
+
|
|
|
out = tor_malloc_zero(sizeof(tor_zlib_state_t));
|
|
|
out->stream.zalloc = Z_NULL;
|
|
|
out->stream.zfree = Z_NULL;
|
|
|
out->stream.opaque = NULL;
|
|
|
out->compress = compress;
|
|
|
- bits = method_bits(method);
|
|
|
+ bits = method_bits(method, compression_level);
|
|
|
+ memlevel = get_memlevel(compression_level);
|
|
|
if (compress) {
|
|
|
if (deflateInit2(&out->stream, Z_BEST_COMPRESSION, Z_DEFLATED,
|
|
|
- bits, 8, Z_DEFAULT_STRATEGY) != Z_OK)
|
|
|
+ bits, memlevel,
|
|
|
+ Z_DEFAULT_STRATEGY) != Z_OK)
|
|
|
goto err;
|
|
|
} else {
|
|
|
if (inflateInit2(&out->stream, bits) != Z_OK)
|
|
|
goto err;
|
|
|
}
|
|
|
- out->allocation = tor_zlib_state_size_precalc(!compress, bits, 8);
|
|
|
+ out->allocation = tor_zlib_state_size_precalc(!compress, bits, memlevel);
|
|
|
|
|
|
total_zlib_allocation += out->allocation;
|
|
|
|