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