added proxy mode
diff --git a/libtelnet.c b/libtelnet.c
index 22fd42f..0b9462a 100644
--- a/libtelnet.c
+++ b/libtelnet.c
@@ -70,6 +70,40 @@
 		fprintf(stderr, "**ERROR**: libtelnet: %s\n", buffer);
 }
 
+/* initialize the zlib box for a telnet box; if deflate is non-zero, it
+ * initializes zlib for delating (compression), otherwise for inflating
+ * (decompression)
+ */
+z_stream *_init_zlib(struct libtelnet_t *telnet, int deflate,
+		void *user_data) {
+	z_stream *zlib;
+	int rs;
+
+	/* allocate zstream box */
+	if ((zlib = (z_stream *)calloc(1, sizeof(z_stream)))
+			== 0) {
+		ERROR_NOMEM(telnet, user_data, "malloc() failed");
+		return 0;
+	}
+
+	/* initialize */
+	if (deflate) {
+		if ((rs = deflateInit(zlib, Z_DEFAULT_COMPRESSION)) != Z_OK) {
+			free(zlib);
+			ERROR_ZLIB(telnet, user_data, rs, "deflateInit() failed");
+			return 0;
+		}
+	} else {
+		if ((rs = inflateInit(zlib)) != Z_OK) {
+			free(zlib);
+			ERROR_ZLIB(telnet, user_data, rs, "inflateInit() failed");
+			return 0;
+		}
+	}
+
+	return zlib;
+}
+
 /* initialize a telnet state tracker */
 void libtelnet_init(struct libtelnet_t *telnet, struct libtelnet_cb_t *cb,
 		enum libtelnet_mode_t mode) {
@@ -88,14 +122,16 @@
 		telnet->length = 0;
 	}
 
-	/* free zlib box */
-	if (telnet->zlib != 0) {
-		if (telnet->mode == LIBTELNET_MODE_SERVER)
-			deflateEnd(telnet->zlib);
-		else
-			inflateEnd(telnet->zlib);
-		free(telnet->zlib);
-		telnet->zlib = 0;
+	/* free zlib box(es) */
+	if (telnet->z_inflate != 0) {
+		inflateEnd(telnet->z_inflate);
+		free(telnet->z_inflate);
+		telnet->z_inflate = 0;
+	}
+	if (telnet->z_deflate != 0) {
+		deflateEnd(telnet->z_deflate);
+		free(telnet->z_deflate);
+		telnet->z_deflate = 0;
 	}
 }
 
@@ -249,29 +285,18 @@
 				telnet->length = 0;
 
 #ifdef HAVE_ZLIB
-				/* if we are a client and just received the COMPRESS2
-				 * begin marker, setup our zlib box and start handling
-				 * the compressed stream
+				/* if we are a client or a proxy and just received the
+				 * COMPRESS2 begin marker, setup our zlib box and start
+				 * handling the compressed stream if it's not already.
 				 */
