From ce6a21dbdaa15e8fb6d3510d9eb545283f327436 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 6 Mar 2011 13:32:53 +0000 Subject: [PATCH] introduce deflate compression extension Signed-off-by: Andy Green --- lib/Makefile.am | 1 + lib/Makefile.in | 17 ++++- lib/extension-deflate-stream.c | 137 +++++++++++++++++++++++++++++++++++++++++ lib/extension-deflate-stream.h | 17 +++++ lib/extension.c | 7 +++ lib/libwebsockets.c | 1 - 6 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 lib/extension-deflate-stream.c create mode 100644 lib/extension-deflate-stream.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 3c17de6..b98e6ef 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -7,6 +7,7 @@ dist_libwebsockets_la_SOURCES=libwebsockets.c \ base64-decode.c \ client-handshake.c \ extension.c \ + extension-deflate-stream.c \ private-libwebsockets.h if LIBCRYPTO else diff --git a/lib/Makefile.in b/lib/Makefile.in index be10d3d..1ef72b3 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -73,14 +73,16 @@ LTLIBRARIES = $(lib_LTLIBRARIES) libwebsockets_la_LIBADD = am__dist_libwebsockets_la_SOURCES_DIST = libwebsockets.c handshake.c \ parsers.c libwebsockets.h base64-decode.c client-handshake.c \ - extension.c private-libwebsockets.h md5.c sha-1.c + extension.c extension-deflate-stream.c private-libwebsockets.h \ + md5.c sha-1.c @LIBCRYPTO_FALSE@am__objects_1 = libwebsockets_la-md5.lo \ @LIBCRYPTO_FALSE@ libwebsockets_la-sha-1.lo dist_libwebsockets_la_OBJECTS = libwebsockets_la-libwebsockets.lo \ libwebsockets_la-handshake.lo libwebsockets_la-parsers.lo \ libwebsockets_la-base64-decode.lo \ libwebsockets_la-client-handshake.lo \ - libwebsockets_la-extension.lo $(am__objects_1) + libwebsockets_la-extension.lo \ + libwebsockets_la-extension-deflate-stream.lo $(am__objects_1) libwebsockets_la_OBJECTS = $(dist_libwebsockets_la_OBJECTS) libwebsockets_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libwebsockets_la_CFLAGS) \ @@ -222,7 +224,8 @@ lib_LTLIBRARIES = libwebsockets.la include_HEADERS = libwebsockets.h dist_libwebsockets_la_SOURCES = libwebsockets.c handshake.c parsers.c \ libwebsockets.h base64-decode.c client-handshake.c extension.c \ - private-libwebsockets.h $(am__append_1) + extension-deflate-stream.c private-libwebsockets.h \ + $(am__append_1) libwebsockets_la_CFLAGS := -rdynamic -fPIC -Wall -Werror -std=gnu99 -pedantic -c \ -DDATADIR=\"@datadir@\" -DLWS_OPENSSL_CLIENT_CERTS=\"@clientcertdir@\" @@ -303,6 +306,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwebsockets_la-base64-decode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwebsockets_la-client-handshake.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwebsockets_la-extension-deflate-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwebsockets_la-extension.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwebsockets_la-handshake.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwebsockets_la-libwebsockets.Plo@am__quote@ @@ -373,6 +377,13 @@ libwebsockets_la-extension.lo: extension.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwebsockets_la_CFLAGS) $(CFLAGS) -c -o libwebsockets_la-extension.lo `test -f 'extension.c' || echo '$(srcdir)/'`extension.c +libwebsockets_la-extension-deflate-stream.lo: extension-deflate-stream.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwebsockets_la_CFLAGS) $(CFLAGS) -MT libwebsockets_la-extension-deflate-stream.lo -MD -MP -MF $(DEPDIR)/libwebsockets_la-extension-deflate-stream.Tpo -c -o libwebsockets_la-extension-deflate-stream.lo `test -f 'extension-deflate-stream.c' || echo '$(srcdir)/'`extension-deflate-stream.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libwebsockets_la-extension-deflate-stream.Tpo $(DEPDIR)/libwebsockets_la-extension-deflate-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='extension-deflate-stream.c' object='libwebsockets_la-extension-deflate-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwebsockets_la_CFLAGS) $(CFLAGS) -c -o libwebsockets_la-extension-deflate-stream.lo `test -f 'extension-deflate-stream.c' || echo '$(srcdir)/'`extension-deflate-stream.c + libwebsockets_la-md5.lo: md5.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwebsockets_la_CFLAGS) $(CFLAGS) -MT libwebsockets_la-md5.lo -MD -MP -MF $(DEPDIR)/libwebsockets_la-md5.Tpo -c -o libwebsockets_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libwebsockets_la-md5.Tpo $(DEPDIR)/libwebsockets_la-md5.Plo diff --git a/lib/extension-deflate-stream.c b/lib/extension-deflate-stream.c new file mode 100644 index 0000000..8d439df --- /dev/null +++ b/lib/extension-deflate-stream.c @@ -0,0 +1,137 @@ +#include "private-libwebsockets.h" +#include "extension-deflate-stream.h" +#include +#include +#include + + + +int lws_extension_callback_deflate_stream( + struct libwebsocket_context *context, 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 = inflateInit(&conn->zs_in); + if (n != Z_OK) { + fprintf(stderr, "deflateInit returned %d\n", n); + return 1; + } + n = deflateInit(&conn->zs_out, + DEFLATE_STREAM_COMPRESSION_LEVEL); + if (n != Z_OK) { + fprintf(stderr, "deflateInit returned %d\n", n); + return 1; + } + fprintf(stderr, "zlibs constructed\n"); + break; + + case LWS_EXT_CALLBACK_DESTROY: + (void)inflateEnd(&conn->zs_in); + (void)deflateEnd(&conn->zs_out); + fprintf(stderr, "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 + */ + + 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; + conn->zs_in.avail_out = sizeof(conn->buf); + + 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 + */ + fprintf(stderr, "zlib error inflate %d\n", n); + return -1; + } + + /* rewrite the buffer pointers and length */ + + eff_buf->token = (char *)conn->buf; + eff_buf->token_len = sizeof(conn->buf) - conn->zs_in.avail_out; + + /* + * 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)) + return 1; + + /* we don't need calling again until new input data comes */ + + return 0; + + 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; + conn->zs_out.avail_out = sizeof(conn->buf); + + n = deflate(&conn->zs_out, Z_PARTIAL_FLUSH); + if (n == Z_STREAM_ERROR) { + /* + * screwed.. close the connection... we will get a + * destroy callback to take care of closing nicely + */ + fprintf(stderr, "zlib error deflate\n"); + + return -1; + } + + /* rewrite the buffer pointers and length */ + + eff_buf->token = (char *)conn->buf; + eff_buf->token_len = sizeof(conn->buf) - 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)) + return 1; + + /* we don't need calling again until new input data comes */ + + return 0; + } + + return 0; +} diff --git a/lib/extension-deflate-stream.h b/lib/extension-deflate-stream.h new file mode 100644 index 0000000..ff43b47 --- /dev/null +++ b/lib/extension-deflate-stream.h @@ -0,0 +1,17 @@ + +#include + +#define DEFLATE_STREAM_CHUNK 128 +#define DEFLATE_STREAM_COMPRESSION_LEVEL 1 + +struct lws_ext_deflate_stream_conn { + z_stream zs_in; + z_stream zs_out; + unsigned char buf[2000]; +}; + +extern int lws_extension_callback_deflate_stream( + struct libwebsocket_context *context, + struct libwebsocket *wsi, + enum libwebsocket_extension_callback_reasons reason, + void *user, void *in, size_t len); diff --git a/lib/extension.c b/lib/extension.c index 16d62d9..df62bd5 100644 --- a/lib/extension.c +++ b/lib/extension.c @@ -1,6 +1,13 @@ #include "private-libwebsockets.h" +#include "extension-deflate-stream.h" + struct libwebsocket_extension libwebsocket_internal_extensions[] = { + { + "deflate-stream", + lws_extension_callback_deflate_stream, + sizeof (struct lws_ext_deflate_stream_conn) + }, { /* terminator */ NULL, NULL, 0 } diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index efce3db..c6aca20 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -557,7 +557,6 @@ libwebsocket_service_fd(struct libwebsocket_context *context, int okay = 0; char ext_name[128]; struct lws_tokens eff_buf; - int more = 1; int ext_count = 0; struct libwebsocket_extension *ext; -- 2.7.4