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