about summary refs log tree commit diff
path: root/src/engine/external/libwebsockets/extension-deflate-stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/external/libwebsockets/extension-deflate-stream.c')
-rw-r--r--src/engine/external/libwebsockets/extension-deflate-stream.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/engine/external/libwebsockets/extension-deflate-stream.c b/src/engine/external/libwebsockets/extension-deflate-stream.c
new file mode 100644
index 00000000..addaa2c7
--- /dev/null
+++ b/src/engine/external/libwebsockets/extension-deflate-stream.c
@@ -0,0 +1,166 @@
+#include "private-libwebsockets.h"
+#include "extension-deflate-stream.h"
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#define LWS_ZLIB_WINDOW_BITS 15
+#define LWS_ZLIB_MEMLEVEL 8
+
+int lws_extension_callback_deflate_stream(
+		struct libwebsocket_context *context,
+		struct libwebsocket_extension *ext,
+		struct libwebsocket *wsi,
+			enum libwebsocket_extension_callback_reasons reason,
+					       void *user, void *in, size_t len)
+{
+	struct lws_ext_deflate_stream_conn *conn =
+				     (struct lws_ext_deflate_stream_conn *)user;
+	int n;
+	struct lws_tokens *eff_buf = (struct lws_tokens *)in;
+
+	switch (reason) {
+
+	/*
+	 * for deflate-stream, both client and server sides act the same
+	 */
+
+	case LWS_EXT_CALLBACK_CLIENT_CONSTRUCT:
+	case LWS_EXT_CALLBACK_CONSTRUCT:
+		conn->zs_in.zalloc = conn->zs_out.zalloc = Z_NULL;
+		conn->zs_in.zfree = conn->zs_out.zfree = Z_NULL;
+		conn->zs_in.opaque = conn->zs_out.opaque = Z_NULL;
+		n = inflateInit2(&conn->zs_in, -LWS_ZLIB_WINDOW_BITS);
+		if (n != Z_OK) {
+			lwsl_err("deflateInit returned %d\n", n);
+			return 1;
+		}
+		n = deflateInit2(&conn->zs_out,
+				 DEFLATE_STREAM_COMPRESSION_LEVEL, Z_DEFLATED,
+				 -LWS_ZLIB_WINDOW_BITS, LWS_ZLIB_MEMLEVEL,
+							    Z_DEFAULT_STRATEGY);
+		if (n != Z_OK) {
+			lwsl_err("deflateInit returned %d\n", n);
+			return 1;
+		}
+		lwsl_ext("zlibs constructed\n");
+		conn->remaining_in = 0;
+		break;
+
+	case LWS_EXT_CALLBACK_DESTROY:
+		(void)inflateEnd(&conn->zs_in);
+		(void)deflateEnd(&conn->zs_out);
+		lwsl_ext("zlibs destructed\n");
+		break;
+
+	case LWS_EXT_CALLBACK_PACKET_RX_PREPARSE:
+
+		/*
+		 * inflate the incoming compressed data
+		 * Notice, length may be 0 and pointer NULL
+		 * in the case we are flushing with nothing new coming in
+		 */
+		if (conn->remaining_in) {
+			conn->zs_in.next_in = conn->buf_in;
+			conn->zs_in.avail_in = conn->remaining_in;
+			conn->remaining_in = 0;
+		} else {
+			conn->zs_in.next_in = (unsigned char *)eff_buf->token;
+			conn->zs_in.avail_in = eff_buf->token_len;
+		}
+
+		conn->zs_in.next_out = conn->buf_out;
+		conn->zs_in.avail_out = sizeof(conn->buf_out);
+
+		n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
+		switch (n) {
+		case Z_NEED_DICT:
+		case Z_DATA_ERROR:
+		case Z_MEM_ERROR:
+			/*
+			 * screwed.. close the connection... we will get a
+			 * destroy callback to take care of closing nicely
+			 */
+			lwsl_err("zlib error inflate %d\n", n);
+			return -1;
+		}
+
+		/* rewrite the buffer pointers and length */
+
+		eff_buf->token = (char *)conn->buf_out;
+		eff_buf->token_len =
+			sizeof(conn->buf_out) - conn->zs_in.avail_out;
+
+		/* copy avail data if not consumed */
+		if (conn->zs_in.avail_in > 0) {
+			conn->remaining_in = conn->zs_in.avail_in;
+			memcpy(conn->buf_in, conn->zs_in.next_in,
+							conn->zs_in.avail_in);
+			return 1;
+		}
+
+		/*
+		 * if we filled the output buffer, signal that we likely have
+		 * more and need to be called again
+		 */
+
+		if (eff_buf->token_len == sizeof(conn->buf_out))
+			return 1;
+
+		/* we don't need calling again until new input data comes */
+
+		return 0;
+
+	case LWS_EXT_CALLBACK_FLUSH_PENDING_TX:
+	case LWS_EXT_CALLBACK_PACKET_TX_PRESEND:
+
+		/*
+		 * deflate the outgoing compressed data
+		 */
+
+		conn->zs_out.next_in = (unsigned char *)eff_buf->token;
+		conn->zs_out.avail_in = eff_buf->token_len;
+
+		conn->zs_out.next_out = conn->buf_out;
+		conn->zs_out.avail_out = sizeof(conn->buf_out);
+
+		n = Z_PARTIAL_FLUSH;
+		if (reason == LWS_EXT_CALLBACK_FLUSH_PENDING_TX)
+			n = Z_FULL_FLUSH;
+
+		n = deflate(&conn->zs_out, n);
+		if (n == Z_STREAM_ERROR) {
+			/*
+			 * screwed.. close the connection... we will get a
+			 * destroy callback to take care of closing nicely
+			 */
+			lwsl_ext("zlib error deflate\n");
+
+			return -1;
+		}
+
+		/* rewrite the buffer pointers and length */
+
+		eff_buf->token = (char *)conn->buf_out;
+		eff_buf->token_len =
+				sizeof(conn->buf_out) - conn->zs_out.avail_out;
+
+		/*
+		 * if we filled the output buffer, signal that we likely have
+		 * more and need to be called again... even in deflate case
+		 * we might sometimes need to spill more than came in
+		 */
+
+		if (eff_buf->token_len == sizeof(conn->buf_out))
+			return 1;
+
+		/* we don't need calling again until new input data comes */
+
+		return 0;
+
+	default:
+		break;
+	}
+
+	return 0;
+}