-				if (telnet->mode == LIBTELNET_MODE_CLIENT &&
-						telnet->buffer[0] == LIBTELNET_TELOPT_COMPRESS2) {
-					int rs;
+				if (telnet->buffer[0] == LIBTELNET_TELOPT_COMPRESS2 &&
+						telnet->z_inflate == 0 &&
+						(telnet->mode == LIBTELNET_MODE_CLIENT ||
+						 telnet->mode == LIBTELNET_MODE_PROXY)) {
 
-					/* allocate zstream box */
-					if ((telnet->zlib = (z_stream *)malloc(sizeof(z_stream)))
-							== 0) {
-						ERROR_NOMEM(telnet, user_data, "malloc() failed");
-					}
-
-					/* initialize */
-					memset(telnet->zlib, 0, sizeof(z_stream));
-					if ((rs = inflateInit(telnet->zlib)) != Z_OK) {
-						free(telnet->zlib);
-						telnet->zlib = 0;
-						ERROR_ZLIB(telnet, user_data, rs,
-								"inflateInit() failed");
+					if ((telnet->z_inflate = _init_zlib(telnet, 0, user_data))
+							== 0)
 						break;
-					}
 
 					/* notify app that compression was enabled */
 					telnet->cb->compress(telnet, 1, user_data);
@@ -322,44 +347,42 @@
 void libtelnet_push(struct libtelnet_t *telnet, unsigned char *buffer,
 		unsigned int size, void *user_data) {
 #ifdef HAVE_ZLIB
-	/* if we are a client and we have a zlib box, then COMPRESS2 has been
-	 * negotiated and we need to inflate the buffer before processing
-	 */
-	if (telnet->mode == LIBTELNET_MODE_CLIENT && telnet->zlib != 0) {
+	/* if we have an inflate (decompression) zlib stream, use it */
+	if (telnet->z_inflate != 0) {
 		unsigned char inflate_buffer[4096];
 		int rs;
 
 		/* initialize zlib state */
-		telnet->zlib->next_in = buffer;
-		telnet->zlib->avail_in = size;
-		telnet->zlib->next_out = inflate_buffer;
-		telnet->zlib->avail_out = sizeof(inflate_buffer);
+		telnet->z_inflate->next_in = buffer;
+		telnet->z_inflate->avail_in = size;
+		telnet->z_inflate->next_out = inflate_buffer;
+		telnet->z_inflate->avail_out = sizeof(inflate_buffer);
 
 		/* inflate until buffer exhausted and all output is produced */
-		while (telnet->zlib->avail_in > 0 || telnet->zlib->avail_out == 0) {
+		while (telnet->z_inflate->avail_in > 0 || telnet->z_inflate->avail_out == 0) {
 			/* reset output buffer */
 
 			/* decompress */
-			rs = inflate(telnet->zlib, Z_SYNC_FLUSH);
+			rs = inflate(telnet->z_inflate, Z_SYNC_FLUSH);
 
 			/* process the decompressed bytes on success */
 			if (rs == Z_OK || rs == Z_STREAM_END)
 				_process(telnet, inflate_buffer, sizeof(inflate_buffer) -
-						telnet->zlib->avail_out, user_data);
+						telnet->z_inflate->avail_out, user_data);
 			else
 				ERROR_ZLIB(telnet, user_data, rs, "inflate() failed");
 
 			/* prepare output buffer for next run */
-			telnet->zlib->next_out = inflate_buffer;
-			telnet->zlib->avail_out = sizeof(inflate_buffer);
+			telnet->z_inflate->next_out = inflate_buffer;
+			telnet->z_inflate->avail_out = sizeof(inflate_buffer);
 
 			/* on error (or on end of stream) disable further inflation */
 			if (rs != Z_OK) {
 				telnet->cb->compress(telnet, 0, user_data);
 
-				inflateEnd(telnet->zlib);
-				free(telnet->zlib);
-				telnet->zlib = 0;
+				inflateEnd(telnet->z_inflate);
+				free(telnet->z_inflate);
+				telnet->z_inflate = 0;
 				break;
 			}
 		}
@@ -373,36 +396,34 @@
 static void _send(struct libtelnet_t *telnet, unsigned char *buffer,
 		unsigned int size, void *user_data) {
 #ifdef HAVE_ZLIB
-	/* if we are a server and we have a zlib box, then COMPRESS2 has been
-	 * negotiated and we need to deflate the buffer before sending it out
-	 */
-	if (telnet->mode == LIBTELNET_MODE_SERVER && telnet->zlib != 0) {
+	/* if we have a deflate (compression) zlib box, use it */
+	if (telnet->z_deflate != 0) {
 		unsigned char deflate_buffer[1024];
 		int rs;
 
-		/* initialize zlib state */
-		telnet->zlib->next_in = buffer;
-		telnet->zlib->avail_in = size;
-		telnet->zlib->next_out = deflate_buffer;
-		telnet->zlib->avail_out = sizeof(deflate_buffer);
+		/* initialize z_deflate state */
+		telnet->z_deflate->next_in = buffer;
+		telnet->z_deflate->avail_in = size;
+		telnet->z_deflate->next_out = deflate_buffer;
+		telnet->z_deflate->avail_out = sizeof(deflate_buffer);
 
 		/* deflate until buffer exhausted and all output is produced */
-		while (telnet->zlib->avail_in > 0 || telnet->zlib->avail_out == 0) {
+		while (telnet->z_deflate->avail_in > 0 || telnet->z_deflate->avail_out == 0) {
 			/* compress */
-			if ((rs = deflate(telnet->zlib, Z_SYNC_FLUSH)) != Z_OK) {
+			if ((rs = deflate(telnet->z_deflate, Z_SYNC_FLUSH)) != Z_OK) {
 				ERROR_ZLIB(telnet, user_data, rs, "deflate() failed");
-				deflateEnd(telnet->zlib);
-				free(telnet->zlib);
-				telnet->zlib = 0;
+				deflateEnd(telnet->z_deflate);
+				free(telnet->z_deflate);
+				telnet->z_deflate = 0;
 				break;
 			}
 
 			telnet->cb->send(telnet, deflate_buffer, sizeof(deflate_buffer) -
-					telnet->zlib->avail_out, user_data);
+					telnet->z_deflate->avail_out, user_data);
 
 			/* prepare output buffer for next run */
-			telnet->zlib->next_out = deflate_buffer;
-			telnet->zlib->avail_out = sizeof(deflate_buffer);
+			telnet->z_deflate->next_out = deflate_buffer;
+			telnet->z_deflate->avail_out = sizeof(deflate_buffer);
 		}
 
 	/* COMPRESS2 is not negotiated, just send */
@@ -457,27 +478,15 @@
 	libtelnet_send_command(telnet, LIBTELNET_SE, user_data);
 
 #ifdef HAVE_ZLIB
-	/* if we're a server and we just sent the COMPRESS2 marker, we must
-	 * make sure all further data is compressed
+	/* if we're a proxy and we just sent the COMPRESS2 marker, we must
+	 * make sure all further data is compressed if not already.
 	 */
-	if (telnet->mode == LIBTELNET_MODE_SERVER && opt ==
-			LIBTELNET_TELOPT_COMPRESS2) {
-		int rs;
+	if (telnet->mode == LIBTELNET_MODE_PROXY &&
+			telnet->z_deflate == 0 &&
+			opt == LIBTELNET_TELOPT_COMPRESS2) {
 
-		/* allocate zstream box */
-		if ((telnet->zlib = (z_stream *)malloc(sizeof(z_stream))) == 0) {
-			ERROR_NOMEM(telnet, user_data, "malloc() failed");
+		if ((telnet->z_deflate = _init_zlib(telnet, 1, user_data)) == 0)
 			return;
-		}
-
-		/* initialize */
-		memset(telnet->zlib, 0, sizeof(z_stream));
-		if ((rs = deflateInit(telnet->zlib, Z_DEFAULT_COMPRESSION)) != Z_OK) {
-			free(telnet->zlib);
-			telnet->zlib = 0;
-			ERROR_ZLIB(telnet, user_data, rs, "delateInit() failed");
-			return;
-		}
 
 		/* notify app that compression was enabled */
 		telnet->cb->compress(telnet, 1, user_data);
diff --git a/libtelnet.h b/libtelnet.h
index 693d065..b6058a0 100644
--- a/libtelnet.h
+++ b/libtelnet.h
@@ -88,7 +88,8 @@
 /* libtelnet modes */
 enum libtelnet_mode_t {
 	LIBTELNET_MODE_SERVER = 0,
-	LIBTELNET_MODE_CLIENT
+	LIBTELNET_MODE_CLIENT,
+	LIBTELNET_MODE_PROXY
 };
 
 /* telnet states */
@@ -145,7 +146,8 @@
 	struct libtelnet_cb_t *cb;
 #ifdef HAVE_ZLIB
 	/* zlib (mccp2) compression */
-	z_stream *zlib;
+	z_stream *z_deflate;
+	z_stream *z_inflate;
 #endif
 	/* sub-request buffer */
 	unsigned char *buffer;
diff --git a/telnet-proxy.c b/telnet-proxy.c
index 0cedaf9..ca808a7 100644
--- a/telnet-proxy.c
+++ b/telnet-proxy.c
@@ -320,13 +320,9 @@
 	cb_table.compress = _compress_cb;
 	cb_table.error = _error_cb;
 
-	/* initialize telnet boxes
-	 * NOTE: we set the server connect to the CLIENT mode because we
-	 * are acting as a client of the server; likewise, we set the
-	 * client connection to SERVER mode becauser we are acting as a
-	 * server to the client. */
-	libtelnet_init(&server.telnet, &cb_table, LIBTELNET_MODE_CLIENT);
-	libtelnet_init(&client.telnet, &cb_table, LIBTELNET_MODE_SERVER);
+	/* initialize telnet boxes */
+	libtelnet_init(&server.telnet, &cb_table, LIBTELNET_MODE_PROXY);
+	libtelnet_init(&client.telnet, &cb_table, LIBTELNET_MODE_PROXY);
 
 	/* initialize poll descriptors */
 	memset(pfd, 0, sizeof(pfd));