pmd: autobahn fixes
[platform/upstream/libwebsockets.git] / lib / extension-permessage-deflate.c
index e23f4ed..f027e1f 100644 (file)
@@ -41,6 +41,28 @@ const struct lws_ext_options lws_ext_pm_deflate_options[] = {
        { 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,
@@ -56,15 +78,35 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
        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 ||
@@ -75,6 +117,17 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
 
        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;
@@ -83,7 +136,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
 
                /* 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 */
 
@@ -102,6 +156,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
                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:
@@ -149,7 +205,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
                 * 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;
                }
@@ -197,7 +253,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
                 * 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.
                 */
@@ -232,7 +288,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
                 * 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
@@ -250,9 +306,10 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
                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;
@@ -271,16 +328,18 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
 
        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 +
@@ -382,7 +441,9 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
                        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;
                }