xref: /aosp_15_r20/external/libwebsockets/lib/roles/ws/client-parser-ws.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  */
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker 
27*1c60b9acSAndroid Build Coastguard Worker /*
28*1c60b9acSAndroid Build Coastguard Worker  * 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