1 #include "private-libwebsockets.h"
2 #include "extension-deflate-stream.h"
7 #define LWS_ZLIB_WINDOW_BITS 15
8 #define LWS_ZLIB_MEMLEVEL 8
10 int lws_extension_callback_deflate_stream(
11 struct libwebsocket_context *context,
12 struct libwebsocket_extension *ext,
13 struct libwebsocket *wsi,
14 enum libwebsocket_extension_callback_reasons reason,
15 void *user, void *in, size_t len)
17 struct lws_ext_deflate_stream_conn *conn =
18 (struct lws_ext_deflate_stream_conn *)user;
20 struct lws_tokens *eff_buf = (struct lws_tokens *)in;
25 * for deflate-stream, both client and server sides act the same
28 case LWS_EXT_CALLBACK_CLIENT_CONSTRUCT:
29 case LWS_EXT_CALLBACK_CONSTRUCT:
30 conn->zs_in.zalloc = conn->zs_out.zalloc = Z_NULL;
31 conn->zs_in.zfree = conn->zs_out.zfree = Z_NULL;
32 conn->zs_in.opaque = conn->zs_out.opaque = Z_NULL;
33 n = inflateInit2(&conn->zs_in, -LWS_ZLIB_WINDOW_BITS);
35 lwsl_err("deflateInit returned %d\n", n);
38 n = deflateInit2(&conn->zs_out,
39 DEFLATE_STREAM_COMPRESSION_LEVEL, Z_DEFLATED,
40 -LWS_ZLIB_WINDOW_BITS, LWS_ZLIB_MEMLEVEL,
43 lwsl_err("deflateInit returned %d\n", n);
46 lwsl_ext("zlibs constructed\n");
47 conn->remaining_in = 0;
50 case LWS_EXT_CALLBACK_DESTROY:
51 (void)inflateEnd(&conn->zs_in);
52 (void)deflateEnd(&conn->zs_out);
53 lwsl_ext("zlibs destructed\n");
56 case LWS_EXT_CALLBACK_PACKET_RX_PREPARSE:
59 * inflate the incoming compressed data
60 * Notice, length may be 0 and pointer NULL
61 * in the case we are flushing with nothing new coming in
63 if (conn->remaining_in) {
64 conn->zs_in.next_in = conn->buf_in;
65 conn->zs_in.avail_in = conn->remaining_in;
66 conn->remaining_in = 0;
68 conn->zs_in.next_in = (unsigned char *)eff_buf->token;
69 conn->zs_in.avail_in = eff_buf->token_len;
72 conn->zs_in.next_out = conn->buf_out;
73 conn->zs_in.avail_out = sizeof(conn->buf_out);
75 n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
81 * screwed.. close the connection... we will get a
82 * destroy callback to take care of closing nicely
84 lwsl_err("zlib error inflate %d\n", n);
88 /* rewrite the buffer pointers and length */
90 eff_buf->token = (char *)conn->buf_out;
92 sizeof(conn->buf_out) - conn->zs_in.avail_out;
94 /* copy avail data if not consumed */
95 if (conn->zs_in.avail_in > 0) {
96 conn->remaining_in = conn->zs_in.avail_in;
97 memcpy(conn->buf_in, conn->zs_in.next_in,
98 conn->zs_in.avail_in);
103 * if we filled the output buffer, signal that we likely have
104 * more and need to be called again
107 if (eff_buf->token_len == sizeof(conn->buf_out))
110 /* we don't need calling again until new input data comes */
114 case LWS_EXT_CALLBACK_FLUSH_PENDING_TX:
115 case LWS_EXT_CALLBACK_PACKET_TX_PRESEND:
118 * deflate the outgoing compressed data
121 conn->zs_out.next_in = (unsigned char *)eff_buf->token;
122 conn->zs_out.avail_in = eff_buf->token_len;
124 conn->zs_out.next_out = conn->buf_out;
125 conn->zs_out.avail_out = sizeof(conn->buf_out);
128 if (reason == LWS_EXT_CALLBACK_FLUSH_PENDING_TX)
131 n = deflate(&conn->zs_out, n);
132 if (n == Z_STREAM_ERROR) {
134 * screwed.. close the connection... we will get a
135 * destroy callback to take care of closing nicely
137 lwsl_ext("zlib error deflate\n");
142 /* rewrite the buffer pointers and length */
144 eff_buf->token = (char *)conn->buf_out;
146 sizeof(conn->buf_out) - conn->zs_out.avail_out;
149 * if we filled the output buffer, signal that we likely have
150 * more and need to be called again... even in deflate case
151 * we might sometimes need to spill more than came in
154 if (eff_buf->token_len == sizeof(conn->buf_out))
157 /* we don't need calling again until new input data comes */