MINOR: compression: memlevel and windowsize

The window size and the memlevel of the zlib are now configurable using
global options tune.zlib.memlevel and tune.zlib.windowsize.

It affects the memory consumption of the zlib.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 225acb7..eb24988 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -474,6 +474,8 @@
    - tune.rcvbuf.server
    - tune.sndbuf.client
    - tune.sndbuf.server
+   - tune.zlib.memlevel
+   - tune.zlib.windowsize
 
  * Debugging
    - debug
@@ -816,6 +818,18 @@
   to the kernel waiting for a large part of the buffer to be read before
   notifying haproxy again.
 
+tune.zlib.memlevel <number>
+  Sets the memLevel parameter in zlib initialization for each session. It
+  defines how much memory should be allocated for the intenal compression
+  state. A value of 1 uses minimum memory but is slow and reduces compression
+  ratio, a value of 9 uses maximum memory for optimal speed.  Can be a value
+  between 1 and 9. The default value is 8.
+
+tune.zlib.windowsize <number>
+  Sets the window size (the size of the history buffer) as a parameter of the
+  zlib initialization for each session. Larger values of this parameter result
+  in better compression at the expense of memory usage.  Can be a value between
+  8 and 15.  The default value is 15.
 
 3.3. Debugging
 --------------
diff --git a/include/types/compression.h b/include/types/compression.h
index 6f418fa..097c42c 100644
--- a/include/types/compression.h
+++ b/include/types/compression.h
@@ -44,7 +44,7 @@
 struct comp_algo {
 	char *name;
 	int name_len;
-	int (*init)(struct comp_ctx *comp_ctx, int);
+	int (*init)(struct comp_ctx *comp_ctx, int level);
 	int (*add_data)(struct comp_ctx *comp_ctx, const char *in_data, int in_len, char *out_data, int out_len);
 	int (*flush)(struct comp_ctx *comp_ctx, struct buffer *out, int flag);
 	int (*reset)(struct comp_ctx *comp_ctx);
diff --git a/include/types/global.h b/include/types/global.h
index 28632b7..2f41be5 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -112,6 +112,10 @@
 #ifdef USE_OPENSSL
 		int sslcachesize;  /* SSL cache size in session, defaults to 20000 */
 #endif
+#ifdef USE_ZLIB
+		int zlibmemlevel;    /* zlib memlevel */
+		int zlibwindowsize;  /* zlib window size */
+#endif
 	} tune;
 	struct {
 		char *prefix;           /* path prefix of unix bind socket */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index d1f18f7..2b45122 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -662,6 +662,50 @@
 		}
 		global.tune.max_http_hdr = atol(args[1]);
 	}
+	else if (!strcmp(args[0], "tune.zlib.memlevel")) {
+#ifdef USE_ZLIB
+		if (*args[1]) {
+			global.tune.zlibmemlevel = atoi(args[1]);
+			if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
+				Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
+				      file, linenum, args[0]);
+				err_code |= ERR_ALERT | ERR_FATAL;
+				goto out;
+			}
+		} else {
+			Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
+			      file, linenum, args[0]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+			goto out;
+		}
+#else
+		Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
+		err_code |= ERR_ALERT | ERR_FATAL;
+		goto out;
+#endif
+	}
+	else if (!strcmp(args[0], "tune.zlib.windowsize")) {
+#ifdef USE_ZLIB
+		if (*args[1]) {
+			global.tune.zlibwindowsize = atoi(args[1]);
+			if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
+				Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
+				      file, linenum, args[0]);
+				err_code |= ERR_ALERT | ERR_FATAL;
+				goto out;
+			}
+		} else {
+			Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
+			      file, linenum, args[0]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+			goto out;
+		}
+#else
+		Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
+		err_code |= ERR_ALERT | ERR_FATAL;
+		goto out;
+#endif
+	}
 	else if (!strcmp(args[0], "uid")) {
 		if (global.uid != 0) {
 			Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
diff --git a/src/compression.c b/src/compression.c
index 1f12df9..c20a449 100644
--- a/src/compression.c
+++ b/src/compression.c
@@ -329,7 +329,7 @@
 	strm->zfree = Z_NULL;
 	strm->opaque = Z_NULL;
 
-	if (deflateInit2(&comp_ctx->strm, level, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK)
+	if (deflateInit2(&comp_ctx->strm, level, Z_DEFLATED, global.tune.zlibwindowsize + 16, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK)
 		return -1;
 
 	return 0;
diff --git a/src/haproxy.c b/src/haproxy.c
index c6933c3..d85a46a 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -126,6 +126,12 @@
 #ifdef USE_OPENSSL
 		.sslcachesize = 20000,
 #endif
+#ifdef USE_ZLIB
+		.zlibmemlevel = 8,
+		.zlibwindowsize = MAX_WBITS,
+#endif
+
+
 	},
 #ifdef USE_OPENSSL
 #ifdef DEFAULT_MAXSSLCONN