1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker */
24*1c60b9acSAndroid Build Coastguard Worker
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker
27*1c60b9acSAndroid Build Coastguard Worker #include "extension-permessage-deflate.h"
28*1c60b9acSAndroid Build Coastguard Worker
29*1c60b9acSAndroid Build Coastguard Worker void
lws_context_init_extensions(const struct lws_context_creation_info * info,struct lws_context * context)30*1c60b9acSAndroid Build Coastguard Worker lws_context_init_extensions(const struct lws_context_creation_info *info,
31*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context)
32*1c60b9acSAndroid Build Coastguard Worker {
33*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(context, " LWS_MAX_EXTENSIONS_ACTIVE: %u", LWS_MAX_EXTENSIONS_ACTIVE);
34*1c60b9acSAndroid Build Coastguard Worker }
35*1c60b9acSAndroid Build Coastguard Worker
36*1c60b9acSAndroid Build Coastguard Worker enum lws_ext_option_parser_states {
37*1c60b9acSAndroid Build Coastguard Worker LEAPS_SEEK_NAME,
38*1c60b9acSAndroid Build Coastguard Worker LEAPS_EAT_NAME,
39*1c60b9acSAndroid Build Coastguard Worker LEAPS_SEEK_VAL,
40*1c60b9acSAndroid Build Coastguard Worker LEAPS_EAT_DEC,
41*1c60b9acSAndroid Build Coastguard Worker LEAPS_SEEK_ARG_TERM
42*1c60b9acSAndroid Build Coastguard Worker };
43*1c60b9acSAndroid Build Coastguard Worker
44*1c60b9acSAndroid Build Coastguard Worker int
lws_ext_parse_options(const struct lws_extension * ext,struct lws * wsi,void * ext_user,const struct lws_ext_options * opts,const char * in,int len)45*1c60b9acSAndroid Build Coastguard Worker lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi,
46*1c60b9acSAndroid Build Coastguard Worker void *ext_user, const struct lws_ext_options *opts,
47*1c60b9acSAndroid Build Coastguard Worker const char *in, int len)
48*1c60b9acSAndroid Build Coastguard Worker {
49*1c60b9acSAndroid Build Coastguard Worker enum lws_ext_option_parser_states leap = LEAPS_SEEK_NAME;
50*1c60b9acSAndroid Build Coastguard Worker unsigned int match_map = 0, n, m, w = 0, count_options = 0,
51*1c60b9acSAndroid Build Coastguard Worker pending_close_quote = 0;
52*1c60b9acSAndroid Build Coastguard Worker struct lws_ext_option_arg oa;
53*1c60b9acSAndroid Build Coastguard Worker
54*1c60b9acSAndroid Build Coastguard Worker oa.option_name = NULL;
55*1c60b9acSAndroid Build Coastguard Worker
56*1c60b9acSAndroid Build Coastguard Worker while (opts[count_options].name)
57*1c60b9acSAndroid Build Coastguard Worker count_options++;
58*1c60b9acSAndroid Build Coastguard Worker while (len) {
59*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "'%c' %d", *in, leap);
60*1c60b9acSAndroid Build Coastguard Worker switch (leap) {
61*1c60b9acSAndroid Build Coastguard Worker case LEAPS_SEEK_NAME:
62*1c60b9acSAndroid Build Coastguard Worker if (*in == ' ')
63*1c60b9acSAndroid Build Coastguard Worker break;
64*1c60b9acSAndroid Build Coastguard Worker if (*in == ',') {
65*1c60b9acSAndroid Build Coastguard Worker len = 1;
66*1c60b9acSAndroid Build Coastguard Worker break;
67*1c60b9acSAndroid Build Coastguard Worker }
68*1c60b9acSAndroid Build Coastguard Worker match_map = (unsigned int)(1 << count_options) - 1;
69*1c60b9acSAndroid Build Coastguard Worker leap = LEAPS_EAT_NAME;
70*1c60b9acSAndroid Build Coastguard Worker w = 0;
71*1c60b9acSAndroid Build Coastguard Worker
72*1c60b9acSAndroid Build Coastguard Worker /* fallthru */
73*1c60b9acSAndroid Build Coastguard Worker
74*1c60b9acSAndroid Build Coastguard Worker case LEAPS_EAT_NAME:
75*1c60b9acSAndroid Build Coastguard Worker oa.start = NULL;
76*1c60b9acSAndroid Build Coastguard Worker oa.len = 0;
77*1c60b9acSAndroid Build Coastguard Worker m = match_map;
78*1c60b9acSAndroid Build Coastguard Worker n = 0;
79*1c60b9acSAndroid Build Coastguard Worker pending_close_quote = 0;
80*1c60b9acSAndroid Build Coastguard Worker while (m) {
81*1c60b9acSAndroid Build Coastguard Worker if (!(m & 1)) {
82*1c60b9acSAndroid Build Coastguard Worker m >>= 1;
83*1c60b9acSAndroid Build Coastguard Worker n++;
84*1c60b9acSAndroid Build Coastguard Worker continue;
85*1c60b9acSAndroid Build Coastguard Worker }
86*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, " m=%d, n=%d, w=%d", m, n, w);
87*1c60b9acSAndroid Build Coastguard Worker
88*1c60b9acSAndroid Build Coastguard Worker if (*in == opts[n].name[w]) {
89*1c60b9acSAndroid Build Coastguard Worker if (!opts[n].name[w + 1]) {
90*1c60b9acSAndroid Build Coastguard Worker oa.option_index = (int)n;
91*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "hit %d",
92*1c60b9acSAndroid Build Coastguard Worker oa.option_index);
93*1c60b9acSAndroid Build Coastguard Worker leap = LEAPS_SEEK_VAL;
94*1c60b9acSAndroid Build Coastguard Worker if (len == 1)
95*1c60b9acSAndroid Build Coastguard Worker goto set_arg;
96*1c60b9acSAndroid Build Coastguard Worker break;
97*1c60b9acSAndroid Build Coastguard Worker }
98*1c60b9acSAndroid Build Coastguard Worker } else {
99*1c60b9acSAndroid Build Coastguard Worker match_map &= (unsigned int)~(1 << n);
100*1c60b9acSAndroid Build Coastguard Worker if (!match_map) {
101*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "empty match map");
102*1c60b9acSAndroid Build Coastguard Worker return -1;
103*1c60b9acSAndroid Build Coastguard Worker }
104*1c60b9acSAndroid Build Coastguard Worker }
105*1c60b9acSAndroid Build Coastguard Worker
106*1c60b9acSAndroid Build Coastguard Worker m >>= 1;
107*1c60b9acSAndroid Build Coastguard Worker n++;
108*1c60b9acSAndroid Build Coastguard Worker }
109*1c60b9acSAndroid Build Coastguard Worker w++;
110*1c60b9acSAndroid Build Coastguard Worker break;
111*1c60b9acSAndroid Build Coastguard Worker case LEAPS_SEEK_VAL:
112*1c60b9acSAndroid Build Coastguard Worker if (*in == ' ')
113*1c60b9acSAndroid Build Coastguard Worker break;
114*1c60b9acSAndroid Build Coastguard Worker if (*in == ',') {
115*1c60b9acSAndroid Build Coastguard Worker len = 1;
116*1c60b9acSAndroid Build Coastguard Worker break;
117*1c60b9acSAndroid Build Coastguard Worker }
118*1c60b9acSAndroid Build Coastguard Worker if (*in == ';' || len == 1) { /* ie,nonoptional */
119*1c60b9acSAndroid Build Coastguard Worker if (opts[oa.option_index].type == EXTARG_DEC)
120*1c60b9acSAndroid Build Coastguard Worker return -1;
121*1c60b9acSAndroid Build Coastguard Worker leap = LEAPS_SEEK_NAME;
122*1c60b9acSAndroid Build Coastguard Worker goto set_arg;
123*1c60b9acSAndroid Build Coastguard Worker }
124*1c60b9acSAndroid Build Coastguard Worker if (*in == '=') {
125*1c60b9acSAndroid Build Coastguard Worker w = 0;
126*1c60b9acSAndroid Build Coastguard Worker pending_close_quote = 0;
127*1c60b9acSAndroid Build Coastguard Worker if (opts[oa.option_index].type == EXTARG_NONE)
128*1c60b9acSAndroid Build Coastguard Worker return -1;
129*1c60b9acSAndroid Build Coastguard Worker
130*1c60b9acSAndroid Build Coastguard Worker leap = LEAPS_EAT_DEC;
131*1c60b9acSAndroid Build Coastguard Worker break;
132*1c60b9acSAndroid Build Coastguard Worker }
133*1c60b9acSAndroid Build Coastguard Worker return -1;
134*1c60b9acSAndroid Build Coastguard Worker
135*1c60b9acSAndroid Build Coastguard Worker case LEAPS_EAT_DEC:
136*1c60b9acSAndroid Build Coastguard Worker if (*in >= '0' && *in <= '9') {
137*1c60b9acSAndroid Build Coastguard Worker if (!w)
138*1c60b9acSAndroid Build Coastguard Worker oa.start = in;
139*1c60b9acSAndroid Build Coastguard Worker w++;
140*1c60b9acSAndroid Build Coastguard Worker if (len != 1)
141*1c60b9acSAndroid Build Coastguard Worker break;
142*1c60b9acSAndroid Build Coastguard Worker }
143*1c60b9acSAndroid Build Coastguard Worker if (!w && *in =='"') {
144*1c60b9acSAndroid Build Coastguard Worker pending_close_quote = 1;
145*1c60b9acSAndroid Build Coastguard Worker break;
146*1c60b9acSAndroid Build Coastguard Worker }
147*1c60b9acSAndroid Build Coastguard Worker if (!w)
148*1c60b9acSAndroid Build Coastguard Worker return -1;
149*1c60b9acSAndroid Build Coastguard Worker if (pending_close_quote && *in != '"' && len != 1)
150*1c60b9acSAndroid Build Coastguard Worker return -1;
151*1c60b9acSAndroid Build Coastguard Worker leap = LEAPS_SEEK_ARG_TERM;
152*1c60b9acSAndroid Build Coastguard Worker if (oa.start)
153*1c60b9acSAndroid Build Coastguard Worker oa.len = lws_ptr_diff(in, oa.start);
154*1c60b9acSAndroid Build Coastguard Worker if (len == 1)
155*1c60b9acSAndroid Build Coastguard Worker oa.len++;
156*1c60b9acSAndroid Build Coastguard Worker
157*1c60b9acSAndroid Build Coastguard Worker set_arg:
158*1c60b9acSAndroid Build Coastguard Worker ext->callback(lws_get_context(wsi),
159*1c60b9acSAndroid Build Coastguard Worker ext, wsi, LWS_EXT_CB_OPTION_SET,
160*1c60b9acSAndroid Build Coastguard Worker ext_user, (char *)&oa, 0);
161*1c60b9acSAndroid Build Coastguard Worker if (len == 1)
162*1c60b9acSAndroid Build Coastguard Worker break;
163*1c60b9acSAndroid Build Coastguard Worker if (pending_close_quote && *in == '"')
164*1c60b9acSAndroid Build Coastguard Worker break;
165*1c60b9acSAndroid Build Coastguard Worker
166*1c60b9acSAndroid Build Coastguard Worker /* fallthru */
167*1c60b9acSAndroid Build Coastguard Worker
168*1c60b9acSAndroid Build Coastguard Worker case LEAPS_SEEK_ARG_TERM:
169*1c60b9acSAndroid Build Coastguard Worker if (*in == ' ')
170*1c60b9acSAndroid Build Coastguard Worker break;
171*1c60b9acSAndroid Build Coastguard Worker if (*in == ';') {
172*1c60b9acSAndroid Build Coastguard Worker leap = LEAPS_SEEK_NAME;
173*1c60b9acSAndroid Build Coastguard Worker break;
174*1c60b9acSAndroid Build Coastguard Worker }
175*1c60b9acSAndroid Build Coastguard Worker if (*in == ',') {
176*1c60b9acSAndroid Build Coastguard Worker len = 1;
177*1c60b9acSAndroid Build Coastguard Worker break;
178*1c60b9acSAndroid Build Coastguard Worker }
179*1c60b9acSAndroid Build Coastguard Worker return -1;
180*1c60b9acSAndroid Build Coastguard Worker }
181*1c60b9acSAndroid Build Coastguard Worker len--;
182*1c60b9acSAndroid Build Coastguard Worker in++;
183*1c60b9acSAndroid Build Coastguard Worker }
184*1c60b9acSAndroid Build Coastguard Worker
185*1c60b9acSAndroid Build Coastguard Worker return 0;
186*1c60b9acSAndroid Build Coastguard Worker }
187*1c60b9acSAndroid Build Coastguard Worker
188*1c60b9acSAndroid Build Coastguard Worker
189*1c60b9acSAndroid Build Coastguard Worker /* 0 = nobody had nonzero return, 1 = somebody had positive return, -1 = fail */
190*1c60b9acSAndroid Build Coastguard Worker
lws_ext_cb_active(struct lws * wsi,int reason,void * arg,int len)191*1c60b9acSAndroid Build Coastguard Worker int lws_ext_cb_active(struct lws *wsi, int reason, void *arg, int len)
192*1c60b9acSAndroid Build Coastguard Worker {
193*1c60b9acSAndroid Build Coastguard Worker int n, m, handled = 0;
194*1c60b9acSAndroid Build Coastguard Worker
195*1c60b9acSAndroid Build Coastguard Worker if (!wsi->ws)
196*1c60b9acSAndroid Build Coastguard Worker return 0;
197*1c60b9acSAndroid Build Coastguard Worker
198*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < wsi->ws->count_act_ext; n++) {
199*1c60b9acSAndroid Build Coastguard Worker m = wsi->ws->active_extensions[n]->callback(
200*1c60b9acSAndroid Build Coastguard Worker lws_get_context(wsi), wsi->ws->active_extensions[n],
201*1c60b9acSAndroid Build Coastguard Worker wsi, (enum lws_extension_callback_reasons)reason, wsi->ws->act_ext_user[n], arg, (size_t)len);
202*1c60b9acSAndroid Build Coastguard Worker if (m < 0) {
203*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "Ext '%s' failed to handle callback %d!",
204*1c60b9acSAndroid Build Coastguard Worker wsi->ws->active_extensions[n]->name, reason);
205*1c60b9acSAndroid Build Coastguard Worker return -1;
206*1c60b9acSAndroid Build Coastguard Worker }
207*1c60b9acSAndroid Build Coastguard Worker /* valgrind... */
208*1c60b9acSAndroid Build Coastguard Worker if (reason == LWS_EXT_CB_DESTROY)
209*1c60b9acSAndroid Build Coastguard Worker wsi->ws->act_ext_user[n] = NULL;
210*1c60b9acSAndroid Build Coastguard Worker if (m > handled)
211*1c60b9acSAndroid Build Coastguard Worker handled = m;
212*1c60b9acSAndroid Build Coastguard Worker }
213*1c60b9acSAndroid Build Coastguard Worker
214*1c60b9acSAndroid Build Coastguard Worker return handled;
215*1c60b9acSAndroid Build Coastguard Worker }
216*1c60b9acSAndroid Build Coastguard Worker
lws_ext_cb_all_exts(struct lws_context * context,struct lws * wsi,int reason,void * arg,int len)217*1c60b9acSAndroid Build Coastguard Worker int lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi,
218*1c60b9acSAndroid Build Coastguard Worker int reason, void *arg, int len)
219*1c60b9acSAndroid Build Coastguard Worker {
220*1c60b9acSAndroid Build Coastguard Worker int n = 0, m, handled = 0;
221*1c60b9acSAndroid Build Coastguard Worker const struct lws_extension *ext;
222*1c60b9acSAndroid Build Coastguard Worker
223*1c60b9acSAndroid Build Coastguard Worker if (!wsi || !wsi->a.vhost || !wsi->ws)
224*1c60b9acSAndroid Build Coastguard Worker return 0;
225*1c60b9acSAndroid Build Coastguard Worker
226*1c60b9acSAndroid Build Coastguard Worker ext = wsi->a.vhost->ws.extensions;
227*1c60b9acSAndroid Build Coastguard Worker
228*1c60b9acSAndroid Build Coastguard Worker while (ext && ext->callback && !handled) {
229*1c60b9acSAndroid Build Coastguard Worker m = ext->callback(context, ext, wsi, (enum lws_extension_callback_reasons)reason,
230*1c60b9acSAndroid Build Coastguard Worker (void *)(lws_intptr_t)n, arg, (size_t)len);
231*1c60b9acSAndroid Build Coastguard Worker if (m < 0) {
232*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "Ext '%s' failed to handle callback %d!",
233*1c60b9acSAndroid Build Coastguard Worker wsi->ws->active_extensions[n]->name, reason);
234*1c60b9acSAndroid Build Coastguard Worker return -1;
235*1c60b9acSAndroid Build Coastguard Worker }
236*1c60b9acSAndroid Build Coastguard Worker if (m)
237*1c60b9acSAndroid Build Coastguard Worker handled = 1;
238*1c60b9acSAndroid Build Coastguard Worker
239*1c60b9acSAndroid Build Coastguard Worker ext++;
240*1c60b9acSAndroid Build Coastguard Worker n++;
241*1c60b9acSAndroid Build Coastguard Worker }
242*1c60b9acSAndroid Build Coastguard Worker
243*1c60b9acSAndroid Build Coastguard Worker return 0;
244*1c60b9acSAndroid Build Coastguard Worker }
245*1c60b9acSAndroid Build Coastguard Worker
246*1c60b9acSAndroid Build Coastguard Worker int
lws_issue_raw_ext_access(struct lws * wsi,unsigned char * buf,size_t len)247*1c60b9acSAndroid Build Coastguard Worker lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len)
248*1c60b9acSAndroid Build Coastguard Worker {
249*1c60b9acSAndroid Build Coastguard Worker struct lws_tokens ebuf;
250*1c60b9acSAndroid Build Coastguard Worker int ret, m, n = 0;
251*1c60b9acSAndroid Build Coastguard Worker
252*1c60b9acSAndroid Build Coastguard Worker ebuf.token = buf;
253*1c60b9acSAndroid Build Coastguard Worker ebuf.len = (int)len;
254*1c60b9acSAndroid Build Coastguard Worker
255*1c60b9acSAndroid Build Coastguard Worker /*
256*1c60b9acSAndroid Build Coastguard Worker * while we have original buf to spill ourselves, or extensions report
257*1c60b9acSAndroid Build Coastguard Worker * more in their pipeline
258*1c60b9acSAndroid Build Coastguard Worker */
259*1c60b9acSAndroid Build Coastguard Worker
260*1c60b9acSAndroid Build Coastguard Worker ret = 1;
261*1c60b9acSAndroid Build Coastguard Worker while (ret == 1) {
262*1c60b9acSAndroid Build Coastguard Worker
263*1c60b9acSAndroid Build Coastguard Worker /* default to nobody has more to spill */
264*1c60b9acSAndroid Build Coastguard Worker
265*1c60b9acSAndroid Build Coastguard Worker ret = 0;
266*1c60b9acSAndroid Build Coastguard Worker
267*1c60b9acSAndroid Build Coastguard Worker /* show every extension the new incoming data */
268*1c60b9acSAndroid Build Coastguard Worker m = lws_ext_cb_active(wsi, LWS_EXT_CB_PACKET_TX_PRESEND,
269*1c60b9acSAndroid Build Coastguard Worker &ebuf, 0);
270*1c60b9acSAndroid Build Coastguard Worker if (m < 0)
271*1c60b9acSAndroid Build Coastguard Worker return -1;
272*1c60b9acSAndroid Build Coastguard Worker if (m) /* handled */
273*1c60b9acSAndroid Build Coastguard Worker ret = 1;
274*1c60b9acSAndroid Build Coastguard Worker
275*1c60b9acSAndroid Build Coastguard Worker if (buf != ebuf.token)
276*1c60b9acSAndroid Build Coastguard Worker /*
277*1c60b9acSAndroid Build Coastguard Worker * extension recreated it:
278*1c60b9acSAndroid Build Coastguard Worker * need to buffer this if not all sent
279*1c60b9acSAndroid Build Coastguard Worker */
280*1c60b9acSAndroid Build Coastguard Worker wsi->ws->clean_buffer = 0;
281*1c60b9acSAndroid Build Coastguard Worker
282*1c60b9acSAndroid Build Coastguard Worker /* assuming they left us something to send, send it */
283*1c60b9acSAndroid Build Coastguard Worker
284*1c60b9acSAndroid Build Coastguard Worker if (ebuf.len) {
285*1c60b9acSAndroid Build Coastguard Worker n = lws_issue_raw(wsi, ebuf.token, (size_t)ebuf.len);
286*1c60b9acSAndroid Build Coastguard Worker if (n < 0) {
287*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "closing from ext access");
288*1c60b9acSAndroid Build Coastguard Worker return -1;
289*1c60b9acSAndroid Build Coastguard Worker }
290*1c60b9acSAndroid Build Coastguard Worker
291*1c60b9acSAndroid Build Coastguard Worker /* always either sent it all or privately buffered */
292*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->clean_buffer)
293*1c60b9acSAndroid Build Coastguard Worker len = (size_t)n;
294*1c60b9acSAndroid Build Coastguard Worker
295*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "written %d bytes to client", n);
296*1c60b9acSAndroid Build Coastguard Worker }
297*1c60b9acSAndroid Build Coastguard Worker
298*1c60b9acSAndroid Build Coastguard Worker /* no extension has more to spill? Then we can go */
299*1c60b9acSAndroid Build Coastguard Worker
300*1c60b9acSAndroid Build Coastguard Worker if (!ret)
301*1c60b9acSAndroid Build Coastguard Worker break;
302*1c60b9acSAndroid Build Coastguard Worker
303*1c60b9acSAndroid Build Coastguard Worker /* we used up what we had */
304*1c60b9acSAndroid Build Coastguard Worker
305*1c60b9acSAndroid Build Coastguard Worker ebuf.token = NULL;
306*1c60b9acSAndroid Build Coastguard Worker ebuf.len = 0;
307*1c60b9acSAndroid Build Coastguard Worker
308*1c60b9acSAndroid Build Coastguard Worker /*
309*1c60b9acSAndroid Build Coastguard Worker * Did that leave the pipe choked?
310*1c60b9acSAndroid Build Coastguard Worker * Or we had to hold on to some of it?
311*1c60b9acSAndroid Build Coastguard Worker */
312*1c60b9acSAndroid Build Coastguard Worker
313*1c60b9acSAndroid Build Coastguard Worker if (!lws_send_pipe_choked(wsi) && !lws_has_buffered_out(wsi))
314*1c60b9acSAndroid Build Coastguard Worker /* no we could add more, lets's do that */
315*1c60b9acSAndroid Build Coastguard Worker continue;
316*1c60b9acSAndroid Build Coastguard Worker
317*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "choked");
318*1c60b9acSAndroid Build Coastguard Worker
319*1c60b9acSAndroid Build Coastguard Worker /*
320*1c60b9acSAndroid Build Coastguard Worker * Yes, he's choked. Don't spill the rest now get a callback
321*1c60b9acSAndroid Build Coastguard Worker * when he is ready to send and take care of it there
322*1c60b9acSAndroid Build Coastguard Worker */
323*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
324*1c60b9acSAndroid Build Coastguard Worker wsi->ws->extension_data_pending = 1;
325*1c60b9acSAndroid Build Coastguard Worker ret = 0;
326*1c60b9acSAndroid Build Coastguard Worker }
327*1c60b9acSAndroid Build Coastguard Worker
328*1c60b9acSAndroid Build Coastguard Worker return (int)len;
329*1c60b9acSAndroid Build Coastguard Worker }
330*1c60b9acSAndroid Build Coastguard Worker
331*1c60b9acSAndroid Build Coastguard Worker int
lws_any_extension_handled(struct lws * wsi,enum lws_extension_callback_reasons r,void * v,size_t len)332*1c60b9acSAndroid Build Coastguard Worker lws_any_extension_handled(struct lws *wsi, enum lws_extension_callback_reasons r,
333*1c60b9acSAndroid Build Coastguard Worker void *v, size_t len)
334*1c60b9acSAndroid Build Coastguard Worker {
335*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = wsi->a.context;
336*1c60b9acSAndroid Build Coastguard Worker int n, handled = 0;
337*1c60b9acSAndroid Build Coastguard Worker
338*1c60b9acSAndroid Build Coastguard Worker if (!wsi->ws)
339*1c60b9acSAndroid Build Coastguard Worker return 0;
340*1c60b9acSAndroid Build Coastguard Worker
341*1c60b9acSAndroid Build Coastguard Worker /* maybe an extension will take care of it for us */
342*1c60b9acSAndroid Build Coastguard Worker
343*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < wsi->ws->count_act_ext && !handled; n++) {
344*1c60b9acSAndroid Build Coastguard Worker if (!wsi->ws->active_extensions[n]->callback)
345*1c60b9acSAndroid Build Coastguard Worker continue;
346*1c60b9acSAndroid Build Coastguard Worker
347*1c60b9acSAndroid Build Coastguard Worker handled |= wsi->ws->active_extensions[n]->callback(context,
348*1c60b9acSAndroid Build Coastguard Worker wsi->ws->active_extensions[n], wsi,
349*1c60b9acSAndroid Build Coastguard Worker r, wsi->ws->act_ext_user[n], v, len);
350*1c60b9acSAndroid Build Coastguard Worker }
351*1c60b9acSAndroid Build Coastguard Worker
352*1c60b9acSAndroid Build Coastguard Worker return handled;
353*1c60b9acSAndroid Build Coastguard Worker }
354*1c60b9acSAndroid Build Coastguard Worker
355*1c60b9acSAndroid Build Coastguard Worker int
lws_set_extension_option(struct lws * wsi,const char * ext_name,const char * opt_name,const char * opt_val)356*1c60b9acSAndroid Build Coastguard Worker lws_set_extension_option(struct lws *wsi, const char *ext_name,
357*1c60b9acSAndroid Build Coastguard Worker const char *opt_name, const char *opt_val)
358*1c60b9acSAndroid Build Coastguard Worker {
359*1c60b9acSAndroid Build Coastguard Worker struct lws_ext_option_arg oa;
360*1c60b9acSAndroid Build Coastguard Worker int idx = 0;
361*1c60b9acSAndroid Build Coastguard Worker
362*1c60b9acSAndroid Build Coastguard Worker if (!wsi->ws)
363*1c60b9acSAndroid Build Coastguard Worker return 0;
364*1c60b9acSAndroid Build Coastguard Worker
365*1c60b9acSAndroid Build Coastguard Worker /* first identify if the ext is active on this wsi */
366*1c60b9acSAndroid Build Coastguard Worker while (idx < wsi->ws->count_act_ext &&
367*1c60b9acSAndroid Build Coastguard Worker strcmp(wsi->ws->active_extensions[idx]->name, ext_name))
368*1c60b9acSAndroid Build Coastguard Worker idx++;
369*1c60b9acSAndroid Build Coastguard Worker
370*1c60b9acSAndroid Build Coastguard Worker if (idx == wsi->ws->count_act_ext)
371*1c60b9acSAndroid Build Coastguard Worker return -1; /* request ext not active on this wsi */
372*1c60b9acSAndroid Build Coastguard Worker
373*1c60b9acSAndroid Build Coastguard Worker oa.option_name = opt_name;
374*1c60b9acSAndroid Build Coastguard Worker oa.option_index = 0;
375*1c60b9acSAndroid Build Coastguard Worker oa.start = opt_val;
376*1c60b9acSAndroid Build Coastguard Worker oa.len = 0;
377*1c60b9acSAndroid Build Coastguard Worker
378*1c60b9acSAndroid Build Coastguard Worker return wsi->ws->active_extensions[idx]->callback(wsi->a.context,
379*1c60b9acSAndroid Build Coastguard Worker wsi->ws->active_extensions[idx], wsi,
380*1c60b9acSAndroid Build Coastguard Worker LWS_EXT_CB_NAMED_OPTION_SET, wsi->ws->act_ext_user[idx],
381*1c60b9acSAndroid Build Coastguard Worker &oa, 0);
382*1c60b9acSAndroid Build Coastguard Worker }
383