xref: /aosp_15_r20/external/libwebsockets/lib/roles/ws/ext/extension.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
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