blob: addaa2c7e1e52414f9831794febee1e5623efd49 [file] [log] [blame]
Andy Greence6a21d2011-03-06 13:32:53 +00001#include "private-libwebsockets.h"
2#include "extension-deflate-stream.h"
3#include <stdio.h>
4#include <string.h>
5#include <assert.h>
6
Andy Green66a36ff2011-04-29 17:43:06 +08007#define LWS_ZLIB_WINDOW_BITS 15
Andy Green26111bc2011-03-22 09:06:52 +00008#define LWS_ZLIB_MEMLEVEL 8
Andy Greence6a21d2011-03-06 13:32:53 +00009
10int lws_extension_callback_deflate_stream(
Andy Green46c2ea02011-03-22 09:04:01 +000011 struct libwebsocket_context *context,
12 struct libwebsocket_extension *ext,
13 struct libwebsocket *wsi,
Andy Greence6a21d2011-03-06 13:32:53 +000014 enum libwebsocket_extension_callback_reasons reason,
15 void *user, void *in, size_t len)
16{
17 struct lws_ext_deflate_stream_conn *conn =
18 (struct lws_ext_deflate_stream_conn *)user;
19 int n;
20 struct lws_tokens *eff_buf = (struct lws_tokens *)in;
21
22 switch (reason) {
23
24 /*
25 * for deflate-stream, both client and server sides act the same
26 */
27
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;
Andy Green26111bc2011-03-22 09:06:52 +000033 n = inflateInit2(&conn->zs_in, -LWS_ZLIB_WINDOW_BITS);
Andy Greence6a21d2011-03-06 13:32:53 +000034 if (n != Z_OK) {
Andy Green43db0452013-01-10 19:50:35 +080035 lwsl_err("deflateInit returned %d\n", n);
Andy Greence6a21d2011-03-06 13:32:53 +000036 return 1;
37 }
Andy Green26111bc2011-03-22 09:06:52 +000038 n = deflateInit2(&conn->zs_out,
39 DEFLATE_STREAM_COMPRESSION_LEVEL, Z_DEFLATED,
40 -LWS_ZLIB_WINDOW_BITS, LWS_ZLIB_MEMLEVEL,
41 Z_DEFAULT_STRATEGY);
Andy Greence6a21d2011-03-06 13:32:53 +000042 if (n != Z_OK) {
Andy Green43db0452013-01-10 19:50:35 +080043 lwsl_err("deflateInit returned %d\n", n);
Andy Greence6a21d2011-03-06 13:32:53 +000044 return 1;
45 }
Andy Green43db0452013-01-10 19:50:35 +080046 lwsl_ext("zlibs constructed\n");
David Galeanod58c6ab2013-01-09 18:03:28 +080047 conn->remaining_in = 0;
Andy Greence6a21d2011-03-06 13:32:53 +000048 break;
49
50 case LWS_EXT_CALLBACK_DESTROY:
51 (void)inflateEnd(&conn->zs_in);
52 (void)deflateEnd(&conn->zs_out);
Andy Green43db0452013-01-10 19:50:35 +080053 lwsl_ext("zlibs destructed\n");
Andy Greence6a21d2011-03-06 13:32:53 +000054 break;
55
56 case LWS_EXT_CALLBACK_PACKET_RX_PREPARSE:
57
58 /*
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
62 */
Andy Greenb5b23192013-02-11 17:13:32 +080063 if (conn->remaining_in) {
David Galeanod58c6ab2013-01-09 18:03:28 +080064 conn->zs_in.next_in = conn->buf_in;
65 conn->zs_in.avail_in = conn->remaining_in;
66 conn->remaining_in = 0;
Andy Greenb5b23192013-02-11 17:13:32 +080067 } else {
David Galeanod58c6ab2013-01-09 18:03:28 +080068 conn->zs_in.next_in = (unsigned char *)eff_buf->token;
69 conn->zs_in.avail_in = eff_buf->token_len;
70 }
Andy Greence6a21d2011-03-06 13:32:53 +000071
David Galeanod58c6ab2013-01-09 18:03:28 +080072 conn->zs_in.next_out = conn->buf_out;
73 conn->zs_in.avail_out = sizeof(conn->buf_out);
Andy Greence6a21d2011-03-06 13:32:53 +000074
75 n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
76 switch (n) {
77 case Z_NEED_DICT:
78 case Z_DATA_ERROR:
79 case Z_MEM_ERROR:
80 /*
81 * screwed.. close the connection... we will get a
82 * destroy callback to take care of closing nicely
83 */
Andy Green43db0452013-01-10 19:50:35 +080084 lwsl_err("zlib error inflate %d\n", n);
Andy Greence6a21d2011-03-06 13:32:53 +000085 return -1;
86 }
87
88 /* rewrite the buffer pointers and length */
89
David Galeanod58c6ab2013-01-09 18:03:28 +080090 eff_buf->token = (char *)conn->buf_out;
Andy Greenb5b23192013-02-11 17:13:32 +080091 eff_buf->token_len =
92 sizeof(conn->buf_out) - conn->zs_in.avail_out;
David Galeanod58c6ab2013-01-09 18:03:28 +080093
94 /* copy avail data if not consumed */
Andy Greenb5b23192013-02-11 17:13:32 +080095 if (conn->zs_in.avail_in > 0) {
David Galeanod58c6ab2013-01-09 18:03:28 +080096 conn->remaining_in = conn->zs_in.avail_in;
Andy Greenb5b23192013-02-11 17:13:32 +080097 memcpy(conn->buf_in, conn->zs_in.next_in,
98 conn->zs_in.avail_in);
David Galeanod58c6ab2013-01-09 18:03:28 +080099 return 1;
100 }
Andy Greence6a21d2011-03-06 13:32:53 +0000101
102 /*
103 * if we filled the output buffer, signal that we likely have
104 * more and need to be called again
105 */
106
David Galeanod58c6ab2013-01-09 18:03:28 +0800107 if (eff_buf->token_len == sizeof(conn->buf_out))
Andy Greence6a21d2011-03-06 13:32:53 +0000108 return 1;
109
110 /* we don't need calling again until new input data comes */
111
112 return 0;
113
Andy Greenc44159f2011-03-07 07:08:18 +0000114 case LWS_EXT_CALLBACK_FLUSH_PENDING_TX:
Andy Greence6a21d2011-03-06 13:32:53 +0000115 case LWS_EXT_CALLBACK_PACKET_TX_PRESEND:
116
117 /*
118 * deflate the outgoing compressed data
119 */
120
121 conn->zs_out.next_in = (unsigned char *)eff_buf->token;
122 conn->zs_out.avail_in = eff_buf->token_len;
123
David Galeanod58c6ab2013-01-09 18:03:28 +0800124 conn->zs_out.next_out = conn->buf_out;
125 conn->zs_out.avail_out = sizeof(conn->buf_out);
Andy Greence6a21d2011-03-06 13:32:53 +0000126
Andy Greenc44159f2011-03-07 07:08:18 +0000127 n = Z_PARTIAL_FLUSH;
128 if (reason == LWS_EXT_CALLBACK_FLUSH_PENDING_TX)
129 n = Z_FULL_FLUSH;
130
131 n = deflate(&conn->zs_out, n);
Andy Greence6a21d2011-03-06 13:32:53 +0000132 if (n == Z_STREAM_ERROR) {
133 /*
134 * screwed.. close the connection... we will get a
135 * destroy callback to take care of closing nicely
136 */
Andy Green43db0452013-01-10 19:50:35 +0800137 lwsl_ext("zlib error deflate\n");
Andy Greence6a21d2011-03-06 13:32:53 +0000138
139 return -1;
140 }
141
142 /* rewrite the buffer pointers and length */
143
David Galeanod58c6ab2013-01-09 18:03:28 +0800144 eff_buf->token = (char *)conn->buf_out;
Andy Greenb5b23192013-02-11 17:13:32 +0800145 eff_buf->token_len =
146 sizeof(conn->buf_out) - conn->zs_out.avail_out;
Andy Greence6a21d2011-03-06 13:32:53 +0000147
148 /*
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
152 */
153
David Galeanod58c6ab2013-01-09 18:03:28 +0800154 if (eff_buf->token_len == sizeof(conn->buf_out))
Andy Greence6a21d2011-03-06 13:32:53 +0000155 return 1;
156
157 /* we don't need calling again until new input data comes */
158
Andy Greena41314f2011-05-23 10:00:03 +0100159 return 0;
160
161 default:
162 break;
Andy Greence6a21d2011-03-06 13:32:53 +0000163 }
164
165 return 0;
166}