{ 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_err(" 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_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_info("%s: option set: idx %d, %s, len %d\n", __func__,
+ 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 ||
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_err(" 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));
*((void **)user) = priv;
/* fill in pointer to options list */
if (in)
- *((const struct lws_ext_options **)in) = lws_ext_pm_deflate_options;
+ *((const struct lws_ext_options **)in) =
+ lws_ext_pm_deflate_options;
/* fallthru */
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:
* rx buffer by the caller, so this assumption is safe while
* we block new rx while draining the existing rx
*/
- if (eff_buf->token && eff_buf->token_len) {
+ 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;
}
* 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 witholding a byte), and he's otherwise working on
+ * 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.
*/
* 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 withold
+ * 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
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 %d\n",
+ "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, priv->count_rx_between_fin);
+ priv->rx.avail_in,
+ (unsigned long)priv->count_rx_between_fin);
if (was_fin) {
priv->count_rx_between_fin = 0;
case LWS_EXT_CB_PAYLOAD_TX:
- if (!priv->tx_init)
- if (deflateInit2(&priv->tx, priv->args[PMD_COMP_LEVEL],
+ if (!priv->tx_init) {
+ n = deflateInit2(&priv->tx, priv->args[PMD_COMP_LEVEL],
Z_DEFLATED,
- -priv->args[PMD_CLIENT_MAX_WINDOW_BITS +
- !wsi->context->listen_port],
+ -priv->args[PMD_SERVER_MAX_WINDOW_BITS +
+ (wsi->vhost->listen_port <= 0)],
priv->args[PMD_MEM_LEVEL],
- Z_DEFAULT_STRATEGY) != Z_OK) {
- lwsl_ext("inflateInit2 failed\n");
+ 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 +
break;
priv->compressed_out = 0;
- if ((*(eff_buf->token) & 0x80) && priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER]) {
+ 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;
}