|  | @@ -92,10 +92,27 @@ tor_zlib_get_header_version_str(void)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Return the 'bits' value to tell zlib to use <b>method</b>.*/
 | 
	
		
			
				|  |  |  static INLINE int
 | 
	
		
			
				|  |  | -method_bits(compress_method_t method)
 | 
	
		
			
				|  |  | +method_bits(compress_method_t method, zlib_compression_level_t level)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    /* Bits+16 means "use gzip" in zlib >= 1.2 */
 | 
	
		
			
				|  |  | -  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()) {
 | 
	
		
			
				|  |  |      /* Old zlib version don't support gzip in inflateInit2 */
 | 
	
	
		
			
				|  | @@ -437,21 +457,29 @@ tor_zlib_new(int compress, compress_method_t method)
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
		
			
				|  |  |   }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | + if (! compress) {
 | 
	
		
			
				|  |  | +   /* use this setting for decompression, since we might have the
 | 
	
		
			
				|  |  | +    * 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;
 | 
	
		
			
				|  |  |  
 |