about summary refs log tree commit diff
path: root/src/engine/external/libwebsockets/extension.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/external/libwebsockets/extension.c')
-rw-r--r--src/engine/external/libwebsockets/extension.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/engine/external/libwebsockets/extension.c b/src/engine/external/libwebsockets/extension.c
new file mode 100644
index 00000000..b7a5792b
--- /dev/null
+++ b/src/engine/external/libwebsockets/extension.c
@@ -0,0 +1,208 @@
+#include "private-libwebsockets.h"
+
+#include "extension-deflate-frame.h"
+#include "extension-deflate-stream.h"
+
+struct libwebsocket_extension libwebsocket_internal_extensions[] = {
+#ifdef LWS_EXT_DEFLATE_STREAM
+	{
+		"deflate-stream",
+		lws_extension_callback_deflate_stream,
+		sizeof(struct lws_ext_deflate_stream_conn)
+	},
+#else
+	{
+		"x-webkit-deflate-frame",
+		lws_extension_callback_deflate_frame,
+		sizeof(struct lws_ext_deflate_frame_conn)
+	},
+	{
+		"deflate-frame",
+		lws_extension_callback_deflate_frame,
+		sizeof(struct lws_ext_deflate_frame_conn)
+	},
+#endif
+	{ /* terminator */
+		NULL, NULL, 0
+	}
+};
+
+LWS_VISIBLE void
+lws_context_init_extensions(struct lws_context_creation_info *info,
+				    struct libwebsocket_context *context)
+{
+	context->extensions = info->extensions;
+	lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
+}
+
+LWS_VISIBLE struct libwebsocket_extension *libwebsocket_get_internal_extensions()
+{
+	return libwebsocket_internal_extensions;
+}
+
+
+/* 0 = nobody had nonzero return, 1 = somebody had positive return, -1 = fail */
+
+int lws_ext_callback_for_each_active(struct libwebsocket *wsi, int reason,
+				void *arg, int len)
+{
+	int n, m, handled = 0;
+
+	for (n = 0; n < wsi->count_active_extensions; n++) {
+		m = wsi->active_extensions[n]->callback(
+			wsi->protocol->owning_server,
+			wsi->active_extensions[n], wsi,
+			reason,
+			wsi->active_extensions_user[n],
+			arg, len);
+		if (m < 0) {
+			lwsl_ext(
+			 "Extension '%s' failed to handle callback %d!\n",
+				      wsi->active_extensions[n]->name, reason);
+			return -1;
+		}
+		if (m > handled)
+			handled = m;
+	}
+	
+	return handled;
+}
+
+int lws_ext_callback_for_each_extension_type(
+		struct libwebsocket_context *context, struct libwebsocket *wsi,
+				int reason, void *arg, int len)
+{
+	int n = 0, m, handled = 0;
+	struct libwebsocket_extension *ext = context->extensions;
+
+	while (ext && ext->callback && !handled) {
+		m = ext->callback(context, ext, wsi, reason,
+						(void *)(long)n, arg, len);
+		if (m < 0) {
+			lwsl_ext(
+			 "Extension '%s' failed to handle callback %d!\n",
+				      wsi->active_extensions[n]->name, reason);
+			return -1;
+		}
+		if (m)
+			handled = 1;
+
+		ext++;
+		n++;
+	}
+	
+	return 0;
+}
+
+int
+lws_issue_raw_ext_access(struct libwebsocket *wsi,
+						 unsigned char *buf, size_t len)
+{
+	int ret;
+	struct lws_tokens eff_buf;
+	int m;
+	int n = 0;
+
+	eff_buf.token = (char *)buf;
+	eff_buf.token_len = len;
+
+	/*
+	 * while we have original buf to spill ourselves, or extensions report
+	 * more in their pipeline
+	 */
+
+	ret = 1;
+	while (ret == 1) {
+
+		/* default to nobody has more to spill */
+
+		ret = 0;
+
+		/* show every extension the new incoming data */
+		m = lws_ext_callback_for_each_active(wsi,
+			       LWS_EXT_CALLBACK_PACKET_TX_PRESEND, &eff_buf, 0);
+		if (m < 0)
+			return -1;
+		if (m) /* handled */
+			ret = 1;
+
+		if ((char *)buf != eff_buf.token)
+			/*
+			 * extension recreated it:
+			 * need to buffer this if not all sent
+			 */
+			wsi->u.ws.clean_buffer = 0;
+
+		/* assuming they left us something to send, send it */
+
+		if (eff_buf.token_len) {
+			n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
+							    eff_buf.token_len);
+			if (n < 0) {
+				lwsl_info("closing from ext access\n");
+				return -1;
+			}
+
+			/* always either sent it all or privately buffered */
+			if (wsi->u.ws.clean_buffer)
+				len = n;
+		}
+
+		lwsl_parser("written %d bytes to client\n", n);
+
+		/* no extension has more to spill?  Then we can go */
+
+		if (!ret)
+			break;
+
+		/* we used up what we had */
+
+		eff_buf.token = NULL;
+		eff_buf.token_len = 0;
+
+		/*
+		 * Did that leave the pipe choked?
+		 * Or we had to hold on to some of it?
+		 */
+
+		if (!lws_send_pipe_choked(wsi) && !wsi->truncated_send_len)
+			/* no we could add more, lets's do that */
+			continue;
+
+		lwsl_debug("choked\n");
+
+		/*
+		 * Yes, he's choked.  Don't spill the rest now get a callback
+		 * when he is ready to send and take care of it there
+		 */
+		libwebsocket_callback_on_writable(
+					     wsi->protocol->owning_server, wsi);
+		wsi->extension_data_pending = 1;
+		ret = 0;
+	}
+
+	return len;
+}
+
+int
+lws_any_extension_handled(struct libwebsocket_context *context,
+			  struct libwebsocket *wsi,
+			  enum libwebsocket_extension_callback_reasons r,
+						       void *v, size_t len)
+{
+	int n;
+	int handled = 0;
+
+	/* maybe an extension will take care of it for us */
+
+	for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
+		if (!wsi->active_extensions[n]->callback)
+			continue;
+
+		handled |= wsi->active_extensions[n]->callback(context,
+			wsi->active_extensions[n], wsi,
+			r, wsi->active_extensions_user[n], v, len);
+	}
+
+	return handled;
+}