207 lines
4.5 KiB
C
207 lines
4.5 KiB
C
#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;
|
|
|
|
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 */
|
|
}
|
|
|
|
lwsl_parser("written %d bytes to client\n", eff_buf.token_len);
|
|
|
|
/* 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;
|
|
}
|