extension-permessage-deflate.c 14 KB

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