diff options
Diffstat (limited to 'thirdparty/lws/ext')
-rw-r--r-- | thirdparty/lws/ext/extension-permessage-deflate.c | 473 | ||||
-rw-r--r-- | thirdparty/lws/ext/extension-permessage-deflate.h | 41 | ||||
-rw-r--r-- | thirdparty/lws/ext/extension.c | 344 |
3 files changed, 0 insertions, 858 deletions
diff --git a/thirdparty/lws/ext/extension-permessage-deflate.c b/thirdparty/lws/ext/extension-permessage-deflate.c deleted file mode 100644 index e2be2ae615..0000000000 --- a/thirdparty/lws/ext/extension-permessage-deflate.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * ./lib/extension-permessage-deflate.c - * - * Copyright (C) 2016 Andy Green <andy@warmcat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation: - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ - -#include "private-libwebsockets.h" -#include "extension-permessage-deflate.h" -#include <stdio.h> -#include <string.h> -#include <assert.h> - -#define LWS_ZLIB_MEMLEVEL 8 - -const struct lws_ext_options lws_ext_pm_deflate_options[] = { - /* public RFC7692 settings */ - { "server_no_context_takeover", EXTARG_NONE }, - { "client_no_context_takeover", EXTARG_NONE }, - { "server_max_window_bits", EXTARG_OPT_DEC }, - { "client_max_window_bits", EXTARG_OPT_DEC }, - /* ones only user code can set */ - { "rx_buf_size", EXTARG_DEC }, - { "tx_buf_size", EXTARG_DEC }, - { "compression_level", EXTARG_DEC }, - { "mem_level", EXTARG_DEC }, - { NULL, 0 }, /* sentinel */ -}; - -static void -lws_extension_pmdeflate_restrict_args(struct lws *wsi, - struct lws_ext_pm_deflate_priv *priv) -{ - int n, extra; - - /* cap the RX buf at the nearest power of 2 to protocol rx buf */ - - n = wsi->context->pt_serv_buf_size; - if (wsi->protocol->rx_buffer_size) - n = wsi->protocol->rx_buffer_size; - - extra = 7; - while (n >= 1 << (extra + 1)) - extra++; - - if (extra < priv->args[PMD_RX_BUF_PWR2]) { - priv->args[PMD_RX_BUF_PWR2] = extra; - lwsl_info(" Capping pmd rx to %d\n", 1 << extra); - } -} - -LWS_VISIBLE int -lws_extension_callback_pm_deflate(struct lws_context *context, - const struct lws_extension *ext, - struct lws *wsi, - enum lws_extension_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct lws_ext_pm_deflate_priv *priv = - (struct lws_ext_pm_deflate_priv *)user; - struct lws_tokens *eff_buf = (struct lws_tokens *)in; - static unsigned char trail[] = { 0, 0, 0xff, 0xff }; - int n, ret = 0, was_fin = 0, extra; - struct lws_ext_option_arg *oa; - - switch (reason) { - case LWS_EXT_CB_NAMED_OPTION_SET: - oa = in; - if (!oa->option_name) - break; - for (n = 0; n < ARRAY_SIZE(lws_ext_pm_deflate_options); n++) - if (!strcmp(lws_ext_pm_deflate_options[n].name, oa->option_name)) - break; - - if (n == ARRAY_SIZE(lws_ext_pm_deflate_options)) - break; - oa->option_index = n; - - /* fallthru */ - - case LWS_EXT_CB_OPTION_SET: - oa = in; - lwsl_notice("%s: option set: idx %d, %s, len %d\n", __func__, - oa->option_index, oa->start, oa->len); - if (oa->start) - priv->args[oa->option_index] = atoi(oa->start); - else - priv->args[oa->option_index] = 1; - - if (priv->args[PMD_CLIENT_MAX_WINDOW_BITS] == 8) - priv->args[PMD_CLIENT_MAX_WINDOW_BITS] = 9; - - lws_extension_pmdeflate_restrict_args(wsi, priv); - break; - - case LWS_EXT_CB_OPTION_CONFIRM: - if (priv->args[PMD_SERVER_MAX_WINDOW_BITS] < 8 || - priv->args[PMD_SERVER_MAX_WINDOW_BITS] > 15 || - priv->args[PMD_CLIENT_MAX_WINDOW_BITS] < 8 || - priv->args[PMD_CLIENT_MAX_WINDOW_BITS] > 15) - return -1; - break; - - case LWS_EXT_CB_CLIENT_CONSTRUCT: - case LWS_EXT_CB_CONSTRUCT: - - n = context->pt_serv_buf_size; - if (wsi->protocol->rx_buffer_size) - n = wsi->protocol->rx_buffer_size; - - if (n < 128) { - lwsl_info(" permessage-deflate requires the protocol (%s) to have an RX buffer >= 128\n", - wsi->protocol->name); - return -1; - } - - /* fill in **user */ - priv = lws_zalloc(sizeof(*priv), "pmd priv"); - *((void **)user) = priv; - lwsl_ext("%s: LWS_EXT_CB_*CONSTRUCT\n", __func__); - memset(priv, 0, sizeof(*priv)); - - /* fill in pointer to options list */ - if (in) - *((const struct lws_ext_options **)in) = - lws_ext_pm_deflate_options; - - /* fallthru */ - - case LWS_EXT_CB_OPTION_DEFAULT: - - /* set the public, RFC7692 defaults... */ - - priv->args[PMD_SERVER_NO_CONTEXT_TAKEOVER] = 0, - priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER] = 0; - priv->args[PMD_SERVER_MAX_WINDOW_BITS] = 15; - priv->args[PMD_CLIENT_MAX_WINDOW_BITS] = 15; - - /* ...and the ones the user code can override */ - - priv->args[PMD_RX_BUF_PWR2] = 10; /* ie, 1024 */ - priv->args[PMD_TX_BUF_PWR2] = 10; /* ie, 1024 */ - priv->args[PMD_COMP_LEVEL] = 1; - priv->args[PMD_MEM_LEVEL] = 8; - - lws_extension_pmdeflate_restrict_args(wsi, priv); - break; - - case LWS_EXT_CB_DESTROY: - lwsl_ext("%s: LWS_EXT_CB_DESTROY\n", __func__); - lws_free(priv->buf_rx_inflated); - lws_free(priv->buf_tx_deflated); - if (priv->rx_init) - (void)inflateEnd(&priv->rx); - if (priv->tx_init) - (void)deflateEnd(&priv->tx); - lws_free(priv); - return ret; - - case LWS_EXT_CB_PAYLOAD_RX: - lwsl_ext(" %s: LWS_EXT_CB_PAYLOAD_RX: in %d, existing in %d\n", - __func__, eff_buf->token_len, priv->rx.avail_in); - if (!(wsi->u.ws.rsv_first_msg & 0x40)) - return 0; - -#if 0 - for (n = 0; n < eff_buf->token_len; n++) { - printf("%02X ", (unsigned char)eff_buf->token[n]); - if ((n & 15) == 15) - printf("\n"); - } - printf("\n"); -#endif - if (!priv->rx_init) - if (inflateInit2(&priv->rx, -priv->args[PMD_SERVER_MAX_WINDOW_BITS]) != Z_OK) { - lwsl_err("%s: iniflateInit failed\n", __func__); - return -1; - } - priv->rx_init = 1; - if (!priv->buf_rx_inflated) - priv->buf_rx_inflated = lws_malloc(LWS_PRE + 7 + 5 + - (1 << priv->args[PMD_RX_BUF_PWR2]), "pmd rx inflate buf"); - if (!priv->buf_rx_inflated) { - lwsl_err("%s: OOM\n", __func__); - return -1; - } - - /* - * We have to leave the input stream alone if we didn't - * finish with it yet. The input stream is held in the wsi - * rx buffer by the caller, so this assumption is safe while - * we block new rx while draining the existing rx - */ - if (!priv->rx.avail_in && eff_buf->token && eff_buf->token_len) { - priv->rx.next_in = (unsigned char *)eff_buf->token; - priv->rx.avail_in = eff_buf->token_len; - } - priv->rx.next_out = priv->buf_rx_inflated + LWS_PRE; - eff_buf->token = (char *)priv->rx.next_out; - priv->rx.avail_out = 1 << priv->args[PMD_RX_BUF_PWR2]; - - if (priv->rx_held_valid) { - lwsl_ext("-- RX piling on held byte --\n"); - *(priv->rx.next_out++) = priv->rx_held; - priv->rx.avail_out--; - priv->rx_held_valid = 0; - } - - /* if... - * - * - he has no remaining input content for this message, and - * - and this is the final fragment, and - * - we used everything that could be drained on the input side - * - * ...then put back the 00 00 FF FF the sender stripped as our - * input to zlib - */ - if (!priv->rx.avail_in && wsi->u.ws.final && - !wsi->u.ws.rx_packet_length) { - lwsl_ext("RX APPEND_TRAILER-DO\n"); - was_fin = 1; - priv->rx.next_in = trail; - priv->rx.avail_in = sizeof(trail); - } - - n = inflate(&priv->rx, Z_NO_FLUSH); - lwsl_ext("inflate ret %d, avi %d, avo %d, wsifinal %d\n", n, - priv->rx.avail_in, priv->rx.avail_out, wsi->u.ws.final); - switch (n) { - case Z_NEED_DICT: - case Z_STREAM_ERROR: - case Z_DATA_ERROR: - case Z_MEM_ERROR: - lwsl_info("zlib error inflate %d: %s\n", - n, priv->rx.msg); - return -1; - } - /* - * If we did not already send in the 00 00 FF FF, and he's - * out of input, he did not EXACTLY fill the output buffer - * (which is ambiguous and we will force it to go around - * again by withholding a byte), and he's otherwise working on - * being a FIN fragment, then do the FIN message processing - * of faking up the 00 00 FF FF that the sender stripped. - */ - if (!priv->rx.avail_in && wsi->u.ws.final && - !wsi->u.ws.rx_packet_length && !was_fin && - priv->rx.avail_out /* ambiguous as to if it is the end */ - ) { - lwsl_ext("RX APPEND_TRAILER-DO\n"); - was_fin = 1; - priv->rx.next_in = trail; - priv->rx.avail_in = sizeof(trail); - n = inflate(&priv->rx, Z_SYNC_FLUSH); - lwsl_ext("RX trailer inf returned %d, avi %d, avo %d\n", n, - priv->rx.avail_in, priv->rx.avail_out); - switch (n) { - case Z_NEED_DICT: - case Z_STREAM_ERROR: - case Z_DATA_ERROR: - case Z_MEM_ERROR: - lwsl_info("zlib error inflate %d: %s\n", - n, priv->rx.msg); - return -1; - } - } - /* - * we must announce in our returncode now if there is more - * output to be expected from inflate, so we can decide to - * set the FIN bit on this bufferload or not. However zlib - * is ambiguous when we exactly filled the inflate buffer. It - * does not give us a clue as to whether we should understand - * that to mean he ended on a buffer boundary, or if there is - * more in the pipeline. - * - * So to work around that safely, if it used all output space - * exactly, we ALWAYS say there is more coming and we withhold - * the last byte of the buffer to guarantee that is true. - * - * That still leaves us at least one byte to finish with a FIN - * on, even if actually nothing more is coming from the next - * inflate action itself. - */ - if (!priv->rx.avail_out) { /* he used all available out buf */ - lwsl_ext("-- rx grabbing held --\n"); - /* snip the last byte and hold it for next time */ - priv->rx_held = *(--priv->rx.next_out); - priv->rx_held_valid = 1; - } - - eff_buf->token_len = (char *)priv->rx.next_out - eff_buf->token; - priv->count_rx_between_fin += eff_buf->token_len; - - lwsl_ext(" %s: RX leaving with new effbuff len %d, " - "ret %d, rx.avail_in=%d, TOTAL RX since FIN %lu\n", - __func__, eff_buf->token_len, priv->rx_held_valid, - priv->rx.avail_in, - (unsigned long)priv->count_rx_between_fin); - - if (was_fin) { - priv->count_rx_between_fin = 0; - if (priv->args[PMD_SERVER_NO_CONTEXT_TAKEOVER]) { - (void)inflateEnd(&priv->rx); - priv->rx_init = 0; - } - } -#if 0 - for (n = 0; n < eff_buf->token_len; n++) - putchar(eff_buf->token[n]); - puts("\n"); -#endif - - return priv->rx_held_valid; - - case LWS_EXT_CB_PAYLOAD_TX: - - if (!priv->tx_init) { - n = deflateInit2(&priv->tx, priv->args[PMD_COMP_LEVEL], - Z_DEFLATED, - -priv->args[PMD_SERVER_MAX_WINDOW_BITS + - (wsi->vhost->listen_port <= 0)], - priv->args[PMD_MEM_LEVEL], - Z_DEFAULT_STRATEGY); - if (n != Z_OK) { - lwsl_ext("inflateInit2 failed %d\n", n); - return 1; - } - } - priv->tx_init = 1; - if (!priv->buf_tx_deflated) - priv->buf_tx_deflated = lws_malloc(LWS_PRE + 7 + 5 + - (1 << priv->args[PMD_TX_BUF_PWR2]), "pmd tx deflate buf"); - if (!priv->buf_tx_deflated) { - lwsl_err("%s: OOM\n", __func__); - return -1; - } - - if (eff_buf->token) { - lwsl_ext("%s: TX: eff_buf length %d\n", __func__, - eff_buf->token_len); - priv->tx.next_in = (unsigned char *)eff_buf->token; - priv->tx.avail_in = eff_buf->token_len; - } - -#if 0 - for (n = 0; n < eff_buf->token_len; n++) { - printf("%02X ", (unsigned char)eff_buf->token[n]); - if ((n & 15) == 15) - printf("\n"); - } - printf("\n"); -#endif - - priv->tx.next_out = priv->buf_tx_deflated + LWS_PRE + 5; - eff_buf->token = (char *)priv->tx.next_out; - priv->tx.avail_out = 1 << priv->args[PMD_TX_BUF_PWR2]; - - n = deflate(&priv->tx, Z_SYNC_FLUSH); - if (n == Z_STREAM_ERROR) { - lwsl_ext("%s: Z_STREAM_ERROR\n", __func__); - return -1; - } - - if (priv->tx_held_valid) { - priv->tx_held_valid = 0; - if (priv->tx.avail_out == 1 << priv->args[PMD_TX_BUF_PWR2]) - /* - * we can get a situation he took something in - * but did not generate anything out, at the end - * of a message (eg, next thing he sends is 80 - * 00, a zero length FIN, like Authobahn can - * send). - * If we have come back as a FIN, we must not - * place the pending trailer 00 00 FF FF, just - * the 1 byte of live data - */ - *(--eff_buf->token) = priv->tx_held[0]; - else { - /* he generated data, prepend whole pending */ - eff_buf->token -= 5; - for (n = 0; n < 5; n++) - eff_buf->token[n] = priv->tx_held[n]; - - } - } - priv->compressed_out = 1; - eff_buf->token_len = (int)(priv->tx.next_out - - (unsigned char *)eff_buf->token); - - /* - * we must announce in our returncode now if there is more - * output to be expected from inflate, so we can decide to - * set the FIN bit on this bufferload or not. However zlib - * is ambiguous when we exactly filled the inflate buffer. It - * does not give us a clue as to whether we should understand - * that to mean he ended on a buffer boundary, or if there is - * more in the pipeline. - * - * Worse, the guy providing the stuff we are sending may not - * know until after that this was, actually, the last chunk, - * that can happen even if we did not fill the output buf, ie - * he may send after this a zero-length FIN fragment. - * - * This is super difficult because we must snip the last 4 - * bytes in the case this is the last compressed output of the - * message. The only way to deal with it is defer sending the - * last 5 bytes of each frame until the next one, when we will - * be in a position to understand if that has a FIN or not. - */ - - extra = !!(len & LWS_WRITE_NO_FIN) || !priv->tx.avail_out; - - if (eff_buf->token_len >= 4 + extra) { - lwsl_ext("tx held %d\n", 4 + extra); - priv->tx_held_valid = extra; - for (n = 3 + extra; n >= 0; n--) - priv->tx_held[n] = *(--priv->tx.next_out); - eff_buf->token_len -= 4 + extra; - } - lwsl_ext(" TX rewritten with new effbuff len %d, ret %d\n", - eff_buf->token_len, !priv->tx.avail_out); - - return !priv->tx.avail_out; /* 1 == have more tx pending */ - - case LWS_EXT_CB_PACKET_TX_PRESEND: - if (!priv->compressed_out) - break; - priv->compressed_out = 0; - - if ((*(eff_buf->token) & 0x80) && - priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER]) { - lwsl_debug("PMD_CLIENT_NO_CONTEXT_TAKEOVER\n"); - (void)deflateEnd(&priv->tx); - priv->tx_init = 0; - } - - n = *(eff_buf->token) & 15; - /* set RSV1, but not on CONTINUATION */ - if (n == LWSWSOPC_TEXT_FRAME || n == LWSWSOPC_BINARY_FRAME) - *eff_buf->token |= 0x40; -#if 0 - for (n = 0; n < eff_buf->token_len; n++) { - printf("%02X ", (unsigned char)eff_buf->token[n]); - if ((n & 15) == 15) - puts("\n"); - } - puts("\n"); -#endif - lwsl_ext("%s: tx opcode 0x%02X\n", __func__, - (unsigned char)*eff_buf->token); - break; - - default: - break; - } - - return 0; -} - diff --git a/thirdparty/lws/ext/extension-permessage-deflate.h b/thirdparty/lws/ext/extension-permessage-deflate.h deleted file mode 100644 index 8737736897..0000000000 --- a/thirdparty/lws/ext/extension-permessage-deflate.h +++ /dev/null @@ -1,41 +0,0 @@ - -#include <zlib.h> - -#define DEFLATE_FRAME_COMPRESSION_LEVEL_SERVER 1 -#define DEFLATE_FRAME_COMPRESSION_LEVEL_CLIENT Z_DEFAULT_COMPRESSION - -enum arg_indexes { - PMD_SERVER_NO_CONTEXT_TAKEOVER, - PMD_CLIENT_NO_CONTEXT_TAKEOVER, - PMD_SERVER_MAX_WINDOW_BITS, - PMD_CLIENT_MAX_WINDOW_BITS, - PMD_RX_BUF_PWR2, - PMD_TX_BUF_PWR2, - PMD_COMP_LEVEL, - PMD_MEM_LEVEL, - - PMD_ARG_COUNT -}; - -struct lws_ext_pm_deflate_priv { - z_stream rx; - z_stream tx; - - unsigned char *buf_rx_inflated; /* RX inflated output buffer */ - unsigned char *buf_tx_deflated; /* TX deflated output buffer */ - - size_t count_rx_between_fin; - - unsigned char args[PMD_ARG_COUNT]; - unsigned char tx_held[5]; - unsigned char rx_held; - - unsigned char tx_init:1; - unsigned char rx_init:1; - unsigned char compressed_out:1; - unsigned char rx_held_valid:1; - unsigned char tx_held_valid:1; - unsigned char rx_append_trailer:1; - unsigned char pending_tx_trailer:1; -}; - diff --git a/thirdparty/lws/ext/extension.c b/thirdparty/lws/ext/extension.c deleted file mode 100644 index ac28204034..0000000000 --- a/thirdparty/lws/ext/extension.c +++ /dev/null @@ -1,344 +0,0 @@ -#include "private-libwebsockets.h" - -#include "extension-permessage-deflate.h" - -LWS_VISIBLE void -lws_context_init_extensions(struct lws_context_creation_info *info, - struct lws_context *context) -{ - lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE); -} - -enum lws_ext_option_parser_states { - LEAPS_SEEK_NAME, - LEAPS_EAT_NAME, - LEAPS_SEEK_VAL, - LEAPS_EAT_DEC, - LEAPS_SEEK_ARG_TERM -}; - -LWS_VISIBLE int -lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi, - void *ext_user, const struct lws_ext_options *opts, - const char *in, int len) -{ - enum lws_ext_option_parser_states leap = LEAPS_SEEK_NAME; - unsigned int match_map = 0, n, m, w = 0, count_options = 0, - pending_close_quote = 0; - struct lws_ext_option_arg oa; - - oa.option_name = NULL; - - while (opts[count_options].name) - count_options++; - while (len) { - lwsl_ext("'%c' %d", *in, leap); - switch (leap) { - case LEAPS_SEEK_NAME: - if (*in == ' ') - break; - if (*in == ',') { - len = 1; - break; - } - match_map = (1 << count_options) - 1; - leap = LEAPS_EAT_NAME; - w = 0; - - /* fallthru */ - - case LEAPS_EAT_NAME: - oa.start = NULL; - oa.len = 0; - m = match_map; - n = 0; - pending_close_quote = 0; - while (m) { - if (m & 1) { - lwsl_ext(" m=%d, n=%d, w=%d\n", m, n, w); - - if (*in == opts[n].name[w]) { - if (!opts[n].name[w + 1]) { - oa.option_index = n; - lwsl_ext("hit %d\n", oa.option_index); - leap = LEAPS_SEEK_VAL; - if (len == 1) - goto set_arg; - break; - } - } else { - match_map &= ~(1 << n); - if (!match_map) { - lwsl_ext("empty match map\n"); - return -1; - } - } - } - m >>= 1; - n++; - } - w++; - break; - case LEAPS_SEEK_VAL: - if (*in == ' ') - break; - if (*in == ',') { - len = 1; - break; - } - if (*in == ';' || len == 1) { /* ie,nonoptional */ - if (opts[oa.option_index].type == EXTARG_DEC) - return -1; - leap = LEAPS_SEEK_NAME; - goto set_arg; - } - if (*in == '=') { - w = 0; - pending_close_quote = 0; - if (opts[oa.option_index].type == EXTARG_NONE) - return -1; - - leap = LEAPS_EAT_DEC; - break; - } - return -1; - - case LEAPS_EAT_DEC: - if (*in >= '0' && *in <= '9') { - if (!w) - oa.start = in; - w++; - if (len != 1) - break; - } - if (!w && *in =='"') { - pending_close_quote = 1; - break; - } - if (!w) - return -1; - if (pending_close_quote && *in != '"' && len != 1) - return -1; - leap = LEAPS_SEEK_ARG_TERM; - if (oa.start) - oa.len = in - oa.start; - if (len == 1) - oa.len++; - -set_arg: - ext->callback(lws_get_context(wsi), - ext, wsi, LWS_EXT_CB_OPTION_SET, - ext_user, (char *)&oa, 0); - if (len == 1) - break; - if (pending_close_quote && *in == '"') - break; - - /* fallthru */ - - case LEAPS_SEEK_ARG_TERM: - if (*in == ' ') - break; - if (*in == ';') { - leap = LEAPS_SEEK_NAME; - break; - } - if (*in == ',') { - len = 1; - break; - } - return -1; - } - len--; - in++; - } - - return 0; -} - - -/* 0 = nobody had nonzero return, 1 = somebody had positive return, -1 = fail */ - -int lws_ext_cb_active(struct lws *wsi, int reason, void *arg, int len) -{ - int n, m, handled = 0; - - for (n = 0; n < wsi->count_act_ext; n++) { - m = wsi->active_extensions[n]->callback(lws_get_context(wsi), - wsi->active_extensions[n], wsi, reason, - wsi->act_ext_user[n], arg, len); - if (m < 0) { - lwsl_ext("Ext '%s' failed to handle callback %d!\n", - wsi->active_extensions[n]->name, reason); - return -1; - } - /* valgrind... */ - if (reason == LWS_EXT_CB_DESTROY) - wsi->act_ext_user[n] = NULL; - if (m > handled) - handled = m; - } - - return handled; -} - -int lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi, - int reason, void *arg, int len) -{ - int n = 0, m, handled = 0; - const struct lws_extension *ext; - - if (!wsi || !wsi->vhost) - return 0; - - ext = wsi->vhost->extensions; - - while (ext && ext->callback && !handled) { - m = ext->callback(context, ext, wsi, reason, - (void *)(lws_intptr_t)n, arg, len); - if (m < 0) { - lwsl_ext("Ext '%s' failed to handle callback %d!\n", - wsi->active_extensions[n]->name, reason); - return -1; - } - if (m) - handled = 1; - - ext++; - n++; - } - - return 0; -} - -int -lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len) -{ - struct lws_tokens eff_buf; - int ret, m, n = 0; - - eff_buf.token = (char *)buf; - eff_buf.token_len = len; - - /* - * while we have original buf to spill ourselves, or extensions report - * more in their pipeline - */ - - ret = 1; - while (ret == 1) { - - /* default to nobody has more to spill */ - - ret = 0; - - /* show every extension the new incoming data */ - m = lws_ext_cb_active(wsi, - LWS_EXT_CB_PACKET_TX_PRESEND, &eff_buf, 0); - if (m < 0) - return -1; - if (m) /* handled */ - ret = 1; - - if ((char *)buf != eff_buf.token) - /* - * extension recreated it: - * need to buffer this if not all sent - */ - wsi->u.ws.clean_buffer = 0; - - /* assuming they left us something to send, send it */ - - if (eff_buf.token_len) { - n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token, - eff_buf.token_len); - if (n < 0) { - lwsl_info("closing from ext access\n"); - return -1; - } - - /* always either sent it all or privately buffered */ - if (wsi->u.ws.clean_buffer) - len = n; - } - - lwsl_parser("written %d bytes to client\n", n); - - /* no extension has more to spill? Then we can go */ - - if (!ret) - break; - - /* we used up what we had */ - - eff_buf.token = NULL; - eff_buf.token_len = 0; - - /* - * Did that leave the pipe choked? - * Or we had to hold on to some of it? - */ - - if (!lws_send_pipe_choked(wsi) && !wsi->trunc_len) - /* no we could add more, lets's do that */ - continue; - - lwsl_debug("choked\n"); - - /* - * Yes, he's choked. Don't spill the rest now get a callback - * when he is ready to send and take care of it there - */ - lws_callback_on_writable(wsi); - wsi->extension_data_pending = 1; - ret = 0; - } - - return len; -} - -int -lws_any_extension_handled(struct lws *wsi, enum lws_extension_callback_reasons r, - void *v, size_t len) -{ - struct lws_context *context = wsi->context; - int n, handled = 0; - - /* maybe an extension will take care of it for us */ - - for (n = 0; n < wsi->count_act_ext && !handled; n++) { - if (!wsi->active_extensions[n]->callback) - continue; - - handled |= wsi->active_extensions[n]->callback(context, - wsi->active_extensions[n], wsi, - r, wsi->act_ext_user[n], v, len); - } - - return handled; -} - -int -lws_set_extension_option(struct lws *wsi, const char *ext_name, - const char *opt_name, const char *opt_val) -{ - struct lws_ext_option_arg oa; - int idx = 0; - - /* first identify if the ext is active on this wsi */ - while (idx < wsi->count_act_ext && - strcmp(wsi->active_extensions[idx]->name, ext_name)) - idx++; - - if (idx == wsi->count_act_ext) - return -1; /* request ext not active on this wsi */ - - oa.option_name = opt_name; - oa.option_index = 0; - oa.start = opt_val; - oa.len = 0; - - return wsi->active_extensions[idx]->callback( - wsi->context, wsi->active_extensions[idx], wsi, - LWS_EXT_CB_NAMED_OPTION_SET, wsi->act_ext_user[idx], &oa, 0); -} |