|
@@ -46,6 +46,12 @@
|
|
|
|
|
|
#include <zlib.h>
|
|
|
|
|
|
+static size_t tor_zlib_state_size_precalc(int inflate,
|
|
|
+ int windowbits, int memlevel);
|
|
|
+
|
|
|
+
|
|
|
+static size_t total_zlib_allocation = 0;
|
|
|
+
|
|
|
|
|
|
* set to -1 if we haven't checked yet. */
|
|
|
static int gzip_is_supported = -1;
|
|
@@ -411,6 +417,9 @@ struct tor_zlib_state_t {
|
|
|
size_t input_so_far;
|
|
|
|
|
|
size_t output_so_far;
|
|
|
+
|
|
|
+
|
|
|
+ size_t allocation;
|
|
|
};
|
|
|
|
|
|
|
|
@@ -420,6 +429,7 @@ tor_zlib_state_t *
|
|
|
tor_zlib_new(int compress, compress_method_t method)
|
|
|
{
|
|
|
tor_zlib_state_t *out;
|
|
|
+ int bits;
|
|
|
|
|
|
if (method == GZIP_METHOD && !is_gzip_supported()) {
|
|
|
|
|
@@ -432,14 +442,19 @@ tor_zlib_new(int compress, compress_method_t method)
|
|
|
out->stream.zfree = Z_NULL;
|
|
|
out->stream.opaque = NULL;
|
|
|
out->compress = compress;
|
|
|
+ bits = method_bits(method);
|
|
|
if (compress) {
|
|
|
if (deflateInit2(&out->stream, Z_BEST_COMPRESSION, Z_DEFLATED,
|
|
|
- method_bits(method), 8, Z_DEFAULT_STRATEGY) != Z_OK)
|
|
|
+ bits, 8, Z_DEFAULT_STRATEGY) != Z_OK)
|
|
|
goto err;
|
|
|
} else {
|
|
|
- if (inflateInit2(&out->stream, method_bits(method)) != Z_OK)
|
|
|
+ if (inflateInit2(&out->stream, bits) != Z_OK)
|
|
|
goto err;
|
|
|
}
|
|
|
+ out->allocation = tor_zlib_state_size_precalc(!compress, bits, 8);
|
|
|
+
|
|
|
+ total_zlib_allocation += out->allocation;
|
|
|
+
|
|
|
return out;
|
|
|
|
|
|
err:
|
|
@@ -517,6 +532,8 @@ tor_zlib_free(tor_zlib_state_t *state)
|
|
|
if (!state)
|
|
|
return;
|
|
|
|
|
|
+ total_zlib_allocation -= state->allocation;
|
|
|
+
|
|
|
if (state->compress)
|
|
|
deflateEnd(&state->stream);
|
|
|
else
|
|
@@ -525,3 +542,47 @@ tor_zlib_free(tor_zlib_state_t *state)
|
|
|
tor_free(state);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * window bits <b>windowBits</b> and compression level 'memlevel' */
|
|
|
+static size_t
|
|
|
+tor_zlib_state_size_precalc(int inflate, int windowbits, int memlevel)
|
|
|
+{
|
|
|
+ windowbits &= 15;
|
|
|
+
|
|
|
+#define A_FEW_KILOBYTES 2048
|
|
|
+
|
|
|
+ if (inflate) {
|
|
|
+
|
|
|
+
|
|
|
+ "The memory requirements for inflate are (in bytes) 1 << windowBits
|
|
|
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
|
|
|
+ for small objects."
|
|
|
+ */
|
|
|
+ return sizeof(tor_zlib_state_t) + sizeof(struct z_stream_s) +
|
|
|
+ (1 << 15) + A_FEW_KILOBYTES;
|
|
|
+ } else {
|
|
|
+
|
|
|
+
|
|
|
+ "The memory requirements for deflate are (in bytes):
|
|
|
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
|
|
|
+ ... plus a few kilobytes for small objects."
|
|
|
+ */
|
|
|
+ return sizeof(tor_zlib_state_t) + sizeof(struct z_stream_s) +
|
|
|
+ (1 << (windowbits + 2)) + (1 << (memlevel + 9)) + A_FEW_KILOBYTES;
|
|
|
+ }
|
|
|
+#undef A_FEW_KILOBYTES
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+size_t
|
|
|
+tor_zlib_state_size(const tor_zlib_state_t *state)
|
|
|
+{
|
|
|
+ return state->allocation;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+size_t
|
|
|
+tor_zlib_get_total_allocation(void)
|
|
|
+{
|
|
|
+ return total_zlib_allocation;
|
|
|
+}
|