xref: /aosp_15_r20/external/libwebsockets/lib/roles/ws/server-ws.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 #define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
28*1c60b9acSAndroid Build Coastguard Worker 
29*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
30*1c60b9acSAndroid Build Coastguard Worker static int
lws_extension_server_handshake(struct lws * wsi,char ** p,int budget)31*1c60b9acSAndroid Build Coastguard Worker lws_extension_server_handshake(struct lws *wsi, char **p, int budget)
32*1c60b9acSAndroid Build Coastguard Worker {
33*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context = wsi->a.context;
34*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
35*1c60b9acSAndroid Build Coastguard Worker 	char ext_name[64], *args, *end = (*p) + budget - 1;
36*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_ext_options *opts, *po;
37*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_extension *ext;
38*1c60b9acSAndroid Build Coastguard Worker 	struct lws_ext_option_arg oa;
39*1c60b9acSAndroid Build Coastguard Worker 	int n, m, more = 1;
40*1c60b9acSAndroid Build Coastguard Worker 	int ext_count = 0;
41*1c60b9acSAndroid Build Coastguard Worker 	char ignore;
42*1c60b9acSAndroid Build Coastguard Worker 	char *c;
43*1c60b9acSAndroid Build Coastguard Worker 
44*1c60b9acSAndroid Build Coastguard Worker 	/*
45*1c60b9acSAndroid Build Coastguard Worker 	 * Figure out which extensions the client has that we want to
46*1c60b9acSAndroid Build Coastguard Worker 	 * enable on this connection, and give him back the list
47*1c60b9acSAndroid Build Coastguard Worker 	 */
48*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS))
49*1c60b9acSAndroid Build Coastguard Worker 		return 0;
50*1c60b9acSAndroid Build Coastguard Worker 
51*1c60b9acSAndroid Build Coastguard Worker 	/*
52*1c60b9acSAndroid Build Coastguard Worker 	 * break down the list of client extensions
53*1c60b9acSAndroid Build Coastguard Worker 	 * and go through them
54*1c60b9acSAndroid Build Coastguard Worker 	 */
55*1c60b9acSAndroid Build Coastguard Worker 
56*1c60b9acSAndroid Build Coastguard Worker 	if (lws_hdr_copy(wsi, (char *)pt->serv_buf, (int)context->pt_serv_buf_size,
57*1c60b9acSAndroid Build Coastguard Worker 			 WSI_TOKEN_EXTENSIONS) < 0)
58*1c60b9acSAndroid Build Coastguard Worker 		return 1;
59*1c60b9acSAndroid Build Coastguard Worker 
60*1c60b9acSAndroid Build Coastguard Worker 	c = (char *)pt->serv_buf;
61*1c60b9acSAndroid Build Coastguard Worker 	lwsl_parser("WSI_TOKEN_EXTENSIONS = '%s'\n", c);
62*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->count_act_ext = 0;
63*1c60b9acSAndroid Build Coastguard Worker 	ignore = 0;
64*1c60b9acSAndroid Build Coastguard Worker 	n = 0;
65*1c60b9acSAndroid Build Coastguard Worker 	args = NULL;
66*1c60b9acSAndroid Build Coastguard Worker 
67*1c60b9acSAndroid Build Coastguard Worker 	/*
68*1c60b9acSAndroid Build Coastguard Worker 	 * We may get a simple request
69*1c60b9acSAndroid Build Coastguard Worker 	 *
70*1c60b9acSAndroid Build Coastguard Worker 	 * Sec-WebSocket-Extensions: permessage-deflate
71*1c60b9acSAndroid Build Coastguard Worker 	 *
72*1c60b9acSAndroid Build Coastguard Worker 	 * or an elaborated one with requested options
73*1c60b9acSAndroid Build Coastguard Worker 	 *
74*1c60b9acSAndroid Build Coastguard Worker 	 * Sec-WebSocket-Extensions: permessage-deflate; \
75*1c60b9acSAndroid Build Coastguard Worker 	 *			     server_no_context_takeover; \
76*1c60b9acSAndroid Build Coastguard Worker 	 *			     client_no_context_takeover
77*1c60b9acSAndroid Build Coastguard Worker 	 */
78*1c60b9acSAndroid Build Coastguard Worker 
79*1c60b9acSAndroid Build Coastguard Worker 	while (more) {
80*1c60b9acSAndroid Build Coastguard Worker 
81*1c60b9acSAndroid Build Coastguard Worker 		if (c >= (char *)pt->serv_buf + 255)
82*1c60b9acSAndroid Build Coastguard Worker 			return -1;
83*1c60b9acSAndroid Build Coastguard Worker 
84*1c60b9acSAndroid Build Coastguard Worker 		if (*c && (*c != ',' && *c != '\t')) {
85*1c60b9acSAndroid Build Coastguard Worker 			if (*c == ';') {
86*1c60b9acSAndroid Build Coastguard Worker 				ignore = 1;
87*1c60b9acSAndroid Build Coastguard Worker 				if (!args)
88*1c60b9acSAndroid Build Coastguard Worker 					args = c + 1;
89*1c60b9acSAndroid Build Coastguard Worker 			}
90*1c60b9acSAndroid Build Coastguard Worker 			if (ignore || *c == ' ') {
91*1c60b9acSAndroid Build Coastguard Worker 				c++;
92*1c60b9acSAndroid Build Coastguard Worker 				continue;
93*1c60b9acSAndroid Build Coastguard Worker 			}
94*1c60b9acSAndroid Build Coastguard Worker 			ext_name[n] = *c++;
95*1c60b9acSAndroid Build Coastguard Worker 			if (n < (int)sizeof(ext_name) - 1)
96*1c60b9acSAndroid Build Coastguard Worker 				n++;
97*1c60b9acSAndroid Build Coastguard Worker 			continue;
98*1c60b9acSAndroid Build Coastguard Worker 		}
99*1c60b9acSAndroid Build Coastguard Worker 		ext_name[n] = '\0';
100*1c60b9acSAndroid Build Coastguard Worker 
101*1c60b9acSAndroid Build Coastguard Worker 		ignore = 0;
102*1c60b9acSAndroid Build Coastguard Worker 		if (!*c)
103*1c60b9acSAndroid Build Coastguard Worker 			more = 0;
104*1c60b9acSAndroid Build Coastguard Worker 		else {
105*1c60b9acSAndroid Build Coastguard Worker 			c++;
106*1c60b9acSAndroid Build Coastguard Worker 			if (!n)
107*1c60b9acSAndroid Build Coastguard Worker 				continue;
108*1c60b9acSAndroid Build Coastguard Worker 		}
109*1c60b9acSAndroid Build Coastguard Worker 
110*1c60b9acSAndroid Build Coastguard Worker 		while (args && *args == ' ')
111*1c60b9acSAndroid Build Coastguard Worker 			args++;
112*1c60b9acSAndroid Build Coastguard Worker 
113*1c60b9acSAndroid Build Coastguard Worker 		/* check a client's extension against our support */
114*1c60b9acSAndroid Build Coastguard Worker 
115*1c60b9acSAndroid Build Coastguard Worker 		ext = wsi->a.vhost->ws.extensions;
116*1c60b9acSAndroid Build Coastguard Worker 
117*1c60b9acSAndroid Build Coastguard Worker 		while (ext && ext->callback) {
118*1c60b9acSAndroid Build Coastguard Worker 
119*1c60b9acSAndroid Build Coastguard Worker 			if (strcmp(ext_name, ext->name)) {
120*1c60b9acSAndroid Build Coastguard Worker 				ext++;
121*1c60b9acSAndroid Build Coastguard Worker 				continue;
122*1c60b9acSAndroid Build Coastguard Worker 			}
123*1c60b9acSAndroid Build Coastguard Worker 
124*1c60b9acSAndroid Build Coastguard Worker 			/*
125*1c60b9acSAndroid Build Coastguard Worker 			 * oh, we do support this one he asked for... but let's
126*1c60b9acSAndroid Build Coastguard Worker 			 * confirm he only gave it once
127*1c60b9acSAndroid Build Coastguard Worker 			 */
128*1c60b9acSAndroid Build Coastguard Worker 			for (m = 0; m < wsi->ws->count_act_ext; m++)
129*1c60b9acSAndroid Build Coastguard Worker 				if (wsi->ws->active_extensions[m] == ext) {
130*1c60b9acSAndroid Build Coastguard Worker 					lwsl_info("ext mentioned twice\n");
131*1c60b9acSAndroid Build Coastguard Worker 					return 1; /* shenanigans */
132*1c60b9acSAndroid Build Coastguard Worker 				}
133*1c60b9acSAndroid Build Coastguard Worker 
134*1c60b9acSAndroid Build Coastguard Worker 			/*
135*1c60b9acSAndroid Build Coastguard Worker 			 * ask user code if it's OK to apply it on this
136*1c60b9acSAndroid Build Coastguard Worker 			 * particular connection + protocol
137*1c60b9acSAndroid Build Coastguard Worker 			 */
138*1c60b9acSAndroid Build Coastguard Worker 			m = (wsi->a.protocol->callback)(wsi,
139*1c60b9acSAndroid Build Coastguard Worker 				LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
140*1c60b9acSAndroid Build Coastguard Worker 				wsi->user_space, ext_name, 0);
141*1c60b9acSAndroid Build Coastguard Worker 
142*1c60b9acSAndroid Build Coastguard Worker 			/*
143*1c60b9acSAndroid Build Coastguard Worker 			 * zero return from callback means go ahead and allow
144*1c60b9acSAndroid Build Coastguard Worker 			 * the extension, it's what we get if the callback is
145*1c60b9acSAndroid Build Coastguard Worker 			 * unhandled
146*1c60b9acSAndroid Build Coastguard Worker 			 */
147*1c60b9acSAndroid Build Coastguard Worker 			if (m) {
148*1c60b9acSAndroid Build Coastguard Worker 				ext++;
149*1c60b9acSAndroid Build Coastguard Worker 				continue;
150*1c60b9acSAndroid Build Coastguard Worker 			}
151*1c60b9acSAndroid Build Coastguard Worker 
152*1c60b9acSAndroid Build Coastguard Worker 			/* apply it */
153*1c60b9acSAndroid Build Coastguard Worker 
154*1c60b9acSAndroid Build Coastguard Worker 			ext_count++;
155*1c60b9acSAndroid Build Coastguard Worker 
156*1c60b9acSAndroid Build Coastguard Worker 			/* instantiate the extension on this conn */
157*1c60b9acSAndroid Build Coastguard Worker 
158*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->active_extensions[wsi->ws->count_act_ext] = ext;
159*1c60b9acSAndroid Build Coastguard Worker 
160*1c60b9acSAndroid Build Coastguard Worker 			/* allow him to construct his context */
161*1c60b9acSAndroid Build Coastguard Worker 
162*1c60b9acSAndroid Build Coastguard Worker 			if (ext->callback(lws_get_context(wsi), ext, wsi,
163*1c60b9acSAndroid Build Coastguard Worker 					  LWS_EXT_CB_CONSTRUCT,
164*1c60b9acSAndroid Build Coastguard Worker 					  (void *)&wsi->ws->act_ext_user[
165*1c60b9acSAndroid Build Coastguard Worker 					                wsi->ws->count_act_ext],
166*1c60b9acSAndroid Build Coastguard Worker 					  (void *)&opts, 0)) {
167*1c60b9acSAndroid Build Coastguard Worker 				lwsl_info("ext %s failed construction\n",
168*1c60b9acSAndroid Build Coastguard Worker 					    ext_name);
169*1c60b9acSAndroid Build Coastguard Worker 				ext_count--;
170*1c60b9acSAndroid Build Coastguard Worker 				ext++;
171*1c60b9acSAndroid Build Coastguard Worker 
172*1c60b9acSAndroid Build Coastguard Worker 				continue;
173*1c60b9acSAndroid Build Coastguard Worker 			}
174*1c60b9acSAndroid Build Coastguard Worker 
175*1c60b9acSAndroid Build Coastguard Worker 			if (ext_count > 1)
176*1c60b9acSAndroid Build Coastguard Worker 				*(*p)++ = ',';
177*1c60b9acSAndroid Build Coastguard Worker 			else
178*1c60b9acSAndroid Build Coastguard Worker 				LWS_CPYAPP(*p,
179*1c60b9acSAndroid Build Coastguard Worker 					  "\x0d\x0aSec-WebSocket-Extensions: ");
180*1c60b9acSAndroid Build Coastguard Worker 			*p += lws_snprintf(*p, lws_ptr_diff_size_t(end, *p), "%s", ext_name);
181*1c60b9acSAndroid Build Coastguard Worker 
182*1c60b9acSAndroid Build Coastguard Worker 			/*
183*1c60b9acSAndroid Build Coastguard Worker 			 * The client may send a bunch of different option
184*1c60b9acSAndroid Build Coastguard Worker 			 * sets for the same extension, we are supposed to
185*1c60b9acSAndroid Build Coastguard Worker 			 * pick one we like the look of.  The option sets are
186*1c60b9acSAndroid Build Coastguard Worker 			 * separated by comma.
187*1c60b9acSAndroid Build Coastguard Worker 			 *
188*1c60b9acSAndroid Build Coastguard Worker 			 * Actually we just either accept the first one or
189*1c60b9acSAndroid Build Coastguard Worker 			 * nothing.
190*1c60b9acSAndroid Build Coastguard Worker 			 *
191*1c60b9acSAndroid Build Coastguard Worker 			 * Go through the options trying to apply the
192*1c60b9acSAndroid Build Coastguard Worker 			 * recognized ones
193*1c60b9acSAndroid Build Coastguard Worker 			 */
194*1c60b9acSAndroid Build Coastguard Worker 
195*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("ext args %s\n", args);
196*1c60b9acSAndroid Build Coastguard Worker 
197*1c60b9acSAndroid Build Coastguard Worker 			while (args && *args && *args != ',') {
198*1c60b9acSAndroid Build Coastguard Worker 				while (*args == ' ')
199*1c60b9acSAndroid Build Coastguard Worker 					args++;
200*1c60b9acSAndroid Build Coastguard Worker 				po = opts;
201*1c60b9acSAndroid Build Coastguard Worker 				while (po->name) {
202*1c60b9acSAndroid Build Coastguard Worker 					/* only support arg-less options... */
203*1c60b9acSAndroid Build Coastguard Worker 					if (po->type != EXTARG_NONE ||
204*1c60b9acSAndroid Build Coastguard Worker 					    strncmp(args, po->name,
205*1c60b9acSAndroid Build Coastguard Worker 						    strlen(po->name))) {
206*1c60b9acSAndroid Build Coastguard Worker 						po++;
207*1c60b9acSAndroid Build Coastguard Worker 						continue;
208*1c60b9acSAndroid Build Coastguard Worker 					}
209*1c60b9acSAndroid Build Coastguard Worker 					oa.option_name = NULL;
210*1c60b9acSAndroid Build Coastguard Worker 					oa.option_index = (int)(po - opts);
211*1c60b9acSAndroid Build Coastguard Worker 					oa.start = NULL;
212*1c60b9acSAndroid Build Coastguard Worker 					oa.len = 0;
213*1c60b9acSAndroid Build Coastguard Worker 					lwsl_info("setting '%s'\n", po->name);
214*1c60b9acSAndroid Build Coastguard Worker 					if (!ext->callback(lws_get_context(wsi),
215*1c60b9acSAndroid Build Coastguard Worker 							   ext, wsi,
216*1c60b9acSAndroid Build Coastguard Worker 						LWS_EXT_CB_OPTION_SET,
217*1c60b9acSAndroid Build Coastguard Worker 						wsi->ws->act_ext_user[
218*1c60b9acSAndroid Build Coastguard Worker 							wsi->ws->count_act_ext],
219*1c60b9acSAndroid Build Coastguard Worker 							  &oa, lws_ptr_diff_size_t(end, *p))) {
220*1c60b9acSAndroid Build Coastguard Worker 
221*1c60b9acSAndroid Build Coastguard Worker 						*p += lws_snprintf(*p,
222*1c60b9acSAndroid Build Coastguard Worker 								   lws_ptr_diff_size_t(end, *p),
223*1c60b9acSAndroid Build Coastguard Worker 							      "; %s", po->name);
224*1c60b9acSAndroid Build Coastguard Worker 						lwsl_debug("adding option %s\n",
225*1c60b9acSAndroid Build Coastguard Worker 							   po->name);
226*1c60b9acSAndroid Build Coastguard Worker 					}
227*1c60b9acSAndroid Build Coastguard Worker 					po++;
228*1c60b9acSAndroid Build Coastguard Worker 				}
229*1c60b9acSAndroid Build Coastguard Worker 				while (*args && *args != ',' && *args != ';')
230*1c60b9acSAndroid Build Coastguard Worker 					args++;
231*1c60b9acSAndroid Build Coastguard Worker 
232*1c60b9acSAndroid Build Coastguard Worker 				if (*args == ';')
233*1c60b9acSAndroid Build Coastguard Worker 					args++;
234*1c60b9acSAndroid Build Coastguard Worker 			}
235*1c60b9acSAndroid Build Coastguard Worker 
236*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->count_act_ext++;
237*1c60b9acSAndroid Build Coastguard Worker 			lwsl_parser("cnt_act_ext <- %d\n",
238*1c60b9acSAndroid Build Coastguard Worker 				    wsi->ws->count_act_ext);
239*1c60b9acSAndroid Build Coastguard Worker 
240*1c60b9acSAndroid Build Coastguard Worker 			if (args && *args == ',')
241*1c60b9acSAndroid Build Coastguard Worker 				more = 0;
242*1c60b9acSAndroid Build Coastguard Worker 
243*1c60b9acSAndroid Build Coastguard Worker 			ext++;
244*1c60b9acSAndroid Build Coastguard Worker 		}
245*1c60b9acSAndroid Build Coastguard Worker 
246*1c60b9acSAndroid Build Coastguard Worker 		n = 0;
247*1c60b9acSAndroid Build Coastguard Worker 		args = NULL;
248*1c60b9acSAndroid Build Coastguard Worker 	}
249*1c60b9acSAndroid Build Coastguard Worker 
250*1c60b9acSAndroid Build Coastguard Worker 	return 0;
251*1c60b9acSAndroid Build Coastguard Worker }
252*1c60b9acSAndroid Build Coastguard Worker #endif
253*1c60b9acSAndroid Build Coastguard Worker 
254*1c60b9acSAndroid Build Coastguard Worker int
lws_process_ws_upgrade2(struct lws * wsi)255*1c60b9acSAndroid Build Coastguard Worker lws_process_ws_upgrade2(struct lws *wsi)
256*1c60b9acSAndroid Build Coastguard Worker {
257*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
258*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_BASIC_AUTH)
259*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_protocol_vhost_options *pvos = NULL;
260*1c60b9acSAndroid Build Coastguard Worker 	const char *ws_prot_basic_auth = NULL;
261*1c60b9acSAndroid Build Coastguard Worker 
262*1c60b9acSAndroid Build Coastguard Worker 
263*1c60b9acSAndroid Build Coastguard Worker 	/*
264*1c60b9acSAndroid Build Coastguard Worker 	 * Allow basic auth a look-in now we bound the wsi to the protocol.
265*1c60b9acSAndroid Build Coastguard Worker 	 *
266*1c60b9acSAndroid Build Coastguard Worker 	 * For vhost ws basic auth, it is "basic-auth": "path" as usual but
267*1c60b9acSAndroid Build Coastguard Worker 	 * applied to the protocol's entry in the vhost's "ws-protocols":
268*1c60b9acSAndroid Build Coastguard Worker 	 * section, as a pvo.
269*1c60b9acSAndroid Build Coastguard Worker 	 */
270*1c60b9acSAndroid Build Coastguard Worker 
271*1c60b9acSAndroid Build Coastguard Worker 	pvos = lws_vhost_protocol_options(wsi->a.vhost, wsi->a.protocol->name);
272*1c60b9acSAndroid Build Coastguard Worker 	if (pvos && pvos->options &&
273*1c60b9acSAndroid Build Coastguard Worker 	    !lws_pvo_get_str((void *)pvos->options, "basic-auth",
274*1c60b9acSAndroid Build Coastguard Worker 			     &ws_prot_basic_auth)) {
275*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: ws upgrade requires basic auth\n", __func__);
276*1c60b9acSAndroid Build Coastguard Worker 		switch (lws_check_basic_auth(wsi, ws_prot_basic_auth, LWSAUTHM_DEFAULT
277*1c60b9acSAndroid Build Coastguard Worker 						/* no callback based auth here */)) {
278*1c60b9acSAndroid Build Coastguard Worker 		case LCBA_CONTINUE:
279*1c60b9acSAndroid Build Coastguard Worker 			break;
280*1c60b9acSAndroid Build Coastguard Worker 		case LCBA_FAILED_AUTH:
281*1c60b9acSAndroid Build Coastguard Worker 			return lws_unauthorised_basic_auth(wsi);
282*1c60b9acSAndroid Build Coastguard Worker 		case LCBA_END_TRANSACTION:
283*1c60b9acSAndroid Build Coastguard Worker 			lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
284*1c60b9acSAndroid Build Coastguard Worker 			return lws_http_transaction_completed(wsi);
285*1c60b9acSAndroid Build Coastguard Worker 		}
286*1c60b9acSAndroid Build Coastguard Worker 	}
287*1c60b9acSAndroid Build Coastguard Worker #endif
288*1c60b9acSAndroid Build Coastguard Worker 
289*1c60b9acSAndroid Build Coastguard Worker 	/*
290*1c60b9acSAndroid Build Coastguard Worker 	 * We are upgrading to ws, so http/1.1 + h2 and keepalive + pipelined
291*1c60b9acSAndroid Build Coastguard Worker 	 * header considerations about keeping the ah around no longer apply.
292*1c60b9acSAndroid Build Coastguard Worker 	 *
293*1c60b9acSAndroid Build Coastguard Worker 	 * However it's common for the first ws protocol data to have been
294*1c60b9acSAndroid Build Coastguard Worker 	 * coalesced with the browser upgrade request and to already be in the
295*1c60b9acSAndroid Build Coastguard Worker 	 * ah rx buffer.
296*1c60b9acSAndroid Build Coastguard Worker 	 */
297*1c60b9acSAndroid Build Coastguard Worker 
298*1c60b9acSAndroid Build Coastguard Worker 	lws_pt_lock(pt, __func__);
299*1c60b9acSAndroid Build Coastguard Worker 
300*1c60b9acSAndroid Build Coastguard Worker 	/*
301*1c60b9acSAndroid Build Coastguard Worker 	 * Switch roles if we're upgrading away from http
302*1c60b9acSAndroid Build Coastguard Worker 	 */
303*1c60b9acSAndroid Build Coastguard Worker 
304*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->h2_stream_carries_ws) {
305*1c60b9acSAndroid Build Coastguard Worker 		lws_role_transition(wsi, LWSIFR_SERVER, LRS_ESTABLISHED,
306*1c60b9acSAndroid Build Coastguard Worker 				    &role_ops_ws);
307*1c60b9acSAndroid Build Coastguard Worker 
308*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER)
309*1c60b9acSAndroid Build Coastguard Worker 
310*1c60b9acSAndroid Build Coastguard Worker 		/*
311*1c60b9acSAndroid Build Coastguard Worker 		 * If we're a SS server object, we have to switch to ss-ws
312*1c60b9acSAndroid Build Coastguard Worker 		 * protocol handler too
313*1c60b9acSAndroid Build Coastguard Worker 		 */
314*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->a.vhost->ss_handle) {
315*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: %s switching to ws protocol\n",
316*1c60b9acSAndroid Build Coastguard Worker 				  __func__, lws_ss_tag(wsi->a.vhost->ss_handle));
317*1c60b9acSAndroid Build Coastguard Worker 			wsi->a.protocol = &protocol_secstream_ws;
318*1c60b9acSAndroid Build Coastguard Worker 
319*1c60b9acSAndroid Build Coastguard Worker 			/*
320*1c60b9acSAndroid Build Coastguard Worker 			 * inform the SS user code that this has done a one-way
321*1c60b9acSAndroid Build Coastguard Worker 			 * upgrade to some other protocol... it will likely
322*1c60b9acSAndroid Build Coastguard Worker 			 * want to treat subsequent payloads differently
323*1c60b9acSAndroid Build Coastguard Worker 			 */
324*1c60b9acSAndroid Build Coastguard Worker 
325*1c60b9acSAndroid Build Coastguard Worker 			(void)lws_ss_event_helper(wsi->a.vhost->ss_handle,
326*1c60b9acSAndroid Build Coastguard Worker 						LWSSSCS_SERVER_UPGRADE);
327*1c60b9acSAndroid Build Coastguard Worker 		}
328*1c60b9acSAndroid Build Coastguard Worker #endif
329*1c60b9acSAndroid Build Coastguard Worker 	}
330*1c60b9acSAndroid Build Coastguard Worker 
331*1c60b9acSAndroid Build Coastguard Worker 	lws_pt_unlock(pt);
332*1c60b9acSAndroid Build Coastguard Worker 
333*1c60b9acSAndroid Build Coastguard Worker 	/* allocate the ws struct for the wsi */
334*1c60b9acSAndroid Build Coastguard Worker 
335*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws = lws_zalloc(sizeof(*wsi->ws), "ws struct");
336*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws) {
337*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("OOM\n");
338*1c60b9acSAndroid Build Coastguard Worker 		return 1;
339*1c60b9acSAndroid Build Coastguard Worker 	}
340*1c60b9acSAndroid Build Coastguard Worker 
341*1c60b9acSAndroid Build Coastguard Worker 	if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
342*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->ietf_spec_revision = (uint8_t)
343*1c60b9acSAndroid Build Coastguard Worker 			       atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
344*1c60b9acSAndroid Build Coastguard Worker 
345*1c60b9acSAndroid Build Coastguard Worker 	/* allocate wsi->user storage */
346*1c60b9acSAndroid Build Coastguard Worker 	if (lws_ensure_user_space(wsi)) {
347*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("problem with user space\n");
348*1c60b9acSAndroid Build Coastguard Worker 		return 1;
349*1c60b9acSAndroid Build Coastguard Worker 	}
350*1c60b9acSAndroid Build Coastguard Worker 
351*1c60b9acSAndroid Build Coastguard Worker 	/*
352*1c60b9acSAndroid Build Coastguard Worker 	 * Give the user code a chance to study the request and
353*1c60b9acSAndroid Build Coastguard Worker 	 * have the opportunity to deny it
354*1c60b9acSAndroid Build Coastguard Worker 	 */
355*1c60b9acSAndroid Build Coastguard Worker 	if ((wsi->a.protocol->callback)(wsi,
356*1c60b9acSAndroid Build Coastguard Worker 			LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
357*1c60b9acSAndroid Build Coastguard Worker 			wsi->user_space,
358*1c60b9acSAndroid Build Coastguard Worker 		      lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) {
359*1c60b9acSAndroid Build Coastguard Worker 		lwsl_warn("User code denied connection\n");
360*1c60b9acSAndroid Build Coastguard Worker 		return 1;
361*1c60b9acSAndroid Build Coastguard Worker 	}
362*1c60b9acSAndroid Build Coastguard Worker 
363*1c60b9acSAndroid Build Coastguard Worker 	/*
364*1c60b9acSAndroid Build Coastguard Worker 	 * Perform the handshake according to the protocol version the
365*1c60b9acSAndroid Build Coastguard Worker 	 * client announced
366*1c60b9acSAndroid Build Coastguard Worker 	 */
367*1c60b9acSAndroid Build Coastguard Worker 
368*1c60b9acSAndroid Build Coastguard Worker 	switch (wsi->ws->ietf_spec_revision) {
369*1c60b9acSAndroid Build Coastguard Worker 	default:
370*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("Unknown client spec version %d\n",
371*1c60b9acSAndroid Build Coastguard Worker 			  wsi->ws->ietf_spec_revision);
372*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->ietf_spec_revision = 13;
373*1c60b9acSAndroid Build Coastguard Worker 		//return 1;
374*1c60b9acSAndroid Build Coastguard Worker 		/* fallthru */
375*1c60b9acSAndroid Build Coastguard Worker 	case 13:
376*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
377*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->h2_stream_carries_ws) {
378*1c60b9acSAndroid Build Coastguard Worker 			if (lws_h2_ws_handshake(wsi)) {
379*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("h2 ws handshake failed\n");
380*1c60b9acSAndroid Build Coastguard Worker 				return 1;
381*1c60b9acSAndroid Build Coastguard Worker 			}
382*1c60b9acSAndroid Build Coastguard Worker 			lws_role_transition(wsi,
383*1c60b9acSAndroid Build Coastguard Worker 					    LWSIFR_SERVER | LWSIFR_P_ENCAP_H2,
384*1c60b9acSAndroid Build Coastguard Worker 					    LRS_ESTABLISHED, &role_ops_ws);
385*1c60b9acSAndroid Build Coastguard Worker 
386*1c60b9acSAndroid Build Coastguard Worker 			/*
387*1c60b9acSAndroid Build Coastguard Worker 			 * There should be no validity checking since we
388*1c60b9acSAndroid Build Coastguard Worker 			 * are encapsulated in something else with its own
389*1c60b9acSAndroid Build Coastguard Worker 			 * validity checking
390*1c60b9acSAndroid Build Coastguard Worker 			 */
391*1c60b9acSAndroid Build Coastguard Worker 
392*1c60b9acSAndroid Build Coastguard Worker 			lws_sul_cancel(&wsi->sul_validity);
393*1c60b9acSAndroid Build Coastguard Worker 		} else
394*1c60b9acSAndroid Build Coastguard Worker #endif
395*1c60b9acSAndroid Build Coastguard Worker 		{
396*1c60b9acSAndroid Build Coastguard Worker 			lwsl_parser("lws_parse calling handshake_04\n");
397*1c60b9acSAndroid Build Coastguard Worker 			if (handshake_0405(wsi->a.context, wsi)) {
398*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("hs0405 has failed the connection\n");
399*1c60b9acSAndroid Build Coastguard Worker 				return 1;
400*1c60b9acSAndroid Build Coastguard Worker 			}
401*1c60b9acSAndroid Build Coastguard Worker 		}
402*1c60b9acSAndroid Build Coastguard Worker 		break;
403*1c60b9acSAndroid Build Coastguard Worker 	}
404*1c60b9acSAndroid Build Coastguard Worker 
405*1c60b9acSAndroid Build Coastguard Worker 	if (lws_server_init_wsi_for_ws(wsi)) {
406*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: user ESTABLISHED failed connection\n", __func__);
407*1c60b9acSAndroid Build Coastguard Worker 		return 1;
408*1c60b9acSAndroid Build Coastguard Worker 	}
409*1c60b9acSAndroid Build Coastguard Worker 	lwsl_parser("accepted v%02d connection\n", wsi->ws->ietf_spec_revision);
410*1c60b9acSAndroid Build Coastguard Worker 
411*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_ACCESS_LOG)
412*1c60b9acSAndroid Build Coastguard Worker 	{
413*1c60b9acSAndroid Build Coastguard Worker 		char *uptr = "unknown method", combo[128], dotstar[64];
414*1c60b9acSAndroid Build Coastguard Worker 		int l = 14, meth = lws_http_get_uri_and_method(wsi, &uptr, &l);
415*1c60b9acSAndroid Build Coastguard Worker 
416*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->h2_stream_carries_ws)
417*1c60b9acSAndroid Build Coastguard Worker 			wsi->http.request_version = HTTP_VERSION_2;
418*1c60b9acSAndroid Build Coastguard Worker 
419*1c60b9acSAndroid Build Coastguard Worker 		wsi->http.access_log.response = 101;
420*1c60b9acSAndroid Build Coastguard Worker 
421*1c60b9acSAndroid Build Coastguard Worker 		lws_strnncpy(dotstar, uptr, l, sizeof(dotstar));
422*1c60b9acSAndroid Build Coastguard Worker 		l = lws_snprintf(combo, sizeof(combo), "%s (%s)", dotstar,
423*1c60b9acSAndroid Build Coastguard Worker 				 wsi->a.protocol->name);
424*1c60b9acSAndroid Build Coastguard Worker 
425*1c60b9acSAndroid Build Coastguard Worker 		if (meth < 0)
426*1c60b9acSAndroid Build Coastguard Worker 			meth = 0;
427*1c60b9acSAndroid Build Coastguard Worker 		lws_prepare_access_log_info(wsi, combo, l, meth);
428*1c60b9acSAndroid Build Coastguard Worker 		lws_access_log(wsi);
429*1c60b9acSAndroid Build Coastguard Worker 	}
430*1c60b9acSAndroid Build Coastguard Worker #endif
431*1c60b9acSAndroid Build Coastguard Worker 
432*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: %s: dropping ah on ws upgrade\n", __func__, lws_wsi_tag(wsi));
433*1c60b9acSAndroid Build Coastguard Worker 	lws_header_table_detach(wsi, 1);
434*1c60b9acSAndroid Build Coastguard Worker 
435*1c60b9acSAndroid Build Coastguard Worker 	return 0;
436*1c60b9acSAndroid Build Coastguard Worker }
437*1c60b9acSAndroid Build Coastguard Worker 
438*1c60b9acSAndroid Build Coastguard Worker int
lws_process_ws_upgrade(struct lws * wsi)439*1c60b9acSAndroid Build Coastguard Worker lws_process_ws_upgrade(struct lws *wsi)
440*1c60b9acSAndroid Build Coastguard Worker {
441*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_protocols *pcol = NULL;
442*1c60b9acSAndroid Build Coastguard Worker 	char buf[128], name[64];
443*1c60b9acSAndroid Build Coastguard Worker 	struct lws_tokenize ts;
444*1c60b9acSAndroid Build Coastguard Worker 	lws_tokenize_elem e;
445*1c60b9acSAndroid Build Coastguard Worker 	int n;
446*1c60b9acSAndroid Build Coastguard Worker 
447*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->a.protocol)
448*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("NULL protocol at lws_read\n");
449*1c60b9acSAndroid Build Coastguard Worker 
450*1c60b9acSAndroid Build Coastguard Worker 	/*
451*1c60b9acSAndroid Build Coastguard Worker 	 * It's either websocket or h2->websocket
452*1c60b9acSAndroid Build Coastguard Worker 	 *
453*1c60b9acSAndroid Build Coastguard Worker 	 * If we are on h1, confirm we got the required "connection: upgrade"
454*1c60b9acSAndroid Build Coastguard Worker 	 * header.  h2 / ws-over-h2 does not have this.
455*1c60b9acSAndroid Build Coastguard Worker 	 */
456*1c60b9acSAndroid Build Coastguard Worker 
457*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
458*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->mux_substream) {
459*1c60b9acSAndroid Build Coastguard Worker #endif
460*1c60b9acSAndroid Build Coastguard Worker 
461*1c60b9acSAndroid Build Coastguard Worker 		lws_tokenize_init(&ts, buf, LWS_TOKENIZE_F_COMMA_SEP_LIST |
462*1c60b9acSAndroid Build Coastguard Worker 					    LWS_TOKENIZE_F_DOT_NONTERM |
463*1c60b9acSAndroid Build Coastguard Worker 					    LWS_TOKENIZE_F_RFC7230_DELIMS |
464*1c60b9acSAndroid Build Coastguard Worker 					    LWS_TOKENIZE_F_MINUS_NONTERM);
465*1c60b9acSAndroid Build Coastguard Worker 		n = lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_CONNECTION);
466*1c60b9acSAndroid Build Coastguard Worker 		if (n <= 0)
467*1c60b9acSAndroid Build Coastguard Worker 			goto bad_conn_format;
468*1c60b9acSAndroid Build Coastguard Worker 		ts.len = (unsigned int)n;
469*1c60b9acSAndroid Build Coastguard Worker 
470*1c60b9acSAndroid Build Coastguard Worker 		do {
471*1c60b9acSAndroid Build Coastguard Worker 			e = lws_tokenize(&ts);
472*1c60b9acSAndroid Build Coastguard Worker 			switch (e) {
473*1c60b9acSAndroid Build Coastguard Worker 			case LWS_TOKZE_TOKEN:
474*1c60b9acSAndroid Build Coastguard Worker 				if (!strncasecmp(ts.token, "upgrade", ts.token_len))
475*1c60b9acSAndroid Build Coastguard Worker 					e = LWS_TOKZE_ENDED;
476*1c60b9acSAndroid Build Coastguard Worker 				break;
477*1c60b9acSAndroid Build Coastguard Worker 
478*1c60b9acSAndroid Build Coastguard Worker 			case LWS_TOKZE_DELIMITER:
479*1c60b9acSAndroid Build Coastguard Worker 				break;
480*1c60b9acSAndroid Build Coastguard Worker 
481*1c60b9acSAndroid Build Coastguard Worker 			default: /* includes ENDED */
482*1c60b9acSAndroid Build Coastguard Worker 	bad_conn_format:
483*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: malformed or absent conn hdr\n",
484*1c60b9acSAndroid Build Coastguard Worker 					 __func__);
485*1c60b9acSAndroid Build Coastguard Worker 
486*1c60b9acSAndroid Build Coastguard Worker 				return 1;
487*1c60b9acSAndroid Build Coastguard Worker 			}
488*1c60b9acSAndroid Build Coastguard Worker 		} while (e > 0);
489*1c60b9acSAndroid Build Coastguard Worker 
490*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP2)
491*1c60b9acSAndroid Build Coastguard Worker 	}
492*1c60b9acSAndroid Build Coastguard Worker #endif
493*1c60b9acSAndroid Build Coastguard Worker 
494*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_PROXY)
495*1c60b9acSAndroid Build Coastguard Worker 	{
496*1c60b9acSAndroid Build Coastguard Worker 		const struct lws_http_mount *hit;
497*1c60b9acSAndroid Build Coastguard Worker 		int uri_len = 0, meth;
498*1c60b9acSAndroid Build Coastguard Worker 		char *uri_ptr;
499*1c60b9acSAndroid Build Coastguard Worker 
500*1c60b9acSAndroid Build Coastguard Worker 		meth = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len);
501*1c60b9acSAndroid Build Coastguard Worker 		hit = lws_find_mount(wsi, uri_ptr, uri_len);
502*1c60b9acSAndroid Build Coastguard Worker 
503*1c60b9acSAndroid Build Coastguard Worker 		if (hit && (meth == LWSHUMETH_GET ||
504*1c60b9acSAndroid Build Coastguard Worker 			    meth == LWSHUMETH_CONNECT ||
505*1c60b9acSAndroid Build Coastguard Worker 			    meth == LWSHUMETH_COLON_PATH) &&
506*1c60b9acSAndroid Build Coastguard Worker 		    (hit->origin_protocol == LWSMPRO_HTTPS ||
507*1c60b9acSAndroid Build Coastguard Worker 		     hit->origin_protocol == LWSMPRO_HTTP))
508*1c60b9acSAndroid Build Coastguard Worker 			/*
509*1c60b9acSAndroid Build Coastguard Worker 			 * We are an h1 ws upgrade on a urlpath that corresponds
510*1c60b9acSAndroid Build Coastguard Worker 			 * to a proxying mount.  Don't try to deal with it
511*1c60b9acSAndroid Build Coastguard Worker 			 * locally, eg, we won't even have the right protocol
512*1c60b9acSAndroid Build Coastguard Worker 			 * handler since we're not the guy handling it, just a
513*1c60b9acSAndroid Build Coastguard Worker 			 * conduit.
514*1c60b9acSAndroid Build Coastguard Worker 			 *
515*1c60b9acSAndroid Build Coastguard Worker 			 * Instead open the related ongoing h1 connection
516*1c60b9acSAndroid Build Coastguard Worker 			 * according to the mount configuration and proxy
517*1c60b9acSAndroid Build Coastguard Worker 			 * whatever that has to say from now on.
518*1c60b9acSAndroid Build Coastguard Worker 			 */
519*1c60b9acSAndroid Build Coastguard Worker 			return lws_http_proxy_start(wsi, hit, uri_ptr, 1);
520*1c60b9acSAndroid Build Coastguard Worker 	}
521*1c60b9acSAndroid Build Coastguard Worker #endif
522*1c60b9acSAndroid Build Coastguard Worker 
523*1c60b9acSAndroid Build Coastguard Worker 	/*
524*1c60b9acSAndroid Build Coastguard Worker 	 * Select the first protocol we support from the list
525*1c60b9acSAndroid Build Coastguard Worker 	 * the client sent us.
526*1c60b9acSAndroid Build Coastguard Worker 	 */
527*1c60b9acSAndroid Build Coastguard Worker 
528*1c60b9acSAndroid Build Coastguard Worker 	lws_tokenize_init(&ts, buf, LWS_TOKENIZE_F_COMMA_SEP_LIST |
529*1c60b9acSAndroid Build Coastguard Worker 				    LWS_TOKENIZE_F_MINUS_NONTERM |
530*1c60b9acSAndroid Build Coastguard Worker 				    LWS_TOKENIZE_F_DOT_NONTERM |
531*1c60b9acSAndroid Build Coastguard Worker 				    LWS_TOKENIZE_F_RFC7230_DELIMS);
532*1c60b9acSAndroid Build Coastguard Worker 	n = lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_PROTOCOL);
533*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
534*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: protocol list too long\n", __func__);
535*1c60b9acSAndroid Build Coastguard Worker 		return 1;
536*1c60b9acSAndroid Build Coastguard Worker 	}
537*1c60b9acSAndroid Build Coastguard Worker 	ts.len = (unsigned int)n;
538*1c60b9acSAndroid Build Coastguard Worker 	if (!ts.len) {
539*1c60b9acSAndroid Build Coastguard Worker 		int n = wsi->a.vhost->default_protocol_index;
540*1c60b9acSAndroid Build Coastguard Worker 		/*
541*1c60b9acSAndroid Build Coastguard Worker 		 * Some clients only have one protocol and do not send the
542*1c60b9acSAndroid Build Coastguard Worker 		 * protocol list header... allow it and match to the vhost's
543*1c60b9acSAndroid Build Coastguard Worker 		 * default protocol (which itself defaults to zero).
544*1c60b9acSAndroid Build Coastguard Worker 		 *
545*1c60b9acSAndroid Build Coastguard Worker 		 * Setting the vhost default protocol index to -1 or anything
546*1c60b9acSAndroid Build Coastguard Worker 		 * more than the actual number of protocols on the vhost causes
547*1c60b9acSAndroid Build Coastguard Worker 		 * these "no protocol" ws connections to be rejected.
548*1c60b9acSAndroid Build Coastguard Worker 		 */
549*1c60b9acSAndroid Build Coastguard Worker 
550*1c60b9acSAndroid Build Coastguard Worker 		if (n >= wsi->a.vhost->count_protocols) {
551*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: rejecting ws upg with no protocol\n",
552*1c60b9acSAndroid Build Coastguard Worker 				    __func__);
553*1c60b9acSAndroid Build Coastguard Worker 
554*1c60b9acSAndroid Build Coastguard Worker 			return 1;
555*1c60b9acSAndroid Build Coastguard Worker 		}
556*1c60b9acSAndroid Build Coastguard Worker 
557*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: defaulting to prot handler %d\n", __func__, n);
558*1c60b9acSAndroid Build Coastguard Worker 
559*1c60b9acSAndroid Build Coastguard Worker 		lws_bind_protocol(wsi, &wsi->a.vhost->protocols[n],
560*1c60b9acSAndroid Build Coastguard Worker 				  "ws upgrade default pcol");
561*1c60b9acSAndroid Build Coastguard Worker 
562*1c60b9acSAndroid Build Coastguard Worker 		goto alloc_ws;
563*1c60b9acSAndroid Build Coastguard Worker 	}
564*1c60b9acSAndroid Build Coastguard Worker 
565*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER)
566*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->a.vhost->ss_handle) {
567*1c60b9acSAndroid Build Coastguard Worker 		lws_ss_handle_t *sssh = wsi->a.vhost->ss_handle;
568*1c60b9acSAndroid Build Coastguard Worker 
569*1c60b9acSAndroid Build Coastguard Worker 		/*
570*1c60b9acSAndroid Build Coastguard Worker 		 * At the moment, once we see it's a ss ws server, whatever
571*1c60b9acSAndroid Build Coastguard Worker 		 * he asked for we bind him to the ss-ws protocol handler.
572*1c60b9acSAndroid Build Coastguard Worker 		 *
573*1c60b9acSAndroid Build Coastguard Worker 		 * In the response subprotocol header, we need to name
574*1c60b9acSAndroid Build Coastguard Worker 		 *
575*1c60b9acSAndroid Build Coastguard Worker 		 * sssh->policy->u.http.u.ws.subprotocol
576*1c60b9acSAndroid Build Coastguard Worker 		 *
577*1c60b9acSAndroid Build Coastguard Worker 		 * though...
578*1c60b9acSAndroid Build Coastguard Worker 		 */
579*1c60b9acSAndroid Build Coastguard Worker 
580*1c60b9acSAndroid Build Coastguard Worker 		if (sssh->policy->u.http.u.ws.subprotocol) {
581*1c60b9acSAndroid Build Coastguard Worker 			pcol = lws_vhost_name_to_protocol(wsi->a.vhost,
582*1c60b9acSAndroid Build Coastguard Worker 							  "lws-secstream-ws");
583*1c60b9acSAndroid Build Coastguard Worker 			if (pcol) {
584*1c60b9acSAndroid Build Coastguard Worker 				lws_bind_protocol(wsi, pcol, "ss ws upg pcol");
585*1c60b9acSAndroid Build Coastguard Worker 
586*1c60b9acSAndroid Build Coastguard Worker 				goto alloc_ws;
587*1c60b9acSAndroid Build Coastguard Worker 			}
588*1c60b9acSAndroid Build Coastguard Worker 		}
589*1c60b9acSAndroid Build Coastguard Worker 	}
590*1c60b9acSAndroid Build Coastguard Worker #endif
591*1c60b9acSAndroid Build Coastguard Worker 
592*1c60b9acSAndroid Build Coastguard Worker 	/* otherwise go through the user-provided protocol list */
593*1c60b9acSAndroid Build Coastguard Worker 
594*1c60b9acSAndroid Build Coastguard Worker 	do {
595*1c60b9acSAndroid Build Coastguard Worker 		e = lws_tokenize(&ts);
596*1c60b9acSAndroid Build Coastguard Worker 		switch (e) {
597*1c60b9acSAndroid Build Coastguard Worker 		case LWS_TOKZE_TOKEN:
598*1c60b9acSAndroid Build Coastguard Worker 
599*1c60b9acSAndroid Build Coastguard Worker 			if (lws_tokenize_cstr(&ts, name, sizeof(name))) {
600*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: pcol name too long\n", __func__);
601*1c60b9acSAndroid Build Coastguard Worker 
602*1c60b9acSAndroid Build Coastguard Worker 				return 1;
603*1c60b9acSAndroid Build Coastguard Worker 			}
604*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("checking %s\n", name);
605*1c60b9acSAndroid Build Coastguard Worker 			pcol = lws_vhost_name_to_protocol(wsi->a.vhost, name);
606*1c60b9acSAndroid Build Coastguard Worker 			if (pcol) {
607*1c60b9acSAndroid Build Coastguard Worker 				/* if we know it, bind to it and stop looking */
608*1c60b9acSAndroid Build Coastguard Worker 				lws_bind_protocol(wsi, pcol, "ws upg pcol");
609*1c60b9acSAndroid Build Coastguard Worker 				e = LWS_TOKZE_ENDED;
610*1c60b9acSAndroid Build Coastguard Worker 			}
611*1c60b9acSAndroid Build Coastguard Worker 			break;
612*1c60b9acSAndroid Build Coastguard Worker 
613*1c60b9acSAndroid Build Coastguard Worker 		case LWS_TOKZE_DELIMITER:
614*1c60b9acSAndroid Build Coastguard Worker 		case LWS_TOKZE_ENDED:
615*1c60b9acSAndroid Build Coastguard Worker 			break;
616*1c60b9acSAndroid Build Coastguard Worker 
617*1c60b9acSAndroid Build Coastguard Worker 		default:
618*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: malformatted protocol list", __func__);
619*1c60b9acSAndroid Build Coastguard Worker 
620*1c60b9acSAndroid Build Coastguard Worker 			return 1;
621*1c60b9acSAndroid Build Coastguard Worker 		}
622*1c60b9acSAndroid Build Coastguard Worker 	} while (e > 0);
623*1c60b9acSAndroid Build Coastguard Worker 
624*1c60b9acSAndroid Build Coastguard Worker 	/* we didn't find a protocol he wanted? */
625*1c60b9acSAndroid Build Coastguard Worker 
626*1c60b9acSAndroid Build Coastguard Worker 	if (!pcol) {
627*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("No supported protocol \"%s\"\n", buf);
628*1c60b9acSAndroid Build Coastguard Worker 
629*1c60b9acSAndroid Build Coastguard Worker 		return 1;
630*1c60b9acSAndroid Build Coastguard Worker 	}
631*1c60b9acSAndroid Build Coastguard Worker 
632*1c60b9acSAndroid Build Coastguard Worker alloc_ws:
633*1c60b9acSAndroid Build Coastguard Worker 
634*1c60b9acSAndroid Build Coastguard Worker 	return lws_process_ws_upgrade2(wsi);
635*1c60b9acSAndroid Build Coastguard Worker }
636*1c60b9acSAndroid Build Coastguard Worker 
637*1c60b9acSAndroid Build Coastguard Worker int
handshake_0405(struct lws_context * context,struct lws * wsi)638*1c60b9acSAndroid Build Coastguard Worker handshake_0405(struct lws_context *context, struct lws *wsi)
639*1c60b9acSAndroid Build Coastguard Worker {
640*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
641*1c60b9acSAndroid Build Coastguard Worker 	struct lws_process_html_args args;
642*1c60b9acSAndroid Build Coastguard Worker 	unsigned char hash[20];
643*1c60b9acSAndroid Build Coastguard Worker 	int n, accept_len;
644*1c60b9acSAndroid Build Coastguard Worker 	char *response;
645*1c60b9acSAndroid Build Coastguard Worker 	char *p;
646*1c60b9acSAndroid Build Coastguard Worker 
647*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST) ||
648*1c60b9acSAndroid Build Coastguard Worker 	    !lws_hdr_total_length(wsi, WSI_TOKEN_KEY)) {
649*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("handshake_04 missing pieces\n");
650*1c60b9acSAndroid Build Coastguard Worker 		/* completed header processing, but missing some bits */
651*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
652*1c60b9acSAndroid Build Coastguard Worker 	}
653*1c60b9acSAndroid Build Coastguard Worker 
654*1c60b9acSAndroid Build Coastguard Worker 	if (lws_hdr_total_length(wsi, WSI_TOKEN_KEY) >=
655*1c60b9acSAndroid Build Coastguard Worker 	    MAX_WEBSOCKET_04_KEY_LEN) {
656*1c60b9acSAndroid Build Coastguard Worker 		lwsl_warn("Client key too long %d\n", MAX_WEBSOCKET_04_KEY_LEN);
657*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
658*1c60b9acSAndroid Build Coastguard Worker 	}
659*1c60b9acSAndroid Build Coastguard Worker 
660*1c60b9acSAndroid Build Coastguard Worker 	/*
661*1c60b9acSAndroid Build Coastguard Worker 	 * since key length is restricted above (currently 128), cannot
662*1c60b9acSAndroid Build Coastguard Worker 	 * overflow
663*1c60b9acSAndroid Build Coastguard Worker 	 */
664*1c60b9acSAndroid Build Coastguard Worker 	n = sprintf((char *)pt->serv_buf,
665*1c60b9acSAndroid Build Coastguard Worker 		    "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
666*1c60b9acSAndroid Build Coastguard Worker 		    lws_hdr_simple_ptr(wsi, WSI_TOKEN_KEY));
667*1c60b9acSAndroid Build Coastguard Worker 
668*1c60b9acSAndroid Build Coastguard Worker 	lws_SHA1(pt->serv_buf, (unsigned int)n, hash);
669*1c60b9acSAndroid Build Coastguard Worker 
670*1c60b9acSAndroid Build Coastguard Worker 	accept_len = lws_b64_encode_string((char *)hash, 20,
671*1c60b9acSAndroid Build Coastguard Worker 			(char *)pt->serv_buf, (int)context->pt_serv_buf_size);
672*1c60b9acSAndroid Build Coastguard Worker 	if (accept_len < 0) {
673*1c60b9acSAndroid Build Coastguard Worker 		lwsl_warn("Base64 encoded hash too long\n");
674*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
675*1c60b9acSAndroid Build Coastguard Worker 	}
676*1c60b9acSAndroid Build Coastguard Worker 
677*1c60b9acSAndroid Build Coastguard Worker 	/* allocate the per-connection user memory (if any) */
678*1c60b9acSAndroid Build Coastguard Worker 	if (lws_ensure_user_space(wsi))
679*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
680*1c60b9acSAndroid Build Coastguard Worker 
681*1c60b9acSAndroid Build Coastguard Worker 	/* create the response packet */
682*1c60b9acSAndroid Build Coastguard Worker 
683*1c60b9acSAndroid Build Coastguard Worker 	/* make a buffer big enough for everything */
684*1c60b9acSAndroid Build Coastguard Worker 
685*1c60b9acSAndroid Build Coastguard Worker 	response = (char *)pt->serv_buf + MAX_WEBSOCKET_04_KEY_LEN +
686*1c60b9acSAndroid Build Coastguard Worker 		   256 + LWS_PRE;
687*1c60b9acSAndroid Build Coastguard Worker 	p = response;
688*1c60b9acSAndroid Build Coastguard Worker 	LWS_CPYAPP(p, "HTTP/1.1 101 Switching Protocols\x0d\x0a"
689*1c60b9acSAndroid Build Coastguard Worker 		      "Upgrade: WebSocket\x0d\x0a"
690*1c60b9acSAndroid Build Coastguard Worker 		      "Connection: Upgrade\x0d\x0a"
691*1c60b9acSAndroid Build Coastguard Worker 		      "Sec-WebSocket-Accept: ");
692*1c60b9acSAndroid Build Coastguard Worker 	strcpy(p, (char *)pt->serv_buf);
693*1c60b9acSAndroid Build Coastguard Worker 	p += accept_len;
694*1c60b9acSAndroid Build Coastguard Worker 
695*1c60b9acSAndroid Build Coastguard Worker 	/* we can only return the protocol header if:
696*1c60b9acSAndroid Build Coastguard Worker 	 *  - one came in, and ... */
697*1c60b9acSAndroid Build Coastguard Worker 	if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) &&
698*1c60b9acSAndroid Build Coastguard Worker 	    /*  - it is not an empty string */
699*1c60b9acSAndroid Build Coastguard Worker 	    wsi->a.protocol->name &&
700*1c60b9acSAndroid Build Coastguard Worker 	    wsi->a.protocol->name[0]) {
701*1c60b9acSAndroid Build Coastguard Worker 		const char *prot = wsi->a.protocol->name;
702*1c60b9acSAndroid Build Coastguard Worker 
703*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_PROXY)
704*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->proxied_ws_parent && wsi->child_list)
705*1c60b9acSAndroid Build Coastguard Worker 			prot = wsi->child_list->ws->actual_protocol;
706*1c60b9acSAndroid Build Coastguard Worker #endif
707*1c60b9acSAndroid Build Coastguard Worker 
708*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SERVER)
709*1c60b9acSAndroid Build Coastguard Worker 		{
710*1c60b9acSAndroid Build Coastguard Worker 			lws_ss_handle_t *sssh = wsi->a.vhost->ss_handle;
711*1c60b9acSAndroid Build Coastguard Worker 
712*1c60b9acSAndroid Build Coastguard Worker 			/*
713*1c60b9acSAndroid Build Coastguard Worker 			 * At the moment, once we see it's a ss ws server, whatever
714*1c60b9acSAndroid Build Coastguard Worker 			 * he asked for we bind him to the ss-ws protocol handler.
715*1c60b9acSAndroid Build Coastguard Worker 			 *
716*1c60b9acSAndroid Build Coastguard Worker 			 * In the response subprotocol header, we need to name
717*1c60b9acSAndroid Build Coastguard Worker 			 *
718*1c60b9acSAndroid Build Coastguard Worker 			 * sssh->policy->u.http.u.ws.subprotocol
719*1c60b9acSAndroid Build Coastguard Worker 			 *
720*1c60b9acSAndroid Build Coastguard Worker 			 * though...
721*1c60b9acSAndroid Build Coastguard Worker 			 */
722*1c60b9acSAndroid Build Coastguard Worker 
723*1c60b9acSAndroid Build Coastguard Worker 			if (sssh && sssh->policy &&
724*1c60b9acSAndroid Build Coastguard Worker 			    sssh->policy->u.http.u.ws.subprotocol)
725*1c60b9acSAndroid Build Coastguard Worker 				prot = sssh->policy->u.http.u.ws.subprotocol;
726*1c60b9acSAndroid Build Coastguard Worker 		}
727*1c60b9acSAndroid Build Coastguard Worker #endif
728*1c60b9acSAndroid Build Coastguard Worker 
729*1c60b9acSAndroid Build Coastguard Worker 		LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Protocol: ");
730*1c60b9acSAndroid Build Coastguard Worker 		p += lws_snprintf(p, 128, "%s", prot);
731*1c60b9acSAndroid Build Coastguard Worker 	}
732*1c60b9acSAndroid Build Coastguard Worker 
733*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
734*1c60b9acSAndroid Build Coastguard Worker 	/*
735*1c60b9acSAndroid Build Coastguard Worker 	 * Figure out which extensions the client has that we want to
736*1c60b9acSAndroid Build Coastguard Worker 	 * enable on this connection, and give him back the list.
737*1c60b9acSAndroid Build Coastguard Worker 	 *
738*1c60b9acSAndroid Build Coastguard Worker 	 * Give him a limited write bugdet
739*1c60b9acSAndroid Build Coastguard Worker 	 */
740*1c60b9acSAndroid Build Coastguard Worker 	if (lws_extension_server_handshake(wsi, &p, 192))
741*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
742*1c60b9acSAndroid Build Coastguard Worker #endif
743*1c60b9acSAndroid Build Coastguard Worker 	LWS_CPYAPP(p, "\x0d\x0a");
744*1c60b9acSAndroid Build Coastguard Worker 
745*1c60b9acSAndroid Build Coastguard Worker 	args.p = p;
746*1c60b9acSAndroid Build Coastguard Worker 	args.max_len = lws_ptr_diff((char *)pt->serv_buf +
747*1c60b9acSAndroid Build Coastguard Worker 				    context->pt_serv_buf_size, p);
748*1c60b9acSAndroid Build Coastguard Worker 	if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi,
749*1c60b9acSAndroid Build Coastguard Worker 					LWS_CALLBACK_ADD_HEADERS,
750*1c60b9acSAndroid Build Coastguard Worker 					wsi->user_space, &args, 0))
751*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
752*1c60b9acSAndroid Build Coastguard Worker 
753*1c60b9acSAndroid Build Coastguard Worker 	p = args.p;
754*1c60b9acSAndroid Build Coastguard Worker 
755*1c60b9acSAndroid Build Coastguard Worker 	/* end of response packet */
756*1c60b9acSAndroid Build Coastguard Worker 
757*1c60b9acSAndroid Build Coastguard Worker 	LWS_CPYAPP(p, "\x0d\x0a");
758*1c60b9acSAndroid Build Coastguard Worker 
759*1c60b9acSAndroid Build Coastguard Worker 	/* okay send the handshake response accepting the connection */
760*1c60b9acSAndroid Build Coastguard Worker 
761*1c60b9acSAndroid Build Coastguard Worker 	lwsl_parser("issuing resp pkt %d len\n",
762*1c60b9acSAndroid Build Coastguard Worker 		    lws_ptr_diff(p, response));
763*1c60b9acSAndroid Build Coastguard Worker #if defined(DEBUG)
764*1c60b9acSAndroid Build Coastguard Worker 	fwrite(response, 1,  p - response, stderr);
765*1c60b9acSAndroid Build Coastguard Worker #endif
766*1c60b9acSAndroid Build Coastguard Worker 	n = lws_write(wsi, (unsigned char *)response, lws_ptr_diff_size_t(p, response),
767*1c60b9acSAndroid Build Coastguard Worker 		      LWS_WRITE_HTTP_HEADERS);
768*1c60b9acSAndroid Build Coastguard Worker 	if (n != lws_ptr_diff(p, response)) {
769*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: ERROR writing to socket %d\n", __func__, n);
770*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
771*1c60b9acSAndroid Build Coastguard Worker 	}
772*1c60b9acSAndroid Build Coastguard Worker 
773*1c60b9acSAndroid Build Coastguard Worker 	/* alright clean up and set ourselves into established state */
774*1c60b9acSAndroid Build Coastguard Worker 
775*1c60b9acSAndroid Build Coastguard Worker 	lwsi_set_state(wsi, LRS_ESTABLISHED);
776*1c60b9acSAndroid Build Coastguard Worker 	wsi->lws_rx_parse_state = LWS_RXPS_NEW;
777*1c60b9acSAndroid Build Coastguard Worker 
778*1c60b9acSAndroid Build Coastguard Worker 	{
779*1c60b9acSAndroid Build Coastguard Worker 		const char * uri_ptr =
780*1c60b9acSAndroid Build Coastguard Worker 			lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI);
781*1c60b9acSAndroid Build Coastguard Worker 		int uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
782*1c60b9acSAndroid Build Coastguard Worker 		const struct lws_http_mount *hit =
783*1c60b9acSAndroid Build Coastguard Worker 			lws_find_mount(wsi, uri_ptr, uri_len);
784*1c60b9acSAndroid Build Coastguard Worker 		if (hit && hit->cgienv &&
785*1c60b9acSAndroid Build Coastguard Worker 		    wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO,
786*1c60b9acSAndroid Build Coastguard Worker 			wsi->user_space, (void *)hit->cgienv, 0))
787*1c60b9acSAndroid Build Coastguard Worker 			return 1;
788*1c60b9acSAndroid Build Coastguard Worker 	}
789*1c60b9acSAndroid Build Coastguard Worker 
790*1c60b9acSAndroid Build Coastguard Worker 	return 0;
791*1c60b9acSAndroid Build Coastguard Worker 
792*1c60b9acSAndroid Build Coastguard Worker bail:
793*1c60b9acSAndroid Build Coastguard Worker 	/* caller will free up his parsing allocations */
794*1c60b9acSAndroid Build Coastguard Worker 	return -1;
795*1c60b9acSAndroid Build Coastguard Worker }
796*1c60b9acSAndroid Build Coastguard Worker 
797*1c60b9acSAndroid Build Coastguard Worker 
798*1c60b9acSAndroid Build Coastguard Worker 
799*1c60b9acSAndroid Build Coastguard Worker /*
800*1c60b9acSAndroid Build Coastguard Worker  * Once we reach LWS_RXPS_WS_FRAME_PAYLOAD, we know how much
801*1c60b9acSAndroid Build Coastguard Worker  * to expect in that state and can deal with it in bulk more efficiently.
802*1c60b9acSAndroid Build Coastguard Worker  */
803*1c60b9acSAndroid Build Coastguard Worker 
804*1c60b9acSAndroid Build Coastguard Worker static int
lws_ws_frame_rest_is_payload(struct lws * wsi,uint8_t ** buf,size_t len)805*1c60b9acSAndroid Build Coastguard Worker lws_ws_frame_rest_is_payload(struct lws *wsi, uint8_t **buf, size_t len)
806*1c60b9acSAndroid Build Coastguard Worker {
807*1c60b9acSAndroid Build Coastguard Worker 	struct lws_ext_pm_deflate_rx_ebufs pmdrx;
808*1c60b9acSAndroid Build Coastguard Worker 	unsigned int avail = (unsigned int)len;
809*1c60b9acSAndroid Build Coastguard Worker 	uint8_t *buffer = *buf, mask[4];
810*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
811*1c60b9acSAndroid Build Coastguard Worker 	unsigned int old_packet_length = (unsigned int)wsi->ws->rx_packet_length;
812*1c60b9acSAndroid Build Coastguard Worker #endif
813*1c60b9acSAndroid Build Coastguard Worker 	int n = 0;
814*1c60b9acSAndroid Build Coastguard Worker 
815*1c60b9acSAndroid Build Coastguard Worker 	/*
816*1c60b9acSAndroid Build Coastguard Worker 	 * With zlib, we can give it as much input as we like.  The pmd
817*1c60b9acSAndroid Build Coastguard Worker 	 * extension will draw it down in chunks (default 1024).
818*1c60b9acSAndroid Build Coastguard Worker 	 *
819*1c60b9acSAndroid Build Coastguard Worker 	 * If we try to restrict how much we give it, because we must go
820*1c60b9acSAndroid Build Coastguard Worker 	 * back to the event loop each time, we will drop the remainder...
821*1c60b9acSAndroid Build Coastguard Worker 	 */
822*1c60b9acSAndroid Build Coastguard Worker 
823*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
824*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws->count_act_ext)
825*1c60b9acSAndroid Build Coastguard Worker #endif
826*1c60b9acSAndroid Build Coastguard Worker 	{
827*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->a.protocol->rx_buffer_size)
828*1c60b9acSAndroid Build Coastguard Worker 			avail = (unsigned int)wsi->a.protocol->rx_buffer_size;
829*1c60b9acSAndroid Build Coastguard Worker 		else
830*1c60b9acSAndroid Build Coastguard Worker 			avail = wsi->a.context->pt_serv_buf_size;
831*1c60b9acSAndroid Build Coastguard Worker 	}
832*1c60b9acSAndroid Build Coastguard Worker 
833*1c60b9acSAndroid Build Coastguard Worker 	/* do not consume more than we should */
834*1c60b9acSAndroid Build Coastguard Worker 	if (avail > wsi->ws->rx_packet_length)
835*1c60b9acSAndroid Build Coastguard Worker 		avail = (unsigned int)wsi->ws->rx_packet_length;
836*1c60b9acSAndroid Build Coastguard Worker 
837*1c60b9acSAndroid Build Coastguard Worker 	/* do not consume more than what is in the buffer */
838*1c60b9acSAndroid Build Coastguard Worker 	if (avail > len)
839*1c60b9acSAndroid Build Coastguard Worker 		avail = (unsigned int)len;
840*1c60b9acSAndroid Build Coastguard Worker 
841*1c60b9acSAndroid Build Coastguard Worker 	if (!avail)
842*1c60b9acSAndroid Build Coastguard Worker 		return 0;
843*1c60b9acSAndroid Build Coastguard Worker 
844*1c60b9acSAndroid Build Coastguard Worker 	pmdrx.eb_in.token = buffer;
845*1c60b9acSAndroid Build Coastguard Worker 	pmdrx.eb_in.len = (int)avail;
846*1c60b9acSAndroid Build Coastguard Worker 	pmdrx.eb_out.token = buffer;
847*1c60b9acSAndroid Build Coastguard Worker 	pmdrx.eb_out.len = (int)avail;
848*1c60b9acSAndroid Build Coastguard Worker 
849*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws->all_zero_nonce) {
850*1c60b9acSAndroid Build Coastguard Worker 
851*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0; n < 4; n++)
852*1c60b9acSAndroid Build Coastguard Worker 			mask[n] = wsi->ws->mask[(wsi->ws->mask_idx + n) & 3];
853*1c60b9acSAndroid Build Coastguard Worker 
854*1c60b9acSAndroid Build Coastguard Worker 		/* deal with 4-byte chunks using unwrapped loop */
855*1c60b9acSAndroid Build Coastguard Worker 		n = (int)(avail >> 2);
856*1c60b9acSAndroid Build Coastguard Worker 		while (n--) {
857*1c60b9acSAndroid Build Coastguard Worker 			*(buffer) = *(buffer) ^ mask[0];
858*1c60b9acSAndroid Build Coastguard Worker 			buffer++;
859*1c60b9acSAndroid Build Coastguard Worker 			*(buffer) = *(buffer) ^ mask[1];
860*1c60b9acSAndroid Build Coastguard Worker 			buffer++;
861*1c60b9acSAndroid Build Coastguard Worker 			*(buffer) = *(buffer) ^ mask[2];
862*1c60b9acSAndroid Build Coastguard Worker 			buffer++;
863*1c60b9acSAndroid Build Coastguard Worker 			*(buffer) = *(buffer) ^ mask[3];
864*1c60b9acSAndroid Build Coastguard Worker 			buffer++;
865*1c60b9acSAndroid Build Coastguard Worker 		}
866*1c60b9acSAndroid Build Coastguard Worker 		/* and the remaining bytes bytewise */
867*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0; n < (int)(avail & 3); n++) {
868*1c60b9acSAndroid Build Coastguard Worker 			*(buffer) = *(buffer) ^ mask[n];
869*1c60b9acSAndroid Build Coastguard Worker 			buffer++;
870*1c60b9acSAndroid Build Coastguard Worker 		}
871*1c60b9acSAndroid Build Coastguard Worker 
872*1c60b9acSAndroid Build Coastguard Worker 		wsi->ws->mask_idx = (wsi->ws->mask_idx + avail) & 3;
873*1c60b9acSAndroid Build Coastguard Worker 	}
874*1c60b9acSAndroid Build Coastguard Worker 
875*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: using %d of raw input (total %d on offer)\n", __func__,
876*1c60b9acSAndroid Build Coastguard Worker 		    avail, (int)len);
877*1c60b9acSAndroid Build Coastguard Worker 
878*1c60b9acSAndroid Build Coastguard Worker 	(*buf) += avail;
879*1c60b9acSAndroid Build Coastguard Worker 	len -= avail;
880*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->rx_packet_length -= avail;
881*1c60b9acSAndroid Build Coastguard Worker 
882*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
883*1c60b9acSAndroid Build Coastguard Worker 	n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &pmdrx, 0);
884*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: ext says %d / ebuf_out.len %d\n", __func__,  n,
885*1c60b9acSAndroid Build Coastguard Worker 			pmdrx.eb_out.len);
886*1c60b9acSAndroid Build Coastguard Worker 
887*1c60b9acSAndroid Build Coastguard Worker 	/*
888*1c60b9acSAndroid Build Coastguard Worker 	 * ebuf may be pointing somewhere completely different now,
889*1c60b9acSAndroid Build Coastguard Worker 	 * it's the output
890*1c60b9acSAndroid Build Coastguard Worker 	 */
891*1c60b9acSAndroid Build Coastguard Worker 
892*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
893*1c60b9acSAndroid Build Coastguard Worker 		/*
894*1c60b9acSAndroid Build Coastguard Worker 		 * we may rely on this to get RX, just drop connection
895*1c60b9acSAndroid Build Coastguard Worker 		 */
896*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: LWS_EXT_CB_PAYLOAD_RX blew out\n", __func__);
897*1c60b9acSAndroid Build Coastguard Worker 		wsi->socket_is_permanently_unusable = 1;
898*1c60b9acSAndroid Build Coastguard Worker 
899*1c60b9acSAndroid Build Coastguard Worker 		return -1;
900*1c60b9acSAndroid Build Coastguard Worker 	}
901*1c60b9acSAndroid Build Coastguard Worker 
902*1c60b9acSAndroid Build Coastguard Worker 	/*
903*1c60b9acSAndroid Build Coastguard Worker 	 * if we had an rx fragment right at the last compressed byte of the
904*1c60b9acSAndroid Build Coastguard Worker 	 * message, we can get a zero length inflated output, where no prior
905*1c60b9acSAndroid Build Coastguard Worker 	 * rx inflated output marked themselves with FIN, since there was
906*1c60b9acSAndroid Build Coastguard Worker 	 * raw ws payload still to drain at that time.
907*1c60b9acSAndroid Build Coastguard Worker 	 *
908*1c60b9acSAndroid Build Coastguard Worker 	 * Then we need to generate a zero length ws rx that can be understood
909*1c60b9acSAndroid Build Coastguard Worker 	 * as the message completion.
910*1c60b9acSAndroid Build Coastguard Worker 	 */
911*1c60b9acSAndroid Build Coastguard Worker 
912*1c60b9acSAndroid Build Coastguard Worker 	if (!pmdrx.eb_out.len &&	      /* zero-length inflation output */
913*1c60b9acSAndroid Build Coastguard Worker 	    n == PMDR_EMPTY_FINAL &&    /* nothing to drain from the inflator */
914*1c60b9acSAndroid Build Coastguard Worker 	    old_packet_length &&	    /* we gave the inflator new input */
915*1c60b9acSAndroid Build Coastguard Worker 	    !wsi->ws->rx_packet_length &&   /* raw ws packet payload all gone */
916*1c60b9acSAndroid Build Coastguard Worker 	    wsi->ws->final &&		    /* the raw ws packet is a FIN guy */
917*1c60b9acSAndroid Build Coastguard Worker 	    wsi->a.protocol->callback &&
918*1c60b9acSAndroid Build Coastguard Worker 	    !wsi->wsistate_pre_close) {
919*1c60b9acSAndroid Build Coastguard Worker 
920*1c60b9acSAndroid Build Coastguard Worker 		lwsl_ext("%s: issuing zero length FIN pkt\n", __func__);
921*1c60b9acSAndroid Build Coastguard Worker 
922*1c60b9acSAndroid Build Coastguard Worker 		if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi,
923*1c60b9acSAndroid Build Coastguard Worker 						LWS_CALLBACK_RECEIVE,
924*1c60b9acSAndroid Build Coastguard Worker 						wsi->user_space, NULL, 0))
925*1c60b9acSAndroid Build Coastguard Worker 			return -1;
926*1c60b9acSAndroid Build Coastguard Worker 
927*1c60b9acSAndroid Build Coastguard Worker 		return (int)avail;
928*1c60b9acSAndroid Build Coastguard Worker 	}
929*1c60b9acSAndroid Build Coastguard Worker 
930*1c60b9acSAndroid Build Coastguard Worker 	/*
931*1c60b9acSAndroid Build Coastguard Worker 	 * If doing permessage-deflate, above was the only way to get a zero
932*1c60b9acSAndroid Build Coastguard Worker 	 * length receive.  Otherwise we're more willing.
933*1c60b9acSAndroid Build Coastguard Worker 	 */
934*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->ws->count_act_ext && !pmdrx.eb_out.len)
935*1c60b9acSAndroid Build Coastguard Worker 		return (int)avail;
936*1c60b9acSAndroid Build Coastguard Worker 
937*1c60b9acSAndroid Build Coastguard Worker 	if (n == PMDR_HAS_PENDING)
938*1c60b9acSAndroid Build Coastguard Worker 		/* extension had more... main loop will come back */
939*1c60b9acSAndroid Build Coastguard Worker 		lws_add_wsi_to_draining_ext_list(wsi);
940*1c60b9acSAndroid Build Coastguard Worker 	else
941*1c60b9acSAndroid Build Coastguard Worker 		lws_remove_wsi_from_draining_ext_list(wsi);
942*1c60b9acSAndroid Build Coastguard Worker #endif
943*1c60b9acSAndroid Build Coastguard Worker 
944*1c60b9acSAndroid Build Coastguard Worker 	if (pmdrx.eb_out.len &&
945*1c60b9acSAndroid Build Coastguard Worker 	    wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
946*1c60b9acSAndroid Build Coastguard Worker 		if (lws_check_utf8(&wsi->ws->utf8,
947*1c60b9acSAndroid Build Coastguard Worker 				   pmdrx.eb_out.token,
948*1c60b9acSAndroid Build Coastguard Worker 				   (unsigned int)pmdrx.eb_out.len)) {
949*1c60b9acSAndroid Build Coastguard Worker 			lws_close_reason(wsi, LWS_CLOSE_STATUS_INVALID_PAYLOAD,
950*1c60b9acSAndroid Build Coastguard Worker 					 (uint8_t *)"bad utf8", 8);
951*1c60b9acSAndroid Build Coastguard Worker 			goto utf8_fail;
952*1c60b9acSAndroid Build Coastguard Worker 		}
953*1c60b9acSAndroid Build Coastguard Worker 
954*1c60b9acSAndroid Build Coastguard Worker 		/* we are ending partway through utf-8 character? */
955*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->ws->rx_packet_length && wsi->ws->final &&
956*1c60b9acSAndroid Build Coastguard Worker 		    wsi->ws->utf8 && !n) {
957*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("FINAL utf8 error\n");
958*1c60b9acSAndroid Build Coastguard Worker 			lws_close_reason(wsi, LWS_CLOSE_STATUS_INVALID_PAYLOAD,
959*1c60b9acSAndroid Build Coastguard Worker 					 (uint8_t *)"partial utf8", 12);
960*1c60b9acSAndroid Build Coastguard Worker 
961*1c60b9acSAndroid Build Coastguard Worker utf8_fail:
962*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("utf8 error\n");
963*1c60b9acSAndroid Build Coastguard Worker 			lwsl_hexdump_info(pmdrx.eb_out.token, (size_t)pmdrx.eb_out.len);
964*1c60b9acSAndroid Build Coastguard Worker 
965*1c60b9acSAndroid Build Coastguard Worker 			return -1;
966*1c60b9acSAndroid Build Coastguard Worker 		}
967*1c60b9acSAndroid Build Coastguard Worker 	}
968*1c60b9acSAndroid Build Coastguard Worker 
969*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->a.protocol->callback && !wsi->wsistate_pre_close)
970*1c60b9acSAndroid Build Coastguard Worker 		if (user_callback_handle_rxflow(wsi->a.protocol->callback, wsi,
971*1c60b9acSAndroid Build Coastguard Worker 						LWS_CALLBACK_RECEIVE,
972*1c60b9acSAndroid Build Coastguard Worker 						wsi->user_space,
973*1c60b9acSAndroid Build Coastguard Worker 						pmdrx.eb_out.token,
974*1c60b9acSAndroid Build Coastguard Worker 						(unsigned int)pmdrx.eb_out.len))
975*1c60b9acSAndroid Build Coastguard Worker 			return -1;
976*1c60b9acSAndroid Build Coastguard Worker 
977*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->first_fragment = 0;
978*1c60b9acSAndroid Build Coastguard Worker 
979*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
980*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: input used %d, output %d, rem len %d, rx_draining_ext %d\n",
981*1c60b9acSAndroid Build Coastguard Worker 		  __func__, avail, pmdrx.eb_out.len, (int)len,
982*1c60b9acSAndroid Build Coastguard Worker 		  wsi->ws->rx_draining_ext);
983*1c60b9acSAndroid Build Coastguard Worker #endif
984*1c60b9acSAndroid Build Coastguard Worker 
985*1c60b9acSAndroid Build Coastguard Worker 	return (int)avail; /* how much we used from the input */
986*1c60b9acSAndroid Build Coastguard Worker }
987*1c60b9acSAndroid Build Coastguard Worker 
988*1c60b9acSAndroid Build Coastguard Worker 
989*1c60b9acSAndroid Build Coastguard Worker int
lws_parse_ws(struct lws * wsi,unsigned char ** buf,size_t len)990*1c60b9acSAndroid Build Coastguard Worker lws_parse_ws(struct lws *wsi, unsigned char **buf, size_t len)
991*1c60b9acSAndroid Build Coastguard Worker {
992*1c60b9acSAndroid Build Coastguard Worker 	unsigned char *bufin = *buf;
993*1c60b9acSAndroid Build Coastguard Worker 	int m, bulk = 0;
994*1c60b9acSAndroid Build Coastguard Worker 
995*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: received %d byte packet\n", __func__, (int)len);
996*1c60b9acSAndroid Build Coastguard Worker 
997*1c60b9acSAndroid Build Coastguard Worker 	//lwsl_hexdump_notice(*buf, len);
998*1c60b9acSAndroid Build Coastguard Worker 
999*1c60b9acSAndroid Build Coastguard Worker 	/* let the rx protocol state machine have as much as it needs */
1000*1c60b9acSAndroid Build Coastguard Worker 
1001*1c60b9acSAndroid Build Coastguard Worker 	while (len) {
1002*1c60b9acSAndroid Build Coastguard Worker 		/*
1003*1c60b9acSAndroid Build Coastguard Worker 		 * we were accepting input but now we stopped doing so
1004*1c60b9acSAndroid Build Coastguard Worker 		 */
1005*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->rxflow_bitmap) {
1006*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: doing rxflow, caching %d\n", __func__,
1007*1c60b9acSAndroid Build Coastguard Worker 				(int)len);
1008*1c60b9acSAndroid Build Coastguard Worker 			/*
1009*1c60b9acSAndroid Build Coastguard Worker 			 * Since we cached the remaining available input, we
1010*1c60b9acSAndroid Build Coastguard Worker 			 * can say we "consumed" it.
1011*1c60b9acSAndroid Build Coastguard Worker 			 *
1012*1c60b9acSAndroid Build Coastguard Worker 			 * But what about the case where the available input
1013*1c60b9acSAndroid Build Coastguard Worker 			 * came out of the rxflow cache already?  If we are
1014*1c60b9acSAndroid Build Coastguard Worker 			 * effectively "putting it back in the cache", we have
1015*1c60b9acSAndroid Build Coastguard Worker 			 * leave it where it is, already pointed to by the head.
1016*1c60b9acSAndroid Build Coastguard Worker 			 */
1017*1c60b9acSAndroid Build Coastguard Worker 			if (lws_rxflow_cache(wsi, *buf, 0, len) ==
1018*1c60b9acSAndroid Build Coastguard Worker 							LWSRXFC_TRIMMED) {
1019*1c60b9acSAndroid Build Coastguard Worker 				/*
1020*1c60b9acSAndroid Build Coastguard Worker 				 * We dealt with it by trimming the existing
1021*1c60b9acSAndroid Build Coastguard Worker 				 * rxflow cache HEAD to account for what we used.
1022*1c60b9acSAndroid Build Coastguard Worker 				 *
1023*1c60b9acSAndroid Build Coastguard Worker 				 * so he doesn't do any consumed processing
1024*1c60b9acSAndroid Build Coastguard Worker 				 */
1025*1c60b9acSAndroid Build Coastguard Worker 				lwsl_info("%s: trimming inside rxflow cache\n",
1026*1c60b9acSAndroid Build Coastguard Worker 					  __func__);
1027*1c60b9acSAndroid Build Coastguard Worker 				*buf = bufin;
1028*1c60b9acSAndroid Build Coastguard Worker 			} else
1029*1c60b9acSAndroid Build Coastguard Worker 				*buf += len;
1030*1c60b9acSAndroid Build Coastguard Worker 
1031*1c60b9acSAndroid Build Coastguard Worker 			return 1;
1032*1c60b9acSAndroid Build Coastguard Worker 		}
1033*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1034*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->rx_draining_ext) {
1035*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s: draining rx ext\n", __func__);
1036*1c60b9acSAndroid Build Coastguard Worker 			m = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR, 0);
1037*1c60b9acSAndroid Build Coastguard Worker 			if (m < 0)
1038*1c60b9acSAndroid Build Coastguard Worker 				return -1;
1039*1c60b9acSAndroid Build Coastguard Worker 			continue;
1040*1c60b9acSAndroid Build Coastguard Worker 		}
1041*1c60b9acSAndroid Build Coastguard Worker #endif
1042*1c60b9acSAndroid Build Coastguard Worker 
1043*1c60b9acSAndroid Build Coastguard Worker 		/* consume payload bytes efficiently */
1044*1c60b9acSAndroid Build Coastguard Worker 		while (wsi->lws_rx_parse_state == LWS_RXPS_WS_FRAME_PAYLOAD &&
1045*1c60b9acSAndroid Build Coastguard Worker 				(wsi->ws->opcode == LWSWSOPC_TEXT_FRAME ||
1046*1c60b9acSAndroid Build Coastguard Worker 				 wsi->ws->opcode == LWSWSOPC_BINARY_FRAME ||
1047*1c60b9acSAndroid Build Coastguard Worker 				 wsi->ws->opcode == LWSWSOPC_CONTINUATION) &&
1048*1c60b9acSAndroid Build Coastguard Worker 		       len) {
1049*1c60b9acSAndroid Build Coastguard Worker 			uint8_t *bin = *buf;
1050*1c60b9acSAndroid Build Coastguard Worker 
1051*1c60b9acSAndroid Build Coastguard Worker 			bulk = 1;
1052*1c60b9acSAndroid Build Coastguard Worker 			m = lws_ws_frame_rest_is_payload(wsi, buf, len);
1053*1c60b9acSAndroid Build Coastguard Worker 			assert((int)lws_ptr_diff(*buf, bin) <= (int)len);
1054*1c60b9acSAndroid Build Coastguard Worker 			len -= lws_ptr_diff_size_t(*buf, bin);
1055*1c60b9acSAndroid Build Coastguard Worker 
1056*1c60b9acSAndroid Build Coastguard Worker 			if (!m) {
1057*1c60b9acSAndroid Build Coastguard Worker 
1058*1c60b9acSAndroid Build Coastguard Worker 				break;
1059*1c60b9acSAndroid Build Coastguard Worker 			}
1060*1c60b9acSAndroid Build Coastguard Worker 			if (m < 0) {
1061*1c60b9acSAndroid Build Coastguard Worker 				lwsl_info("%s: rest_is_payload bailed\n",
1062*1c60b9acSAndroid Build Coastguard Worker 					  __func__);
1063*1c60b9acSAndroid Build Coastguard Worker 				return -1;
1064*1c60b9acSAndroid Build Coastguard Worker 			}
1065*1c60b9acSAndroid Build Coastguard Worker 		}
1066*1c60b9acSAndroid Build Coastguard Worker 
1067*1c60b9acSAndroid Build Coastguard Worker 		if (!bulk) {
1068*1c60b9acSAndroid Build Coastguard Worker 			/* process the byte */
1069*1c60b9acSAndroid Build Coastguard Worker 			m = lws_ws_rx_sm(wsi, 0, *(*buf)++);
1070*1c60b9acSAndroid Build Coastguard Worker 			len--;
1071*1c60b9acSAndroid Build Coastguard Worker 		} else {
1072*1c60b9acSAndroid Build Coastguard Worker 			/*
1073*1c60b9acSAndroid Build Coastguard Worker 			 * We already handled this byte in bulk, just deal
1074*1c60b9acSAndroid Build Coastguard Worker 			 * with the ramifications
1075*1c60b9acSAndroid Build Coastguard Worker 			 */
1076*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
1077*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s: coming out of bulk with len %d, "
1078*1c60b9acSAndroid Build Coastguard Worker 				   "wsi->ws->rx_draining_ext %d\n",
1079*1c60b9acSAndroid Build Coastguard Worker 				   __func__, (int)len,
1080*1c60b9acSAndroid Build Coastguard Worker 				   wsi->ws->rx_draining_ext);
1081*1c60b9acSAndroid Build Coastguard Worker #endif
1082*1c60b9acSAndroid Build Coastguard Worker 			m = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR |
1083*1c60b9acSAndroid Build Coastguard Worker 					      ALREADY_PROCESSED_NO_CB, 0);
1084*1c60b9acSAndroid Build Coastguard Worker 		}
1085*1c60b9acSAndroid Build Coastguard Worker 
1086*1c60b9acSAndroid Build Coastguard Worker 		if (m < 0) {
1087*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: lws_ws_rx_sm bailed %d\n", __func__,
1088*1c60b9acSAndroid Build Coastguard Worker 				  bulk);
1089*1c60b9acSAndroid Build Coastguard Worker 
1090*1c60b9acSAndroid Build Coastguard Worker 			return -1;
1091*1c60b9acSAndroid Build Coastguard Worker 		}
1092*1c60b9acSAndroid Build Coastguard Worker 
1093*1c60b9acSAndroid Build Coastguard Worker 		bulk = 0;
1094*1c60b9acSAndroid Build Coastguard Worker 	}
1095*1c60b9acSAndroid Build Coastguard Worker 
1096*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: exit with %d unused\n", __func__, (int)len);
1097*1c60b9acSAndroid Build Coastguard Worker 
1098*1c60b9acSAndroid Build Coastguard Worker 	return 0;
1099*1c60b9acSAndroid Build Coastguard Worker }
1100