From c44159fb3a76ebc55554f3559c03baa2d8cdc69d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 7 Mar 2011 07:08:18 +0000 Subject: [PATCH] flush extensions when closing 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 --- lib/extension-deflate-stream.c | 7 ++++++- lib/libwebsockets.c | 46 ++++++++++++++++++++++++++++++++++++++++++ lib/libwebsockets.h | 1 + 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/lib/extension-deflate-stream.c b/lib/extension-deflate-stream.c index 8d439df..7ea7c04 100644 --- a/lib/extension-deflate-stream.c +++ b/lib/extension-deflate-stream.c @@ -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 diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index fdfaa46..6e36ff1 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -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 diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 23adf3a..c3096c9 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -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 { -- 2.7.4