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 * parsers.c: lws_ws_rx_sm() needs to be roughly kept in
29*1c60b9acSAndroid Build Coastguard Worker * sync with changes here, esp related to ext draining
30*1c60b9acSAndroid Build Coastguard Worker */
31*1c60b9acSAndroid Build Coastguard Worker
lws_ws_client_rx_sm(struct lws * wsi,unsigned char c)32*1c60b9acSAndroid Build Coastguard Worker int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c)
33*1c60b9acSAndroid Build Coastguard Worker {
34*1c60b9acSAndroid Build Coastguard Worker int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
35*1c60b9acSAndroid Build Coastguard Worker struct lws_ext_pm_deflate_rx_ebufs pmdrx;
36*1c60b9acSAndroid Build Coastguard Worker unsigned short close_code;
37*1c60b9acSAndroid Build Coastguard Worker unsigned char *pp;
38*1c60b9acSAndroid Build Coastguard Worker int handled, m, n;
39*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
40*1c60b9acSAndroid Build Coastguard Worker int rx_draining_ext = 0;
41*1c60b9acSAndroid Build Coastguard Worker #endif
42*1c60b9acSAndroid Build Coastguard Worker
43*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_in.token = NULL;
44*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_in.len = 0;
45*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_out.token = NULL;
46*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_out.len = 0;
47*1c60b9acSAndroid Build Coastguard Worker
48*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
49*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->rx_draining_ext) {
50*1c60b9acSAndroid Build Coastguard Worker assert(!c);
51*1c60b9acSAndroid Build Coastguard Worker
52*1c60b9acSAndroid Build Coastguard Worker lws_remove_wsi_from_draining_ext_list(wsi);
53*1c60b9acSAndroid Build Coastguard Worker rx_draining_ext = 1;
54*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "doing draining flow");
55*1c60b9acSAndroid Build Coastguard Worker
56*1c60b9acSAndroid Build Coastguard Worker goto drain_extension;
57*1c60b9acSAndroid Build Coastguard Worker }
58*1c60b9acSAndroid Build Coastguard Worker #endif
59*1c60b9acSAndroid Build Coastguard Worker
60*1c60b9acSAndroid Build Coastguard Worker switch (wsi->lws_rx_parse_state) {
61*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_NEW:
62*1c60b9acSAndroid Build Coastguard Worker /* control frames (PING) may interrupt checkable sequences */
63*1c60b9acSAndroid Build Coastguard Worker wsi->ws->defeat_check_utf8 = 0;
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Worker switch (wsi->ws->ietf_spec_revision) {
66*1c60b9acSAndroid Build Coastguard Worker case 13:
67*1c60b9acSAndroid Build Coastguard Worker wsi->ws->opcode = c & 0xf;
68*1c60b9acSAndroid Build Coastguard Worker /* revisit if an extension wants them... */
69*1c60b9acSAndroid Build Coastguard Worker switch (wsi->ws->opcode) {
70*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_TEXT_FRAME:
71*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rsv_first_msg = (c & 0x70);
72*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
73*1c60b9acSAndroid Build Coastguard Worker /*
74*1c60b9acSAndroid Build Coastguard Worker * set the expectation that we will have to
75*1c60b9acSAndroid Build Coastguard Worker * fake up the zlib trailer to the inflator for
76*1c60b9acSAndroid Build Coastguard Worker * this frame
77*1c60b9acSAndroid Build Coastguard Worker */
78*1c60b9acSAndroid Build Coastguard Worker wsi->ws->pmd_trailer_application = !!(c & 0x40);
79*1c60b9acSAndroid Build Coastguard Worker #endif
80*1c60b9acSAndroid Build Coastguard Worker wsi->ws->continuation_possible = 1;
81*1c60b9acSAndroid Build Coastguard Worker wsi->ws->check_utf8 = lws_check_opt(
82*1c60b9acSAndroid Build Coastguard Worker wsi->a.context->options,
83*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_VALIDATE_UTF8);
84*1c60b9acSAndroid Build Coastguard Worker wsi->ws->utf8 = 0;
85*1c60b9acSAndroid Build Coastguard Worker wsi->ws->first_fragment = 1;
86*1c60b9acSAndroid Build Coastguard Worker break;
87*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_BINARY_FRAME:
88*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rsv_first_msg = (c & 0x70);
89*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
90*1c60b9acSAndroid Build Coastguard Worker /*
91*1c60b9acSAndroid Build Coastguard Worker * set the expectation that we will have to
92*1c60b9acSAndroid Build Coastguard Worker * fake up the zlib trailer to the inflator for
93*1c60b9acSAndroid Build Coastguard Worker * this frame
94*1c60b9acSAndroid Build Coastguard Worker */
95*1c60b9acSAndroid Build Coastguard Worker wsi->ws->pmd_trailer_application = !!(c & 0x40);
96*1c60b9acSAndroid Build Coastguard Worker #endif
97*1c60b9acSAndroid Build Coastguard Worker wsi->ws->check_utf8 = 0;
98*1c60b9acSAndroid Build Coastguard Worker wsi->ws->continuation_possible = 1;
99*1c60b9acSAndroid Build Coastguard Worker wsi->ws->first_fragment = 1;
100*1c60b9acSAndroid Build Coastguard Worker break;
101*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_CONTINUATION:
102*1c60b9acSAndroid Build Coastguard Worker if (!wsi->ws->continuation_possible) {
103*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "disordered continuation");
104*1c60b9acSAndroid Build Coastguard Worker return -1;
105*1c60b9acSAndroid Build Coastguard Worker }
106*1c60b9acSAndroid Build Coastguard Worker wsi->ws->first_fragment = 0;
107*1c60b9acSAndroid Build Coastguard Worker break;
108*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_CLOSE:
109*1c60b9acSAndroid Build Coastguard Worker wsi->ws->check_utf8 = 0;
110*1c60b9acSAndroid Build Coastguard Worker wsi->ws->utf8 = 0;
111*1c60b9acSAndroid Build Coastguard Worker break;
112*1c60b9acSAndroid Build Coastguard Worker case 3:
113*1c60b9acSAndroid Build Coastguard Worker case 4:
114*1c60b9acSAndroid Build Coastguard Worker case 5:
115*1c60b9acSAndroid Build Coastguard Worker case 6:
116*1c60b9acSAndroid Build Coastguard Worker case 7:
117*1c60b9acSAndroid Build Coastguard Worker case 0xb:
118*1c60b9acSAndroid Build Coastguard Worker case 0xc:
119*1c60b9acSAndroid Build Coastguard Worker case 0xd:
120*1c60b9acSAndroid Build Coastguard Worker case 0xe:
121*1c60b9acSAndroid Build Coastguard Worker case 0xf:
122*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "illegal opcode");
123*1c60b9acSAndroid Build Coastguard Worker return -1;
124*1c60b9acSAndroid Build Coastguard Worker default:
125*1c60b9acSAndroid Build Coastguard Worker wsi->ws->defeat_check_utf8 = 1;
126*1c60b9acSAndroid Build Coastguard Worker break;
127*1c60b9acSAndroid Build Coastguard Worker }
128*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rsv = (c & 0x70);
129*1c60b9acSAndroid Build Coastguard Worker /* revisit if an extension wants them... */
130*1c60b9acSAndroid Build Coastguard Worker if (
131*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
132*1c60b9acSAndroid Build Coastguard Worker !wsi->ws->count_act_ext &&
133*1c60b9acSAndroid Build Coastguard Worker #endif
134*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rsv) {
135*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "illegal rsv bits set");
136*1c60b9acSAndroid Build Coastguard Worker return -1;
137*1c60b9acSAndroid Build Coastguard Worker }
138*1c60b9acSAndroid Build Coastguard Worker wsi->ws->final = !!((c >> 7) & 1);
139*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, " This RX frame Final %d",
140*1c60b9acSAndroid Build Coastguard Worker wsi->ws->final);
141*1c60b9acSAndroid Build Coastguard Worker
142*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->owed_a_fin &&
143*1c60b9acSAndroid Build Coastguard Worker (wsi->ws->opcode == LWSWSOPC_TEXT_FRAME ||
144*1c60b9acSAndroid Build Coastguard Worker wsi->ws->opcode == LWSWSOPC_BINARY_FRAME)) {
145*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "hey you owed us a FIN");
146*1c60b9acSAndroid Build Coastguard Worker return -1;
147*1c60b9acSAndroid Build Coastguard Worker }
148*1c60b9acSAndroid Build Coastguard Worker if ((!(wsi->ws->opcode & 8)) && wsi->ws->final) {
149*1c60b9acSAndroid Build Coastguard Worker wsi->ws->continuation_possible = 0;
150*1c60b9acSAndroid Build Coastguard Worker wsi->ws->owed_a_fin = 0;
151*1c60b9acSAndroid Build Coastguard Worker }
152*1c60b9acSAndroid Build Coastguard Worker
153*1c60b9acSAndroid Build Coastguard Worker if ((wsi->ws->opcode & 8) && !wsi->ws->final) {
154*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "control msg can't be fragmented");
155*1c60b9acSAndroid Build Coastguard Worker return -1;
156*1c60b9acSAndroid Build Coastguard Worker }
157*1c60b9acSAndroid Build Coastguard Worker if (!wsi->ws->final)
158*1c60b9acSAndroid Build Coastguard Worker wsi->ws->owed_a_fin = 1;
159*1c60b9acSAndroid Build Coastguard Worker
160*1c60b9acSAndroid Build Coastguard Worker switch (wsi->ws->opcode) {
161*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_TEXT_FRAME:
162*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_BINARY_FRAME:
163*1c60b9acSAndroid Build Coastguard Worker wsi->ws->frame_is_binary = wsi->ws->opcode ==
164*1c60b9acSAndroid Build Coastguard Worker LWSWSOPC_BINARY_FRAME;
165*1c60b9acSAndroid Build Coastguard Worker break;
166*1c60b9acSAndroid Build Coastguard Worker }
167*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
168*1c60b9acSAndroid Build Coastguard Worker break;
169*1c60b9acSAndroid Build Coastguard Worker
170*1c60b9acSAndroid Build Coastguard Worker default:
171*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_err(wsi, "unknown spec version %02d",
172*1c60b9acSAndroid Build Coastguard Worker wsi->ws->ietf_spec_revision);
173*1c60b9acSAndroid Build Coastguard Worker break;
174*1c60b9acSAndroid Build Coastguard Worker }
175*1c60b9acSAndroid Build Coastguard Worker break;
176*1c60b9acSAndroid Build Coastguard Worker
177*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_04_FRAME_HDR_LEN:
178*1c60b9acSAndroid Build Coastguard Worker
179*1c60b9acSAndroid Build Coastguard Worker wsi->ws->this_frame_masked = !!(c & 0x80);
180*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->this_frame_masked)
181*1c60b9acSAndroid Build Coastguard Worker goto server_cannot_mask;
182*1c60b9acSAndroid Build Coastguard Worker
183*1c60b9acSAndroid Build Coastguard Worker switch (c & 0x7f) {
184*1c60b9acSAndroid Build Coastguard Worker case 126:
185*1c60b9acSAndroid Build Coastguard Worker /* control frames are not allowed to have big lengths */
186*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->opcode & 8)
187*1c60b9acSAndroid Build Coastguard Worker goto illegal_ctl_length;
188*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
189*1c60b9acSAndroid Build Coastguard Worker break;
190*1c60b9acSAndroid Build Coastguard Worker case 127:
191*1c60b9acSAndroid Build Coastguard Worker /* control frames are not allowed to have big lengths */
192*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->opcode & 8)
193*1c60b9acSAndroid Build Coastguard Worker goto illegal_ctl_length;
194*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
195*1c60b9acSAndroid Build Coastguard Worker break;
196*1c60b9acSAndroid Build Coastguard Worker default:
197*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length = c & 0x7f;
198*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->this_frame_masked)
199*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state =
200*1c60b9acSAndroid Build Coastguard Worker LWS_RXPS_07_COLLECT_FRAME_KEY_1;
201*1c60b9acSAndroid Build Coastguard Worker else {
202*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->rx_packet_length) {
203*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state =
204*1c60b9acSAndroid Build Coastguard Worker LWS_RXPS_WS_FRAME_PAYLOAD;
205*1c60b9acSAndroid Build Coastguard Worker } else {
206*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_NEW;
207*1c60b9acSAndroid Build Coastguard Worker goto spill;
208*1c60b9acSAndroid Build Coastguard Worker }
209*1c60b9acSAndroid Build Coastguard Worker }
210*1c60b9acSAndroid Build Coastguard Worker break;
211*1c60b9acSAndroid Build Coastguard Worker }
212*1c60b9acSAndroid Build Coastguard Worker break;
213*1c60b9acSAndroid Build Coastguard Worker
214*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_04_FRAME_HDR_LEN16_2:
215*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length = (size_t)((unsigned int)c << 8);
216*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
217*1c60b9acSAndroid Build Coastguard Worker break;
218*1c60b9acSAndroid Build Coastguard Worker
219*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_04_FRAME_HDR_LEN16_1:
220*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length |= c;
221*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->this_frame_masked)
222*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1;
223*1c60b9acSAndroid Build Coastguard Worker else {
224*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->rx_packet_length)
225*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state =
226*1c60b9acSAndroid Build Coastguard Worker LWS_RXPS_WS_FRAME_PAYLOAD;
227*1c60b9acSAndroid Build Coastguard Worker else {
228*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_NEW;
229*1c60b9acSAndroid Build Coastguard Worker goto spill;
230*1c60b9acSAndroid Build Coastguard Worker }
231*1c60b9acSAndroid Build Coastguard Worker }
232*1c60b9acSAndroid Build Coastguard Worker break;
233*1c60b9acSAndroid Build Coastguard Worker
234*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_04_FRAME_HDR_LEN64_8:
235*1c60b9acSAndroid Build Coastguard Worker if (c & 0x80) {
236*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_warn(wsi, "b63 of length must be zero");
237*1c60b9acSAndroid Build Coastguard Worker /* kill the connection */
238*1c60b9acSAndroid Build Coastguard Worker return -1;
239*1c60b9acSAndroid Build Coastguard Worker }
240*1c60b9acSAndroid Build Coastguard Worker #if defined __LP64__
241*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length = ((size_t)c) << 56;
242*1c60b9acSAndroid Build Coastguard Worker #else
243*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length = 0;
244*1c60b9acSAndroid Build Coastguard Worker #endif
245*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
246*1c60b9acSAndroid Build Coastguard Worker break;
247*1c60b9acSAndroid Build Coastguard Worker
248*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_04_FRAME_HDR_LEN64_7:
249*1c60b9acSAndroid Build Coastguard Worker #if defined __LP64__
250*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length |= ((size_t)c) << 48;
251*1c60b9acSAndroid Build Coastguard Worker #endif
252*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
253*1c60b9acSAndroid Build Coastguard Worker break;
254*1c60b9acSAndroid Build Coastguard Worker
255*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_04_FRAME_HDR_LEN64_6:
256*1c60b9acSAndroid Build Coastguard Worker #if defined __LP64__
257*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length |= ((size_t)c) << 40;
258*1c60b9acSAndroid Build Coastguard Worker #endif
259*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
260*1c60b9acSAndroid Build Coastguard Worker break;
261*1c60b9acSAndroid Build Coastguard Worker
262*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_04_FRAME_HDR_LEN64_5:
263*1c60b9acSAndroid Build Coastguard Worker #if defined __LP64__
264*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length |= ((size_t)c) << 32;
265*1c60b9acSAndroid Build Coastguard Worker #endif
266*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
267*1c60b9acSAndroid Build Coastguard Worker break;
268*1c60b9acSAndroid Build Coastguard Worker
269*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_04_FRAME_HDR_LEN64_4:
270*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length |= ((size_t)c) << 24;
271*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
272*1c60b9acSAndroid Build Coastguard Worker break;
273*1c60b9acSAndroid Build Coastguard Worker
274*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_04_FRAME_HDR_LEN64_3:
275*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length |= ((size_t)c) << 16;
276*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
277*1c60b9acSAndroid Build Coastguard Worker break;
278*1c60b9acSAndroid Build Coastguard Worker
279*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_04_FRAME_HDR_LEN64_2:
280*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length |= ((size_t)c) << 8;
281*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
282*1c60b9acSAndroid Build Coastguard Worker break;
283*1c60b9acSAndroid Build Coastguard Worker
284*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_04_FRAME_HDR_LEN64_1:
285*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_packet_length |= (size_t)c;
286*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->this_frame_masked)
287*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state =
288*1c60b9acSAndroid Build Coastguard Worker LWS_RXPS_07_COLLECT_FRAME_KEY_1;
289*1c60b9acSAndroid Build Coastguard Worker else {
290*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->rx_packet_length)
291*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state =
292*1c60b9acSAndroid Build Coastguard Worker LWS_RXPS_WS_FRAME_PAYLOAD;
293*1c60b9acSAndroid Build Coastguard Worker else {
294*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_NEW;
295*1c60b9acSAndroid Build Coastguard Worker goto spill;
296*1c60b9acSAndroid Build Coastguard Worker }
297*1c60b9acSAndroid Build Coastguard Worker }
298*1c60b9acSAndroid Build Coastguard Worker break;
299*1c60b9acSAndroid Build Coastguard Worker
300*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
301*1c60b9acSAndroid Build Coastguard Worker wsi->ws->mask[0] = c;
302*1c60b9acSAndroid Build Coastguard Worker if (c)
303*1c60b9acSAndroid Build Coastguard Worker wsi->ws->all_zero_nonce = 0;
304*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
305*1c60b9acSAndroid Build Coastguard Worker break;
306*1c60b9acSAndroid Build Coastguard Worker
307*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
308*1c60b9acSAndroid Build Coastguard Worker wsi->ws->mask[1] = c;
309*1c60b9acSAndroid Build Coastguard Worker if (c)
310*1c60b9acSAndroid Build Coastguard Worker wsi->ws->all_zero_nonce = 0;
311*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
312*1c60b9acSAndroid Build Coastguard Worker break;
313*1c60b9acSAndroid Build Coastguard Worker
314*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
315*1c60b9acSAndroid Build Coastguard Worker wsi->ws->mask[2] = c;
316*1c60b9acSAndroid Build Coastguard Worker if (c)
317*1c60b9acSAndroid Build Coastguard Worker wsi->ws->all_zero_nonce = 0;
318*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
319*1c60b9acSAndroid Build Coastguard Worker break;
320*1c60b9acSAndroid Build Coastguard Worker
321*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
322*1c60b9acSAndroid Build Coastguard Worker wsi->ws->mask[3] = c;
323*1c60b9acSAndroid Build Coastguard Worker if (c)
324*1c60b9acSAndroid Build Coastguard Worker wsi->ws->all_zero_nonce = 0;
325*1c60b9acSAndroid Build Coastguard Worker
326*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->rx_packet_length)
327*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state =
328*1c60b9acSAndroid Build Coastguard Worker LWS_RXPS_WS_FRAME_PAYLOAD;
329*1c60b9acSAndroid Build Coastguard Worker else {
330*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_NEW;
331*1c60b9acSAndroid Build Coastguard Worker goto spill;
332*1c60b9acSAndroid Build Coastguard Worker }
333*1c60b9acSAndroid Build Coastguard Worker break;
334*1c60b9acSAndroid Build Coastguard Worker
335*1c60b9acSAndroid Build Coastguard Worker case LWS_RXPS_WS_FRAME_PAYLOAD:
336*1c60b9acSAndroid Build Coastguard Worker
337*1c60b9acSAndroid Build Coastguard Worker assert(wsi->ws->rx_ubuf);
338*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
339*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->rx_draining_ext)
340*1c60b9acSAndroid Build Coastguard Worker goto drain_extension;
341*1c60b9acSAndroid Build Coastguard Worker #endif
342*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->this_frame_masked && !wsi->ws->all_zero_nonce)
343*1c60b9acSAndroid Build Coastguard Worker c ^= wsi->ws->mask[(wsi->ws->mask_idx++) & 3];
344*1c60b9acSAndroid Build Coastguard Worker
345*1c60b9acSAndroid Build Coastguard Worker /*
346*1c60b9acSAndroid Build Coastguard Worker * unmask and collect the payload body in
347*1c60b9acSAndroid Build Coastguard Worker * rx_ubuf_head + LWS_PRE
348*1c60b9acSAndroid Build Coastguard Worker */
349*1c60b9acSAndroid Build Coastguard Worker
350*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf[LWS_PRE + (wsi->ws->rx_ubuf_head++)] = c;
351*1c60b9acSAndroid Build Coastguard Worker
352*1c60b9acSAndroid Build Coastguard Worker if (--wsi->ws->rx_packet_length == 0) {
353*1c60b9acSAndroid Build Coastguard Worker /* spill because we have the whole frame */
354*1c60b9acSAndroid Build Coastguard Worker wsi->lws_rx_parse_state = LWS_RXPS_NEW;
355*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "spilling as we have the whole frame");
356*1c60b9acSAndroid Build Coastguard Worker goto spill;
357*1c60b9acSAndroid Build Coastguard Worker }
358*1c60b9acSAndroid Build Coastguard Worker
359*1c60b9acSAndroid Build Coastguard Worker /*
360*1c60b9acSAndroid Build Coastguard Worker * if there's no protocol max frame size given, we are
361*1c60b9acSAndroid Build Coastguard Worker * supposed to default to context->pt_serv_buf_size
362*1c60b9acSAndroid Build Coastguard Worker */
363*1c60b9acSAndroid Build Coastguard Worker if (!wsi->a.protocol->rx_buffer_size &&
364*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf_head != wsi->a.context->pt_serv_buf_size)
365*1c60b9acSAndroid Build Coastguard Worker break;
366*1c60b9acSAndroid Build Coastguard Worker
367*1c60b9acSAndroid Build Coastguard Worker if (wsi->a.protocol->rx_buffer_size &&
368*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf_head != wsi->a.protocol->rx_buffer_size)
369*1c60b9acSAndroid Build Coastguard Worker break;
370*1c60b9acSAndroid Build Coastguard Worker
371*1c60b9acSAndroid Build Coastguard Worker /* spill because we filled our rx buffer */
372*1c60b9acSAndroid Build Coastguard Worker
373*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "spilling as we filled our rx buffer");
374*1c60b9acSAndroid Build Coastguard Worker spill:
375*1c60b9acSAndroid Build Coastguard Worker
376*1c60b9acSAndroid Build Coastguard Worker handled = 0;
377*1c60b9acSAndroid Build Coastguard Worker
378*1c60b9acSAndroid Build Coastguard Worker /*
379*1c60b9acSAndroid Build Coastguard Worker * is this frame a control packet we should take care of at this
380*1c60b9acSAndroid Build Coastguard Worker * layer? If so service it and hide it from the user callback
381*1c60b9acSAndroid Build Coastguard Worker */
382*1c60b9acSAndroid Build Coastguard Worker
383*1c60b9acSAndroid Build Coastguard Worker switch (wsi->ws->opcode) {
384*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_CLOSE:
385*1c60b9acSAndroid Build Coastguard Worker pp = &wsi->ws->rx_ubuf[LWS_PRE];
386*1c60b9acSAndroid Build Coastguard Worker if (lws_check_opt(wsi->a.context->options,
387*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_VALIDATE_UTF8) &&
388*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf_head > 2 &&
389*1c60b9acSAndroid Build Coastguard Worker lws_check_utf8(&wsi->ws->utf8, pp + 2,
390*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf_head - 2))
391*1c60b9acSAndroid Build Coastguard Worker goto utf8_fail;
392*1c60b9acSAndroid Build Coastguard Worker
393*1c60b9acSAndroid Build Coastguard Worker /* is this an acknowledgment of our close? */
394*1c60b9acSAndroid Build Coastguard Worker if (lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK) {
395*1c60b9acSAndroid Build Coastguard Worker /*
396*1c60b9acSAndroid Build Coastguard Worker * fine he has told us he is closing too, let's
397*1c60b9acSAndroid Build Coastguard Worker * finish our close
398*1c60b9acSAndroid Build Coastguard Worker */
399*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_parser(wsi, "seen server's close ack");
400*1c60b9acSAndroid Build Coastguard Worker return -1;
401*1c60b9acSAndroid Build Coastguard Worker }
402*1c60b9acSAndroid Build Coastguard Worker
403*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_parser(wsi, "client sees server close len = %d",
404*1c60b9acSAndroid Build Coastguard Worker (int)wsi->ws->rx_ubuf_head);
405*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->rx_ubuf_head >= 2) {
406*1c60b9acSAndroid Build Coastguard Worker close_code = (unsigned short)((pp[0] << 8) | pp[1]);
407*1c60b9acSAndroid Build Coastguard Worker if (close_code < 1000 ||
408*1c60b9acSAndroid Build Coastguard Worker close_code == 1004 ||
409*1c60b9acSAndroid Build Coastguard Worker close_code == 1005 ||
410*1c60b9acSAndroid Build Coastguard Worker close_code == 1006 ||
411*1c60b9acSAndroid Build Coastguard Worker (close_code >= 1016 && close_code < 3000)
412*1c60b9acSAndroid Build Coastguard Worker ) {
413*1c60b9acSAndroid Build Coastguard Worker pp[0] = (LWS_CLOSE_STATUS_PROTOCOL_ERR >> 8) & 0xff;
414*1c60b9acSAndroid Build Coastguard Worker pp[1] = LWS_CLOSE_STATUS_PROTOCOL_ERR & 0xff;
415*1c60b9acSAndroid Build Coastguard Worker }
416*1c60b9acSAndroid Build Coastguard Worker }
417*1c60b9acSAndroid Build Coastguard Worker if (user_callback_handle_rxflow(
418*1c60b9acSAndroid Build Coastguard Worker wsi->a.protocol->callback, wsi,
419*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
420*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, pp,
421*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf_head))
422*1c60b9acSAndroid Build Coastguard Worker return -1;
423*1c60b9acSAndroid Build Coastguard Worker
424*1c60b9acSAndroid Build Coastguard Worker memcpy(wsi->ws->ping_payload_buf + LWS_PRE, pp,
425*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf_head);
426*1c60b9acSAndroid Build Coastguard Worker wsi->ws->close_in_ping_buffer_len =
427*1c60b9acSAndroid Build Coastguard Worker (uint8_t)wsi->ws->rx_ubuf_head;
428*1c60b9acSAndroid Build Coastguard Worker
429*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "scheduling return close as ack");
430*1c60b9acSAndroid Build Coastguard Worker __lws_change_pollfd(wsi, LWS_POLLIN, 0);
431*1c60b9acSAndroid Build Coastguard Worker lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_SEND, 3);
432*1c60b9acSAndroid Build Coastguard Worker wsi->waiting_to_send_close_frame = 1;
433*1c60b9acSAndroid Build Coastguard Worker wsi->close_needs_ack = 0;
434*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_WAITING_TO_SEND_CLOSE);
435*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
436*1c60b9acSAndroid Build Coastguard Worker handled = 1;
437*1c60b9acSAndroid Build Coastguard Worker break;
438*1c60b9acSAndroid Build Coastguard Worker
439*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_PING:
440*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "received %d byte ping, sending pong",
441*1c60b9acSAndroid Build Coastguard Worker (int)wsi->ws->rx_ubuf_head);
442*1c60b9acSAndroid Build Coastguard Worker
443*1c60b9acSAndroid Build Coastguard Worker /* he set a close reason on this guy, ignore PING */
444*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->close_in_ping_buffer_len)
445*1c60b9acSAndroid Build Coastguard Worker goto ping_drop;
446*1c60b9acSAndroid Build Coastguard Worker
447*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->pong_pending_flag) {
448*1c60b9acSAndroid Build Coastguard Worker /*
449*1c60b9acSAndroid Build Coastguard Worker * there is already a pending pong payload
450*1c60b9acSAndroid Build Coastguard Worker * we should just log and drop
451*1c60b9acSAndroid Build Coastguard Worker */
452*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_parser(wsi, "DROP PING since one pending");
453*1c60b9acSAndroid Build Coastguard Worker goto ping_drop;
454*1c60b9acSAndroid Build Coastguard Worker }
455*1c60b9acSAndroid Build Coastguard Worker
456*1c60b9acSAndroid Build Coastguard Worker /* control packets can only be < 128 bytes long */
457*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->rx_ubuf_head > 128 - 3) {
458*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_parser(wsi, "DROP PING payload too large");
459*1c60b9acSAndroid Build Coastguard Worker goto ping_drop;
460*1c60b9acSAndroid Build Coastguard Worker }
461*1c60b9acSAndroid Build Coastguard Worker
462*1c60b9acSAndroid Build Coastguard Worker /* stash the pong payload */
463*1c60b9acSAndroid Build Coastguard Worker memcpy(wsi->ws->pong_payload_buf + LWS_PRE,
464*1c60b9acSAndroid Build Coastguard Worker &wsi->ws->rx_ubuf[LWS_PRE],
465*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf_head);
466*1c60b9acSAndroid Build Coastguard Worker
467*1c60b9acSAndroid Build Coastguard Worker wsi->ws->pong_payload_len = (uint8_t)wsi->ws->rx_ubuf_head;
468*1c60b9acSAndroid Build Coastguard Worker wsi->ws->pong_pending_flag = 1;
469*1c60b9acSAndroid Build Coastguard Worker
470*1c60b9acSAndroid Build Coastguard Worker /* get it sent as soon as possible */
471*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
472*1c60b9acSAndroid Build Coastguard Worker ping_drop:
473*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf_head = 0;
474*1c60b9acSAndroid Build Coastguard Worker handled = 1;
475*1c60b9acSAndroid Build Coastguard Worker break;
476*1c60b9acSAndroid Build Coastguard Worker
477*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_PONG:
478*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "Received pong");
479*1c60b9acSAndroid Build Coastguard Worker lwsl_hexdump_wsi_debug(wsi, &wsi->ws->rx_ubuf[LWS_PRE],
480*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf_head);
481*1c60b9acSAndroid Build Coastguard Worker
482*1c60b9acSAndroid Build Coastguard Worker lws_validity_confirmed(wsi);
483*1c60b9acSAndroid Build Coastguard Worker /* issue it */
484*1c60b9acSAndroid Build Coastguard Worker callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
485*1c60b9acSAndroid Build Coastguard Worker break;
486*1c60b9acSAndroid Build Coastguard Worker
487*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_CONTINUATION:
488*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_TEXT_FRAME:
489*1c60b9acSAndroid Build Coastguard Worker case LWSWSOPC_BINARY_FRAME:
490*1c60b9acSAndroid Build Coastguard Worker break;
491*1c60b9acSAndroid Build Coastguard Worker
492*1c60b9acSAndroid Build Coastguard Worker default:
493*1c60b9acSAndroid Build Coastguard Worker /* not handled or failed */
494*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "Unhandled ext opc 0x%x", wsi->ws->opcode);
495*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf_head = 0;
496*1c60b9acSAndroid Build Coastguard Worker
497*1c60b9acSAndroid Build Coastguard Worker return -1;
498*1c60b9acSAndroid Build Coastguard Worker }
499*1c60b9acSAndroid Build Coastguard Worker
500*1c60b9acSAndroid Build Coastguard Worker /*
501*1c60b9acSAndroid Build Coastguard Worker * No it's real payload, pass it up to the user callback.
502*1c60b9acSAndroid Build Coastguard Worker *
503*1c60b9acSAndroid Build Coastguard Worker * We have been statefully collecting it in the
504*1c60b9acSAndroid Build Coastguard Worker * LWS_RXPS_WS_FRAME_PAYLOAD clause above.
505*1c60b9acSAndroid Build Coastguard Worker *
506*1c60b9acSAndroid Build Coastguard Worker * It's nicely buffered with the pre-padding taken care of
507*1c60b9acSAndroid Build Coastguard Worker * so it can be sent straight out again using lws_write.
508*1c60b9acSAndroid Build Coastguard Worker *
509*1c60b9acSAndroid Build Coastguard Worker * However, now we have a chunk of it, we want to deal with it
510*1c60b9acSAndroid Build Coastguard Worker * all here. Since this may be input to permessage-deflate and
511*1c60b9acSAndroid Build Coastguard Worker * there are block limits on that for input and output, we may
512*1c60b9acSAndroid Build Coastguard Worker * need to iterate.
513*1c60b9acSAndroid Build Coastguard Worker */
514*1c60b9acSAndroid Build Coastguard Worker if (handled)
515*1c60b9acSAndroid Build Coastguard Worker goto already_done;
516*1c60b9acSAndroid Build Coastguard Worker
517*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_in.token = &wsi->ws->rx_ubuf[LWS_PRE];
518*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_in.len = (int)wsi->ws->rx_ubuf_head;
519*1c60b9acSAndroid Build Coastguard Worker
520*1c60b9acSAndroid Build Coastguard Worker /* for the non-pm-deflate case */
521*1c60b9acSAndroid Build Coastguard Worker
522*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_out = pmdrx.eb_in;
523*1c60b9acSAndroid Build Coastguard Worker
524*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "starting disbursal of %d deframed rx",
525*1c60b9acSAndroid Build Coastguard Worker (int)wsi->ws->rx_ubuf_head);
526*1c60b9acSAndroid Build Coastguard Worker
527*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
528*1c60b9acSAndroid Build Coastguard Worker drain_extension:
529*1c60b9acSAndroid Build Coastguard Worker #endif
530*1c60b9acSAndroid Build Coastguard Worker do {
531*1c60b9acSAndroid Build Coastguard Worker
532*1c60b9acSAndroid Build Coastguard Worker // lwsl_wsi_notice("pmdrx.eb_in.len: %d",
533*1c60b9acSAndroid Build Coastguard Worker // (int)pmdrx.eb_in.len);
534*1c60b9acSAndroid Build Coastguard Worker
535*1c60b9acSAndroid Build Coastguard Worker n = PMDR_DID_NOTHING;
536*1c60b9acSAndroid Build Coastguard Worker
537*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
538*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "+++ passing %d %p to ext",
539*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_in.len, pmdrx.eb_in.token);
540*1c60b9acSAndroid Build Coastguard Worker
541*1c60b9acSAndroid Build Coastguard Worker n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX,
542*1c60b9acSAndroid Build Coastguard Worker &pmdrx, 0);
543*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "Ext RX returned %d", n);
544*1c60b9acSAndroid Build Coastguard Worker if (n < 0) {
545*1c60b9acSAndroid Build Coastguard Worker wsi->socket_is_permanently_unusable = 1;
546*1c60b9acSAndroid Build Coastguard Worker return -1;
547*1c60b9acSAndroid Build Coastguard Worker }
548*1c60b9acSAndroid Build Coastguard Worker if (n == PMDR_DID_NOTHING)
549*1c60b9acSAndroid Build Coastguard Worker /* ie, not PMDR_NOTHING_WE_SHOULD_DO */
550*1c60b9acSAndroid Build Coastguard Worker break;
551*1c60b9acSAndroid Build Coastguard Worker #endif
552*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "post inflate ebuf in len %d / out len %d",
553*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_in.len, pmdrx.eb_out.len);
554*1c60b9acSAndroid Build Coastguard Worker
555*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
556*1c60b9acSAndroid Build Coastguard Worker if (rx_draining_ext && !pmdrx.eb_out.len) {
557*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, " --- ending drain on 0 read result");
558*1c60b9acSAndroid Build Coastguard Worker goto already_done;
559*1c60b9acSAndroid Build Coastguard Worker }
560*1c60b9acSAndroid Build Coastguard Worker
561*1c60b9acSAndroid Build Coastguard Worker if (n == PMDR_HAS_PENDING) { /* 1 means stuff to drain */
562*1c60b9acSAndroid Build Coastguard Worker /* extension had more... main loop will come back */
563*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "adding to draining ext list");
564*1c60b9acSAndroid Build Coastguard Worker lws_add_wsi_to_draining_ext_list(wsi);
565*1c60b9acSAndroid Build Coastguard Worker } else {
566*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_ext(wsi, "removing from draining ext list");
567*1c60b9acSAndroid Build Coastguard Worker lws_remove_wsi_from_draining_ext_list(wsi);
568*1c60b9acSAndroid Build Coastguard Worker }
569*1c60b9acSAndroid Build Coastguard Worker rx_draining_ext = wsi->ws->rx_draining_ext;
570*1c60b9acSAndroid Build Coastguard Worker #endif
571*1c60b9acSAndroid Build Coastguard Worker
572*1c60b9acSAndroid Build Coastguard Worker if (wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
573*1c60b9acSAndroid Build Coastguard Worker
574*1c60b9acSAndroid Build Coastguard Worker if (lws_check_utf8(&wsi->ws->utf8,
575*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_out.token,
576*1c60b9acSAndroid Build Coastguard Worker (unsigned int)pmdrx.eb_out.len)) {
577*1c60b9acSAndroid Build Coastguard Worker lws_close_reason(wsi,
578*1c60b9acSAndroid Build Coastguard Worker LWS_CLOSE_STATUS_INVALID_PAYLOAD,
579*1c60b9acSAndroid Build Coastguard Worker (uint8_t *)"bad utf8", 8);
580*1c60b9acSAndroid Build Coastguard Worker goto utf8_fail;
581*1c60b9acSAndroid Build Coastguard Worker }
582*1c60b9acSAndroid Build Coastguard Worker
583*1c60b9acSAndroid Build Coastguard Worker /* we are ending partway through utf-8 character? */
584*1c60b9acSAndroid Build Coastguard Worker if (!wsi->ws->rx_packet_length &&
585*1c60b9acSAndroid Build Coastguard Worker wsi->ws->final && wsi->ws->utf8
586*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
587*1c60b9acSAndroid Build Coastguard Worker /* if ext not negotiated, going to be UNKNOWN */
588*1c60b9acSAndroid Build Coastguard Worker && (n == PMDR_EMPTY_FINAL || n == PMDR_UNKNOWN)
589*1c60b9acSAndroid Build Coastguard Worker #endif
590*1c60b9acSAndroid Build Coastguard Worker ) {
591*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "FINAL utf8 error");
592*1c60b9acSAndroid Build Coastguard Worker lws_close_reason(wsi,
593*1c60b9acSAndroid Build Coastguard Worker LWS_CLOSE_STATUS_INVALID_PAYLOAD,
594*1c60b9acSAndroid Build Coastguard Worker (uint8_t *)"partial utf8", 12);
595*1c60b9acSAndroid Build Coastguard Worker utf8_fail:
596*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "utf8 error");
597*1c60b9acSAndroid Build Coastguard Worker lwsl_hexdump_wsi_info(wsi, pmdrx.eb_out.token,
598*1c60b9acSAndroid Build Coastguard Worker (unsigned int)pmdrx.eb_out.len);
599*1c60b9acSAndroid Build Coastguard Worker
600*1c60b9acSAndroid Build Coastguard Worker return -1;
601*1c60b9acSAndroid Build Coastguard Worker }
602*1c60b9acSAndroid Build Coastguard Worker }
603*1c60b9acSAndroid Build Coastguard Worker
604*1c60b9acSAndroid Build Coastguard Worker if (pmdrx.eb_out.len < 0 &&
605*1c60b9acSAndroid Build Coastguard Worker callback_action != LWS_CALLBACK_CLIENT_RECEIVE_PONG)
606*1c60b9acSAndroid Build Coastguard Worker goto already_done;
607*1c60b9acSAndroid Build Coastguard Worker
608*1c60b9acSAndroid Build Coastguard Worker if (!pmdrx.eb_out.token)
609*1c60b9acSAndroid Build Coastguard Worker goto already_done;
610*1c60b9acSAndroid Build Coastguard Worker
611*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_out.token[pmdrx.eb_out.len] = '\0';
612*1c60b9acSAndroid Build Coastguard Worker
613*1c60b9acSAndroid Build Coastguard Worker if (!wsi->a.protocol->callback)
614*1c60b9acSAndroid Build Coastguard Worker goto already_done;
615*1c60b9acSAndroid Build Coastguard Worker
616*1c60b9acSAndroid Build Coastguard Worker if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
617*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "Client doing pong callback");
618*1c60b9acSAndroid Build Coastguard Worker
619*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
620*1c60b9acSAndroid Build Coastguard Worker if (n == PMDR_HAS_PENDING)
621*1c60b9acSAndroid Build Coastguard Worker /* extension had more... main loop will come back
622*1c60b9acSAndroid Build Coastguard Worker * we want callback to be done with this set, if so,
623*1c60b9acSAndroid Build Coastguard Worker * because lws_is_final() hides it was final until the
624*1c60b9acSAndroid Build Coastguard Worker * last chunk
625*1c60b9acSAndroid Build Coastguard Worker */
626*1c60b9acSAndroid Build Coastguard Worker lws_add_wsi_to_draining_ext_list(wsi);
627*1c60b9acSAndroid Build Coastguard Worker else
628*1c60b9acSAndroid Build Coastguard Worker lws_remove_wsi_from_draining_ext_list(wsi);
629*1c60b9acSAndroid Build Coastguard Worker #endif
630*1c60b9acSAndroid Build Coastguard Worker
631*1c60b9acSAndroid Build Coastguard Worker if (lwsi_state(wsi) == LRS_RETURNED_CLOSE ||
632*1c60b9acSAndroid Build Coastguard Worker lwsi_state(wsi) == LRS_WAITING_TO_SEND_CLOSE ||
633*1c60b9acSAndroid Build Coastguard Worker lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK)
634*1c60b9acSAndroid Build Coastguard Worker goto already_done;
635*1c60b9acSAndroid Build Coastguard Worker
636*1c60b9acSAndroid Build Coastguard Worker /* if pmd not enabled, in == out */
637*1c60b9acSAndroid Build Coastguard Worker
638*1c60b9acSAndroid Build Coastguard Worker if (n == PMDR_DID_NOTHING
639*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
640*1c60b9acSAndroid Build Coastguard Worker || n == PMDR_UNKNOWN
641*1c60b9acSAndroid Build Coastguard Worker #endif
642*1c60b9acSAndroid Build Coastguard Worker )
643*1c60b9acSAndroid Build Coastguard Worker pmdrx.eb_in.len -= pmdrx.eb_out.len;
644*1c60b9acSAndroid Build Coastguard Worker
645*1c60b9acSAndroid Build Coastguard Worker m = wsi->a.protocol->callback(wsi,
646*1c60b9acSAndroid Build Coastguard Worker (enum lws_callback_reasons)callback_action,
647*1c60b9acSAndroid Build Coastguard Worker wsi->user_space, pmdrx.eb_out.token,
648*1c60b9acSAndroid Build Coastguard Worker (unsigned int)pmdrx.eb_out.len);
649*1c60b9acSAndroid Build Coastguard Worker
650*1c60b9acSAndroid Build Coastguard Worker wsi->ws->first_fragment = 0;
651*1c60b9acSAndroid Build Coastguard Worker
652*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "bulk ws rx: inp used %d, output %d",
653*1c60b9acSAndroid Build Coastguard Worker (int)wsi->ws->rx_ubuf_head,
654*1c60b9acSAndroid Build Coastguard Worker (int)pmdrx.eb_out.len);
655*1c60b9acSAndroid Build Coastguard Worker
656*1c60b9acSAndroid Build Coastguard Worker /* if user code wants to close, let caller know */
657*1c60b9acSAndroid Build Coastguard Worker if (m)
658*1c60b9acSAndroid Build Coastguard Worker return 1;
659*1c60b9acSAndroid Build Coastguard Worker
660*1c60b9acSAndroid Build Coastguard Worker } while (pmdrx.eb_in.len
661*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITHOUT_EXTENSIONS)
662*1c60b9acSAndroid Build Coastguard Worker || rx_draining_ext
663*1c60b9acSAndroid Build Coastguard Worker #endif
664*1c60b9acSAndroid Build Coastguard Worker );
665*1c60b9acSAndroid Build Coastguard Worker
666*1c60b9acSAndroid Build Coastguard Worker already_done:
667*1c60b9acSAndroid Build Coastguard Worker wsi->ws->rx_ubuf_head = 0;
668*1c60b9acSAndroid Build Coastguard Worker break;
669*1c60b9acSAndroid Build Coastguard Worker default:
670*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_err(wsi, "client rx illegal state");
671*1c60b9acSAndroid Build Coastguard Worker return 1;
672*1c60b9acSAndroid Build Coastguard Worker }
673*1c60b9acSAndroid Build Coastguard Worker
674*1c60b9acSAndroid Build Coastguard Worker return 0;
675*1c60b9acSAndroid Build Coastguard Worker
676*1c60b9acSAndroid Build Coastguard Worker illegal_ctl_length:
677*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_warn(wsi, "Control frame asking for extended length is illegal");
678*1c60b9acSAndroid Build Coastguard Worker
679*1c60b9acSAndroid Build Coastguard Worker /* kill the connection */
680*1c60b9acSAndroid Build Coastguard Worker return -1;
681*1c60b9acSAndroid Build Coastguard Worker
682*1c60b9acSAndroid Build Coastguard Worker server_cannot_mask:
683*1c60b9acSAndroid Build Coastguard Worker lws_close_reason(wsi,
684*1c60b9acSAndroid Build Coastguard Worker LWS_CLOSE_STATUS_PROTOCOL_ERR,
685*1c60b9acSAndroid Build Coastguard Worker (uint8_t *)"srv mask", 8);
686*1c60b9acSAndroid Build Coastguard Worker
687*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_warn(wsi, "Server must not mask");
688*1c60b9acSAndroid Build Coastguard Worker
689*1c60b9acSAndroid Build Coastguard Worker /* kill the connection */
690*1c60b9acSAndroid Build Coastguard Worker return -1;
691*1c60b9acSAndroid Build Coastguard Worker }
692*1c60b9acSAndroid Build Coastguard Worker
693*1c60b9acSAndroid Build Coastguard Worker
694