diff options
Diffstat (limited to 'src/engine/external/libwebsockets/extension-deflate-stream.c')
| -rw-r--r-- | src/engine/external/libwebsockets/extension-deflate-stream.c | 166 |
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; +} |