xref: /aosp_15_r20/external/libwebsockets/lib/roles/ws/client-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 /*
28*1c60b9acSAndroid Build Coastguard Worker  * In-place str to lower case
29*1c60b9acSAndroid Build Coastguard Worker  */
30*1c60b9acSAndroid Build Coastguard Worker 
31*1c60b9acSAndroid Build Coastguard Worker static void
strtolower(char * s)32*1c60b9acSAndroid Build Coastguard Worker strtolower(char *s)
33*1c60b9acSAndroid Build Coastguard Worker {
34*1c60b9acSAndroid Build Coastguard Worker 	while (*s) {
35*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_PLAT_OPTEE
36*1c60b9acSAndroid Build Coastguard Worker 		int tolower_optee(int c);
37*1c60b9acSAndroid Build Coastguard Worker 		*s = tolower_optee((int)*s);
38*1c60b9acSAndroid Build Coastguard Worker #else
39*1c60b9acSAndroid Build Coastguard Worker 		*s = (char)tolower((int)*s);
40*1c60b9acSAndroid Build Coastguard Worker #endif
41*1c60b9acSAndroid Build Coastguard Worker 		s++;
42*1c60b9acSAndroid Build Coastguard Worker 	}
43*1c60b9acSAndroid Build Coastguard Worker }
44*1c60b9acSAndroid Build Coastguard Worker 
45*1c60b9acSAndroid Build Coastguard Worker int
lws_create_client_ws_object(const struct lws_client_connect_info * i,struct lws * wsi)46*1c60b9acSAndroid Build Coastguard Worker lws_create_client_ws_object(const struct lws_client_connect_info *i,
47*1c60b9acSAndroid Build Coastguard Worker 			    struct lws *wsi)
48*1c60b9acSAndroid Build Coastguard Worker {
49*1c60b9acSAndroid Build Coastguard Worker 	int v = SPEC_LATEST_SUPPORTED;
50*1c60b9acSAndroid Build Coastguard Worker 
51*1c60b9acSAndroid Build Coastguard Worker 	/* allocate the ws struct for the wsi */
52*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws = lws_zalloc(sizeof(*wsi->ws), "client ws struct");
53*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws) {
54*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_notice(wsi, "OOM");
55*1c60b9acSAndroid Build Coastguard Worker 		return 1;
56*1c60b9acSAndroid Build Coastguard Worker 	}
57*1c60b9acSAndroid Build Coastguard Worker 
58*1c60b9acSAndroid Build Coastguard Worker 	/* -1 means just use latest supported */
59*1c60b9acSAndroid Build Coastguard Worker 	if (i->ietf_version_or_minus_one != -1 &&
60*1c60b9acSAndroid Build Coastguard Worker 	    i->ietf_version_or_minus_one)
61*1c60b9acSAndroid Build Coastguard Worker 		v = i->ietf_version_or_minus_one;
62*1c60b9acSAndroid Build Coastguard Worker 
63*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->ietf_spec_revision = (uint8_t)v;
64*1c60b9acSAndroid Build Coastguard Worker 
65*1c60b9acSAndroid Build Coastguard Worker 	return 0;
66*1c60b9acSAndroid Build Coastguard Worker }
67*1c60b9acSAndroid Build Coastguard Worker 
68*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
69*1c60b9acSAndroid Build Coastguard Worker int
lws_ws_handshake_client(struct lws * wsi,unsigned char ** buf,size_t len)70*1c60b9acSAndroid Build Coastguard Worker lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len)
71*1c60b9acSAndroid Build Coastguard Worker {
72*1c60b9acSAndroid Build Coastguard Worker 	unsigned char *bufin = *buf;
73*1c60b9acSAndroid Build Coastguard Worker 
74*1c60b9acSAndroid Build Coastguard Worker 	if ((lwsi_state(wsi) != LRS_WAITING_PROXY_REPLY) &&
75*1c60b9acSAndroid Build Coastguard Worker 	    (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE) &&
76*1c60b9acSAndroid Build Coastguard Worker 	    (lwsi_state(wsi) != LRS_WAITING_SERVER_REPLY) &&
77*1c60b9acSAndroid Build Coastguard Worker 	    !lwsi_role_client(wsi))
78*1c60b9acSAndroid Build Coastguard Worker 		return 0;
79*1c60b9acSAndroid Build Coastguard Worker 
80*1c60b9acSAndroid Build Coastguard Worker 	lwsl_wsi_debug(wsi, "hs client feels it has %d in", (int)len);
81*1c60b9acSAndroid Build Coastguard Worker 
82*1c60b9acSAndroid Build Coastguard Worker 	while (len) {
83*1c60b9acSAndroid Build Coastguard Worker 		/*
84*1c60b9acSAndroid Build Coastguard Worker 		 * we were accepting input but now we stopped doing so
85*1c60b9acSAndroid Build Coastguard Worker 		 */
86*1c60b9acSAndroid Build Coastguard Worker 		if (lws_is_flowcontrolled(wsi)) {
87*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_debug(wsi, "caching %ld", (long)len);
88*1c60b9acSAndroid Build Coastguard Worker 			/*
89*1c60b9acSAndroid Build Coastguard Worker 			 * Since we cached the remaining available input, we
90*1c60b9acSAndroid Build Coastguard Worker 			 * can say we "consumed" it.
91*1c60b9acSAndroid Build Coastguard Worker 			 *
92*1c60b9acSAndroid Build Coastguard Worker 			 * But what about the case where the available input
93*1c60b9acSAndroid Build Coastguard Worker 			 * came out of the rxflow cache already?  If we are
94*1c60b9acSAndroid Build Coastguard Worker 			 * effectively "putting it back in the cache", we have
95*1c60b9acSAndroid Build Coastguard Worker 			 * to place it at the cache head, not the tail as usual.
96*1c60b9acSAndroid Build Coastguard Worker 			 */
97*1c60b9acSAndroid Build Coastguard Worker 			if (lws_rxflow_cache(wsi, *buf, 0, len) ==
98*1c60b9acSAndroid Build Coastguard Worker 							LWSRXFC_TRIMMED) {
99*1c60b9acSAndroid Build Coastguard Worker 				/*
100*1c60b9acSAndroid Build Coastguard Worker 				 * we dealt with it by trimming the existing
101*1c60b9acSAndroid Build Coastguard Worker 				 * rxflow cache HEAD to account for what we used.
102*1c60b9acSAndroid Build Coastguard Worker 				 *
103*1c60b9acSAndroid Build Coastguard Worker 				 * indicate we didn't use anything to the caller
104*1c60b9acSAndroid Build Coastguard Worker 				 * so he doesn't do any consumed processing
105*1c60b9acSAndroid Build Coastguard Worker 				 */
106*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_info(wsi, "trimming inside rxflow cache");
107*1c60b9acSAndroid Build Coastguard Worker 				*buf = bufin;
108*1c60b9acSAndroid Build Coastguard Worker 			} else
109*1c60b9acSAndroid Build Coastguard Worker 				*buf += len;
110*1c60b9acSAndroid Build Coastguard Worker 
111*1c60b9acSAndroid Build Coastguard Worker 			return 0;
112*1c60b9acSAndroid Build Coastguard Worker 		}
113*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
114*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->ws->rx_draining_ext) {
115*1c60b9acSAndroid Build Coastguard Worker 			int m;
116*1c60b9acSAndroid Build Coastguard Worker 
117*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_info(wsi, "draining ext");
118*1c60b9acSAndroid Build Coastguard Worker 			if (lwsi_role_client(wsi))
119*1c60b9acSAndroid Build Coastguard Worker 				m = lws_ws_client_rx_sm(wsi, 0);
120*1c60b9acSAndroid Build Coastguard Worker 			else
121*1c60b9acSAndroid Build Coastguard Worker 				m = lws_ws_rx_sm(wsi, 0, 0);
122*1c60b9acSAndroid Build Coastguard Worker 			if (m < 0)
123*1c60b9acSAndroid Build Coastguard Worker 				return -1;
124*1c60b9acSAndroid Build Coastguard Worker 			continue;
125*1c60b9acSAndroid Build Coastguard Worker 		}
126*1c60b9acSAndroid Build Coastguard Worker #endif
127*1c60b9acSAndroid Build Coastguard Worker 		/*
128*1c60b9acSAndroid Build Coastguard Worker 		 * caller will account for buflist usage by studying what
129*1c60b9acSAndroid Build Coastguard Worker 		 * happened to *buf
130*1c60b9acSAndroid Build Coastguard Worker 		 */
131*1c60b9acSAndroid Build Coastguard Worker 
132*1c60b9acSAndroid Build Coastguard Worker 		if (lws_ws_client_rx_sm(wsi, *(*buf)++)) {
133*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_info(wsi, "client_rx_sm exited, DROPPING %d",
134*1c60b9acSAndroid Build Coastguard Worker 				      (int)len);
135*1c60b9acSAndroid Build Coastguard Worker 			return -1;
136*1c60b9acSAndroid Build Coastguard Worker 		}
137*1c60b9acSAndroid Build Coastguard Worker 		len--;
138*1c60b9acSAndroid Build Coastguard Worker 	}
139*1c60b9acSAndroid Build Coastguard Worker 	// lwsl_wsi_notice(wsi, "finished with %ld", (long)len);
140*1c60b9acSAndroid Build Coastguard Worker 
141*1c60b9acSAndroid Build Coastguard Worker 	return 0;
142*1c60b9acSAndroid Build Coastguard Worker }
143*1c60b9acSAndroid Build Coastguard Worker #endif
144*1c60b9acSAndroid Build Coastguard Worker 
145*1c60b9acSAndroid Build Coastguard Worker char *
lws_generate_client_ws_handshake(struct lws * wsi,char * p,const char * conn1)146*1c60b9acSAndroid Build Coastguard Worker lws_generate_client_ws_handshake(struct lws *wsi, char *p, const char *conn1)
147*1c60b9acSAndroid Build Coastguard Worker {
148*1c60b9acSAndroid Build Coastguard Worker 	char buf[128], hash[20], key_b64[40];
149*1c60b9acSAndroid Build Coastguard Worker 	int n;
150*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
151*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_extension *ext;
152*1c60b9acSAndroid Build Coastguard Worker 	int ext_count = 0;
153*1c60b9acSAndroid Build Coastguard Worker #endif
154*1c60b9acSAndroid Build Coastguard Worker 
155*1c60b9acSAndroid Build Coastguard Worker 	/*
156*1c60b9acSAndroid Build Coastguard Worker 	 * create the random key
157*1c60b9acSAndroid Build Coastguard Worker 	 */
158*1c60b9acSAndroid Build Coastguard Worker 	if (lws_get_random(wsi->a.context, hash, 16) != 16) {
159*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_err(wsi, "Unable to read from random dev %s",
160*1c60b9acSAndroid Build Coastguard Worker 			 SYSTEM_RANDOM_FILEPATH);
161*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
162*1c60b9acSAndroid Build Coastguard Worker 	}
163*1c60b9acSAndroid Build Coastguard Worker 
164*1c60b9acSAndroid Build Coastguard Worker 	/* coverity[tainted_scalar] */
165*1c60b9acSAndroid Build Coastguard Worker 	lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));
166*1c60b9acSAndroid Build Coastguard Worker 
167*1c60b9acSAndroid Build Coastguard Worker 	p += sprintf(p, "Upgrade: websocket\x0d\x0a"
168*1c60b9acSAndroid Build Coastguard Worker 			"Connection: %sUpgrade\x0d\x0a"
169*1c60b9acSAndroid Build Coastguard Worker 			"Sec-WebSocket-Key: ", conn1);
170*1c60b9acSAndroid Build Coastguard Worker 	strcpy(p, key_b64);
171*1c60b9acSAndroid Build Coastguard Worker 	p += strlen(key_b64);
172*1c60b9acSAndroid Build Coastguard Worker 	p += sprintf(p, "\x0d\x0a");
173*1c60b9acSAndroid Build Coastguard Worker 	if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS))
174*1c60b9acSAndroid Build Coastguard Worker 		p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
175*1c60b9acSAndroid Build Coastguard Worker 		     lws_hdr_simple_ptr(wsi,
176*1c60b9acSAndroid Build Coastguard Worker 				     _WSI_TOKEN_CLIENT_SENT_PROTOCOLS));
177*1c60b9acSAndroid Build Coastguard Worker 
178*1c60b9acSAndroid Build Coastguard Worker 	/* tell the server what extensions we could support */
179*1c60b9acSAndroid Build Coastguard Worker 
180*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
181*1c60b9acSAndroid Build Coastguard Worker 	ext = wsi->a.vhost->ws.extensions;
182*1c60b9acSAndroid Build Coastguard Worker 	while (ext && ext->callback) {
183*1c60b9acSAndroid Build Coastguard Worker 
184*1c60b9acSAndroid Build Coastguard Worker 		n = wsi->a.vhost->protocols[0].callback(wsi,
185*1c60b9acSAndroid Build Coastguard Worker 			LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
186*1c60b9acSAndroid Build Coastguard Worker 				wsi->user_space, (char *)ext->name, 0);
187*1c60b9acSAndroid Build Coastguard Worker 
188*1c60b9acSAndroid Build Coastguard Worker 		/*
189*1c60b9acSAndroid Build Coastguard Worker 		 * zero return from callback means go ahead and allow
190*1c60b9acSAndroid Build Coastguard Worker 		 * the extension, it's what we get if the callback is
191*1c60b9acSAndroid Build Coastguard Worker 		 * unhandled
192*1c60b9acSAndroid Build Coastguard Worker 		 */
193*1c60b9acSAndroid Build Coastguard Worker 
194*1c60b9acSAndroid Build Coastguard Worker 		if (n) {
195*1c60b9acSAndroid Build Coastguard Worker 			ext++;
196*1c60b9acSAndroid Build Coastguard Worker 			continue;
197*1c60b9acSAndroid Build Coastguard Worker 		}
198*1c60b9acSAndroid Build Coastguard Worker 
199*1c60b9acSAndroid Build Coastguard Worker 		/* apply it */
200*1c60b9acSAndroid Build Coastguard Worker 
201*1c60b9acSAndroid Build Coastguard Worker 		if (ext_count)
202*1c60b9acSAndroid Build Coastguard Worker 			*p++ = ',';
203*1c60b9acSAndroid Build Coastguard Worker 		else
204*1c60b9acSAndroid Build Coastguard Worker 			p += sprintf(p, "Sec-WebSocket-Extensions: ");
205*1c60b9acSAndroid Build Coastguard Worker 		p += sprintf(p, "%s", ext->client_offer);
206*1c60b9acSAndroid Build Coastguard Worker 		ext_count++;
207*1c60b9acSAndroid Build Coastguard Worker 
208*1c60b9acSAndroid Build Coastguard Worker 		ext++;
209*1c60b9acSAndroid Build Coastguard Worker 	}
210*1c60b9acSAndroid Build Coastguard Worker 	if (ext_count)
211*1c60b9acSAndroid Build Coastguard Worker 		p += sprintf(p, "\x0d\x0a");
212*1c60b9acSAndroid Build Coastguard Worker #endif
213*1c60b9acSAndroid Build Coastguard Worker 
214*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->ws->ietf_spec_revision)
215*1c60b9acSAndroid Build Coastguard Worker 		p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
216*1c60b9acSAndroid Build Coastguard Worker 			     wsi->ws->ietf_spec_revision);
217*1c60b9acSAndroid Build Coastguard Worker 
218*1c60b9acSAndroid Build Coastguard Worker 	/* prepare the expected server accept response */
219*1c60b9acSAndroid Build Coastguard Worker 
220*1c60b9acSAndroid Build Coastguard Worker 	key_b64[39] = '\0'; /* enforce composed length below buf sizeof */
221*1c60b9acSAndroid Build Coastguard Worker 	n = sprintf(buf, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
222*1c60b9acSAndroid Build Coastguard Worker 			  key_b64);
223*1c60b9acSAndroid Build Coastguard Worker 
224*1c60b9acSAndroid Build Coastguard Worker 	lws_SHA1((unsigned char *)buf, (unsigned int)n, (unsigned char *)hash);
225*1c60b9acSAndroid Build Coastguard Worker 
226*1c60b9acSAndroid Build Coastguard Worker 	lws_b64_encode_string(hash, 20,
227*1c60b9acSAndroid Build Coastguard Worker 		  wsi->http.ah->initial_handshake_hash_base64,
228*1c60b9acSAndroid Build Coastguard Worker 		  sizeof(wsi->http.ah->initial_handshake_hash_base64));
229*1c60b9acSAndroid Build Coastguard Worker 
230*1c60b9acSAndroid Build Coastguard Worker 	return p;
231*1c60b9acSAndroid Build Coastguard Worker }
232*1c60b9acSAndroid Build Coastguard Worker 
233*1c60b9acSAndroid Build Coastguard Worker int
lws_client_ws_upgrade(struct lws * wsi,const char ** cce)234*1c60b9acSAndroid Build Coastguard Worker lws_client_ws_upgrade(struct lws *wsi, const char **cce)
235*1c60b9acSAndroid Build Coastguard Worker {
236*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context = wsi->a.context;
237*1c60b9acSAndroid Build Coastguard Worker 	struct lws_tokenize ts;
238*1c60b9acSAndroid Build Coastguard Worker 	int n, len, okay = 0;
239*1c60b9acSAndroid Build Coastguard Worker 	lws_tokenize_elem e;
240*1c60b9acSAndroid Build Coastguard Worker 	char *p, buf[64];
241*1c60b9acSAndroid Build Coastguard Worker 	const char *pc;
242*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
243*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
244*1c60b9acSAndroid Build Coastguard Worker 	char *sb = (char *)&pt->serv_buf[0];
245*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_ext_options *opts;
246*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_extension *ext;
247*1c60b9acSAndroid Build Coastguard Worker 	char ext_name[128];
248*1c60b9acSAndroid Build Coastguard Worker 	const char *c, *a;
249*1c60b9acSAndroid Build Coastguard Worker 	int more = 1;
250*1c60b9acSAndroid Build Coastguard Worker 	char ignore;
251*1c60b9acSAndroid Build Coastguard Worker #endif
252*1c60b9acSAndroid Build Coastguard Worker 
253*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->client_mux_substream) {/* !!! client ws-over-h2 not there yet */
254*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_warn(wsi, "client ws-over-h2 upgrade not supported yet");
255*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: h2 / ws upgrade unsupported";
256*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
257*1c60b9acSAndroid Build Coastguard Worker 	}
258*1c60b9acSAndroid Build Coastguard Worker 
259*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->http.ah->http_response == 401) {
260*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_warn(wsi, "got bad HTTP response '%d'",
261*1c60b9acSAndroid Build Coastguard Worker 			      wsi->http.ah->http_response);
262*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: ws upgrade unauthorized";
263*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
264*1c60b9acSAndroid Build Coastguard Worker 	}
265*1c60b9acSAndroid Build Coastguard Worker 
266*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->http.ah->http_response != 101) {
267*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_warn(wsi, "got bad HTTP response '%d'",
268*1c60b9acSAndroid Build Coastguard Worker 			      wsi->http.ah->http_response);
269*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: ws upgrade response not 101";
270*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
271*1c60b9acSAndroid Build Coastguard Worker 	}
272*1c60b9acSAndroid Build Coastguard Worker 
273*1c60b9acSAndroid Build Coastguard Worker 	if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
274*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_info(wsi, "no ACCEPT");
275*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: ACCEPT missing";
276*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
277*1c60b9acSAndroid Build Coastguard Worker 	}
278*1c60b9acSAndroid Build Coastguard Worker 
279*1c60b9acSAndroid Build Coastguard Worker 	p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE);
280*1c60b9acSAndroid Build Coastguard Worker 	if (!p) {
281*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_info(wsi, "no UPGRADE");
282*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: UPGRADE missing";
283*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
284*1c60b9acSAndroid Build Coastguard Worker 	}
285*1c60b9acSAndroid Build Coastguard Worker 	strtolower(p);
286*1c60b9acSAndroid Build Coastguard Worker 	if (strcmp(p, "websocket")) {
287*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_warn(wsi, "got bad Upgrade header '%s'", p);
288*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: Upgrade to something other than websocket";
289*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
290*1c60b9acSAndroid Build Coastguard Worker 	}
291*1c60b9acSAndroid Build Coastguard Worker 
292*1c60b9acSAndroid Build Coastguard Worker 	/* connection: must have "upgrade" */
293*1c60b9acSAndroid Build Coastguard Worker 
294*1c60b9acSAndroid Build Coastguard Worker 	lws_tokenize_init(&ts, buf, LWS_TOKENIZE_F_COMMA_SEP_LIST |
295*1c60b9acSAndroid Build Coastguard Worker 				    LWS_TOKENIZE_F_MINUS_NONTERM);
296*1c60b9acSAndroid Build Coastguard Worker 	n = lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_CONNECTION);
297*1c60b9acSAndroid Build Coastguard Worker 	if (n <= 0) /* won't fit, or absent */
298*1c60b9acSAndroid Build Coastguard Worker 		goto bad_conn_format;
299*1c60b9acSAndroid Build Coastguard Worker 	ts.len = (unsigned int)n;
300*1c60b9acSAndroid Build Coastguard Worker 
301*1c60b9acSAndroid Build Coastguard Worker 	do {
302*1c60b9acSAndroid Build Coastguard Worker 		e = lws_tokenize(&ts);
303*1c60b9acSAndroid Build Coastguard Worker 		switch (e) {
304*1c60b9acSAndroid Build Coastguard Worker 		case LWS_TOKZE_TOKEN:
305*1c60b9acSAndroid Build Coastguard Worker 			if (!strncasecmp(ts.token, "upgrade", ts.token_len))
306*1c60b9acSAndroid Build Coastguard Worker 				e = LWS_TOKZE_ENDED;
307*1c60b9acSAndroid Build Coastguard Worker 			break;
308*1c60b9acSAndroid Build Coastguard Worker 
309*1c60b9acSAndroid Build Coastguard Worker 		case LWS_TOKZE_DELIMITER:
310*1c60b9acSAndroid Build Coastguard Worker 			break;
311*1c60b9acSAndroid Build Coastguard Worker 
312*1c60b9acSAndroid Build Coastguard Worker 		default: /* includes ENDED found by the tokenizer itself */
313*1c60b9acSAndroid Build Coastguard Worker bad_conn_format:
314*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_info(wsi, "malformed connection '%s'", buf);
315*1c60b9acSAndroid Build Coastguard Worker 			*cce = "HS: UPGRADE malformed";
316*1c60b9acSAndroid Build Coastguard Worker 			goto bail3;
317*1c60b9acSAndroid Build Coastguard Worker 		}
318*1c60b9acSAndroid Build Coastguard Worker 	} while (e > 0);
319*1c60b9acSAndroid Build Coastguard Worker 
320*1c60b9acSAndroid Build Coastguard Worker 	pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
321*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
322*1c60b9acSAndroid Build Coastguard Worker 	if (!pc)
323*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_parser(wsi, "lws_client_int_s_hs: no protocol list");
324*1c60b9acSAndroid Build Coastguard Worker 	else
325*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_parser(wsi, "lws_client_int_s_hs: protocol list '%s'", pc);
326*1c60b9acSAndroid Build Coastguard Worker #endif
327*1c60b9acSAndroid Build Coastguard Worker 
328*1c60b9acSAndroid Build Coastguard Worker 	/*
329*1c60b9acSAndroid Build Coastguard Worker 	 * confirm the protocol the server wants to talk was in the list
330*1c60b9acSAndroid Build Coastguard Worker 	 * of protocols we offered
331*1c60b9acSAndroid Build Coastguard Worker 	 */
332*1c60b9acSAndroid Build Coastguard Worker 
333*1c60b9acSAndroid Build Coastguard Worker 	len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
334*1c60b9acSAndroid Build Coastguard Worker 	if (!len) {
335*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_info(wsi, "WSI_TOKEN_PROTOCOL is null");
336*1c60b9acSAndroid Build Coastguard Worker 		/*
337*1c60b9acSAndroid Build Coastguard Worker 		 * no protocol name to work from, if we don't already have one
338*1c60b9acSAndroid Build Coastguard Worker 		 * default to first protocol
339*1c60b9acSAndroid Build Coastguard Worker 		 */
340*1c60b9acSAndroid Build Coastguard Worker 
341*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->a.protocol) {
342*1c60b9acSAndroid Build Coastguard Worker 			p = (char *)wsi->a.protocol->name;
343*1c60b9acSAndroid Build Coastguard Worker 			goto identify_protocol;
344*1c60b9acSAndroid Build Coastguard Worker 		}
345*1c60b9acSAndroid Build Coastguard Worker 
346*1c60b9acSAndroid Build Coastguard Worker 		/* no choice but to use the default protocol */
347*1c60b9acSAndroid Build Coastguard Worker 
348*1c60b9acSAndroid Build Coastguard Worker 		n = 0;
349*1c60b9acSAndroid Build Coastguard Worker 		wsi->a.protocol = &wsi->a.vhost->protocols[0];
350*1c60b9acSAndroid Build Coastguard Worker 		goto check_extensions;
351*1c60b9acSAndroid Build Coastguard Worker 	}
352*1c60b9acSAndroid Build Coastguard Worker 
353*1c60b9acSAndroid Build Coastguard Worker 	p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL);
354*1c60b9acSAndroid Build Coastguard Worker 	len = (int)strlen(p);
355*1c60b9acSAndroid Build Coastguard Worker 
356*1c60b9acSAndroid Build Coastguard Worker 	while (pc && *pc && !okay) {
357*1c60b9acSAndroid Build Coastguard Worker 		if (!strncmp(pc, p, (unsigned int)len) &&
358*1c60b9acSAndroid Build Coastguard Worker 		    (pc[len] == ',' || pc[len] == '\0')) {
359*1c60b9acSAndroid Build Coastguard Worker 			okay = 1;
360*1c60b9acSAndroid Build Coastguard Worker 			continue;
361*1c60b9acSAndroid Build Coastguard Worker 		}
362*1c60b9acSAndroid Build Coastguard Worker 		while (*pc && *pc++ != ',')
363*1c60b9acSAndroid Build Coastguard Worker 			;
364*1c60b9acSAndroid Build Coastguard Worker 		while (*pc == ' ')
365*1c60b9acSAndroid Build Coastguard Worker 			pc++;
366*1c60b9acSAndroid Build Coastguard Worker 	}
367*1c60b9acSAndroid Build Coastguard Worker 
368*1c60b9acSAndroid Build Coastguard Worker 	if (!okay) {
369*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_info(wsi, "got bad protocol %s", p);
370*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: PROTOCOL malformed";
371*1c60b9acSAndroid Build Coastguard Worker 		goto bail2;
372*1c60b9acSAndroid Build Coastguard Worker 	}
373*1c60b9acSAndroid Build Coastguard Worker 
374*1c60b9acSAndroid Build Coastguard Worker identify_protocol:
375*1c60b9acSAndroid Build Coastguard Worker 
376*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_HTTP_PROXY)
377*1c60b9acSAndroid Build Coastguard Worker 	lws_strncpy(wsi->ws->actual_protocol, p,
378*1c60b9acSAndroid Build Coastguard Worker 		    sizeof(wsi->ws->actual_protocol));
379*1c60b9acSAndroid Build Coastguard Worker #endif
380*1c60b9acSAndroid Build Coastguard Worker 
381*1c60b9acSAndroid Build Coastguard Worker 	/*
382*1c60b9acSAndroid Build Coastguard Worker 	 * identify the selected protocol struct and set it
383*1c60b9acSAndroid Build Coastguard Worker 	 */
384*1c60b9acSAndroid Build Coastguard Worker 	n = 0;
385*1c60b9acSAndroid Build Coastguard Worker 	/* keep client connection pre-bound protocol */
386*1c60b9acSAndroid Build Coastguard Worker 	if (!lwsi_role_client(wsi))
387*1c60b9acSAndroid Build Coastguard Worker 		wsi->a.protocol = NULL;
388*1c60b9acSAndroid Build Coastguard Worker 
389*1c60b9acSAndroid Build Coastguard Worker 	while (n < wsi->a.vhost->count_protocols) {
390*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->a.protocol &&
391*1c60b9acSAndroid Build Coastguard Worker 		    strcmp(p, wsi->a.vhost->protocols[n].name) == 0) {
392*1c60b9acSAndroid Build Coastguard Worker 			wsi->a.protocol = &wsi->a.vhost->protocols[n];
393*1c60b9acSAndroid Build Coastguard Worker 			break;
394*1c60b9acSAndroid Build Coastguard Worker 		}
395*1c60b9acSAndroid Build Coastguard Worker 		n++;
396*1c60b9acSAndroid Build Coastguard Worker 	}
397*1c60b9acSAndroid Build Coastguard Worker 
398*1c60b9acSAndroid Build Coastguard Worker 	if (n == wsi->a.vhost->count_protocols) { /* no match */
399*1c60b9acSAndroid Build Coastguard Worker 		/* if server, that's already fatal */
400*1c60b9acSAndroid Build Coastguard Worker 		if (!lwsi_role_client(wsi)) {
401*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_info(wsi, "fail protocol %s", p);
402*1c60b9acSAndroid Build Coastguard Worker 			*cce = "HS: Cannot match protocol";
403*1c60b9acSAndroid Build Coastguard Worker 			goto bail2;
404*1c60b9acSAndroid Build Coastguard Worker 		}
405*1c60b9acSAndroid Build Coastguard Worker 
406*1c60b9acSAndroid Build Coastguard Worker 		/* for client, find the index of our pre-bound protocol */
407*1c60b9acSAndroid Build Coastguard Worker 
408*1c60b9acSAndroid Build Coastguard Worker 		n = 0;
409*1c60b9acSAndroid Build Coastguard Worker 		while (wsi->a.vhost->protocols[n].callback) {
410*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->a.protocol && strcmp(wsi->a.protocol->name,
411*1c60b9acSAndroid Build Coastguard Worker 				   wsi->a.vhost->protocols[n].name) == 0) {
412*1c60b9acSAndroid Build Coastguard Worker 				wsi->a.protocol = &wsi->a.vhost->protocols[n];
413*1c60b9acSAndroid Build Coastguard Worker 				break;
414*1c60b9acSAndroid Build Coastguard Worker 			}
415*1c60b9acSAndroid Build Coastguard Worker 			n++;
416*1c60b9acSAndroid Build Coastguard Worker 		}
417*1c60b9acSAndroid Build Coastguard Worker 
418*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->a.vhost->protocols[n].callback) {
419*1c60b9acSAndroid Build Coastguard Worker 			if (wsi->a.protocol)
420*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_err(wsi, "Failed to match protocol %s",
421*1c60b9acSAndroid Build Coastguard Worker 						wsi->a.protocol->name);
422*1c60b9acSAndroid Build Coastguard Worker 			else
423*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_err(wsi, "No protocol on client");
424*1c60b9acSAndroid Build Coastguard Worker 			*cce = "ws protocol no match";
425*1c60b9acSAndroid Build Coastguard Worker 			goto bail2;
426*1c60b9acSAndroid Build Coastguard Worker 		}
427*1c60b9acSAndroid Build Coastguard Worker 	}
428*1c60b9acSAndroid Build Coastguard Worker 
429*1c60b9acSAndroid Build Coastguard Worker 	lwsl_wsi_debug(wsi, "Selected protocol %s", wsi->a.protocol ?
430*1c60b9acSAndroid Build Coastguard Worker 					     wsi->a.protocol->name : "no pcol");
431*1c60b9acSAndroid Build Coastguard Worker 
432*1c60b9acSAndroid Build Coastguard Worker check_extensions:
433*1c60b9acSAndroid Build Coastguard Worker 	/*
434*1c60b9acSAndroid Build Coastguard Worker 	 * stitch protocol choice into the vh protocol linked list
435*1c60b9acSAndroid Build Coastguard Worker 	 * We always insert ourselves at the start of the list
436*1c60b9acSAndroid Build Coastguard Worker 	 *
437*1c60b9acSAndroid Build Coastguard Worker 	 * X <-> B
438*1c60b9acSAndroid Build Coastguard Worker 	 * X <-> pAn <-> pB
439*1c60b9acSAndroid Build Coastguard Worker 	 */
440*1c60b9acSAndroid Build Coastguard Worker 
441*1c60b9acSAndroid Build Coastguard Worker 	lws_same_vh_protocol_insert(wsi, n);
442*1c60b9acSAndroid Build Coastguard Worker 
443*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
444*1c60b9acSAndroid Build Coastguard Worker 	/* instantiate the accepted extensions */
445*1c60b9acSAndroid Build Coastguard Worker 
446*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) {
447*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_ext(wsi, "no client extensions allowed by server");
448*1c60b9acSAndroid Build Coastguard Worker 		goto check_accept;
449*1c60b9acSAndroid Build Coastguard Worker 	}
450*1c60b9acSAndroid Build Coastguard Worker 
451*1c60b9acSAndroid Build Coastguard Worker 	/*
452*1c60b9acSAndroid Build Coastguard Worker 	 * break down the list of server accepted extensions
453*1c60b9acSAndroid Build Coastguard Worker 	 * and go through matching them or identifying bogons
454*1c60b9acSAndroid Build Coastguard Worker 	 */
455*1c60b9acSAndroid Build Coastguard Worker 
456*1c60b9acSAndroid Build Coastguard Worker 	if (lws_hdr_copy(wsi, sb, (int)context->pt_serv_buf_size,
457*1c60b9acSAndroid Build Coastguard Worker 			 WSI_TOKEN_EXTENSIONS) < 0) {
458*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_warn(wsi, "ext list from server failed to copy");
459*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: EXT: list too big";
460*1c60b9acSAndroid Build Coastguard Worker 		goto bail2;
461*1c60b9acSAndroid Build Coastguard Worker 	}
462*1c60b9acSAndroid Build Coastguard Worker 
463*1c60b9acSAndroid Build Coastguard Worker 	c = sb;
464*1c60b9acSAndroid Build Coastguard Worker 	n = 0;
465*1c60b9acSAndroid Build Coastguard Worker 	ignore = 0;
466*1c60b9acSAndroid Build Coastguard Worker 	a = NULL;
467*1c60b9acSAndroid Build Coastguard Worker 	while (more) {
468*1c60b9acSAndroid Build Coastguard Worker 
469*1c60b9acSAndroid Build Coastguard Worker 		if (*c && (*c != ',' && *c != '\t')) {
470*1c60b9acSAndroid Build Coastguard Worker 			if (*c == ';') {
471*1c60b9acSAndroid Build Coastguard Worker 				ignore = 1;
472*1c60b9acSAndroid Build Coastguard Worker 				if (!a)
473*1c60b9acSAndroid Build Coastguard Worker 					a = c + 1;
474*1c60b9acSAndroid Build Coastguard Worker 			}
475*1c60b9acSAndroid Build Coastguard Worker 			if (ignore || *c == ' ') {
476*1c60b9acSAndroid Build Coastguard Worker 				c++;
477*1c60b9acSAndroid Build Coastguard Worker 				continue;
478*1c60b9acSAndroid Build Coastguard Worker 			}
479*1c60b9acSAndroid Build Coastguard Worker 
480*1c60b9acSAndroid Build Coastguard Worker 			ext_name[n] = *c++;
481*1c60b9acSAndroid Build Coastguard Worker 			if (n < (int)sizeof(ext_name) - 1)
482*1c60b9acSAndroid Build Coastguard Worker 				n++;
483*1c60b9acSAndroid Build Coastguard Worker 			continue;
484*1c60b9acSAndroid Build Coastguard Worker 		}
485*1c60b9acSAndroid Build Coastguard Worker 		ext_name[n] = '\0';
486*1c60b9acSAndroid Build Coastguard Worker 		ignore = 0;
487*1c60b9acSAndroid Build Coastguard Worker 		if (!*c)
488*1c60b9acSAndroid Build Coastguard Worker 			more = 0;
489*1c60b9acSAndroid Build Coastguard Worker 		else {
490*1c60b9acSAndroid Build Coastguard Worker 			c++;
491*1c60b9acSAndroid Build Coastguard Worker 			if (!n)
492*1c60b9acSAndroid Build Coastguard Worker 				continue;
493*1c60b9acSAndroid Build Coastguard Worker 		}
494*1c60b9acSAndroid Build Coastguard Worker 
495*1c60b9acSAndroid Build Coastguard Worker 		/* check we actually support it */
496*1c60b9acSAndroid Build Coastguard Worker 
497*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_notice(wsi, "checking client ext %s", ext_name);
498*1c60b9acSAndroid Build Coastguard Worker 
499*1c60b9acSAndroid Build Coastguard Worker 		n = 0;
500*1c60b9acSAndroid Build Coastguard Worker 		ext = wsi->a.vhost->ws.extensions;
501*1c60b9acSAndroid Build Coastguard Worker 		while (ext && ext->callback) {
502*1c60b9acSAndroid Build Coastguard Worker 			if (strcmp(ext_name, ext->name)) {
503*1c60b9acSAndroid Build Coastguard Worker 				ext++;
504*1c60b9acSAndroid Build Coastguard Worker 				continue;
505*1c60b9acSAndroid Build Coastguard Worker 			}
506*1c60b9acSAndroid Build Coastguard Worker 
507*1c60b9acSAndroid Build Coastguard Worker 			n = 1;
508*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_notice(wsi, "instantiating client ext %s", ext_name);
509*1c60b9acSAndroid Build Coastguard Worker 
510*1c60b9acSAndroid Build Coastguard Worker 			/* instantiate the extension on this conn */
511*1c60b9acSAndroid Build Coastguard Worker 
512*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->active_extensions[wsi->ws->count_act_ext] = ext;
513*1c60b9acSAndroid Build Coastguard Worker 
514*1c60b9acSAndroid Build Coastguard Worker 			/* allow him to construct his ext instance */
515*1c60b9acSAndroid Build Coastguard Worker 
516*1c60b9acSAndroid Build Coastguard Worker 			if (ext->callback(lws_get_context(wsi), ext, wsi,
517*1c60b9acSAndroid Build Coastguard Worker 				   LWS_EXT_CB_CLIENT_CONSTRUCT,
518*1c60b9acSAndroid Build Coastguard Worker 				   (void *)&wsi->ws->act_ext_user[
519*1c60b9acSAndroid Build Coastguard Worker 				                        wsi->ws->count_act_ext],
520*1c60b9acSAndroid Build Coastguard Worker 				   (void *)&opts, 0)) {
521*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_info(wsi, " ext %s failed construction",
522*1c60b9acSAndroid Build Coastguard Worker 					  ext_name);
523*1c60b9acSAndroid Build Coastguard Worker 				ext++;
524*1c60b9acSAndroid Build Coastguard Worker 				continue;
525*1c60b9acSAndroid Build Coastguard Worker 			}
526*1c60b9acSAndroid Build Coastguard Worker 
527*1c60b9acSAndroid Build Coastguard Worker 			/*
528*1c60b9acSAndroid Build Coastguard Worker 			 * allow the user code to override ext defaults if it
529*1c60b9acSAndroid Build Coastguard Worker 			 * wants to
530*1c60b9acSAndroid Build Coastguard Worker 			 */
531*1c60b9acSAndroid Build Coastguard Worker 			ext_name[0] = '\0';
532*1c60b9acSAndroid Build Coastguard Worker 			if (user_callback_handle_rxflow(wsi->a.protocol->callback,
533*1c60b9acSAndroid Build Coastguard Worker 					wsi, LWS_CALLBACK_WS_EXT_DEFAULTS,
534*1c60b9acSAndroid Build Coastguard Worker 					(char *)ext->name, ext_name,
535*1c60b9acSAndroid Build Coastguard Worker 					sizeof(ext_name))) {
536*1c60b9acSAndroid Build Coastguard Worker 				*cce = "HS: EXT: failed setting defaults";
537*1c60b9acSAndroid Build Coastguard Worker 				goto bail2;
538*1c60b9acSAndroid Build Coastguard Worker 			}
539*1c60b9acSAndroid Build Coastguard Worker 
540*1c60b9acSAndroid Build Coastguard Worker 			if (ext_name[0] &&
541*1c60b9acSAndroid Build Coastguard Worker 			    lws_ext_parse_options(ext, wsi,
542*1c60b9acSAndroid Build Coastguard Worker 					          wsi->ws->act_ext_user[
543*1c60b9acSAndroid Build Coastguard Worker 						        wsi->ws->count_act_ext],
544*1c60b9acSAndroid Build Coastguard Worker 					          opts, ext_name,
545*1c60b9acSAndroid Build Coastguard Worker 						  (int)strlen(ext_name))) {
546*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_err(wsi, "unable to parse user defaults '%s'",
547*1c60b9acSAndroid Build Coastguard Worker 					     ext_name);
548*1c60b9acSAndroid Build Coastguard Worker 				*cce = "HS: EXT: failed parsing defaults";
549*1c60b9acSAndroid Build Coastguard Worker 				goto bail2;
550*1c60b9acSAndroid Build Coastguard Worker 			}
551*1c60b9acSAndroid Build Coastguard Worker 
552*1c60b9acSAndroid Build Coastguard Worker 			/*
553*1c60b9acSAndroid Build Coastguard Worker 			 * give the extension the server options
554*1c60b9acSAndroid Build Coastguard Worker 			 */
555*1c60b9acSAndroid Build Coastguard Worker 			if (a && lws_ext_parse_options(ext, wsi,
556*1c60b9acSAndroid Build Coastguard Worker 					wsi->ws->act_ext_user[
557*1c60b9acSAndroid Build Coastguard Worker 					                wsi->ws->count_act_ext],
558*1c60b9acSAndroid Build Coastguard Worker 					opts, a, lws_ptr_diff(c, a))) {
559*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_err(wsi, "unable to parse remote def '%s'", a);
560*1c60b9acSAndroid Build Coastguard Worker 				*cce = "HS: EXT: failed parsing options";
561*1c60b9acSAndroid Build Coastguard Worker 				goto bail2;
562*1c60b9acSAndroid Build Coastguard Worker 			}
563*1c60b9acSAndroid Build Coastguard Worker 
564*1c60b9acSAndroid Build Coastguard Worker 			if (ext->callback(lws_get_context(wsi), ext, wsi,
565*1c60b9acSAndroid Build Coastguard Worker 					LWS_EXT_CB_OPTION_CONFIRM,
566*1c60b9acSAndroid Build Coastguard Worker 				      wsi->ws->act_ext_user[wsi->ws->count_act_ext],
567*1c60b9acSAndroid Build Coastguard Worker 				      NULL, 0)) {
568*1c60b9acSAndroid Build Coastguard Worker 				lwsl_wsi_err(wsi, "ext %s rejects server options %s",
569*1c60b9acSAndroid Build Coastguard Worker 					     ext->name, a);
570*1c60b9acSAndroid Build Coastguard Worker 				*cce = "HS: EXT: Rejects server options";
571*1c60b9acSAndroid Build Coastguard Worker 				goto bail2;
572*1c60b9acSAndroid Build Coastguard Worker 			}
573*1c60b9acSAndroid Build Coastguard Worker 
574*1c60b9acSAndroid Build Coastguard Worker 			wsi->ws->count_act_ext++;
575*1c60b9acSAndroid Build Coastguard Worker 
576*1c60b9acSAndroid Build Coastguard Worker 			ext++;
577*1c60b9acSAndroid Build Coastguard Worker 		}
578*1c60b9acSAndroid Build Coastguard Worker 
579*1c60b9acSAndroid Build Coastguard Worker 		if (n == 0) {
580*1c60b9acSAndroid Build Coastguard Worker 			lwsl_wsi_warn(wsi, "Unknown ext '%s'!", ext_name);
581*1c60b9acSAndroid Build Coastguard Worker 			*cce = "HS: EXT: unknown ext";
582*1c60b9acSAndroid Build Coastguard Worker 			goto bail2;
583*1c60b9acSAndroid Build Coastguard Worker 		}
584*1c60b9acSAndroid Build Coastguard Worker 
585*1c60b9acSAndroid Build Coastguard Worker 		a = NULL;
586*1c60b9acSAndroid Build Coastguard Worker 		n = 0;
587*1c60b9acSAndroid Build Coastguard Worker 	}
588*1c60b9acSAndroid Build Coastguard Worker 
589*1c60b9acSAndroid Build Coastguard Worker check_accept:
590*1c60b9acSAndroid Build Coastguard Worker #endif
591*1c60b9acSAndroid Build Coastguard Worker 
592*1c60b9acSAndroid Build Coastguard Worker 	/*
593*1c60b9acSAndroid Build Coastguard Worker 	 * Confirm his accept token is the one we precomputed
594*1c60b9acSAndroid Build Coastguard Worker 	 */
595*1c60b9acSAndroid Build Coastguard Worker 
596*1c60b9acSAndroid Build Coastguard Worker 	p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT);
597*1c60b9acSAndroid Build Coastguard Worker 	if (strcmp(p, wsi->http.ah->initial_handshake_hash_base64)) {
598*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_warn(wsi, "lws_client_int_s_hs: accept '%s' wrong vs '%s'", p,
599*1c60b9acSAndroid Build Coastguard Worker 				  wsi->http.ah->initial_handshake_hash_base64);
600*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: Accept hash wrong";
601*1c60b9acSAndroid Build Coastguard Worker 		goto bail2;
602*1c60b9acSAndroid Build Coastguard Worker 	}
603*1c60b9acSAndroid Build Coastguard Worker 
604*1c60b9acSAndroid Build Coastguard Worker 	/* allocate the per-connection user memory (if any) */
605*1c60b9acSAndroid Build Coastguard Worker 	if (lws_ensure_user_space(wsi)) {
606*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_err(wsi, "Problem allocating wsi user mem");
607*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: OOM";
608*1c60b9acSAndroid Build Coastguard Worker 		goto bail2;
609*1c60b9acSAndroid Build Coastguard Worker 	}
610*1c60b9acSAndroid Build Coastguard Worker 
611*1c60b9acSAndroid Build Coastguard Worker 	/*
612*1c60b9acSAndroid Build Coastguard Worker 	 * we seem to be good to go, give client last chance to check
613*1c60b9acSAndroid Build Coastguard Worker 	 * headers and OK it
614*1c60b9acSAndroid Build Coastguard Worker 	 */
615*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->a.protocol->callback(wsi,
616*1c60b9acSAndroid Build Coastguard Worker 				    LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
617*1c60b9acSAndroid Build Coastguard Worker 				    wsi->user_space, NULL, 0)) {
618*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: Rejected by filter cb";
619*1c60b9acSAndroid Build Coastguard Worker 		goto bail2;
620*1c60b9acSAndroid Build Coastguard Worker 	}
621*1c60b9acSAndroid Build Coastguard Worker 
622*1c60b9acSAndroid Build Coastguard Worker 	/* clear his proxy connection timeout */
623*1c60b9acSAndroid Build Coastguard Worker 	lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
624*1c60b9acSAndroid Build Coastguard Worker 
625*1c60b9acSAndroid Build Coastguard Worker 	/* free up his parsing allocations */
626*1c60b9acSAndroid Build Coastguard Worker 	lws_header_table_detach(wsi, 0);
627*1c60b9acSAndroid Build Coastguard Worker 
628*1c60b9acSAndroid Build Coastguard Worker 	lws_role_transition(wsi, LWSIFR_CLIENT, LRS_ESTABLISHED, &role_ops_ws);
629*1c60b9acSAndroid Build Coastguard Worker 	lws_validity_confirmed(wsi);
630*1c60b9acSAndroid Build Coastguard Worker 
631*1c60b9acSAndroid Build Coastguard Worker 	wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
632*1c60b9acSAndroid Build Coastguard Worker 
633*1c60b9acSAndroid Build Coastguard Worker 	/*
634*1c60b9acSAndroid Build Coastguard Worker 	 * create the frame buffer for this connection according to the
635*1c60b9acSAndroid Build Coastguard Worker 	 * size mentioned in the protocol definition.  If 0 there, then
636*1c60b9acSAndroid Build Coastguard Worker 	 * use a big default for compatibility
637*1c60b9acSAndroid Build Coastguard Worker 	 */
638*1c60b9acSAndroid Build Coastguard Worker 	n = (int)wsi->a.protocol->rx_buffer_size;
639*1c60b9acSAndroid Build Coastguard Worker 	if (!n)
640*1c60b9acSAndroid Build Coastguard Worker 		n = (int)context->pt_serv_buf_size;
641*1c60b9acSAndroid Build Coastguard Worker 	n += LWS_PRE;
642*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->rx_ubuf = lws_malloc((unsigned int)n + 4 /* 0x0000ffff zlib */,
643*1c60b9acSAndroid Build Coastguard Worker 				"client frame buffer");
644*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->ws->rx_ubuf) {
645*1c60b9acSAndroid Build Coastguard Worker 		lwsl_wsi_err(wsi, "OOM allocating rx buffer %d", n);
646*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: OOM";
647*1c60b9acSAndroid Build Coastguard Worker 		goto bail2;
648*1c60b9acSAndroid Build Coastguard Worker 	}
649*1c60b9acSAndroid Build Coastguard Worker 	wsi->ws->rx_ubuf_alloc = (unsigned int)n;
650*1c60b9acSAndroid Build Coastguard Worker 
651*1c60b9acSAndroid Build Coastguard Worker 	lwsl_wsi_debug(wsi, "handshake OK for protocol %s", wsi->a.protocol->name);
652*1c60b9acSAndroid Build Coastguard Worker 
653*1c60b9acSAndroid Build Coastguard Worker 	/* call him back to inform him he is up */
654*1c60b9acSAndroid Build Coastguard Worker 
655*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_CLIENT_ESTABLISHED,
656*1c60b9acSAndroid Build Coastguard Worker 				    wsi->user_space, NULL, 0)) {
657*1c60b9acSAndroid Build Coastguard Worker 		*cce = "HS: Rejected at CLIENT_ESTABLISHED";
658*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
659*1c60b9acSAndroid Build Coastguard Worker 	}
660*1c60b9acSAndroid Build Coastguard Worker 
661*1c60b9acSAndroid Build Coastguard Worker 	return 0;
662*1c60b9acSAndroid Build Coastguard Worker 
663*1c60b9acSAndroid Build Coastguard Worker bail3:
664*1c60b9acSAndroid Build Coastguard Worker 	return 3;
665*1c60b9acSAndroid Build Coastguard Worker 
666*1c60b9acSAndroid Build Coastguard Worker bail2:
667*1c60b9acSAndroid Build Coastguard Worker 	return 2;
668*1c60b9acSAndroid Build Coastguard Worker }
669