Fix some typos.
[platform/upstream/libwebsockets.git] / lib / extension-permessage-deflate.c
1 /*
2  * ./lib/extension-permessage-deflate.c
3  *
4  *  Copyright (C) 2016 Andy Green <andy@warmcat.com>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation:
9  *  version 2.1 of the License.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *  MA  02110-1301  USA
20  */
21
22 #include "private-libwebsockets.h"
23 #include "extension-permessage-deflate.h"
24 #include <stdio.h>
25 #include <string.h>
26 #include <assert.h>
27
28 #define LWS_ZLIB_MEMLEVEL 8
29
30 const struct lws_ext_options lws_ext_pm_deflate_options[] = {
31         /* public RFC7692 settings */
32         { "server_no_context_takeover", EXTARG_NONE },
33         { "client_no_context_takeover", EXTARG_NONE },
34         { "server_max_window_bits",     EXTARG_OPT_DEC },
35         { "client_max_window_bits",     EXTARG_OPT_DEC },
36         /* ones only user code can set */
37         { "rx_buf_size",                EXTARG_DEC },
38         { "tx_buf_size",                EXTARG_DEC },
39         { "compression_level",          EXTARG_DEC },
40         { "mem_level",                  EXTARG_DEC },
41         { NULL, 0 }, /* sentinel */
42 };
43
44 LWS_VISIBLE int
45 lws_extension_callback_pm_deflate(struct lws_context *context,
46                                   const struct lws_extension *ext,
47                                   struct lws *wsi,
48                                   enum lws_extension_callback_reasons reason,
49                                   void *user, void *in, size_t len)
50 {
51         struct lws_ext_pm_deflate_priv *priv =
52                                      (struct lws_ext_pm_deflate_priv *)user;
53         struct lws_tokens *eff_buf = (struct lws_tokens *)in;
54         static unsigned char trail[] = { 0, 0, 0xff, 0xff };
55         int n, ret = 0, was_fin = 0, extra;
56         struct lws_ext_option_arg *oa;
57
58         switch (reason) {
59         case LWS_EXT_CB_OPTION_SET:
60                 oa = in;
61                 lwsl_info("%s: option set: idx %d, %s, len %d\n", __func__,
62                           oa->option_index, oa->start, oa->len);
63                 if (oa->start)
64                         priv->args[oa->option_index] = atoi(oa->start);
65                 else
66                         priv->args[oa->option_index] = 1;
67                 break;
68         case LWS_EXT_CB_OPTION_CONFIRM:
69                 if (priv->args[PMD_SERVER_MAX_WINDOW_BITS] < 8 ||
70                     priv->args[PMD_SERVER_MAX_WINDOW_BITS] > 15 ||
71                     priv->args[PMD_CLIENT_MAX_WINDOW_BITS] < 8 ||
72                     priv->args[PMD_CLIENT_MAX_WINDOW_BITS] > 15)
73                         return -1;
74                 break;
75
76         case LWS_EXT_CB_CLIENT_CONSTRUCT:
77         case LWS_EXT_CB_CONSTRUCT:
78                 /* fill in **user */
79                 priv = lws_zalloc(sizeof(*priv));
80                 *((void **)user) = priv;
81                 lwsl_ext("%s: LWS_EXT_CB_*CONSTRUCT\n", __func__);
82                 memset(priv, 0, sizeof(*priv));
83
84                 /* fill in pointer to options list */
85                 if (in)
86                         *((const struct lws_ext_options **)in) = lws_ext_pm_deflate_options;
87
88                 /* fallthru */
89
90         case LWS_EXT_CB_OPTION_DEFAULT:
91
92                 /* set the public, RFC7692 defaults... */
93
94                 priv->args[PMD_SERVER_NO_CONTEXT_TAKEOVER] = 0,
95                 priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER] = 0;
96                 priv->args[PMD_SERVER_MAX_WINDOW_BITS] = 15;
97                 priv->args[PMD_CLIENT_MAX_WINDOW_BITS] = 15;
98
99                 /* ...and the ones the user code can override */
100
101                 priv->args[PMD_RX_BUF_PWR2] = 10; /* ie, 1024 */
102                 priv->args[PMD_TX_BUF_PWR2] = 10; /* ie, 1024 */
103                 priv->args[PMD_COMP_LEVEL] = 1;
104                 priv->args[PMD_MEM_LEVEL] = 8;
105                 break;
106
107         case LWS_EXT_CB_DESTROY:
108                 lwsl_ext("%s: LWS_EXT_CB_DESTROY\n", __func__);
109                 lws_free(priv->buf_rx_inflated);
110                 lws_free(priv->buf_tx_deflated);
111                 if (priv->rx_init)
112                         (void)inflateEnd(&priv->rx);
113                 if (priv->tx_init)
114                         (void)deflateEnd(&priv->tx);
115                 lws_free(priv);
116                 return ret;
117
118         case LWS_EXT_CB_PAYLOAD_RX:
119                 lwsl_ext(" %s: LWS_EXT_CB_PAYLOAD_RX: in %d, existing in %d\n",
120                          __func__, eff_buf->token_len, priv->rx.avail_in);
121                 if (!(wsi->u.ws.rsv_first_msg & 0x40))
122                         return 0;
123
124 #if 0
125                 for (n = 0; n < eff_buf->token_len; n++) {
126                         printf("%02X ", (unsigned char)eff_buf->token[n]);
127                         if ((n & 15) == 15)
128                                 printf("\n");
129                 }
130                 printf("\n");
131 #endif
132                 if (!priv->rx_init)
133                         if (inflateInit2(&priv->rx, -priv->args[PMD_SERVER_MAX_WINDOW_BITS]) != Z_OK) {
134                                 lwsl_err("%s: iniflateInit failed\n", __func__);
135                                 return -1;
136                         }
137                 priv->rx_init = 1;
138                 if (!priv->buf_rx_inflated)
139                         priv->buf_rx_inflated = lws_malloc(LWS_PRE + 7 + 5 +
140                                             (1 << priv->args[PMD_RX_BUF_PWR2]));
141                 if (!priv->buf_rx_inflated) {
142                         lwsl_err("%s: OOM\n", __func__);
143                         return -1;
144                 }
145
146                 /*
147                  * We have to leave the input stream alone if we didn't
148                  * finish with it yet.  The input stream is held in the wsi
149                  * rx buffer by the caller, so this assumption is safe while
150                  * we block new rx while draining the existing rx
151                  */
152                 if (eff_buf->token && eff_buf->token_len) {
153                         priv->rx.next_in = (unsigned char *)eff_buf->token;
154                         priv->rx.avail_in = eff_buf->token_len;
155                 }
156                 priv->rx.next_out = priv->buf_rx_inflated + LWS_PRE;
157                 eff_buf->token = (char *)priv->rx.next_out;
158                 priv->rx.avail_out = 1 << priv->args[PMD_RX_BUF_PWR2];
159
160                 if (priv->rx_held_valid) {
161                         lwsl_ext("-- RX piling on held byte --\n");
162                         *(priv->rx.next_out++) = priv->rx_held;
163                         priv->rx.avail_out--;
164                         priv->rx_held_valid = 0;
165                 }
166
167                 /* if...
168                  *
169                  *  - he has no remaining input content for this message, and
170                  *  - and this is the final fragment, and
171                  *  - we used everything that could be drained on the input side
172                  *
173                  * ...then put back the 00 00 FF FF the sender stripped as our
174                  * input to zlib
175                  */
176                 if (!priv->rx.avail_in && wsi->u.ws.final &&
177                     !wsi->u.ws.rx_packet_length) {
178                         lwsl_ext("RX APPEND_TRAILER-DO\n");
179                         was_fin = 1;
180                         priv->rx.next_in = trail;
181                         priv->rx.avail_in = sizeof(trail);
182                 }
183
184                 n = inflate(&priv->rx, Z_NO_FLUSH);
185                 lwsl_ext("inflate ret %d, avi %d, avo %d, wsifinal %d\n", n,
186                          priv->rx.avail_in, priv->rx.avail_out, wsi->u.ws.final);
187                 switch (n) {
188                 case Z_NEED_DICT:
189                 case Z_STREAM_ERROR:
190                 case Z_DATA_ERROR:
191                 case Z_MEM_ERROR:
192                         lwsl_info("zlib error inflate %d: %s\n",
193                                   n, priv->rx.msg);
194                         return -1;
195                 }
196                 /*
197                  * If we did not already send in the 00 00 FF FF, and he's
198                  * out of input, he did not EXACTLY fill the output buffer
199                  * (which is ambiguous and we will force it to go around
200                  * again by withholding a byte), and he's otherwise working on
201                  * being a FIN fragment, then do the FIN message processing
202                  * of faking up the 00 00 FF FF that the sender stripped.
203                  */
204                 if (!priv->rx.avail_in && wsi->u.ws.final &&
205                     !wsi->u.ws.rx_packet_length && !was_fin &&
206                     priv->rx.avail_out /* ambiguous as to if it is the end */
207                 ) {
208                         lwsl_ext("RX APPEND_TRAILER-DO\n");
209                         was_fin = 1;
210                         priv->rx.next_in = trail;
211                         priv->rx.avail_in = sizeof(trail);
212                         n = inflate(&priv->rx, Z_SYNC_FLUSH);
213                         lwsl_ext("RX trailer inf returned %d, avi %d, avo %d\n", n,
214                                  priv->rx.avail_in, priv->rx.avail_out);
215                         switch (n) {
216                         case Z_NEED_DICT:
217                         case Z_STREAM_ERROR:
218                         case Z_DATA_ERROR:
219                         case Z_MEM_ERROR:
220                                 lwsl_info("zlib error inflate %d: %s\n",
221                                           n, priv->rx.msg);
222                                 return -1;
223                         }
224                 }
225                 /*
226                  * we must announce in our returncode now if there is more
227                  * output to be expected from inflate, so we can decide to
228                  * set the FIN bit on this bufferload or not.  However zlib
229                  * is ambiguous when we exactly filled the inflate buffer.  It
230                  * does not give us a clue as to whether we should understand
231                  * that to mean he ended on a buffer boundary, or if there is
232                  * more in the pipeline.
233                  *
234                  * So to work around that safely, if it used all output space
235                  * exactly, we ALWAYS say there is more coming and we withhold
236                  * the last byte of the buffer to guarantee that is true.
237                  *
238                  * That still leaves us at least one byte to finish with a FIN
239                  * on, even if actually nothing more is coming from the next
240                  * inflate action itself.
241                  */
242                 if (!priv->rx.avail_out) { /* he used all available out buf */
243                         lwsl_ext("-- rx grabbing held --\n");
244                         /* snip the last byte and hold it for next time */
245                         priv->rx_held = *(--priv->rx.next_out);
246                         priv->rx_held_valid = 1;
247                 }
248
249                 eff_buf->token_len = (char *)priv->rx.next_out - eff_buf->token;
250                 priv->count_rx_between_fin += eff_buf->token_len;
251
252                 lwsl_ext("  %s: RX leaving with new effbuff len %d, "
253                          "ret %d, rx.avail_in=%d, TOTAL RX since FIN %d\n",
254                          __func__, eff_buf->token_len, priv->rx_held_valid,
255                          priv->rx.avail_in, priv->count_rx_between_fin);
256
257                 if (was_fin) {
258                         priv->count_rx_between_fin = 0;
259                         if (priv->args[PMD_SERVER_NO_CONTEXT_TAKEOVER]) {
260                                 (void)inflateEnd(&priv->rx);
261                                 priv->rx_init = 0;
262                         }
263                 }
264 #if 0
265                 for (n = 0; n < eff_buf->token_len; n++)
266                         putchar(eff_buf->token[n]);
267                 puts("\n");
268 #endif
269
270                 return priv->rx_held_valid;
271
272         case LWS_EXT_CB_PAYLOAD_TX:
273
274                 if (!priv->tx_init)
275                         if (deflateInit2(&priv->tx, priv->args[PMD_COMP_LEVEL],
276                                          Z_DEFLATED,
277                                          -priv->args[PMD_CLIENT_MAX_WINDOW_BITS +
278                                                      !wsi->context->listen_port],
279                                          priv->args[PMD_MEM_LEVEL],
280                                          Z_DEFAULT_STRATEGY) != Z_OK) {
281                                 lwsl_ext("inflateInit2 failed\n");
282                                 return 1;
283                         }
284                 priv->tx_init = 1;
285                 if (!priv->buf_tx_deflated)
286                         priv->buf_tx_deflated = lws_malloc(LWS_PRE + 7 + 5 +
287                                             (1 << priv->args[PMD_TX_BUF_PWR2]));
288                 if (!priv->buf_tx_deflated) {
289                         lwsl_err("%s: OOM\n", __func__);
290                         return -1;
291                 }
292
293                 if (eff_buf->token) {
294                         lwsl_ext("%s: TX: eff_buf length %d\n", __func__,
295                                  eff_buf->token_len);
296                         priv->tx.next_in = (unsigned char *)eff_buf->token;
297                         priv->tx.avail_in = eff_buf->token_len;
298                 }
299
300 #if 0
301                 for (n = 0; n < eff_buf->token_len; n++) {
302                         printf("%02X ", (unsigned char)eff_buf->token[n]);
303                         if ((n & 15) == 15)
304                                 printf("\n");
305                 }
306                 printf("\n");
307 #endif
308
309                 priv->tx.next_out = priv->buf_tx_deflated + LWS_PRE + 5;
310                 eff_buf->token = (char *)priv->tx.next_out;
311                 priv->tx.avail_out = 1 << priv->args[PMD_TX_BUF_PWR2];
312
313                 n = deflate(&priv->tx, Z_SYNC_FLUSH);
314                 if (n == Z_STREAM_ERROR) {
315                         lwsl_ext("%s: Z_STREAM_ERROR\n", __func__);
316                         return -1;
317                 }
318
319                 if (priv->tx_held_valid) {
320                         priv->tx_held_valid = 0;
321                         if (priv->tx.avail_out == 1 << priv->args[PMD_TX_BUF_PWR2])
322                                 /*
323                                  * we can get a situation he took something in
324                                  * but did not generate anything out, at the end
325                                  * of a message (eg, next thing he sends is 80
326                                  * 00, a zero length FIN, like Authobahn can
327                                  * send).
328                                  * If we have come back as a FIN, we must not
329                                  * place the pending trailer 00 00 FF FF, just
330                                  * the 1 byte of live data
331                                  */
332                                 *(--eff_buf->token) = priv->tx_held[0];
333                         else {
334                                 /* he generated data, prepend whole pending */
335                                 eff_buf->token -= 5;
336                                 for (n = 0; n < 5; n++)
337                                         eff_buf->token[n] = priv->tx_held[n];
338
339                         }
340                 }
341                 priv->compressed_out = 1;
342                 eff_buf->token_len = (int)(priv->tx.next_out -
343                                            (unsigned char *)eff_buf->token);
344
345                 /*
346                  * we must announce in our returncode now if there is more
347                  * output to be expected from inflate, so we can decide to
348                  * set the FIN bit on this bufferload or not.  However zlib
349                  * is ambiguous when we exactly filled the inflate buffer.  It
350                  * does not give us a clue as to whether we should understand
351                  * that to mean he ended on a buffer boundary, or if there is
352                  * more in the pipeline.
353                  *
354                  * Worse, the guy providing the stuff we are sending may not
355                  * know until after that this was, actually, the last chunk,
356                  * that can happen even if we did not fill the output buf, ie
357                  * he may send after this a zero-length FIN fragment.
358                  *
359                  * This is super difficult because we must snip the last 4
360                  * bytes in the case this is the last compressed output of the
361                  * message.  The only way to deal with it is defer sending the
362                  * last 5 bytes of each frame until the next one, when we will
363                  * be in a position to understand if that has a FIN or not.
364                  */
365
366                 extra = !!(len & LWS_WRITE_NO_FIN) || !priv->tx.avail_out;
367
368                 if (eff_buf->token_len >= 4 + extra) {
369                         lwsl_ext("tx held %d\n", 4 + extra);
370                         priv->tx_held_valid = extra;
371                         for (n = 3 + extra; n >= 0; n--)
372                                 priv->tx_held[n] = *(--priv->tx.next_out);
373                         eff_buf->token_len -= 4 + extra;
374                 }
375                 lwsl_ext("  TX rewritten with new effbuff len %d, ret %d\n",
376                          eff_buf->token_len, !priv->tx.avail_out);
377
378                 return !priv->tx.avail_out; /* 1 == have more tx pending */
379
380         case LWS_EXT_CB_PACKET_TX_PRESEND:
381                 if (!priv->compressed_out)
382                         break;
383                 priv->compressed_out = 0;
384
385                 if ((*(eff_buf->token) & 0x80) && priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER]) {
386                         (void)deflateEnd(&priv->tx);
387                         priv->tx_init = 0;
388                 }
389
390                 n = *(eff_buf->token) & 15;
391                 /* set RSV1, but not on CONTINUATION */
392                 if (n == LWSWSOPC_TEXT_FRAME || n == LWSWSOPC_BINARY_FRAME)
393                         *eff_buf->token |= 0x40;
394 #if 0
395                 for (n = 0; n < eff_buf->token_len; n++) {
396                         printf("%02X ", (unsigned char)eff_buf->token[n]);
397                         if ((n & 15) == 15)
398                                 puts("\n");
399                 }
400                 puts("\n");
401 #endif
402                 lwsl_ext("%s: tx opcode 0x%02X\n", __func__,
403                          (unsigned char)*eff_buf->token);
404                 break;
405
406         default:
407                 break;
408         }
409
410         return 0;
411 }
412