flush extensions when closing
authorAndy Green <andy@warmcat.com>
Mon, 7 Mar 2011 07:08:18 +0000 (07:08 +0000)
committerAndy Green <andy@warmcat.com>
Mon, 7 Mar 2011 07:08:18 +0000 (07:08 +0000)
Extensions might be caching stuff that we should spill before a controlled close.
It's not allowed to send anything on the wire after the close request, so we need
to make the extensions spill just before.

Signed-off-by: Andy Green <andy@warmcat.com>
lib/extension-deflate-stream.c
lib/libwebsockets.c
lib/libwebsockets.h

index 8d439df..7ea7c04 100644 (file)
@@ -91,6 +91,7 @@ int lws_extension_callback_deflate_stream(
 
                return 0;
 
+       case LWS_EXT_CALLBACK_FLUSH_PENDING_TX:
        case LWS_EXT_CALLBACK_PACKET_TX_PRESEND:
 
                /*
@@ -103,7 +104,11 @@ int lws_extension_callback_deflate_stream(
                conn->zs_out.next_out = conn->buf;
                conn->zs_out.avail_out = sizeof(conn->buf);
 
-               n = deflate(&conn->zs_out, Z_PARTIAL_FLUSH);
+               n = Z_PARTIAL_FLUSH;
+               if (reason == LWS_EXT_CALLBACK_FLUSH_PENDING_TX)
+                       n = Z_FULL_FLUSH;
+
+               n = deflate(&conn->zs_out, n);
                if (n == Z_STREAM_ERROR) {
                        /*
                         * screwed.. close the connection... we will get a
index fdfaa46..6e36ff1 100644 (file)
@@ -149,6 +149,9 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
        int old_state;
        unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
                                                  LWS_SEND_BUFFER_POST_PADDING];
+       int ret;
+       int m;
+       struct lws_tokens eff_buf;
 
        if (!wsi)
                return;
@@ -161,6 +164,48 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
        wsi->close_reason = reason;
 
        /*
+        * flush any tx pending from extensions, since we may send close packet
+        * if there are problems with send, just nuke the connection
+        */
+
+       ret = 1;
+       while (ret == 1) {
+
+               /* default to nobody has more to spill */
+
+               ret = 0;
+               eff_buf.token = NULL;
+               eff_buf.token_len = 0;
+
+               /* show every extension the new incoming data */
+
+               for (n = 0; n < wsi->count_active_extensions; n++) {
+                       m = wsi->active_extensions[n]->callback(
+                               wsi->protocol->owning_server, wsi,
+                                       LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
+                                  wsi->active_extensions_user[n], &eff_buf, 0);
+                       if (m < 0) {
+                               fprintf(stderr, "Extension reports "
+                                                              "fatal error\n");
+                               goto just_kill_connection;
+                       }
+                       if (m)
+                               /*
+                                * at least one extension told us he has more
+                                * to spill, so we will go around again after
+                                */
+                               ret = 1;
+               }
+
+               /* assuming they left us something to send, send it */
+
+               if (eff_buf.token_len)
+                       if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
+                                                            eff_buf.token_len))
+                               goto just_kill_connection;
+       }
+
+       /*
         * signal we are closing, libsocket_write will
         * add any necessary version-specific stuff.  If the write fails,
         * no worries we are closing anyway.  If we didn't initiate this
@@ -197,6 +242,7 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
                /* else, the send failed and we should just hang up */
        }
 
+just_kill_connection:
        /*
         * we won't be servicing or receiving anything further from this guy
         * remove this fd from wsi mapping hashtable
index 23adf3a..c3096c9 100644 (file)
@@ -78,6 +78,7 @@ enum libwebsocket_extension_callback_reasons {
        LWS_EXT_CALLBACK_DESTROY,
        LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
        LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
+       LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
 };
 
 enum libwebsocket_write_protocol {