callback each active extension on packet tx pre send

Signed-off-by: Andy Green <andy@warmcat.com>
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index a8f2cf1..ec71d79 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -413,6 +413,111 @@
 	return 0;
 }
 
+static int
+lws_handle_POLLOUT_event(struct libwebsocket_context *context,
+				struct libwebsocket *wsi, struct pollfd *pollfd)
+{
+	struct lws_tokens eff_buf;
+	int n;
+	int ret;
+	int m;
+
+	if (!wsi->extension_data_pending)
+		goto user_service;
+
+	/*
+	 * check in on the active extensions, see if they
+	 * had pending stuff to spill... they need to get the
+	 * first look-in otherwise sequence will be disordered
+	 *
+	 * NULL, zero-length eff_buf means just spill pending
+	 */
+
+	ret = 1;
+	while (ret == 1) {
+
+		/* default to nobody has more to spill */
+
+		ret = 0;
+		eff_buf.token = NULL;
+		eff_buf.token_len = 0;
+
+		/* give every extension a chance to spill */
+
+		for (n = 0; n < wsi->count_active_extensions; n++) {
+			m = wsi->active_extensions[n]->callback(
+				wsi->protocol->owning_server, wsi,
+					LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
+				   wsi->active_extensions_user[n], &eff_buf, 0);
+			if (m < 0) {
+				fprintf(stderr, "extension reports fatal error\n");
+				return -1;
+			}
+			if (m)
+				/*
+				 * at least one extension told us he has more
+				 * to spill, so we will go around again after
+				 */
+				ret = 1;
+		}
+
+		/* assuming they gave 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))
+				return -1;
+		} else
+			continue;
+
+		/* no extension has more to spill */
+
+		if (!ret)
+			continue;
+
+		/*
+		 * There's more to spill from an extension, but we just sent
+		 * something... did that leave the pipe choked?
+		 */
+
+		if (!lws_send_pipe_choked(wsi))
+			/* no we could add more */
+			continue;
+
+		fprintf(stderr, "choked in POLLOUT service\n");
+
+		/*
+		 * Yes, he's choked.  Leave the POLLOUT masked on so we will
+		 * come back here when he is unchoked.  Don't call the user
+		 * callback to enforce ordering of spilling, he'll get called
+		 * when we come back here and there's nothing more to spill.
+		 */
+
+		return 0;
+	}
+
+	wsi->extension_data_pending = 0;
+
+user_service:
+	/* one shot */
+
+	pollfd->events &= ~POLLOUT;
+
+	/* external POLL support via protocol 0 */
+	context->protocols[0].callback(context, wsi,
+		LWS_CALLBACK_CLEAR_MODE_POLL_FD,
+		(void *)(long)wsi->sock, NULL, POLLOUT);
+
+	wsi->protocol->callback(context, wsi,
+		LWS_CALLBACK_CLIENT_WRITEABLE,
+		wsi->user_space,
+		NULL, 0);
+
+	return 0;
+}
+
+
+
 /**
  * libwebsocket_service_fd() - Service polled socket with something waiting
  * @context:	Websocket context
@@ -428,7 +533,7 @@
 libwebsocket_service_fd(struct libwebsocket_context *context,
 							  struct pollfd *pollfd)
 {
-	unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_BROADCAST_PAYLOAD +
+	unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 + MAX_BROADCAST_PAYLOAD +
 						  LWS_SEND_BUFFER_POST_PADDING];
 	struct libwebsocket *wsi;
 	struct libwebsocket *new_wsi;
@@ -712,24 +817,17 @@
 			return 1;
 		}
 
-		/* the guy requested a callback when it was OK to write */
+		/*
+		 * either extension code with stuff to spill, or the user code,
+		 * requested a callback when it was OK to write
+		 */
 
-		if (pollfd->revents & POLLOUT) {
-
-			/* one shot */
-
-			pollfd->events &= ~POLLOUT;
-
-			/* external POLL support via protocol 0 */
-			context->protocols[0].callback(context, wsi,
-				LWS_CALLBACK_CLEAR_MODE_POLL_FD,
-				(void *)(long)wsi->sock, NULL, POLLOUT);
-
-			wsi->protocol->callback(context, wsi,
-				LWS_CALLBACK_CLIENT_WRITEABLE,
-				wsi->user_space,
-				NULL, 0);
-		}
+		if (pollfd->revents & POLLOUT)
+			if (lws_handle_POLLOUT_event(context, wsi, pollfd) < 0) {
+				libwebsocket_close_and_free_session(context, wsi,
+						       LWS_CLOSE_STATUS_NORMAL);
+				return 1;
+			}
 
 		/* any incoming data ready? */
 
@@ -1397,20 +1495,13 @@
 
 		/* the guy requested a callback when it was OK to write */
 
-		if (pollfd->revents & POLLOUT) {
+		if (pollfd->revents & POLLOUT)
+			if (lws_handle_POLLOUT_event(context, wsi, pollfd) < 0) {
+				libwebsocket_close_and_free_session(context, wsi,
+						       LWS_CLOSE_STATUS_NORMAL);
+				return 1;
+			}
 
-			pollfd->events &= ~POLLOUT;
-
-			/* external POLL support via protocol 0 */
-			context->protocols[0].callback(context, wsi,
-				LWS_CALLBACK_CLEAR_MODE_POLL_FD,
-				(void *)(long)wsi->sock, NULL, POLLOUT);
-
-			wsi->protocol->callback(context, wsi,
-				LWS_CALLBACK_CLIENT_WRITEABLE,
-				wsi->user_space,
-				NULL, 0);
-		}
 
 		/* any incoming data ready? */