1 #include "private-libwebsockets.h"
3 #include "extension-permessage-deflate.h"
6 lws_context_init_extensions(struct lws_context_creation_info *info,
7 struct lws_context *context)
9 context->extensions = info->extensions;
10 lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
13 enum lws_ext_option_parser_states {
22 lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi,
23 void *ext_user, const struct lws_ext_options *opts,
24 const char *in, int len)
26 enum lws_ext_option_parser_states leap = LEAPS_SEEK_NAME;
27 unsigned int match_map = 0, n, m, w = 0, count_options = 0,
28 pending_close_quote = 0;
29 struct lws_ext_option_arg oa;
31 while (opts[count_options].name)
34 lwsl_ext("'%c' %d", *in, leap);
43 match_map = (1 << count_options) - 1;
44 leap = LEAPS_EAT_NAME;
54 pending_close_quote = 0;
57 lwsl_ext(" m=%d, n=%d, w=%d\n", m, n, w);
59 if (*in == opts[n].name[w]) {
60 if (!opts[n].name[w + 1]) {
62 lwsl_ext("hit %d\n", oa.option_index);
63 leap = LEAPS_SEEK_VAL;
69 match_map &= ~(1 << n);
71 lwsl_ext("empty match map\n");
88 if (*in == ';' || len == 1) { /* ie,nonoptional */
89 if (opts[oa.option_index].type == EXTARG_DEC)
91 leap = LEAPS_SEEK_NAME;
96 pending_close_quote = 0;
97 if (opts[oa.option_index].type == EXTARG_NONE)
100 leap = LEAPS_EAT_DEC;
106 if (*in >= '0' && *in <= '9') {
113 if (!w && *in =='"') {
114 pending_close_quote = 1;
119 if (pending_close_quote && *in != '"' && len != 1)
121 leap = LEAPS_SEEK_ARG_TERM;
123 oa.len = in - oa.start;
128 ext->callback(lws_get_context(wsi),
129 ext, wsi, LWS_EXT_CB_OPTION_SET,
130 ext_user, (char *)&oa, 0);
133 if (pending_close_quote && *in == '"')
138 case LEAPS_SEEK_ARG_TERM:
142 leap = LEAPS_SEEK_NAME;
159 /* 0 = nobody had nonzero return, 1 = somebody had positive return, -1 = fail */
161 int lws_ext_cb_active(struct lws *wsi, int reason, void *arg, int len)
163 int n, m, handled = 0;
165 for (n = 0; n < wsi->count_act_ext; n++) {
166 m = wsi->active_extensions[n]->callback(lws_get_context(wsi),
167 wsi->active_extensions[n], wsi, reason,
168 wsi->act_ext_user[n], arg, len);
170 lwsl_ext("Ext '%s' failed to handle callback %d!\n",
171 wsi->active_extensions[n]->name, reason);
175 if (reason == LWS_EXT_CB_DESTROY)
176 wsi->act_ext_user[n] = NULL;
184 int lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi,
185 int reason, void *arg, int len)
187 int n = 0, m, handled = 0;
188 const struct lws_extension *ext = context->extensions;
190 while (ext && ext->callback && !handled) {
191 m = ext->callback(context, ext, wsi, reason,
192 (void *)(long)n, arg, len);
194 lwsl_ext("Ext '%s' failed to handle callback %d!\n",
195 wsi->active_extensions[n]->name, reason);
209 lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len)
211 struct lws_tokens eff_buf;
214 eff_buf.token = (char *)buf;
215 eff_buf.token_len = len;
218 * while we have original buf to spill ourselves, or extensions report
219 * more in their pipeline
225 /* default to nobody has more to spill */
229 /* show every extension the new incoming data */
230 m = lws_ext_cb_active(wsi,
231 LWS_EXT_CB_PACKET_TX_PRESEND, &eff_buf, 0);
237 if ((char *)buf != eff_buf.token)
239 * extension recreated it:
240 * need to buffer this if not all sent
242 wsi->u.ws.clean_buffer = 0;
244 /* assuming they left us something to send, send it */
246 if (eff_buf.token_len) {
247 n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
250 lwsl_info("closing from ext access\n");
254 /* always either sent it all or privately buffered */
255 if (wsi->u.ws.clean_buffer)
259 lwsl_parser("written %d bytes to client\n", n);
261 /* no extension has more to spill? Then we can go */
266 /* we used up what we had */
268 eff_buf.token = NULL;
269 eff_buf.token_len = 0;
272 * Did that leave the pipe choked?
273 * Or we had to hold on to some of it?
276 if (!lws_send_pipe_choked(wsi) && !wsi->trunc_len)
277 /* no we could add more, lets's do that */
280 lwsl_debug("choked\n");
283 * Yes, he's choked. Don't spill the rest now get a callback
284 * when he is ready to send and take care of it there
286 lws_callback_on_writable(wsi);
287 wsi->extension_data_pending = 1;
295 lws_any_extension_handled(struct lws *wsi, enum lws_extension_callback_reasons r,
298 struct lws_context *context = wsi->context;
301 /* maybe an extension will take care of it for us */
303 for (n = 0; n < wsi->count_act_ext && !handled; n++) {
304 if (!wsi->active_extensions[n]->callback)
307 handled |= wsi->active_extensions[n]->callback(context,
308 wsi->active_extensions[n], wsi,
309 r, wsi->act_ext_user[n], v, len);